13 #include "SymbianMain.h"
14 #include "SymbianSockets.h"
16 #define min(a,b) ((a) < (b) ? (a) : (b))
17 #define SOCKET_BUFFER_SIZE 2048
23 char buffer
[SOCKET_BUFFER_SIZE
];
31 memset(buffer
, 0, sizeof(buffer
));
38 memset(buffer
, 0, sizeof(buffer
));
43 TRequestStatus status
;
44 TPtr8
ptr8((TUint8
*)buffer
, sizeof(buffer
), sizeof(buffer
));
46 socket
.RecvOneOrMore(ptr8
, 0, status
, tlen
);
47 User::WaitForRequest(status
);
53 TInt
ReadChar(char* ch
)
55 TInt status
= KErrNone
;
56 if(bufferTop
== bufferBottom
)
58 status
= ReadIntoBuffer();
61 if(status
== KErrNone
)
63 *ch
= buffer
[bufferBottom
++];
69 TInt
ReadAllChars(char* ch
, int length
)
71 TInt status
= KErrNone
;
75 if(bufferTop
== bufferBottom
)
77 status
= ReadIntoBuffer();
78 if(status
!= KErrNone
)
82 if(bufferTop
- bufferBottom
>= length
)
84 memcpy(ch
, buffer
+ bufferBottom
, length
);
85 bufferBottom
+= length
;
90 int l
= min(length
, bufferTop
- bufferBottom
);
91 memcpy(ch
, buffer
+ bufferBottom
, l
);
101 TInt
ReadLine(char* ch
, int length
)
103 TInt status
= KErrNone
;
108 if(bufferTop
== bufferBottom
)
110 status
= ReadIntoBuffer();
111 if(status
!= KErrNone
)
115 if(bufferTop
- bufferBottom
>= length
)
117 char* start
= buffer
+ bufferBottom
;
118 char* end
= buffer
+ length
;
132 bufferBottom
= start
- buffer
;
155 bufferBottom
+= length
;
160 int l
= min(length
, bufferTop
- bufferBottom
);
161 char* start
= buffer
+ bufferBottom
;
162 char* end
= buffer
+ l
;
163 while(state
!= 2 && start
!= end
)
175 bufferBottom
= start
- buffer
;
207 TInt
ReadOneOrMore(char* ch
, int length
)
209 TInt status
= KErrNone
;
211 if(bufferTop
== bufferBottom
)
213 status
= ReadIntoBuffer();
214 if(status
!= KErrNone
)
218 if(bufferTop
- bufferBottom
>= length
)
220 memcpy(ch
, buffer
+ bufferBottom
, length
);
221 bufferBottom
+= length
;
225 int l
= min(length
, bufferTop
- bufferBottom
);
226 memcpy(ch
, buffer
+ bufferBottom
, l
);
235 class CConnectingSocket
;
236 class CReadLineSocket
;
244 InternalSocket
* socket
;
250 CConnectingSocket
*activeConnect
;
251 CReadLineSocket
* activeReadLine
;
254 IoValue
*IoSocket_clone(IoSocket
*self
, IoValue
*locals
, IoMessage
*m
);
255 void IoSocket_free(IoSocket
*self
);
256 char *IoSocket_name(IoSocket
*self
);
257 void IoSocket_mark(IoSocket
*self
);
258 IoValue
*IoSocket_host(IoSocket
*self
, IoValue
*locals
, IoMessage
*m
);
259 IoValue
*IoSocket_host_(IoSocket
*self
, IoValue
*locals
, IoMessage
*m
);
260 IoValue
*IoSocket_port(IoSocket
*self
, IoValue
*locals
, IoMessage
*m
);
261 IoValue
*IoSocket_port_(IoSocket
*self
, IoValue
*locals
, IoMessage
*m
);
262 IoValue
*IoSocket_open(IoSocket
*self
, IoValue
*locals
, IoMessage
*m
);
263 IoValue
*IoSocket_connect(IoSocket
*self
, IoValue
*locals
, IoMessage
*m
);
264 IoValue
*IoSocket_asyncConnect(IoSocket
*self
, IoValue
*locals
, IoMessage
*m
);
265 IoValue
*IoSocket_waitForConnect(IoSocket
*self
, IoValue
*locals
, IoMessage
*m
);
266 IoValue
*IoSocket_isConnected(IoSocket
*self
, IoValue
*locals
, IoMessage
*m
);
267 IoValue
*IoSocket_isConnected_(IoSocket
*self
, IoValue
*locals
, IoMessage
*m
);
268 IoValue
*IoSocket_write(IoSocket
*self
, IoValue
*locals
, IoMessage
*m
);
269 IoValue
*IoSocket_writeLine(IoSocket
*self
, IoValue
*locals
, IoMessage
*m
);
270 IoValue
*IoSocket_read(IoSocket
*self
, IoValue
*locals
, IoMessage
*m
);
271 IoValue
*IoSocket_readLine(IoSocket
*self
, IoValue
*locals
, IoMessage
*m
);
272 IoValue
*IoSocket_close(IoSocket
*self
, IoValue
*locals
, IoMessage
*m
);
274 IoValue
*IoSocket_isLineRead(IoSocket
*self
, IoValue
*locals
, IoMessage
*m
);
275 IoValue
*IoSocket_asyncReadLine(IoSocket
*self
, IoValue
*locals
, IoMessage
*m
);
276 IoValue
*IoSocket_waitForReadLine(IoSocket
*self
, IoValue
*locals
, IoMessage
*m
);
277 IoValue
*IoSocket_getLineRead(IoSocket
*self
, IoValue
*locals
, IoMessage
*m
);
279 class CConnectingSocket
: public CActive
282 InternalSocket
* socket
;
285 RHostResolver resolver
;
290 static CConnectingSocket
* NewL(InternalSocket
* s
, IoSocket
* ios
)
292 CConnectingSocket
* self
= new (ELeave
) CConnectingSocket(s
, ios
);
297 CConnectingSocket(InternalSocket
* s
, IoSocket
* ios
) :
298 CActive(CActive::EPriorityStandard
),
312 CActiveScheduler::Add(this);
317 IoState
* state
= (IoState
*)ioSocket
->tag
->state
;
318 CConsoleControl
* control
= (CConsoleControl
*)IoState_userData(state
);
319 TInt result
= resolver
.Open(control
->socketServer
, 2048, 17);
323 IoState_error_description_(state
, "IoSocket.connect", "Could not open resolver: '%d'\n", result
);
327 TPtr16 ptr16
= stringToPtr16(ioSocket
->host
);
328 resolver
.GetByName(ptr16
, entry
, iStatus
);
337 if(iStatus
.Int() != 0)
340 IoState_error_description_((IoState
*)ioSocket
->tag
->state
, "IoSocket.connect", "resolver.GetByName: '%d'\n", iStatus
.Int());
343 TNameRecord
record(entry());
344 TSockAddr
addr(record
.iAddr
);
345 addr
.SetPort(ioSocket
->port
);
348 socket
->socket
.Connect(addr
, iStatus
);
353 ioSocket
->isConnected
= 1;
354 if(iStatus
.Int() != 0)
357 IoState_error_description_((IoState
*)ioSocket
->tag
->state
, "IoSocket.connect", "socket.connect: '%d'\n", iStatus
.Int());
368 socket
->socket
.CancelAll();
369 socket
->socket
.Close();
373 #define READ_STATE_BUFFER_UNDERFLOW 1
374 #define READ_STATE_BUFFER_READ 2
375 #define READ_STATE_BUFFER_POST_UNDERFLOW 3
376 #define READ_STATE_BUFFER_COMPLETE 4
378 class CReadLineSocket
: public CActive
381 InternalSocket
* socket
;
383 char* originalBuffer
;
391 static CReadLineSocket
* NewL(InternalSocket
* s
, IoSocket
* ios
, char* buffer
, int length
)
393 CReadLineSocket
* self
= new (ELeave
) CReadLineSocket(s
, ios
, buffer
, length
);
398 CReadLineSocket(InternalSocket
* s
, IoSocket
* ios
, char* b
, int len
) :
399 CActive(CActive::EPriorityStandard
),
417 CActiveScheduler::Add(this);
424 state
= READ_STATE_BUFFER_COMPLETE
;
426 else if(socket
->bufferTop
== socket
->bufferBottom
)
428 state
= READ_STATE_BUFFER_UNDERFLOW
;
432 state
= READ_STATE_BUFFER_READ
;
434 TRequestStatus
* tempStatus
= &iStatus
;
435 User::RequestComplete(tempStatus
, KErrNone
);
438 void StartReadLineL()
448 case READ_STATE_BUFFER_UNDERFLOW
:
450 TPtr8
ptr8((TUint8
*)socket
->buffer
, SOCKET_BUFFER_SIZE
, SOCKET_BUFFER_SIZE
);
451 socket
->socket
.RecvOneOrMore(ptr8
, 0, iStatus
, tlen
);
452 state
= READ_STATE_BUFFER_POST_UNDERFLOW
;
457 case READ_STATE_BUFFER_POST_UNDERFLOW
:
459 socket
->bufferTop
= tlen();
460 socket
->bufferBottom
= 0;
461 state
= READ_STATE_BUFFER_READ
;
463 TRequestStatus
* tempStatus
= &iStatus
;
464 User::RequestComplete(tempStatus
, KErrNone
);
468 case READ_STATE_BUFFER_READ
:
472 state
= READ_STATE_BUFFER_COMPLETE
;
474 TRequestStatus
* tempStatus
= &iStatus
;
475 User::RequestComplete(tempStatus
, KErrNone
);
478 else if(socket
->bufferTop
== socket
->bufferBottom
)
480 state
= READ_STATE_BUFFER_UNDERFLOW
;
482 TRequestStatus
* tempStatus
= &iStatus
;
483 User::RequestComplete(tempStatus
, KErrNone
);
486 else if(socket
->bufferTop
- socket
->bufferBottom
>= length
)
488 char* start
= socket
->buffer
+ socket
->bufferBottom
;
489 char* end
= socket
->buffer
+ length
;
503 socket
->bufferBottom
= start
- socket
->buffer
;
505 state
= READ_STATE_BUFFER_COMPLETE
;
507 TRequestStatus
* tempStatus
= &iStatus
;
508 User::RequestComplete(tempStatus
, KErrNone
);
529 socket
->bufferBottom
+= length
;
531 state
= READ_STATE_BUFFER_COMPLETE
;
533 TRequestStatus
* tempStatus
= &iStatus
;
534 User::RequestComplete(tempStatus
, KErrNone
);
539 int l
= min(length
, socket
->bufferTop
- socket
->bufferBottom
);
540 char* start
= socket
->buffer
+ socket
->bufferBottom
;
541 char* end
= socket
->buffer
+ l
;
542 while(lineState
!= 2 && start
!= end
)
554 socket
->bufferBottom
= start
- socket
->buffer
;
555 state
= READ_STATE_BUFFER_COMPLETE
;
557 TRequestStatus
* tempStatus
= &iStatus
;
558 User::RequestComplete(tempStatus
, KErrNone
);
582 socket
->bufferBottom
+= l
;
585 state
= READ_STATE_BUFFER_READ
;
587 TRequestStatus
* tempStatus
= &iStatus
;
588 User::RequestComplete(tempStatus
, KErrNone
);
592 case READ_STATE_BUFFER_COMPLETE
:
594 ioSocket
->lineRead
= originalBuffer
;
602 socket
->socket
.CancelAll();
607 IoTag
*IoSocket_initTagWithId_(void *ioState
, int tagId
)
609 IoTag
*tag
= IoTag_new();
610 tag
->state
= ioState
;
611 tag
->freeCallback
= (TagFreeCallback
*)IoSocket_free
;
612 tag
->nameCallback
= (TagNameCallback
*)IoSocket_name
;
613 tag
->markCallback
= (TagMarkCallback
*)IoSocket_mark
;
615 Tag_addMethod(tag
, "clone", (void*)IoSocket_clone
);
616 Tag_addMethod(tag
, "setHost", (void*)IoSocket_host_
);
617 Tag_addMethod(tag
, "host", (void*)IoSocket_host
);
618 Tag_addMethod(tag
, "setPort", (void*)IoSocket_port_
);
619 Tag_addMethod(tag
, "port", (void*)IoSocket_port
);
620 Tag_addMethod(tag
, "open", (void*)IoSocket_open
);
621 Tag_addMethod(tag
, "connect", (void*)IoSocket_connect
);
622 Tag_addMethod(tag
, "asyncConnect", (void*)IoSocket_asyncConnect
);
623 Tag_addMethod(tag
, "waitForConnect", (void*)IoSocket_waitForConnect
);
624 Tag_addMethod(tag
, "isConnected", (void*)IoSocket_isConnected
);
625 Tag_addMethod(tag
, "setIsConnected", (void*)IoSocket_isConnected_
);
626 Tag_addMethod(tag
, "write", (void*)IoSocket_write
);
627 Tag_addMethod(tag
, "writeLine", (void*)IoSocket_writeLine
);
628 Tag_addMethod(tag
, "read", (void*)IoSocket_read
);
629 Tag_addMethod(tag
, "readLine", (void*)IoSocket_readLine
);
630 Tag_addMethod(tag
, "close", (void*)IoSocket_close
);
633 Tag_addMethod(tag
, "isLineRead", (void*)IoSocket_isLineRead
);
634 Tag_addMethod(tag
, "asyncReadLine", (void*)IoSocket_asyncReadLine
);
635 Tag_addMethod(tag
, "waitForReadLine", (void*)IoSocket_waitForReadLine
);
636 Tag_addMethod(tag
, "getLineRead", (void*)IoSocket_getLineRead
);
641 IoSocket
*IoSocket_new(void *state
)
643 IoTag
*tag
= IoState_tagWithInitFunction_((IoState
*)state
, IoSocket_initTagWithId_
);
644 IoSocket
*self
= (IoSocket
*)malloc(sizeof(IoSocket
));
645 memset(self
, 0x0, sizeof(IoSocket
));
647 self
->color
= IOVALUE_WHITE();
648 self
->socket
= new InternalSocket();
649 self
->host
= strdup("localhost");
650 self
->isConnected
= false;
652 self
->activeConnect
= 0;
653 self
->activeReadLine
= 0;
654 IoState_addValue_((IoState
*)self
->tag
->state
, (IoValue
*)self
);
658 IoValue
*IoSocket_clone(IoSocket
*self
, IoValue
*locals
, IoMessage
*m
)
660 IoSocket
*newSocket
= IoSocket_new(self
->tag
->state
);
661 newSocket
->host
= strdup(self
->host
);
662 return (IoValue
*)newSocket
;
665 void IoSocket_free(IoSocket
*self
)
667 if(self
->activeConnect
)
669 delete self
->activeConnect
;
670 self
->activeConnect
= 0;
672 self
->socket
->socket
.Close();
679 char *IoSocket_name(IoSocket
*self
)
684 void IoSocket_mark(IoSocket
*self
)
688 IoValue
*IoSocket_host(IoSocket
*self
, IoValue
*locals
, IoMessage
*m
)
690 return (IoValue
*)USTRING(self
->host
);
693 IoValue
*IoSocket_host_(IoSocket
*self
, IoValue
*locals
, IoMessage
*m
)
695 IoString
*host
= (IoString
*)IoMessage_locals_stringArgAt_(m
, locals
, 0);
696 self
->host
= strdup(CSTRING(host
));
697 return (IoValue
*)self
;
700 IoValue
*IoSocket_port(IoSocket
*self
, IoValue
*locals
, IoMessage
*m
)
702 return (IoValue
*)IONUMBER(self
->port
);
705 IoValue
*IoSocket_port_(IoSocket
*self
, IoValue
*locals
, IoMessage
*m
)
707 IoNumber
*port
= (IoNumber
*)IoMessage_locals_numberArgAt_(m
, locals
, 0);
708 self
->port
= IoNumber_asInt(port
);
709 return (IoValue
*)self
;
712 IoValue
*IoSocket_isConnected(IoSocket
*self
, IoValue
*locals
, IoMessage
*m
)
714 return (IoValue
*)IONUMBER(self
->isConnected
);
717 IoValue
*IoSocket_isConnected_(IoSocket
*self
, IoValue
*locals
, IoMessage
*m
)
719 IoNumber
*isConnected
= (IoNumber
*)IoMessage_locals_numberArgAt_(m
, locals
, 0);
720 self
->isConnected
= IoNumber_asInt(isConnected
);
721 return (IoValue
*)self
;
724 IoValue
*IoSocket_open(IoSocket
*self
, IoValue
*locals
, IoMessage
*m
)
726 self
->socket
->ResetBuffer();
727 IoState
* state
= (IoState
*)self
->tag
->state
;
728 CConsoleControl
* control
= (CConsoleControl
*)IoState_userData(state
);
730 return (IoValue
*)IONUMBER(self
->socket
->socket
.Open(control
->socketServer
, KAfInet
, KSockStream
, KProtocolInetTcp
));
733 IoValue
*IoSocket_connect(IoSocket
*self
, IoValue
*locals
, IoMessage
*m
)
735 if(self
->activeConnect
)
737 delete self
->activeConnect
;
739 self
->activeConnect
= CConnectingSocket::NewL(self
->socket
, self
);
740 self
->activeConnect
->StartConnectL();
741 IoState
* state
= (IoState
*)self
->tag
->state
;
742 while(!self
->isConnected
)
744 IoState_yield(state
);
746 return (IoValue
*)self
;
749 IoValue
*IoSocket_asyncConnect(IoSocket
*self
, IoValue
*locals
, IoMessage
*m
)
751 if(self
->activeConnect
)
753 delete self
->activeConnect
;
755 self
->activeConnect
= CConnectingSocket::NewL(self
->socket
, self
);
756 self
->activeConnect
->StartConnectL();
757 return (IoValue
*)self
;
760 IoValue
*IoSocket_waitForConnect(IoSocket
*self
, IoValue
*locals
, IoMessage
*m
)
762 IoState
* state
= (IoState
*)self
->tag
->state
;
763 while(!self
->isConnected
)
765 IoState_yield(state
);
767 return (IoValue
*)self
;
770 IoValue
*IoSocket_asyncReadLine(IoSocket
*self
, IoValue
*locals
, IoMessage
*m
)
772 if(self
->activeReadLine
)
774 delete self
->activeReadLine
;
777 IoNumber
*size
= (IoNumber
*)IoMessage_locals_numberArgAt_(m
, locals
, 0);
778 int trueSize
= IoNumber_asInt(size
);
779 char* buffer
= (char*)malloc(trueSize
+ 1);
780 memset(buffer
, 0, trueSize
+ 1);
781 self
->activeReadLine
= CReadLineSocket::NewL(self
->socket
, self
, buffer
, trueSize
);
782 self
->activeReadLine
->StartReadLineL();
783 return (IoValue
*)self
;
786 IoValue
*IoSocket_waitForReadLine(IoSocket
*self
, IoValue
*locals
, IoMessage
*m
)
788 IoState
* state
= (IoState
*)self
->tag
->state
;
789 while(!self
->lineRead
)
791 IoState_yield(state
);
793 IoValue
* value
= (IoValue
*)USTRING(self
->lineRead
);
794 free(self
->lineRead
);
796 return (IoValue
*)value
;
799 IoValue
*IoSocket_isLineRead(IoSocket
*self
, IoValue
*locals
, IoMessage
*m
)
801 bool value
= self
->lineRead
!= 0;
802 return (IoValue
*)IONUMBER(value
);
805 IoValue
*IoSocket_getLineRead(IoSocket
*self
, IoValue
*locals
, IoMessage
*m
)
807 return (IoValue
*)USTRING(self
->lineRead
);
810 IoValue
*IoSocket_close(IoSocket
*self
, IoValue
*locals
, IoMessage
*m
)
812 if(self
->activeConnect
)
814 delete self
->activeConnect
;
815 self
->activeConnect
= 0;
817 if(self
->activeReadLine
)
819 delete self
->activeReadLine
;
820 self
->activeReadLine
= 0;
822 self
->socket
->socket
.Close();
823 return (IoValue
*)self
;
826 IoValue
*IoSocket_write(IoSocket
*self
, IoValue
*locals
, IoMessage
*m
)
828 IoState
* state
= (IoState
*)self
->tag
->state
;
829 IoString
*ioText
= (IoString
*)IoMessage_locals_stringArgAt_(m
, locals
, 0);
830 char* text
= CSTRING(ioText
);
831 int len
= strlen(text
);
832 TRequestStatus status
;
833 TPtr8
ptr8((TUint8
*)text
, len
, len
);
834 self
->socket
->socket
.Write(ptr8
, status
);
835 User::WaitForRequest(status
);
836 if(status
.Int() != 0)
838 IoState_error_description_(state
, "IoSocket.write", "RSocket.Write: '%d'\n", status
.Int());
841 return (IoValue
*)self
;
844 IoValue
*IoSocket_writeLine(IoSocket
*self
, IoValue
*locals
, IoMessage
*m
)
846 IoState
* state
= (IoState
*)self
->tag
->state
;
847 IoString
*ioText
= (IoString
*)IoMessage_locals_stringArgAt_(m
, locals
, 0);
848 char* text
= strdup(CSTRING(ioText
));
849 int len
= strlen(text
);
850 text
= (char*)realloc(text
, len
+ 3);
855 TRequestStatus status
;
856 TPtr8
ptr8((TUint8
*)text
, len
+ 2, len
+ 3);
857 self
->socket
->socket
.Write(ptr8
, status
);
859 User::WaitForRequest(status
);
860 if(status
.Int() != 0)
862 IoState_error_description_(state
, "IoSocket.write", "RSocket.Write: '%d'\n", status
.Int());
865 return (IoValue
*)self
;
868 IoValue
*IoSocket_read(IoSocket
*self
, IoValue
*locals
, IoMessage
*m
)
870 IoNumber
*size
= (IoNumber
*)IoMessage_locals_numberArgAt_(m
, locals
, 0);
871 IoState
* state
= (IoState
*)self
->tag
->state
;
872 int trueSize
= IoNumber_asInt(size
);
873 char* buffer
= (char*)malloc(trueSize
+ 1);
874 memset(buffer
, 0, trueSize
+ 1);
875 TInt status
= self
->socket
->ReadOneOrMore(buffer
, trueSize
);
878 IoState_error_description_(state
, "IoSocket.read", "RSocket.Read: '%d'\n", status
);
881 IoValue
* result
= (IoValue
*)USTRING(buffer
);
886 IoValue
*IoSocket_readLine(IoSocket
*self
, IoValue
*locals
, IoMessage
*m
)
888 IoNumber
*size
= (IoNumber
*)IoMessage_locals_numberArgAt_(m
, locals
, 0);
889 IoState
* state
= (IoState
*)self
->tag
->state
;
890 if(self
->activeReadLine
)
892 delete self
->activeReadLine
;
893 self
->activeReadLine
= 0;
895 int trueSize
= IoNumber_asInt(size
);
896 char* buffer
= (char*)malloc(trueSize
+ 1);
897 memset(buffer
, 0, trueSize
+ 1);
898 self
->activeReadLine
= CReadLineSocket::NewL(self
->socket
, self
, buffer
, trueSize
);
899 self
->activeReadLine
->StartReadLineL();
900 while(!self
->lineRead
)
902 IoState_yield(state
);
904 IoValue
* value
= (IoValue
*)USTRING(self
->lineRead
);
905 free(self
->lineRead
);
907 return (IoValue
*)value
;
912 void initSocketAddons(IoState
* state
)
914 IoState_addTagWithInitFunc_(state
, IoSocket_initTagWithId_
);
915 IoObject_setSlot_to_(state
->lobby
, IoState_stringWithCString_(state
, "Socket"), IoSocket_new(state
));