Socket.swift 2.4 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071
  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, 4) == -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: sizeof(sockaddr_in).bridgeToObjectiveC().unsignedCharValue,
  23. sin_family: sa_family_t(AF_INET),
  24. sin_port: port,
  25. sin_addr: in_addr(s_addr: inet_addr("0.0.0.0")),
  26. sin_zero: (0, 0, 0, 0, 0, 0, 0, 0))
  27. 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))
  28. memcpy(&sock_addr, &addr, UInt(sizeof(sockaddr_in)))
  29. if ( bind(s, &sock_addr, sizeof(sockaddr_in).bridgeToObjectiveC().unsignedIntValue) == -1 ) {
  30. let error = "bind(...) failed \(errno) - \(strerror(errno))"
  31. release(s)
  32. return (-1, error)
  33. }
  34. if ( listen(s, 20 /* max pending connection */ ) == -1 ) {
  35. let error = "listen(...) failed \(errno) - \(strerror(errno))"
  36. release(s)
  37. return (-1, error)
  38. }
  39. return (s, nil)
  40. }
  41. static func writeString(socket: CInt, response: String) {
  42. var sent = 0;
  43. let nsdata = response.bridgeToObjectiveC().dataUsingEncoding(NSUTF8StringEncoding)
  44. let pointer = nsdata.bytes
  45. while ( sent < nsdata.length ) {
  46. // TODO pointer + sent
  47. let s = write(socket, pointer, UInt(nsdata.length - sent))
  48. if ( s <= 0 ) {
  49. return
  50. }
  51. sent += s
  52. }
  53. }
  54. static func nosigpipe(socket: CInt) {
  55. // prevents crashes when blocking calls are pending and the app is paused ( via Home button )
  56. var no_sig_pipe: Int32 = 1;
  57. setsockopt(socket, SOL_SOCKET, SO_NOSIGPIPE, &no_sig_pipe, 4);
  58. }
  59. static func release(socket: CInt) {
  60. shutdown(socket, 2)
  61. close(socket)
  62. }
  63. }