3 silcsymbiansocketstream.cpp
5 Author: Pekka Riikonen <priikone@silcnet.org>
7 Copyright (C) 2006 - 2007 Pekka Riikonen
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; version 2 of the License.
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
20 /* In this implementation the sockets are in blocking mode, except that
21 on Symbian the blocking mode is actually asynchronous, which semantically
22 translates into non-blocking mode. The non-blocking mode just is not
23 explicitly set because it would require us also to explicitly poll for the
24 socket, which is done automatically by the Active Scheduler in blocking
28 #include "silcsymbiansocketstream.h"
30 /***************************** Socket Classes *******************************/
32 /* Socket stream sender */
34 class SilcSymbianSocketSend : public CActive {
37 SilcSymbianSocketSend() : CActive(CActive::EPriorityStandard)
39 CActiveScheduler::Add(this);
43 ~SilcSymbianSocketSend()
49 void Send(const TDesC8& buf, TSockXfrLength& ret_len)
51 s->sock->Send(buf, 0, iStatus, ret_len);
56 void Send(const TDesC8& buf, TSockXfrLength& ret_len,
57 const char *remote_ip, int remote_port)
62 remote = TInetAddr(remote_port);
63 tmp = (TText *)remote_ip;
64 if (remote.Input(tmp) == KErrNone) {
65 s->sock->SendTo(buf, remote, 0, iStatus, ret_len);
70 /* Sending callback */
73 if (iStatus != KErrNone) {
74 if (iStatus == KErrEof)
81 /* Call stream callback */
82 if (s->stream && s->stream->notifier)
83 s->stream->notifier(s->stream, SILC_STREAM_CAN_WRITE,
84 s->stream->notifier_context);
88 virtual void DoCancel()
90 s->sock->CancelWrite();
96 /* Socket stream receiver */
98 class SilcSymbianSocketReceive : public CActive {
101 SilcSymbianSocketReceive() : CActive(CActive::EPriorityStandard)
103 CActiveScheduler::Add(this);
107 ~SilcSymbianSocketReceive()
115 if (!s->stream || s->stream->connected)
116 s->sock->RecvOneOrMore(inbuf, 0, iStatus, inbuf_len);
118 s->sock->RecvFrom(inbuf, remote, 0, iStatus);
122 /* Reading callback */
125 if (iStatus != KErrNone) {
126 if (iStatus == KErrEof)
134 inbuf_ptr = inbuf.Ptr();
135 inbuf_len = inbuf.Length();
137 /* Call stream callback */
138 if (s->stream && s->stream->notifier)
139 s->stream->notifier(s->stream, SILC_STREAM_CAN_READ,
140 s->stream->notifier_context);
147 virtual void DoCancel()
149 s->sock->CancelRecv();
153 const unsigned char *inbuf_ptr;
154 TSockXfrLength inbuf_len;
155 SilcSymbianSocket *s;
159 /* Creates symbian socket stream context */
161 SilcSymbianSocket *silc_create_symbian_socket(RSocket *sock,
164 SilcSymbianSocket *stream;
166 stream = (SilcSymbianSocket *)silc_calloc(1, sizeof(*stream));
172 stream->send = new SilcSymbianSocketSend;
178 stream->receive = new SilcSymbianSocketReceive;
179 if (!stream->receive) {
188 /***************************** SILC Stream API ******************************/
190 /* Stream read operation */
192 int silc_socket_stream_read(SilcStream stream, unsigned char *buf,
195 SilcSocketStream socket_stream = (SilcSocketStream)stream;
196 SilcSymbianSocket *s = (SilcSymbianSocket *)socket_stream->sock;
197 SilcSymbianSocketReceive *recv = s->receive;
200 if (s->error || !s->stream)
204 if (!recv->inbuf_len() || !recv->inbuf_ptr)
207 len = recv->inbuf_len();
211 /* Copy the read data */
212 memcpy(buf, recv->inbuf_ptr, len);
214 recv->inbuf_ptr = NULL;
215 if (len < recv->inbuf_len())
216 recv->inbuf_ptr += len;
221 /* Stream write operation */
223 int silc_socket_stream_write(SilcStream stream, const unsigned char *data,
226 SilcSocketStream socket_stream = (SilcSocketStream)stream;
227 SilcSymbianSocket *s = (SilcSymbianSocket *)socket_stream->sock;
228 SilcSymbianSocketSend *send = s->send;
229 TSockXfrLength ret_len;
230 TPtrC8 write_buf(data, data_len);
234 if (s->error || !s->stream)
240 send->Send(write_buf, ret_len);
241 if (send->iStatus.Int() != KErrNone) {
242 if (send->iStatus.Int() == KErrEof)
251 if (ret_len() < data_len)
257 /* Receive UDP packet, connected socket. */
259 int silc_socket_udp_stream_read(SilcStream stream, unsigned char *buf,
262 return silc_net_udp_receive(stream, NULL, 0, NULL, buf, buf_len);
265 /* Send UDP packet, connected socket. */
267 int silc_socket_udp_stream_write(SilcStream stream, const unsigned char *data,
270 SilcSocketStream sock = (SilcSocketStream)stream;
272 /* In connectionless state check if remote IP and port is provided */
273 if (!sock->connected && sock->ip && sock->port)
274 return silc_net_udp_send(stream, sock->ip, sock->port, data, data_len);
276 /* In connected state use normal writing to socket. */
277 return silc_socket_stream_write(stream, data, data_len);
280 /* Receive UDP packet, connectionless socket */
282 int silc_net_udp_receive(SilcStream stream, char *remote_ip_addr,
283 SilcUInt32 remote_ip_addr_size, int *remote_port,
284 unsigned char *buf, SilcUInt32 buf_len)
286 SilcSocketStream socket_stream = (SilcSocketStream)stream;
287 SilcSymbianSocket *s = (SilcSymbianSocket *)socket_stream->sock;
288 SilcSymbianSocketReceive *recv = s->receive;
293 if (!recv->inbuf_len() || !recv->inbuf_ptr)
296 len = recv->inbuf_len();
300 /* Copy the read data */
301 memcpy(buf, recv->inbuf_ptr, len);
303 recv->inbuf_ptr = NULL;
304 if (len < recv->inbuf_len())
305 recv->inbuf_ptr += len;
307 if (remote_ip_addr && remote_ip_addr_size && remote_port) {
309 recv->remote.Output(ip);
310 silc_strncat(remote_ip_addr, remote_ip_addr_size, (const char *)ip.Ptr(),
312 *remote_port = recv->remote.Port();
318 /* Send UDP packet, connectionless socket */
320 int silc_net_udp_send(SilcStream stream,
321 const char *remote_ip_addr, int remote_port,
322 const unsigned char *data, SilcUInt32 data_len)
324 SilcSocketStream socket_stream = (SilcSocketStream)stream;
325 SilcSymbianSocket *s = (SilcSymbianSocket *)socket_stream->sock;
326 SilcSymbianSocketSend *send = s->send;
327 TSockXfrLength ret_len;
328 TPtrC8 write_buf(data, data_len);
336 send->Send(write_buf, ret_len, remote_ip_addr, remote_port);
337 if (send->iStatus.Int() != KErrNone) {
338 if (send->iStatus.Int() == KErrEof)
347 if (ret_len() < data_len)
355 SilcBool silc_socket_stream_close(SilcStream stream)
357 SilcSocketStream socket_stream = (SilcSocketStream)stream;
358 SilcSymbianSocket *s = (SilcSymbianSocket *)socket_stream->sock;
364 /* Destroys the stream */
366 void silc_socket_stream_destroy(SilcStream stream)
368 SilcSocketStream socket_stream = (SilcSocketStream)stream;
369 SilcSymbianSocket *s = (SilcSymbianSocket *)socket_stream->sock;
371 silc_socket_stream_close(stream);
372 silc_free(socket_stream->ip);
373 silc_free(socket_stream->hostname);
374 silc_free(socket_stream);
385 /* Sets stream notification callback for the stream */
387 void silc_socket_stream_notifier(SilcStream stream,
388 SilcSchedule schedule,
389 SilcStreamNotifier callback,
392 SilcSocketStream socket_stream = (SilcSocketStream)stream;
393 SilcSymbianSocket *s = (SilcSymbianSocket *)socket_stream->sock;
396 s->stream = socket_stream;
400 socket_stream->notifier = callback;
401 socket_stream->notifier_context = context;
402 socket_stream->schedule = schedule;