Socket.swift 2.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869
  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. // Can't find htonl(...) function in Swift runtime so port value will be diffrent.
  23. var addr = sockaddr_in(sin_len: __uint8_t(sizeof(sockaddr_in)), sin_family: sa_family_t(AF_INET),
  24. 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))
  25. var sock_addr = sockaddr(sa_len: 0, sa_family: 0, sa_data: (0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0))
  26. memcpy(&sock_addr, &addr, UInt(sizeof(sockaddr_in)))
  27. if ( bind(s, &sock_addr, socklen_t(sizeof(sockaddr_in))) == -1 ) {
  28. let error = "bind(...) failed \(errno) - \(strerror(errno))"
  29. release(s)
  30. return (-1, error)
  31. }
  32. if ( listen(s, 20 /* max pending connection */ ) == -1 ) {
  33. let error = "listen(...) failed \(errno) - \(strerror(errno))"
  34. release(s)
  35. return (-1, error)
  36. }
  37. return (s, nil)
  38. }
  39. static func writeStringUTF8(socket: CInt, string: String) {
  40. var sent = 0;
  41. let nsdata = string.bridgeToObjectiveC().dataUsingEncoding(NSUTF8StringEncoding)
  42. let unsafePointer = UnsafePointer<UInt8>(nsdata.bytes)
  43. while ( sent < nsdata.length ) {
  44. let s = write(socket, unsafePointer + sent, UInt(nsdata.length - sent))
  45. if ( s <= 0 ) {
  46. return
  47. }
  48. sent += s
  49. }
  50. return
  51. }
  52. static func nosigpipe(socket: CInt) {
  53. // prevents crashes when blocking calls are pending and the app is paused ( via Home button )
  54. var no_sig_pipe: Int32 = 1;
  55. setsockopt(socket, SOL_SOCKET, SO_NOSIGPIPE, &no_sig_pipe, socklen_t(sizeof(Int32)));
  56. }
  57. static func release(socket: CInt) {
  58. shutdown(socket, SHUT_RDWR)
  59. close(socket)
  60. }
  61. }