| 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788 |
- //
- // Socket.swift
- //
- // Created by Damian Kolakowski on 05/06/14.
- // Copyright (c) 2014 Damian Kołakowski. All rights reserved.
- //
- import Foundation
- /* Low level routines for POSIX sockets */
- struct Socket {
-
- static func socketRecentError(reason:String) -> NSError {
- let code = errno
- return NSError.errorWithDomain("SOCKET", code: Int(code), userInfo:
- [NSLocalizedFailureReasonErrorKey : reason, NSLocalizedDescriptionKey : String.fromCString(strerror(code))])
- }
-
- static func tcpForListen(port: in_port_t = 8080, error:NSErrorPointer = nil) -> CInt? {
- let s = socket(AF_INET, SOCK_STREAM, 0)
- if ( s == -1 ) {
- if error { error.memory = socketRecentError("socket(...) failed.") }
- return nil
- }
- var value: Int32 = 1;
- if ( setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &value, socklen_t(sizeof(Int32))) == -1 ) {
- release(s)
- if error { error.memory = socketRecentError("setsockopt(...) failed.") }
- return nil
- }
- nosigpipe(s)
- // Can't find htonl(...) function in Swift runtime so port value will be diffrent.
- var addr = sockaddr_in(sin_len: __uint8_t(sizeof(sockaddr_in)), sin_family: sa_family_t(AF_INET),
- 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))
-
- 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))
- memcpy(&sock_addr, &addr, UInt(sizeof(sockaddr_in)))
- if ( bind(s, &sock_addr, socklen_t(sizeof(sockaddr_in))) == -1 ) {
- release(s)
- if error { error.memory = socketRecentError("bind(...) failed.") }
- return nil
- }
- if ( listen(s, 20 /* max pending connection */ ) == -1 ) {
- release(s)
- if error { error.memory = socketRecentError("listen(...) failed.") }
- return nil
- }
- return s
- }
-
- static func writeStringUTF8(socket: CInt, string: String, error:NSErrorPointer = nil) -> Bool {
- var sent = 0;
- let nsdata = string.bridgeToObjectiveC().dataUsingEncoding(NSUTF8StringEncoding)
- let unsafePointer = UnsafePointer<UInt8>(nsdata.bytes)
- while ( sent < nsdata.length ) {
- let s = write(socket, unsafePointer + sent, UInt(nsdata.length - sent))
- if ( s <= 0 ) {
- if error { error.memory = socketRecentError("write(...) failed.") }
- return false
- }
- sent += s
- }
- return true
- }
-
- static func acceptClientSocket(socket: CInt, error:NSErrorPointer = nil) -> CInt? {
- var addr = sockaddr(sa_len: 0, sa_family: 0, sa_data: (0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0)), len: socklen_t = 0
- let clientSocket = accept(socket, &addr, &len)
- if ( clientSocket != -1 ) {
- Socket.nosigpipe(clientSocket)
- return clientSocket
- }
- if error { error.memory = socketRecentError("accept(...) failed.") }
- return nil
- }
-
- static func nosigpipe(socket: CInt) {
- // prevents crashes when blocking calls are pending and the app is paused ( via Home button )
- var no_sig_pipe: Int32 = 1;
- setsockopt(socket, SOL_SOCKET, SO_NOSIGPIPE, &no_sig_pipe, socklen_t(sizeof(Int32)));
- }
-
- static func release(socket: CInt) {
- shutdown(socket, SHUT_RDWR)
- close(socket)
- }
- }
|