PageRenderTime 31ms CodeModel.GetById 2ms app.highlight 25ms RepoModel.GetById 1ms app.codeStats 0ms

/addons/Socket/source/IoSocket.c

https://github.com/qxjit/io
C | 597 lines | 401 code | 103 blank | 93 comment | 38 complexity | 42fe6e51823d4bc6bc37b9c1722f6a40 MD5 | raw file
  1//metadoc Socket copyright Steve Dekorte, 2004
  2//metadoc Socket license BSD revised
  3
  4/*metadoc Socket description
  5Interface to network communication.
  6Sockets will auto yield to other coroutines while waiting on a request.
  7All blocking operations use the timeout settings of the socket.
  8Reads are appended to the socket's read buffer which can 
  9be accessed using the readBuffer method.
 10
 11Example:
 12
 13<pre>	
 14socket := Socket clone setHost("www.yahoo.com") setPort(80) connect
 15if(socket error) then( write(socket error, "\n"); exit)
 16
 17socket write("GET /\n\n")
 18
 19while(socket read, Nop)
 20if(socket error) then(write(socket error, "\n"); exit)
 21
 22write("read ", socket readBuffer length, " bytes\n")
 23</pre>
 24*/
 25
 26//metadoc Socket category Networking
 27
 28
 29/*doc Socket setHost(hostName)
 30Translates hostName to an IP using asynchronous DNS and sets 
 31the host attribute. Returns self.
 32*/
 33
 34#include "IoSocket.h"
 35#include "IoIPAddress.h"
 36#include "IoState.h"
 37#include "IoNumber.h"
 38#include "IoSeq.h"
 39#include "UArray.h"
 40#include "List.h"
 41
 42IoSocket *IoMessage_locals_socketArgAt_(IoMessage *self, IoObject *locals, int n)
 43{
 44	IoObject *v = IoMessage_locals_valueArgAt_(self, locals, n);
 45
 46	if (!ISSOCKET(v))
 47	{
 48		IoMessage_locals_numberArgAt_errorForType_(self, locals, n, "Socket");
 49	}
 50
 51	return v;
 52}
 53
 54#define SOCKET(self) ((Socket *)IoObject_dataPointer(self))
 55
 56void IoSocket_tagCleanup(IoTag *self)
 57{
 58	Socket_GlobalCleanup();
 59}
 60
 61IoTag *IoSocket_newTag(void *state)
 62{
 63	IoTag *tag = IoTag_newWithName_("Socket");
 64	IoTag_state_(tag, state);
 65	IoTag_freeFunc_(tag, (IoTagFreeFunc *)IoSocket_free);
 66	IoTag_cloneFunc_(tag, (IoTagCloneFunc *)IoSocket_rawClone);
 67	IoTag_cleanupFunc_(tag, (IoTagCleanupFunc *)IoSocket_tagCleanup);
 68	Socket_GlobalInit();
 69	return tag;
 70}
 71
 72IoSocket *IoSocket_proto(void *state)
 73{
 74	IoObject *self = IoObject_new(state);
 75
 76	IoObject_tag_(self, IoSocket_newTag(state));
 77	IoObject_setDataPointer_(self, Socket_new());
 78
 79	IoState_registerProtoWithFunc_((IoState *)state, self, IoSocket_proto);
 80
 81	{
 82		IoMethodTable methodTable[] = {
 83		{"asyncStreamOpen", IoSocket_asyncStreamOpen},
 84		{"asyncUdpOpen", IoSocket_asyncUdpOpen},
 85		{"isOpen", IoSocket_isOpen},
 86		{"isValid", IoSocket_isValid},
 87		{"isStream", IoSocket_isStream},
 88
 89		{"asyncBind", IoSocket_asyncBind},
 90		{"asyncListen", IoSocket_asyncListen},
 91		{"asyncAccept", IoSocket_asyncAccept},
 92
 93		{"asyncConnect", IoSocket_asyncConnect},
 94
 95		{"asyncStreamRead", IoSocket_asyncStreamRead},
 96		{"asyncStreamWrite", IoSocket_asyncStreamWrite},
 97
 98		{"asyncUdpRead", IoSocket_asyncUdpRead},
 99		{"asyncUdpWrite", IoSocket_asyncUdpWrite},
100
101		{"close", IoSocket_close},
102		{"descriptorId", IoSocket_descriptorId},
103
104		{"setSocketReadBufferSize", IoSocket_setSocketReadBufferSize},
105		{"setSocketWriteBufferSize", IoSocket_setSocketWriteBufferSize},
106
107		{"getSocketReadLowWaterMark", IoSocket_getSocketReadLowWaterMark},
108		{"getSocketWriteLowWaterMark", IoSocket_getSocketWriteLowWaterMark},
109
110		{"setSocketReadLowWaterMark", IoSocket_setSocketReadLowWaterMark},
111		{"setSocketWriteLowWaterMark", IoSocket_setSocketWriteLowWaterMark},
112
113		{"setNoDelay", IoSocket_setNoDelay},
114		
115		{"errorNumber", IoSocket_errorNumber},
116		{"errorDescription", IoSocket_errorDescription},
117
118		{NULL, NULL}
119		};
120		IoObject_addMethodTable_(self, methodTable);
121	}
122
123	return self;
124}
125
126IoSocket *IoSocket_rawClone(IoSocket *proto)
127{
128	IoObject *self = IoObject_rawClonePrimitive(proto);
129	IoObject_setDataPointer_(self, Socket_new());
130	return self;
131}
132
133IoSocket *IoSocket_new(void *state)
134{
135	IoObject *proto = IoState_protoWithInitFunction_((IoState *)state, IoSocket_proto);
136	return IOCLONE(proto);
137}
138
139// -----------------------------------------------------------
140
141IoSocket *IoSocket_newWithSocket_(void *state, Socket *socket)
142{
143	IoSocket *self = IoSocket_new(state);
144	Socket_free(SOCKET(self));
145	IoObject_setDataPointer_(self, socket);
146	return self;
147}
148
149void IoSocket_free(IoSocket *self)
150{
151	Socket_free(SOCKET(self));
152}
153
154// ----------------------------------------
155
156IoSocket *IoSocket_rawSetupEvent_(IoSocket *self, IoObject *locals, IoMessage *m, char *eventSlotName)
157{
158	IoObject *event = IoObject_rawGetSlot_(self, IOSYMBOL(eventSlotName));
159	if(!event || ISNIL(event))
160	{
161		IoState_error_(IOSTATE, m, "Expected %s slot to be set!", eventSlotName);
162		return IONIL(self);
163	}
164	else
165	{
166		IoObject_setSlot_to_(event, IOSYMBOL("descriptorId"), IoSocket_descriptorId(self, locals, m));
167		return self;
168	}
169}
170
171IoSocket *IoSocket_rawSetupEvents(IoSocket *self, IoObject *locals, IoMessage *m)
172{
173	IoSocket_rawSetupEvent_(self, locals, m, "readEvent");
174	IoSocket_rawSetupEvent_(self, locals, m, "writeEvent");
175	return self;
176}
177
178IoObject *IoSocket_descriptorId(IoSocket *self, IoObject *locals, IoMessage *m)
179{
180	//doc Socket descriptorId Returns the socket's file descriptor id as a Number.
181	return IONUMBER((int) Socket_descriptor(SOCKET(self)));
182}
183
184SOCKET_DESCRIPTOR IoSocket_rawDescriptor(IoSocket *self)
185{
186	return Socket_descriptor(SOCKET(self));
187}
188
189// ----------------------------------------
190
191IoObject *IoSocket_isStream(IoSocket *self, IoObject *locals, IoMessage *m)
192{
193	//doc Socket isStream Returns true if the socket is a stream, false otherwise.
194	return IOBOOL(self, Socket_isStream(SOCKET(self)));
195}
196
197IoObject *IoSocket_isOpen(IoSocket *self, IoObject *locals, IoMessage *m)
198{
199	//doc Socket isOpen Returns true if the socket is open, false otherwise.
200	return IOBOOL(self, Socket_isOpen(SOCKET(self)));
201}
202
203IoObject *IoSocket_isValid(IoSocket *self, IoObject *locals, IoMessage *m)
204{
205	//doc Socket isValid Returns true if the socket is in valid state, closes the socket and returns false otherwise.
206	int isValid = Socket_isValid(SOCKET(self));
207
208	if (!isValid)
209		IoSocket_close(self, locals, m);
210
211	return IOBOOL(self, isValid);
212}
213
214// ----------------------------------------
215
216IoObject *IoSocket_asyncStreamOpen(IoSocket *self, IoObject *locals, IoMessage *m)
217{
218	//doc Socket asyncStreamOpen Submits an async request to open the socket in stream mode and returns self immediately or an Error object on error.
219	
220	Socket *socket = SOCKET(self);
221	SocketResetErrorStatus();
222
223	if (Socket_streamOpen(socket) && Socket_isOpen(socket) && Socket_makeReusable(socket) && Socket_makeAsync(socket))
224	{
225		IoSocket_rawSetupEvents(self, locals, m);
226		return self;
227	}
228	else
229	{
230		return SOCKETERROR("Failed to create stream socket");
231	}
232}
233
234IoObject *IoSocket_asyncUdpOpen(IoSocket *self, IoObject *locals, IoMessage *m)
235{
236	//doc Socket asyncUdpOpen Submits an async request to open the socket in UDP mode and returns self immediately or an Error object on error.
237	
238	Socket *socket = SOCKET(self);
239
240	if (Socket_udpOpen(socket) && Socket_isOpen(socket) && Socket_makeReusable(socket) && Socket_makeAsync(socket))
241	{
242		IoSocket_rawSetupEvents(self, locals, m);
243		return self;
244	}
245	else
246	{
247		return SOCKETERROR("Failed to create udp socket");
248	}
249}
250
251// ----------------------------------------
252
253IoObject *IoSocket_asyncConnect(IoSocket *self, IoObject *locals, IoMessage *m)
254{
255	//doc Socket asyncConnect(ipAddressObject) Connects ti the given IPAddress and returns self or an Error object on error.
256	
257	IPAddress *address = IoMessage_locals_rawIPAddressArgAt_(m, locals, 0);
258	
259	if (Socket_connectTo(SOCKET(self), address))
260	{
261		return self;
262	}
263	else
264	{
265		if (Socket_connectToFailed())
266		{
267			return SOCKETERROR("Socket connect failed");
268		}
269		else
270		{
271			return IONIL(self);
272		}
273	}
274}
275
276IoObject *IoSocket_close(IoSocket *self, IoObject *locals, IoMessage *m)
277{
278	//doc Socket close Closes the socket and returns self. Returns nil on error.
279	
280	if (Socket_close(SOCKET(self)))
281	{
282		IoSocket_rawSetupEvents(self, locals, m);
283		return self;
284	}
285	else
286	{
287		if (Socket_closeFailed())
288		{
289			return SOCKETERROR("Failed to close socket");
290		}
291		else
292		{
293			return IONIL(self);
294		}
295	}
296}
297
298// server -------------------------------
299
300IoObject *IoSocket_asyncBind(IoSocket *self, IoObject *locals, IoMessage *m)
301{
302	//doc Socket asyncBind Binds the socket and returns self immediately or an Error object on error.
303
304	IPAddress *address = IoMessage_locals_rawIPAddressArgAt_(m, locals, 0);
305	
306	if (Socket_bind(SOCKET(self), address))
307	{
308		return self;
309	}
310	else
311	{
312		return SOCKETERROR("Failed to bind socket");
313	}
314}
315
316IoObject *IoSocket_asyncListen(IoSocket *self, IoObject *locals, IoMessage *m)
317{
318	//doc Socket asyncListen Listens to the socket and returns self immediately or an Error object on error.
319	
320	if (Socket_listen(SOCKET(self)))
321	{
322		return self;
323	}
324	else
325	{
326		return SOCKETERROR("Socket listen failed");
327	}
328}
329
330IoObject *IoSocket_asyncAccept(IoSocket *self, IoObject *locals, IoMessage *m)
331{
332	//doc Socket asyncAccept(ipAddressObject) Immediately returns a socket for an connection if one is available or nil otherwise. Returns an Error object on error.
333
334	IPAddress *address = IoMessage_locals_rawIPAddressArgAt_(m, locals, 0);
335	Socket *socket = Socket_accept(SOCKET(self), address);
336	
337	if (socket)
338	{
339		IoObject *newSocket = IoSocket_newWithSocket_(IOSTATE, socket);
340		newSocket = IoObject_initClone_(self, locals, m, newSocket);
341		return IoSocket_rawSetupEvents(newSocket, locals, m);
342	}
343	else
344	{
345		if (Socket_asyncFailed())
346		{
347			return SOCKETERROR("Socket accept failed");
348		}
349		else
350		{
351			return IONIL(self);
352		}
353	}
354}
355
356// stream -------------------------------
357
358IoObject *IoSocket_asyncStreamRead(IoSocket *self, IoObject *locals, IoMessage *m)
359{
360	/*doc Socket asyncStreamRead(aSeq, readSize) 
361	Reads up to readSize number of bytes into aSeq if data is available. 
362	Returns self immediately if successful. Returns an error object on Error. Returns nil if the socket is disconnected.
363	*/
364	
365	IoSeq *bufferSeq = IoMessage_locals_mutableSeqArgAt_(m, locals, 0);
366	UArray *buffer = IoSeq_rawUArray(bufferSeq);
367	size_t readSize = IoMessage_locals_intArgAt_(m, locals, 1);
368
369	if (Socket_streamRead(SOCKET(self), buffer, readSize))
370	{
371		return self;
372	}
373
374	if (Socket_asyncFailed())
375	{
376		IoSocket_close(self, locals, m);
377		return SOCKETERROR("Socket stream read failed");
378	}
379
380	//if (readSize == 0) //SocketErrorStatus() == 0)
381	if (SocketErrorStatus() == 0)
382	{
383		// 0 bytes means the other end disconnected
384		//printf("SocketErrorStatus() == 0, closing\n");
385		IoSocket_close(self, locals, m);
386	}
387	
388	return IONIL(self);
389}
390
391IoObject *IoSocket_asyncStreamWrite(IoSocket *self, IoObject *locals, IoMessage *m)
392{
393	/*doc Socket asyncStreamWrite(aSeq, start, writeSize) 
394	Writes the slice of aSeq from start to start + writeSize to the socket.
395	Returns self immediately if successful, otherwise closes the socket. 
396	Returns an error object on Error. 
397	Returns nil if the socket is disconnected.
398	*/
399	
400	IoSeq *bufferSeq = IoMessage_locals_seqArgAt_(m, locals, 0);
401	UArray *buffer = IoSeq_rawUArray(bufferSeq);
402	size_t start = IoMessage_locals_intArgAt_(m, locals, 1);
403	size_t writeSize = IoMessage_locals_intArgAt_(m, locals, 2);
404	size_t bytesWritten = Socket_streamWrite(SOCKET(self), buffer, start, writeSize);
405	
406	if (bytesWritten)
407	{
408		UArray_removeRange(buffer, start, bytesWritten);
409		return self;
410	}
411	else
412	{
413		if (Socket_asyncFailed())
414		{
415			IoSocket_close(self, locals, m);
416			return SOCKETERROR("Socket stream write failed");
417		}
418		else
419		{
420			if (IoSocket_errorNumber(self, locals, m) == 0)
421			// 0 bytes means the other end disconnected
422				IoSocket_close(self, locals, m);
423			return IONIL(self);
424		}
425	}
426}
427
428// udp ------------------------------
429
430IoObject *IoSocket_asyncUdpRead(IoSocket *self, IoObject *locals, IoMessage *m)
431{
432	/*doc Socket asyncUdpRead(ipAddress, aSeq, readSize) 
433	Reads up to readSize number of bytes from ipAddress into aSeq if data is available. 
434	Returns self immediately if successful. Returns an error object on Error. Returns nil if the socket is disconnected.
435	*/
436	
437	IPAddress *address = IoMessage_locals_rawIPAddressArgAt_(m, locals, 0);
438	UArray *buffer = IoSeq_rawUArray(IoMessage_locals_mutableSeqArgAt_(m, locals, 1));
439	size_t readSize = IoMessage_locals_sizetArgAt_(m, locals, 2);
440	
441	if (Socket_udpRead(SOCKET(self), address, buffer, readSize))
442	{
443		return self;
444	}
445	else
446	{
447		if (Socket_asyncFailed())
448		{
449			return SOCKETERROR("Socket udp read failed");
450		}
451		else
452		{
453			return IONIL(self);
454		}
455	}
456}
457
458IoObject *IoSocket_asyncUdpWrite(IoSocket *self, IoObject *locals, IoMessage *m)
459{
460	/*doc Socket asyncUdpWrite(ipAddress, aSeq, startIndex, readSize) 
461	Writes readsize bytes from aSeq starting at startIndex to ipAddress. 
462	Returns self immediately if successful. Returns an error object on Error. Returns nil if the socket is disconnected.
463	*/
464	
465	IPAddress *address = IoMessage_locals_rawIPAddressArgAt_(m, locals, 0);
466	UArray *buffer = IoSeq_rawUArray(IoMessage_locals_seqArgAt_(m, locals, 1));
467	size_t start = IoMessage_locals_intArgAt_(m, locals, 2);
468	size_t writeSize = IoMessage_locals_intArgAt_(m, locals, 3);
469	size_t bytesWritten = Socket_udpWrite(SOCKET(self), address, buffer, start, writeSize);
470	
471	if (bytesWritten)
472	{
473		if (bytesWritten < writeSize)
474		{
475			return SOCKETERROR("Socket udp write failed");
476		}
477		else
478		{
479			UArray_removeRange(buffer, start, bytesWritten);
480			return self;
481		}
482	}
483	else
484	{
485		if (Socket_asyncFailed())
486		{
487			return SOCKETERROR("Socket udp write failed");
488		}
489		else
490		{
491			return IONIL(self);
492		}
493	}
494}
495
496// ----------------------------------
497
498IoObject *IoSocket_setSocketReadBufferSize(IoSocket *self, IoObject *locals, IoMessage *m)
499{
500	//doc Socket setSocketReadBufferSize(numberOfBytes) Sets the read buffer size for the socket. Returns self on success or nil on error.
501	
502	int size = IoMessage_locals_intArgAt_(m, locals, 0);
503	int r = setsockopt(SOCKET(self)->fd, SOL_SOCKET, SO_RCVBUF, &size, sizeof(int));
504	return (r == 0) ? self : IONIL(self);
505}
506
507IoObject *IoSocket_setSocketWriteBufferSize(IoSocket *self, IoObject *locals, IoMessage *m)
508{
509	//doc Socket setSocketWriteBufferSize(numberOfBytes) Sets the write buffer size for the socket. Returns self on success or nil on error.
510
511	int size = IoMessage_locals_intArgAt_(m, locals, 0);
512	int r = setsockopt(SOCKET(self)->fd, SOL_SOCKET, SO_SNDBUF, &size, sizeof(int));
513	return (r == 0) ? self : IONIL(self);
514}
515
516IoObject *IoSocket_setSocketReadLowWaterMark(IoSocket *self, IoObject *locals, IoMessage *m)
517{
518	/*doc Socket setSocketReadLowWaterMark(numberOfBytes) 
519	Sets the read low water mark for the socket. Returns self on success or nil on error.
520	*/
521	
522	int size = IoMessage_locals_intArgAt_(m, locals, 0);
523	int r = setsockopt(SOCKET(self)->fd, SOL_SOCKET, SO_RCVLOWAT, &size, sizeof(int));
524	return (r == 0) ? self : IONIL(self);
525}
526
527IoObject *IoSocket_setSocketWriteLowWaterMark(IoSocket *self, IoObject *locals, IoMessage *m)
528{
529	/*doc Socket setSocketWriteLowWaterMark(numberOfBytes) 
530	Sets the write low water mark for the socket. Returns self on success or nil on error.
531	*/
532	
533	int size = IoMessage_locals_intArgAt_(m, locals, 0);
534	int r = setsockopt(SOCKET(self)->fd, SOL_SOCKET, SO_SNDLOWAT, &size, sizeof(int));
535	return (r == 0) ? self : IONIL(self);
536}
537
538IoObject *IoSocket_getSocketReadLowWaterMark(IoSocket *self, IoObject *locals, IoMessage *m)
539{
540	/*doc Socket getSocketReadLowWaterMark
541	Returns the read low water mark for the socket on success or nil on error.
542	*/
543	
544	int size = 0;
545	socklen_t length = sizeof(int);
546	//int r =
547	getsockopt(SOCKET(self)->fd, SOL_SOCKET, SO_RCVLOWAT, &size, &length);
548	// return (r == 0) ? IONUMBER(size) : IONIL(self);
549	return IONUMBER(size);
550}
551
552IoObject *IoSocket_getSocketWriteLowWaterMark(IoSocket *self, IoObject *locals, IoMessage *m)
553{
554	/*doc Socket getSocketWriteLowWaterMark
555	Returns the write low water mark for the socket on success or nil on error.
556	*/
557	
558	int size = 0;
559	socklen_t length = sizeof(int);
560	//int r =
561	getsockopt(SOCKET(self)->fd, SOL_SOCKET, SO_SNDLOWAT, &size, &length);
562	// return (r == 0) ? IONUMBER(size) : IONIL(self);
563	return IONUMBER(size);
564}
565
566#ifndef WIN32
567#include <sys/socket.h>
568#endif
569
570IoObject *IoSocket_setNoDelay(IoSocket *self, IoObject *locals, IoMessage *m)
571{
572	/*doc Socket setNoDelay
573	Sets the socket to be no-delay. Returns self on success or nil on error.
574	*/
575	
576	int r = -1;
577	#ifdef TCP_NODELAY
578	int flag = 1;
579	r = setsockopt(SOCKET(self)->fd, IPPROTO_TCP, TCP_NODELAY, (char *) &flag, sizeof(int));
580	#endif
581	
582	return (r == 0) ? self : IONIL(self);
583}
584
585IoObject *IoSocket_errorNumber(IoSocket *self, IoObject *locals, IoMessage *m)
586{
587	//doc Socket errorNumber Returns the socket error number for the last error.
588	
589	return IONUMBER(SocketErrorStatus());
590}
591
592IoObject *IoSocket_errorDescription(IoSocket *self, IoObject *locals, IoMessage *m)
593{
594	//doc Socket errorDescription Returns a description of the last error on the socket as a string.
595
596	return IOSYMBOL(Socket_errorDescription());
597}