-/*\r
-\r
- silcsymbiansocketstream.cpp\r
-\r
- Author: Pekka Riikonen <priikone@silcnet.org>\r
-\r
- Copyright (C) 2006 - 2007 Pekka Riikonen\r
-\r
- This program is free software; you can redistribute it and/or modify\r
- it under the terms of the GNU General Public License as published by\r
- the Free Software Foundation; version 2 of the License.\r
-\r
- This program is distributed in the hope that it will be useful,\r
- but WITHOUT ANY WARRANTY; without even the implied warranty of\r
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\r
- GNU General Public License for more details.\r
-\r
-*/\r
-\r
-/* In this implementation the sockets are in blocking mode, except that\r
- on Symbian the blocking mode is actually asynchronous, which semantically\r
- translates into non-blocking mode. The non-blocking mode just is not\r
- explicitly set because it would require us also to explicitly poll for the\r
- socket, which is done automatically by the Active Scheduler in blocking\r
- mode. */\r
-\r
-#include "silc.h"\r
-#include "silcsymbiansocketstream.h"\r
-\r
-/***************************** Socket Classes *******************************/\r
-\r
-/* Socket stream sender */\r
-\r
-class SilcSymbianSocketSend : public CActive {\r
-public:\r
- /* Constructor */\r
- SilcSymbianSocketSend() : CActive(CActive::EPriorityStandard)\r
- {\r
- CActiveScheduler::Add(this);\r
- }\r
-\r
- /* Destructor */\r
- ~SilcSymbianSocketSend()\r
- {\r
- Cancel();\r
- }\r
-\r
- /* Send data */\r
- void Send(const TDesC8& buf, TSockXfrLength& ret_len)\r
- {\r
- s->sock->Send(buf, 0, iStatus, ret_len);\r
- SetActive();\r
- }\r
-\r
- /* Send data */\r
- void Send(const TDesC8& buf, TSockXfrLength& ret_len,\r
- const char *remote_ip, int remote_port)\r
- {\r
- TInetAddr remote;\r
- TBuf<64> tmp;\r
-\r
- remote = TInetAddr(remote_port);\r
- tmp = (TText *)remote_ip;\r
- if (remote.Input(tmp) == KErrNone) {\r
- s->sock->SendTo(buf, remote, 0, iStatus, ret_len);\r
- SetActive();\r
- }\r
- }\r
-\r
- /* Sending callback */\r
- virtual void RunL()\r
- {\r
- if (iStatus != KErrNone) {\r
- if (iStatus == KErrEof)\r
- s->eof = 1;\r
- else\r
- s->error = 1;\r
- return;\r
- }\r
-\r
- /* Call stream callback */\r
- if (s->stream && s->stream->notifier)\r
- s->stream->notifier(s->stream, SILC_STREAM_CAN_WRITE,\r
- s->stream->notifier_context);\r
- }\r
-\r
- /* Cancel */\r
- virtual void DoCancel()\r
- {\r
- s->sock->CancelWrite();\r
- }\r
-\r
- SilcSymbianSocket *s;\r
-};\r
-\r
-/* Socket stream receiver */\r
-\r
-class SilcSymbianSocketReceive : public CActive {\r
-public:\r
- /* Constructor */\r
- SilcSymbianSocketReceive() : CActive(CActive::EPriorityStandard)\r
- {\r
- CActiveScheduler::Add(this);\r
- }\r
-\r
- /* Destructor */\r
- ~SilcSymbianSocketReceive()\r
- {\r
- Cancel();\r
- }\r
-\r
- /* Read data */\r
- void Read()\r
- {\r
- if (!s->stream || s->stream->connected)\r
- s->sock->RecvOneOrMore(inbuf, 0, iStatus, inbuf_len);\r
- else\r
- s->sock->RecvFrom(inbuf, remote, 0, iStatus);\r
- SetActive();\r
- }\r
-\r
- /* Reading callback */\r
- virtual void RunL()\r
- {\r
- if (iStatus != KErrNone) {\r
- if (iStatus == KErrEof)\r
- s->eof = 1;\r
- else\r
- s->error = 1;\r
- return;\r
- }\r
-\r
- if (!inbuf_ptr)\r
- inbuf_ptr = inbuf.Ptr();\r
- inbuf_len = inbuf.Length();\r
-\r
- /* Call stream callback */\r
- if (s->stream && s->stream->notifier)\r
- s->stream->notifier(s->stream, SILC_STREAM_CAN_READ,\r
- s->stream->notifier_context);\r
-\r
- /* Read more */\r
- Read();\r
- }\r
-\r
- /* Cancel */\r
- virtual void DoCancel()\r
- {\r
- s->sock->CancelRecv();\r
- }\r
-\r
- TBuf8<8192> inbuf;\r
- const unsigned char *inbuf_ptr;\r
- TSockXfrLength inbuf_len;\r
- SilcSymbianSocket *s;\r
- TInetAddr remote;\r
-};\r
-\r
-/* Creates symbian socket stream context */\r
-\r
-SilcSymbianSocket *silc_create_symbian_socket(RSocket *sock,\r
- RSocketServ *ss)\r
-{\r
- SilcSymbianSocket *stream;\r
-\r
- stream = (SilcSymbianSocket *)silc_calloc(1, sizeof(*stream));\r
- if (!stream)\r
- return NULL;\r
- stream->sock = sock;\r
- stream->ss = ss;\r
-\r
- stream->send = new SilcSymbianSocketSend;\r
- if (!stream->send) {\r
- silc_free(stream);\r
- return NULL;\r
- }\r
-\r
- stream->receive = new SilcSymbianSocketReceive;\r
- if (!stream->receive) {\r
- delete stream->send;\r
- silc_free(stream);\r
- return NULL;\r
- }\r
-\r
- return stream;\r
-}\r
-\r
-/***************************** SILC Stream API ******************************/\r
-\r
-/* Stream read operation */\r
-\r
-int silc_socket_stream_read(SilcStream stream, unsigned char *buf,\r
- SilcUInt32 buf_len)\r
-{\r
- SilcSocketStream socket_stream = (SilcSocketStream)stream;\r
- SilcSymbianSocket *s = (SilcSymbianSocket *)socket_stream->sock;\r
- SilcSymbianSocketReceive *recv = s->receive;\r
- int len;\r
-\r
- if (s->error || !s->stream)\r
- return -2;\r
- if (s->eof)\r
- return 0;\r
- if (!recv->inbuf_len() || !recv->inbuf_ptr)\r
- return -1;\r
-\r
- len = recv->inbuf_len();\r
- if (buf_len < len)\r
- len = buf_len;\r
-\r
- /* Copy the read data */\r
- memcpy(buf, recv->inbuf_ptr, len);\r
-\r
- recv->inbuf_ptr = NULL;\r
- if (len < recv->inbuf_len())\r
- recv->inbuf_ptr += len;\r
-\r
- return len;\r
-}\r
-\r
-/* Stream write operation */\r
-\r
-int silc_socket_stream_write(SilcStream stream, const unsigned char *data,\r
- SilcUInt32 data_len)\r
-{\r
- SilcSocketStream socket_stream = (SilcSocketStream)stream;\r
- SilcSymbianSocket *s = (SilcSymbianSocket *)socket_stream->sock;\r
- SilcSymbianSocketSend *send = s->send;\r
- TSockXfrLength ret_len;\r
- TPtrC8 write_buf(data, data_len);\r
-\r
- if (s->would_block)\r
- return -1;\r
- if (s->error || !s->stream)\r
- return -2;\r
- if (s->eof)\r
- return 0;\r
-\r
- /* Send data */\r
- send->Send(write_buf, ret_len);\r
- if (send->iStatus.Int() != KErrNone) {\r
- if (send->iStatus.Int() == KErrEof)\r
- return 0;\r
- return -2;\r
- }\r
-\r
- if (!ret_len())\r
- return -1;\r
-\r
- s->would_block = 0;\r
- if (ret_len() < data_len)\r
- s->would_block = 1;\r
-\r
- return ret_len();\r
-}\r
-\r
-/* Receive UDP packet, connected socket. */\r
-\r
-int silc_socket_udp_stream_read(SilcStream stream, unsigned char *buf,\r
- SilcUInt32 buf_len)\r
-{\r
- return silc_net_udp_receive(stream, NULL, 0, NULL, buf, buf_len);\r
-}\r
-\r
-/* Send UDP packet, connected socket. */\r
-\r
-int silc_socket_udp_stream_write(SilcStream stream, const unsigned char *data,\r
- SilcUInt32 data_len)\r
-{\r
- SilcSocketStream sock = (SilcSocketStream)stream;\r
-\r
- /* In connectionless state check if remote IP and port is provided */\r
- if (!sock->connected && sock->ip && sock->port)\r
- return silc_net_udp_send(stream, sock->ip, sock->port, data, data_len);\r
-\r
- /* In connected state use normal writing to socket. */\r
- return silc_socket_stream_write(stream, data, data_len);\r
-}\r
-\r
-/* Receive UDP packet, connectionless socket */\r
-\r
-int silc_net_udp_receive(SilcStream stream, char *remote_ip_addr,\r
- SilcUInt32 remote_ip_addr_size, int *remote_port,\r
- unsigned char *buf, SilcUInt32 buf_len)\r
-{\r
- SilcSocketStream socket_stream = (SilcSocketStream)stream;\r
- SilcSymbianSocket *s = (SilcSymbianSocket *)socket_stream->sock;\r
- SilcSymbianSocketReceive *recv = s->receive;\r
- int len;\r
-\r
- if (s->eof)\r
- return 0;\r
- if (!recv->inbuf_len() || !recv->inbuf_ptr)\r
- return -1;\r
-\r
- len = recv->inbuf_len();\r
- if (buf_len < len)\r
- len = buf_len;\r
-\r
- /* Copy the read data */\r
- memcpy(buf, recv->inbuf_ptr, len);\r
-\r
- recv->inbuf_ptr = NULL;\r
- if (len < recv->inbuf_len())\r
- recv->inbuf_ptr += len;\r
-\r
- if (remote_ip_addr && remote_ip_addr_size && remote_port) {\r
- TBuf<64> ip;\r
- recv->remote.Output(ip);\r
- silc_strncat(remote_ip_addr, remote_ip_addr_size, (const char *)ip.Ptr(),\r
- ip.Length());\r
- *remote_port = recv->remote.Port();\r
- }\r
-\r
- return len;\r
-}\r
-\r
-/* Send UDP packet, connectionless socket */\r
-\r
-int silc_net_udp_send(SilcStream stream,\r
- const char *remote_ip_addr, int remote_port,\r
- const unsigned char *data, SilcUInt32 data_len)\r
-{\r
- SilcSocketStream socket_stream = (SilcSocketStream)stream;\r
- SilcSymbianSocket *s = (SilcSymbianSocket *)socket_stream->sock;\r
- SilcSymbianSocketSend *send = s->send;\r
- TSockXfrLength ret_len;\r
- TPtrC8 write_buf(data, data_len);\r
-\r
- if (s->would_block)\r
- return -1;\r
- if (s->eof)\r
- return 0;\r
-\r
- /* Send data */\r
- send->Send(write_buf, ret_len, remote_ip_addr, remote_port);\r
- if (send->iStatus.Int() != KErrNone) {\r
- if (send->iStatus.Int() == KErrEof)\r
- return 0;\r
- return -2;\r
- }\r
-\r
- if (!ret_len())\r
- return -1;\r
-\r
- s->would_block = 0;\r
- if (ret_len() < data_len)\r
- s->would_block = 1;\r
-\r
- return ret_len();\r
-}\r
-\r
-/* Closes socket */\r
-\r
-SilcBool silc_socket_stream_close(SilcStream stream)\r
-{\r
- SilcSocketStream socket_stream = (SilcSocketStream)stream;\r
- SilcSymbianSocket *s;\r
-\r
- if (!SILC_IS_SOCKET_STREAM(socket_stream) &&\r
- !SILC_IS_SOCKET_STREAM_UDP(socket_stream))\r
- return FALSE;\r
-\r
- s = (SilcSymbianSocket *)socket_stream->sock;\r
- s->sock->Close();\r
-\r
- return TRUE;\r
-}\r
-\r
-/* Destroys the stream */\r
-\r
-void silc_socket_stream_destroy(SilcStream stream)\r
-{\r
- SilcSocketStream socket_stream = (SilcSocketStream)stream;\r
- SilcSymbianSocket *s;\r
-\r
- if (!SILC_IS_SOCKET_STREAM(socket_stream) &&\r
- !SILC_IS_SOCKET_STREAM_UDP(socket_stream))\r
- return;\r
-\r
- s = (SilcSymbianSocket *)socket_stream->sock;\r
-\r
- silc_socket_stream_close(stream);\r
- silc_free(socket_stream->ip);\r
- silc_free(socket_stream->hostname);\r
- silc_free(socket_stream);\r
- delete s->send;\r
- delete s->receive;\r
- delete s->sock;\r
- if (s->ss) {\r
- s->ss->Close();\r
- delete s->ss;\r
- }\r
- silc_free(s);\r
-}\r
-\r
-/* Sets stream notification callback for the stream */\r
-\r
-void silc_socket_stream_notifier(SilcStream stream,\r
- SilcSchedule schedule,\r
- SilcStreamNotifier callback,\r
- void *context)\r
-{\r
- SilcSocketStream socket_stream = (SilcSocketStream)stream;\r
- SilcSymbianSocket *s;\r
-\r
- if (!SILC_IS_SOCKET_STREAM(socket_stream) &&\r
- !SILC_IS_SOCKET_STREAM_UDP(socket_stream))\r
- return;\r
-\r
- s = (SilcSymbianSocket *)socket_stream->sock;\r
- if (callback)\r
- s->stream = socket_stream;\r
- else\r
- s->stream = NULL;\r
-\r
- socket_stream->notifier = callback;\r
- socket_stream->notifier_context = context;\r
- socket_stream->schedule = schedule;\r
-}\r
+/*
+
+ silcsymbiansocketstream.cpp
+
+ Author: Pekka Riikonen <priikone@silcnet.org>
+
+ Copyright (C) 2006 - 2007 Pekka Riikonen
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; version 2 of the License.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+*/
+
+/* In this implementation the sockets are in blocking mode, except that
+ on Symbian the blocking mode is actually asynchronous, which semantically
+ translates into non-blocking mode. The non-blocking mode just is not
+ explicitly set because it would require us also to explicitly poll for the
+ socket, which is done automatically by the Active Scheduler in blocking
+ mode. */
+
+#include "silc.h"
+#include "silcsymbiansocketstream.h"
+
+/***************************** Socket Classes *******************************/
+
+/* Socket stream sender */
+
+class SilcSymbianSocketSend : public CActive {
+public:
+ /* Constructor */
+ SilcSymbianSocketSend() : CActive(CActive::EPriorityStandard)
+ {
+ CActiveScheduler::Add(this);
+ }
+
+ /* Destructor */
+ ~SilcSymbianSocketSend()
+ {
+ Cancel();
+ }
+
+ /* Send data */
+ void Send(const TDesC8& buf, TSockXfrLength& ret_len)
+ {
+ s->sock->Send(buf, 0, iStatus, ret_len);
+ SetActive();
+ }
+
+ /* Send data */
+ void Send(const TDesC8& buf, TSockXfrLength& ret_len,
+ const char *remote_ip, int remote_port)
+ {
+ TInetAddr remote;
+ TBuf<64> tmp;
+
+ remote = TInetAddr(remote_port);
+ tmp = (TText *)remote_ip;
+ if (remote.Input(tmp) == KErrNone) {
+ s->sock->SendTo(buf, remote, 0, iStatus, ret_len);
+ SetActive();
+ }
+ }
+
+ /* Sending callback */
+ virtual void RunL()
+ {
+ if (iStatus != KErrNone) {
+ if (iStatus == KErrEof)
+ s->eof = 1;
+ else
+ s->error = 1;
+ return;
+ }
+
+ /* Call stream callback */
+ if (s->stream && s->stream->notifier)
+ s->stream->notifier(s->stream, SILC_STREAM_CAN_WRITE,
+ s->stream->notifier_context);
+ }
+
+ /* Cancel */
+ virtual void DoCancel()
+ {
+ s->sock->CancelWrite();
+ }
+
+ SilcSymbianSocket *s;
+};
+
+/* Socket stream receiver */
+
+class SilcSymbianSocketReceive : public CActive {
+public:
+ /* Constructor */
+ SilcSymbianSocketReceive() : CActive(CActive::EPriorityStandard)
+ {
+ CActiveScheduler::Add(this);
+ }
+
+ /* Destructor */
+ ~SilcSymbianSocketReceive()
+ {
+ Cancel();
+ }
+
+ /* Read data */
+ void Read()
+ {
+ if (!s->stream || s->stream->connected)
+ s->sock->RecvOneOrMore(inbuf, 0, iStatus, inbuf_len);
+ else
+ s->sock->RecvFrom(inbuf, remote, 0, iStatus);
+ SetActive();
+ }
+
+ /* Reading callback */
+ virtual void RunL()
+ {
+ if (iStatus != KErrNone) {
+ if (iStatus == KErrEof)
+ s->eof = 1;
+ else
+ s->error = 1;
+ return;
+ }
+
+ if (!inbuf_ptr)
+ inbuf_ptr = inbuf.Ptr();
+ inbuf_len = inbuf.Length();
+
+ /* Call stream callback */
+ if (s->stream && s->stream->notifier)
+ s->stream->notifier(s->stream, SILC_STREAM_CAN_READ,
+ s->stream->notifier_context);
+
+ /* Read more */
+ Read();
+ }
+
+ /* Cancel */
+ virtual void DoCancel()
+ {
+ s->sock->CancelRecv();
+ }
+
+ TBuf8<8192> inbuf;
+ const unsigned char *inbuf_ptr;
+ TSockXfrLength inbuf_len;
+ SilcSymbianSocket *s;
+ TInetAddr remote;
+};
+
+/* Creates symbian socket stream context */
+
+SilcSymbianSocket *silc_create_symbian_socket(RSocket *sock,
+ RSocketServ *ss)
+{
+ SilcSymbianSocket *stream;
+
+ stream = (SilcSymbianSocket *)silc_calloc(1, sizeof(*stream));
+ if (!stream)
+ return NULL;
+ stream->sock = sock;
+ stream->ss = ss;
+
+ stream->send = new SilcSymbianSocketSend;
+ if (!stream->send) {
+ silc_free(stream);
+ return NULL;
+ }
+
+ stream->receive = new SilcSymbianSocketReceive;
+ if (!stream->receive) {
+ delete stream->send;
+ silc_free(stream);
+ return NULL;
+ }
+
+ return stream;
+}
+
+/***************************** SILC Stream API ******************************/
+
+/* Stream read operation */
+
+int silc_socket_stream_read(SilcStream stream, unsigned char *buf,
+ SilcUInt32 buf_len)
+{
+ SilcSocketStream socket_stream = (SilcSocketStream)stream;
+ SilcSymbianSocket *s = (SilcSymbianSocket *)socket_stream->sock;
+ SilcSymbianSocketReceive *recv = s->receive;
+ int len;
+
+ if (s->error || !s->stream)
+ return -2;
+ if (s->eof)
+ return 0;
+ if (!recv->inbuf_len() || !recv->inbuf_ptr)
+ return -1;
+
+ len = recv->inbuf_len();
+ if (buf_len < len)
+ len = buf_len;
+
+ /* Copy the read data */
+ memcpy(buf, recv->inbuf_ptr, len);
+
+ recv->inbuf_ptr = NULL;
+ if (len < recv->inbuf_len())
+ recv->inbuf_ptr += len;
+
+ return len;
+}
+
+/* Stream write operation */
+
+int silc_socket_stream_write(SilcStream stream, const unsigned char *data,
+ SilcUInt32 data_len)
+{
+ SilcSocketStream socket_stream = (SilcSocketStream)stream;
+ SilcSymbianSocket *s = (SilcSymbianSocket *)socket_stream->sock;
+ SilcSymbianSocketSend *send = s->send;
+ TSockXfrLength ret_len;
+ TPtrC8 write_buf(data, data_len);
+
+ if (s->would_block)
+ return -1;
+ if (s->error || !s->stream)
+ return -2;
+ if (s->eof)
+ return 0;
+
+ /* Send data */
+ send->Send(write_buf, ret_len);
+ if (send->iStatus.Int() != KErrNone) {
+ if (send->iStatus.Int() == KErrEof)
+ return 0;
+ return -2;
+ }
+
+ if (!ret_len())
+ return -1;
+
+ s->would_block = 0;
+ if (ret_len() < data_len)
+ s->would_block = 1;
+
+ return ret_len();
+}
+
+/* Receive UDP packet, connected socket. */
+
+int silc_socket_udp_stream_read(SilcStream stream, unsigned char *buf,
+ SilcUInt32 buf_len)
+{
+ return silc_net_udp_receive(stream, NULL, 0, NULL, buf, buf_len);
+}
+
+/* Send UDP packet, connected socket. */
+
+int silc_socket_udp_stream_write(SilcStream stream, const unsigned char *data,
+ SilcUInt32 data_len)
+{
+ SilcSocketStream sock = (SilcSocketStream)stream;
+
+ /* In connectionless state check if remote IP and port is provided */
+ if (!sock->connected && sock->ip && sock->port)
+ return silc_net_udp_send(stream, sock->ip, sock->port, data, data_len);
+
+ /* In connected state use normal writing to socket. */
+ return silc_socket_stream_write(stream, data, data_len);
+}
+
+/* Receive UDP packet, connectionless socket */
+
+int silc_net_udp_receive(SilcStream stream, char *remote_ip_addr,
+ SilcUInt32 remote_ip_addr_size, int *remote_port,
+ unsigned char *buf, SilcUInt32 buf_len)
+{
+ SilcSocketStream socket_stream = (SilcSocketStream)stream;
+ SilcSymbianSocket *s = (SilcSymbianSocket *)socket_stream->sock;
+ SilcSymbianSocketReceive *recv = s->receive;
+ int len;
+
+ if (s->eof)
+ return 0;
+ if (!recv->inbuf_len() || !recv->inbuf_ptr)
+ return -1;
+
+ len = recv->inbuf_len();
+ if (buf_len < len)
+ len = buf_len;
+
+ /* Copy the read data */
+ memcpy(buf, recv->inbuf_ptr, len);
+
+ recv->inbuf_ptr = NULL;
+ if (len < recv->inbuf_len())
+ recv->inbuf_ptr += len;
+
+ if (remote_ip_addr && remote_ip_addr_size && remote_port) {
+ TBuf<64> ip;
+ recv->remote.Output(ip);
+ silc_strncat(remote_ip_addr, remote_ip_addr_size, (const char *)ip.Ptr(),
+ ip.Length());
+ *remote_port = recv->remote.Port();
+ }
+
+ return len;
+}
+
+/* Send UDP packet, connectionless socket */
+
+int silc_net_udp_send(SilcStream stream,
+ const char *remote_ip_addr, int remote_port,
+ const unsigned char *data, SilcUInt32 data_len)
+{
+ SilcSocketStream socket_stream = (SilcSocketStream)stream;
+ SilcSymbianSocket *s = (SilcSymbianSocket *)socket_stream->sock;
+ SilcSymbianSocketSend *send = s->send;
+ TSockXfrLength ret_len;
+ TPtrC8 write_buf(data, data_len);
+
+ if (s->would_block)
+ return -1;
+ if (s->eof)
+ return 0;
+
+ /* Send data */
+ send->Send(write_buf, ret_len, remote_ip_addr, remote_port);
+ if (send->iStatus.Int() != KErrNone) {
+ if (send->iStatus.Int() == KErrEof)
+ return 0;
+ return -2;
+ }
+
+ if (!ret_len())
+ return -1;
+
+ s->would_block = 0;
+ if (ret_len() < data_len)
+ s->would_block = 1;
+
+ return ret_len();
+}
+
+/* Closes socket */
+
+SilcBool silc_socket_stream_close(SilcStream stream)
+{
+ SilcSocketStream socket_stream = (SilcSocketStream)stream;
+ SilcSymbianSocket *s = (SilcSymbianSocket *)socket_stream->sock;
+ s->sock->Close();
+
+ return TRUE;
+}
+
+/* Destroys the stream */
+
+void silc_socket_stream_destroy(SilcStream stream)
+{
+ SilcSocketStream socket_stream = (SilcSocketStream)stream;
+ SilcSymbianSocket *s = (SilcSymbianSocket *)socket_stream->sock;
+
+ silc_socket_stream_close(stream);
+ silc_free(socket_stream->ip);
+ silc_free(socket_stream->hostname);
+ silc_free(socket_stream);
+ delete s->send;
+ delete s->receive;
+ delete s->sock;
+ if (s->ss) {
+ s->ss->Close();
+ delete s->ss;
+ }
+ silc_free(s);
+}
+
+/* Sets stream notification callback for the stream */
+
+void silc_socket_stream_notifier(SilcStream stream,
+ SilcSchedule schedule,
+ SilcStreamNotifier callback,
+ void *context)
+{
+ SilcSocketStream socket_stream = (SilcSocketStream)stream;
+ SilcSymbianSocket *s = (SilcSymbianSocket *)socket_stream->sock;
+
+ if (callback)
+ s->stream = socket_stream;
+ else
+ s->stream = NULL;
+
+ socket_stream->notifier = callback;
+ socket_stream->notifier_context = context;
+ socket_stream->schedule = schedule;
+}