1 /*metadoc Socket copyright
5 /*metadoc Socket license
9 /*metadoc Socket dependsOn
13 /*metadoc Socket description
14 Interface to network communication.
15 Sockets will auto yield to other coroutines while waiting on a request.
16 All blocking operations use the timeout settings of the socket.
17 Reads are appended to the socket's read buffer which can
18 be accessed using the readBuffer method.
23 socket := Socket clone setHost("www.yahoo.com") setPort(80) connect
24 if(socket error) then( write(socket error, "\n"); exit)
26 socket write("GET /\n\n")
28 while(socket read, Nop)
29 if(socket error) then(write(socket error, "\n"); exit)
31 write("read ", socket readBuffer length, " bytes\n")
33 //metadoc category Networking")
37 /*doc Socket setHost(hostName)
38 Translates hostName to an IP using asynchronous DNS and sets
39 the host attribute. Returns self.
43 #include "IoIPAddress.h"
50 IoSocket
*IoMessage_locals_socketArgAt_(IoMessage
*self
, IoObject
*locals
, int n
)
52 IoObject
*v
= IoMessage_locals_valueArgAt_(self
, locals
, n
);
56 IoMessage_locals_numberArgAt_errorForType_(self
, locals
, n
, "Socket");
62 #define SOCKET(self) ((Socket *)IoObject_dataPointer(self))
64 void IoSocket_tagCleanup(IoTag
*self
)
66 Socket_GlobalCleanup();
69 IoTag
*IoSocket_newTag(void *state
)
71 IoTag
*tag
= IoTag_newWithName_("Socket");
72 IoTag_state_(tag
, state
);
73 IoTag_freeFunc_(tag
, (IoTagFreeFunc
*)IoSocket_free
);
74 IoTag_cloneFunc_(tag
, (IoTagCloneFunc
*)IoSocket_rawClone
);
75 IoTag_cleanupFunc_(tag
, (IoTagCleanupFunc
*)IoSocket_tagCleanup
);
80 IoSocket
*IoSocket_proto(void *state
)
82 IoObject
*self
= IoObject_new(state
);
84 IoObject_tag_(self
, IoSocket_newTag(state
));
85 IoObject_setDataPointer_(self
, Socket_new());
87 IoState_registerProtoWithFunc_((IoState
*)state
, self
, IoSocket_proto
);
90 IoMethodTable methodTable
[] = {
91 {"asyncStreamOpen", IoSocket_asyncStreamOpen
},
92 {"asyncUdpOpen", IoSocket_asyncUdpOpen
},
93 {"isOpen", IoSocket_isOpen
},
94 {"isValid", IoSocket_isValid
},
95 {"isStream", IoSocket_isStream
},
97 {"asyncBind", IoSocket_asyncBind
},
98 {"asyncListen", IoSocket_asyncListen
},
99 {"asyncAccept", IoSocket_asyncAccept
},
101 {"asyncConnect", IoSocket_connectTo
},
103 {"asyncStreamRead", IoSocket_asyncStreamRead
},
104 {"asyncStreamWrite", IoSocket_asyncStreamWrite
},
106 {"asyncUdpRead", IoSocket_udpRead
},
107 {"asyncUdpWrite", IoSocket_udpWrite
},
109 {"close", IoSocket_close
},
110 {"descriptorId", IoSocket_descriptorId
},
112 {"setSocketReadBufferSize", IoSocket_setSocketReadBufferSize
},
113 {"setSocketWriteBufferSize", IoSocket_setSocketWriteBufferSize
},
115 {"getSocketReadLowWaterMark", IoSocket_getSocketReadLowWaterMark
},
116 {"getSocketWriteLowWaterMark", IoSocket_getSocketWriteLowWaterMark
},
118 {"setSocketReadLowWaterMark", IoSocket_setSocketReadLowWaterMark
},
119 {"setSocketWriteLowWaterMark", IoSocket_setSocketWriteLowWaterMark
},
121 {"setNoDelay", IoSocket_setNoDelay
},
123 {"errorNumber", IoSocket_errorNumber
},
124 {"errorDescription", IoSocket_errorDescription
},
128 IoObject_addMethodTable_(self
, methodTable
);
134 IoSocket
*IoSocket_rawClone(IoSocket
*proto
)
136 IoObject
*self
= IoObject_rawClonePrimitive(proto
);
137 IoObject_setDataPointer_(self
, Socket_new());
141 IoSocket
*IoSocket_new(void *state
)
143 IoObject
*proto
= IoState_protoWithInitFunction_((IoState
*)state
, IoSocket_proto
);
144 return IOCLONE(proto
);
147 // -----------------------------------------------------------
149 IoSocket
*IoSocket_newWithSocket_(void *state
, Socket
*socket
)
151 IoSocket
*self
= IoSocket_new(state
);
152 Socket_free(SOCKET(self
));
153 IoObject_setDataPointer_(self
, socket
);
157 void IoSocket_free(IoSocket
*self
)
159 Socket_free(SOCKET(self
));
162 // ----------------------------------------
164 IoSocket
*IoSocket_rawSetupEvent_(IoSocket
*self
, IoObject
*locals
, IoMessage
*m
, char *eventSlotName
)
166 IoObject
*event
= IoObject_rawGetSlot_(self
, IOSYMBOL(eventSlotName
));
167 if(!event
|| ISNIL(event
))
169 IoState_error_(IOSTATE
, m
, "Expected %s slot to be set!", eventSlotName
);
174 IoObject_setSlot_to_(event
, IOSYMBOL("descriptorId"), IoSocket_descriptorId(self
, locals
, m
));
179 IoSocket
*IoSocket_rawSetupEvents(IoSocket
*self
, IoObject
*locals
, IoMessage
*m
)
181 IoSocket_rawSetupEvent_(self
, locals
, m
, "readEvent");
182 IoSocket_rawSetupEvent_(self
, locals
, m
, "writeEvent");
186 IoObject
*IoSocket_descriptorId(IoSocket
*self
, IoObject
*locals
, IoMessage
*m
)
188 return IONUMBER((int) Socket_descriptor(SOCKET(self
)));
191 SOCKET_DESCRIPTOR
IoSocket_rawDescriptor(IoSocket
*self
)
193 return Socket_descriptor(SOCKET(self
));
196 // ----------------------------------------
198 IoObject
*IoSocket_isStream(IoSocket
*self
, IoObject
*locals
, IoMessage
*m
)
200 return IOBOOL(self
, Socket_isStream(SOCKET(self
)));
203 IoObject
*IoSocket_isOpen(IoSocket
*self
, IoObject
*locals
, IoMessage
*m
)
205 return IOBOOL(self
, Socket_isOpen(SOCKET(self
)));
208 IoObject
*IoSocket_isValid(IoSocket
*self
, IoObject
*locals
, IoMessage
*m
)
210 int isValid
= Socket_isValid(SOCKET(self
));
213 IoSocket_close(self
, locals
, m
);
215 return IOBOOL(self
, isValid
);
218 // ----------------------------------------
220 IoObject
*IoSocket_asyncStreamOpen(IoSocket
*self
, IoObject
*locals
, IoMessage
*m
)
222 Socket
*socket
= SOCKET(self
);
223 SocketResetErrorStatus();
225 if (Socket_streamOpen(socket
) && Socket_isOpen(socket
) && Socket_makeReusable(socket
) && Socket_makeAsync(socket
))
227 IoSocket_rawSetupEvents(self
, locals
, m
);
232 return SOCKETERROR("Failed to create stream socket");
236 IoObject
*IoSocket_asyncUdpOpen(IoSocket
*self
, IoObject
*locals
, IoMessage
*m
)
238 Socket
*socket
= SOCKET(self
);
240 if (Socket_udpOpen(socket
) && Socket_isOpen(socket
) && Socket_makeReusable(socket
) && Socket_makeAsync(socket
))
242 IoSocket_rawSetupEvents(self
, locals
, m
);
247 return SOCKETERROR("Failed to create udp socket");
251 // ----------------------------------------
253 IoObject
*IoSocket_connectTo(IoSocket
*self
, IoObject
*locals
, IoMessage
*m
)
255 IPAddress
*address
= IoMessage_locals_rawIPAddressArgAt_(m
, locals
, 0);
256 if (Socket_connectTo(SOCKET(self
), address
))
260 if (Socket_connectToFailed())
261 return SOCKETERROR("Socket connect failed");
267 IoObject
*IoSocket_close(IoSocket
*self
, IoObject
*locals
, IoMessage
*m
)
269 if (Socket_close(SOCKET(self
)))
271 IoSocket_rawSetupEvents(self
, locals
, m
);
276 if (Socket_closeFailed())
277 return SOCKETERROR("Failed to close socket");
283 // server -------------------------------
285 IoObject
*IoSocket_asyncBind(IoSocket
*self
, IoObject
*locals
, IoMessage
*m
)
287 IPAddress
*address
= IoMessage_locals_rawIPAddressArgAt_(m
, locals
, 0);
288 if (Socket_bind(SOCKET(self
), address
))
291 return SOCKETERROR("Failed to bind socket");
294 IoObject
*IoSocket_asyncListen(IoSocket
*self
, IoObject
*locals
, IoMessage
*m
)
296 if (Socket_listen(SOCKET(self
)))
299 return SOCKETERROR("Socket listen failed");
302 IoObject
*IoSocket_asyncAccept(IoSocket
*self
, IoObject
*locals
, IoMessage
*m
)
304 IPAddress
*address
= IoMessage_locals_rawIPAddressArgAt_(m
, locals
, 0);
305 Socket
*socket
= Socket_accept(SOCKET(self
), address
);
308 IoObject
*newSocket
= IoSocket_newWithSocket_(IOSTATE
, socket
);
309 newSocket
= IoObject_initClone_(self
, locals
, m
, newSocket
);
310 return IoSocket_rawSetupEvents(newSocket
, locals
, m
);
314 if (Socket_asyncFailed())
315 return SOCKETERROR("Socket accept failed");
321 // stream -------------------------------
323 IoObject
*IoSocket_asyncStreamRead(IoSocket
*self
, IoObject
*locals
, IoMessage
*m
)
325 IoSeq
*bufferSeq
= IoMessage_locals_mutableSeqArgAt_(m
, locals
, 0);
326 UArray
*buffer
= IoSeq_rawUArray(bufferSeq
);
327 size_t readSize
= IoMessage_locals_intArgAt_(m
, locals
, 1);
329 if (Socket_streamRead(SOCKET(self
), buffer
, readSize
))
335 if (Socket_asyncFailed())
337 IoSocket_close(self
, locals
, m
);
338 return SOCKETERROR("Socket stream read failed");
342 if (SocketErrorStatus() == 0)
343 // 0 bytes means the other end disconnected
344 IoSocket_close(self
, locals
, m
);
350 IoObject
*IoSocket_asyncStreamWrite(IoSocket
*self
, IoObject
*locals
, IoMessage
*m
)
352 IoSeq
*bufferSeq
= IoMessage_locals_seqArgAt_(m
, locals
, 0);
353 UArray
*buffer
= IoSeq_rawUArray(bufferSeq
);
354 size_t start
= IoMessage_locals_intArgAt_(m
, locals
, 1);
355 size_t writeSize
= IoMessage_locals_intArgAt_(m
, locals
, 2);
356 size_t bytesWritten
= Socket_streamWrite(SOCKET(self
), buffer
, start
, writeSize
);
360 UArray_removeRange(buffer
, start
, bytesWritten
);
365 if (Socket_asyncFailed())
367 IoSocket_close(self
, locals
, m
);
368 return SOCKETERROR("Socket stream write failed");
372 if (IoSocket_errorNumber(self
, locals
, m
) == 0)
373 // 0 bytes means the other end disconnected
374 IoSocket_close(self
, locals
, m
);
380 // udp ------------------------------
382 IoObject
*IoSocket_udpRead(IoSocket
*self
, IoObject
*locals
, IoMessage
*m
)
384 IPAddress
*address
= IoMessage_locals_rawIPAddressArgAt_(m
, locals
, 0);
385 UArray
*buffer
= IoSeq_rawUArray(IoMessage_locals_mutableSeqArgAt_(m
, locals
, 1));
386 size_t readSize
= IoMessage_locals_sizetArgAt_(m
, locals
, 2);
388 if (Socket_udpRead(SOCKET(self
), address
, buffer
, readSize
))
394 if (Socket_asyncFailed())
395 return SOCKETERROR("Socket udp read failed");
401 IoObject
*IoSocket_udpWrite(IoSocket
*self
, IoObject
*locals
, IoMessage
*m
)
403 IPAddress
*address
= IoMessage_locals_rawIPAddressArgAt_(m
, locals
, 0);
404 UArray
*buffer
= IoSeq_rawUArray(IoMessage_locals_seqArgAt_(m
, locals
, 1));
405 size_t start
= IoMessage_locals_intArgAt_(m
, locals
, 2);
406 size_t writeSize
= IoMessage_locals_intArgAt_(m
, locals
, 3);
407 size_t bytesWritten
= Socket_udpWrite(SOCKET(self
), address
, buffer
, start
, writeSize
);
411 if (bytesWritten
< writeSize
)
413 return SOCKETERROR("Socket udp write failed");
417 UArray_removeRange(buffer
, start
, bytesWritten
);
423 if (Socket_asyncFailed())
424 return SOCKETERROR("Socket udp write failed");
430 // ----------------------------------
432 IoObject
*IoSocket_setSocketReadBufferSize(IoSocket
*self
, IoObject
*locals
, IoMessage
*m
)
434 int size
= IoMessage_locals_intArgAt_(m
, locals
, 0);
435 int r
= setsockopt(SOCKET(self
)->fd
, SOL_SOCKET
, SO_RCVBUF
, &size
, sizeof(int));
439 IoObject
*IoSocket_setSocketWriteBufferSize(IoSocket
*self
, IoObject
*locals
, IoMessage
*m
)
441 int size
= IoMessage_locals_intArgAt_(m
, locals
, 0);
442 int r
= setsockopt(SOCKET(self
)->fd
, SOL_SOCKET
, SO_SNDBUF
, &size
, sizeof(int));
446 IoObject
*IoSocket_setSocketReadLowWaterMark(IoSocket
*self
, IoObject
*locals
, IoMessage
*m
)
448 int size
= IoMessage_locals_intArgAt_(m
, locals
, 0);
449 int r
= setsockopt(SOCKET(self
)->fd
, SOL_SOCKET
, SO_RCVLOWAT
, &size
, sizeof(int));
453 IoObject
*IoSocket_setSocketWriteLowWaterMark(IoSocket
*self
, IoObject
*locals
, IoMessage
*m
)
455 int size
= IoMessage_locals_intArgAt_(m
, locals
, 0);
456 int r
= setsockopt(SOCKET(self
)->fd
, SOL_SOCKET
, SO_SNDLOWAT
, &size
, sizeof(int));
460 IoObject
*IoSocket_getSocketReadLowWaterMark(IoSocket
*self
, IoObject
*locals
, IoMessage
*m
)
463 socklen_t length
= sizeof(int);
465 getsockopt(SOCKET(self
)->fd
, SOL_SOCKET
, SO_RCVLOWAT
, &size
, &length
);
467 return IONUMBER(size
);
470 IoObject
*IoSocket_getSocketWriteLowWaterMark(IoSocket
*self
, IoObject
*locals
, IoMessage
*m
)
473 socklen_t length
= sizeof(int);
475 getsockopt(SOCKET(self
)->fd
, SOL_SOCKET
, SO_SNDLOWAT
, &size
, &length
);
476 return IONUMBER(size
);
480 #include <sys/socket.h>
483 IoObject
*IoSocket_setNoDelay(IoSocket
*self
, IoObject
*locals
, IoMessage
*m
)
488 r
= setsockopt(SOCKET(self
)->fd
, IPPROTO_TCP
, TCP_NODELAY
, (char *) &flag
, sizeof(int));
493 IoObject
*IoSocket_errorNumber(IoSocket
*self
, IoObject
*locals
, IoMessage
*m
)
495 return IONUMBER(SocketErrorStatus());
498 IoObject
*IoSocket_errorDescription(IoSocket
*self
, IoObject
*locals
, IoMessage
*m
)
500 return IOSYMBOL(Socket_errorDescription());