1
0

Socket.swift 2.4 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667
  1. //
  2. // Socket.swift
  3. //
  4. // Created by Damian Kolakowski on 05/06/14.
  5. // Copyright (c) 2014 Damian Kołakowski. All rights reserved.
  6. //
  7. import Foundation
  8. /* Low level routines for POSIX sockets */
  9. struct Socket {
  10. static func tcpForListen(port: in_port_t) -> (CInt, String?) {
  11. let s = socket(AF_INET, SOCK_STREAM, 0)
  12. if ( s == -1 ) {
  13. return (-1, "socket() failed \(errno) - \(strerror(errno))")
  14. }
  15. var value: Int32 = 1;
  16. if ( setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &value, socklen_t(sizeof(Int32))) == -1 ) {
  17. let error = "setsockopt(...) failed \(errno) - \(strerror(errno))"
  18. release(s)
  19. return (-1, error)
  20. }
  21. nosigpipe(s)
  22. var addr: sockaddr_in = sockaddr_in(sin_len: __uint8_t(sizeof(sockaddr_in)), sin_family: sa_family_t(AF_INET),
  23. sin_port: port, sin_addr: in_addr(s_addr: inet_addr("0.0.0.0")), sin_zero: (0, 0, 0, 0, 0, 0, 0, 0))
  24. var sock_addr: sockaddr = sockaddr(sa_len: 0, sa_family: 0, sa_data: (0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0))
  25. memcpy(&sock_addr, &addr, UInt(sizeof(sockaddr_in)))
  26. if ( bind(s, &sock_addr, socklen_t(sizeof(sockaddr_in))) == -1 ) {
  27. let error = "bind(...) failed \(errno) - \(strerror(errno))"
  28. release(s)
  29. return (-1, error)
  30. }
  31. if ( listen(s, 20 /* max pending connection */ ) == -1 ) {
  32. let error = "listen(...) failed \(errno) - \(strerror(errno))"
  33. release(s)
  34. return (-1, error)
  35. }
  36. return (s, nil)
  37. }
  38. static func writeString(socket: CInt, response: String) {
  39. var sent = 0;
  40. let nsdata = response.bridgeToObjectiveC().dataUsingEncoding(NSUTF8StringEncoding)
  41. let unsafePointer = UnsafePointer<UInt8>(nsdata.bytes)
  42. while ( sent < nsdata.length ) {
  43. let s = write(socket, unsafePointer + sent, UInt(nsdata.length - sent))
  44. if ( s <= 0 ) {
  45. return
  46. }
  47. sent += s
  48. }
  49. }
  50. static func nosigpipe(socket: CInt) {
  51. // prevents crashes when blocking calls are pending and the app is paused ( via Home button )
  52. var no_sig_pipe: Int32 = 1;
  53. setsockopt(socket, SOL_SOCKET, SO_NOSIGPIPE, &no_sig_pipe, socklen_t(sizeof(Int32)));
  54. }
  55. static func release(socket: CInt) {
  56. shutdown(socket, SHUT_RDWR)
  57. close(socket)
  58. }
  59. }