blob: 9027350a0abe648e920b8901162ae290c769331e [file] [log] [blame]
Nanang Izzuddin6c62bf42009-08-27 19:55:13 +00001/* $Id$ */
2/*
3 * Copyright (C) 2009 Teluu Inc. (http://www.teluu.com)
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18 */
19#include <pj/ssl_sock.h>
20#include <pj/compat/socket.h>
21#include <pj/assert.h>
22#include <pj/errno.h>
Nanang Izzuddin006cc012009-10-16 03:06:13 +000023#include <pj/math.h>
Nanang Izzuddin6c62bf42009-08-27 19:55:13 +000024#include <pj/pool.h>
25#include <pj/sock.h>
26#include <pj/string.h>
27
28#include "os_symbian.h"
29#include <securesocket.h>
30#include <x509cert.h>
31#include <e32des8.h>
32
33#define THIS_FILE "ssl_sock_symbian.cpp"
34
35typedef void (*CPjSSLSocket_cb)(int err, void *key);
36
37class CPjSSLSocketReader : public CActive
38{
39public:
40 static CPjSSLSocketReader *NewL(CSecureSocket &sock)
41 {
42 CPjSSLSocketReader *self = new (ELeave)
43 CPjSSLSocketReader(sock);
44 CleanupStack::PushL(self);
45 self->ConstructL();
46 CleanupStack::Pop(self);
47 return self;
48 }
49
50 ~CPjSSLSocketReader() {
51 Cancel();
52 }
53
54 /* Asynchronous read from the socket. */
55 int Read(CPjSSLSocket_cb cb, void *key, TPtr8 &data, TUint flags)
56 {
57 PJ_ASSERT_RETURN(!IsActive(), PJ_EBUSY);
58
59 cb_ = cb;
60 key_ = key;
61 sock_.RecvOneOrMore(data, iStatus, len_received_);
62 SetActive();
63
64 return PJ_EPENDING;
65 }
66
67private:
68 CSecureSocket &sock_;
69 CPjSSLSocket_cb cb_;
70 void *key_;
71 TSockXfrLength len_received_; /* not really useful? */
72
73 void DoCancel() {
74 sock_.CancelAll();
75 }
76
77 void RunL() {
78 (*cb_)(iStatus.Int(), key_);
79 }
80
81 CPjSSLSocketReader(CSecureSocket &sock) :
82 CActive(0), sock_(sock), cb_(NULL), key_(NULL)
83 {}
84
85 void ConstructL() {
86 CActiveScheduler::Add(this);
87 }
88};
89
90class CPjSSLSocket : public CActive
91{
92public:
93 enum ssl_state {
94 SSL_STATE_NULL,
95 SSL_STATE_CONNECTING,
96 SSL_STATE_HANDSHAKING,
97 SSL_STATE_ESTABLISHED
98 };
99
Benny Prijonoa25bc9d2009-11-09 08:51:34 +0000100 static CPjSSLSocket *NewL(const TDesC8 &ssl_proto,
101 pj_qos_type qos_type,
102 const pj_qos_params &qos_params)
103 {
104 CPjSSLSocket *self = new (ELeave) CPjSSLSocket(qos_type, qos_params);
Nanang Izzuddin6c62bf42009-08-27 19:55:13 +0000105 CleanupStack::PushL(self);
106 self->ConstructL(ssl_proto);
107 CleanupStack::Pop(self);
108 return self;
109 }
110
111 ~CPjSSLSocket() {
112 Cancel();
113 CleanupSubObjects();
114 }
115
116 int Connect(CPjSSLSocket_cb cb, void *key, const TInetAddr &local_addr,
117 const TInetAddr &rem_addr,
118 const TDesC8 &servername = TPtrC8(NULL,0));
119 int Send(CPjSSLSocket_cb cb, void *key, const TDesC8 &aDesc, TUint flags);
120 int SendSync(const TDesC8 &aDesc, TUint flags);
121
122 CPjSSLSocketReader* GetReader();
123 enum ssl_state GetState() const { return state_; }
124 const TInetAddr* GetLocalAddr() const { return &local_addr_; }
125 int GetCipher(TDes8 &cipher) const {
126 if (securesock_)
127 return securesock_->CurrentCipherSuite(cipher);
128 return KErrNotFound;
129 }
Nanang Izzuddin2fb937e2010-02-24 05:43:34 +0000130 const CX509Certificate *GetPeerCert() {
131 if (securesock_)
132 return securesock_->ServerCert();
133 return NULL;
134 }
Nanang Izzuddin6c62bf42009-08-27 19:55:13 +0000135
136private:
137 enum ssl_state state_;
138 pj_sock_t sock_;
139 CSecureSocket *securesock_;
140 bool is_connected_;
Benny Prijonoa25bc9d2009-11-09 08:51:34 +0000141
142 pj_qos_type qos_type_;
143 pj_qos_params qos_params_;
144
Nanang Izzuddin6c62bf42009-08-27 19:55:13 +0000145 CPjSSLSocketReader *reader_;
146 TBuf<32> ssl_proto_;
147 TInetAddr rem_addr_;
148 TPtrC8 servername_;
149 TInetAddr local_addr_;
150 TSockXfrLength sent_len_;
151
152 CPjSSLSocket_cb cb_;
153 void *key_;
154
155 void DoCancel();
156 void RunL();
157
Benny Prijonoa25bc9d2009-11-09 08:51:34 +0000158 CPjSSLSocket(pj_qos_type qos_type, const pj_qos_params &qos_params) :
Nanang Izzuddin6c62bf42009-08-27 19:55:13 +0000159 CActive(0), state_(SSL_STATE_NULL), sock_(PJ_INVALID_SOCKET),
Benny Prijonoa25bc9d2009-11-09 08:51:34 +0000160 securesock_(NULL), is_connected_(false),
161 qos_type_(qos_type), qos_params_(qos_params),
162 reader_(NULL), cb_(NULL), key_(NULL)
Nanang Izzuddin6c62bf42009-08-27 19:55:13 +0000163 {}
164
165 void ConstructL(const TDesC8 &ssl_proto) {
166 ssl_proto_.Copy(ssl_proto);
167 CActiveScheduler::Add(this);
168 }
169
170 void CleanupSubObjects() {
171 delete reader_;
172 reader_ = NULL;
173 if (securesock_) {
Nanang Izzuddina7719d32010-03-06 02:04:52 +0000174 if (state_ == SSL_STATE_ESTABLISHED)
175 securesock_->Close();
Nanang Izzuddin6c62bf42009-08-27 19:55:13 +0000176 delete securesock_;
177 securesock_ = NULL;
178 }
179 if (sock_ != PJ_INVALID_SOCKET) {
Benny Prijonoa25bc9d2009-11-09 08:51:34 +0000180 pj_sock_close(sock_);
Nanang Izzuddin6c62bf42009-08-27 19:55:13 +0000181 sock_ = PJ_INVALID_SOCKET;
182 }
183 }
184};
185
186int CPjSSLSocket::Connect(CPjSSLSocket_cb cb, void *key,
187 const TInetAddr &local_addr,
188 const TInetAddr &rem_addr,
189 const TDesC8 &servername)
190{
191 pj_status_t status;
192
193 PJ_ASSERT_RETURN(state_ == SSL_STATE_NULL, PJ_EINVALIDOP);
194
195 status = pj_sock_socket(rem_addr.Family(), pj_SOCK_STREAM(), 0, &sock_);
196 if (status != PJ_SUCCESS)
197 return status;
198
Benny Prijonoa25bc9d2009-11-09 08:51:34 +0000199 // Apply QoS
200 status = pj_sock_apply_qos2(sock_, qos_type_, &qos_params_,
201 2, THIS_FILE, NULL);
202
Nanang Izzuddin6c62bf42009-08-27 19:55:13 +0000203 RSocket &rSock = ((CPjSocket*)sock_)->Socket();
204
205 local_addr_ = local_addr;
206
207 if (!local_addr_.IsUnspecified()) {
208 TInt err = rSock.Bind(local_addr_);
209 if (err != KErrNone)
210 return PJ_RETURN_OS_ERROR(err);
211 }
212
213 cb_ = cb;
214 key_ = key;
215 rem_addr_ = rem_addr;
216 servername_.Set(servername);
Nanang Izzuddin6c62bf42009-08-27 19:55:13 +0000217 rSock.Connect(rem_addr_, iStatus);
218 SetActive();
Nanang Izzuddina7719d32010-03-06 02:04:52 +0000219 state_ = SSL_STATE_CONNECTING;
Nanang Izzuddin6c62bf42009-08-27 19:55:13 +0000220
221 rSock.LocalName(local_addr_);
222
223 return PJ_EPENDING;
224}
225
226int CPjSSLSocket::Send(CPjSSLSocket_cb cb, void *key, const TDesC8 &aDesc,
227 TUint flags)
228{
229 PJ_UNUSED_ARG(flags);
230
231 PJ_ASSERT_RETURN(state_ == SSL_STATE_ESTABLISHED, PJ_EINVALIDOP);
232
233 if (IsActive())
234 return PJ_EBUSY;
235
236 cb_ = cb;
237 key_ = key;
238
239 securesock_->Send(aDesc, iStatus, sent_len_);
240 SetActive();
241
242 return PJ_EPENDING;
243}
244
245int CPjSSLSocket::SendSync(const TDesC8 &aDesc, TUint flags)
246{
247 PJ_UNUSED_ARG(flags);
248
249 PJ_ASSERT_RETURN(state_ == SSL_STATE_ESTABLISHED, PJ_EINVALIDOP);
250
251 TRequestStatus reqStatus;
252 securesock_->Send(aDesc, reqStatus, sent_len_);
253 User::WaitForRequest(reqStatus);
254
255 return PJ_RETURN_OS_ERROR(reqStatus.Int());
256}
257
258CPjSSLSocketReader* CPjSSLSocket::GetReader()
259{
260 PJ_ASSERT_RETURN(state_ == SSL_STATE_ESTABLISHED, NULL);
261
262 if (reader_)
263 return reader_;
264
265 TRAPD(err, reader_ = CPjSSLSocketReader::NewL(*securesock_));
266 if (err != KErrNone)
267 return NULL;
268
269 return reader_;
270}
271
272void CPjSSLSocket::DoCancel()
273{
274 /* Operation to be cancelled depends on current state */
275 switch (state_) {
276 case SSL_STATE_CONNECTING:
277 {
278 RSocket &rSock = ((CPjSocket*)sock_)->Socket();
Nanang Izzuddin6c62bf42009-08-27 19:55:13 +0000279
Nanang Izzuddina7719d32010-03-06 02:04:52 +0000280 rSock.CancelConnect();
281 CleanupSubObjects();
Nanang Izzuddin6c62bf42009-08-27 19:55:13 +0000282 state_ = SSL_STATE_NULL;
283 }
284 break;
285 case SSL_STATE_HANDSHAKING:
286 {
287 securesock_->CancelHandshake();
Nanang Izzuddin6c62bf42009-08-27 19:55:13 +0000288 CleanupSubObjects();
Nanang Izzuddin6c62bf42009-08-27 19:55:13 +0000289 state_ = SSL_STATE_NULL;
290 }
291 break;
292 case SSL_STATE_ESTABLISHED:
293 securesock_->CancelSend();
294 break;
295 default:
296 break;
297 }
298}
299
300void CPjSSLSocket::RunL()
301{
302 switch (state_) {
303 case SSL_STATE_CONNECTING:
304 if (iStatus != KErrNone) {
305 CleanupSubObjects();
306 state_ = SSL_STATE_NULL;
307 /* Dispatch connect failure notification */
308 if (cb_) (*cb_)(iStatus.Int(), key_);
309 } else {
310 RSocket &rSock = ((CPjSocket*)sock_)->Socket();
311
312 /* Get local addr */
313 rSock.LocalName(local_addr_);
314
315 /* Prepare and start handshake */
316 securesock_ = CSecureSocket::NewL(rSock, ssl_proto_);
317 securesock_->SetDialogMode(EDialogModeAttended);
318 if (servername_.Length() > 0)
319 securesock_->SetOpt(KSoSSLDomainName, KSolInetSSL,
320 servername_);
Nanang Izzuddina7719d32010-03-06 02:04:52 +0000321
322 // FlushSessionCache() seems to also fire signals to all
323 // completed AOs (something like CActiveScheduler::RunIfReady())
324 // which may cause problem, e.g: we've experienced that when
325 // SSL timeout is set to 1s, the SSL timeout timer fires up
326 // at this point and securesock_ instance gets deleted here!
327 // So be careful using this. And we don't think we need it here.
328 //securesock_->FlushSessionCache();
329
Nanang Izzuddin6c62bf42009-08-27 19:55:13 +0000330 securesock_->StartClientHandshake(iStatus);
331 SetActive();
332 state_ = SSL_STATE_HANDSHAKING;
333 }
334 break;
335 case SSL_STATE_HANDSHAKING:
336 if (iStatus == KErrNone) {
337 state_ = SSL_STATE_ESTABLISHED;
338 } else {
339 state_ = SSL_STATE_NULL;
340 CleanupSubObjects();
341 }
342 /* Dispatch connect status notification */
343 if (cb_) (*cb_)(iStatus.Int(), key_);
344 break;
345 case SSL_STATE_ESTABLISHED:
346 /* Dispatch data sent notification */
347 if (cb_) (*cb_)(iStatus.Int(), key_);
348 break;
349 default:
350 pj_assert(0);
351 break;
352 }
353}
354
355typedef void (*CPjTimer_cb)(void *user_data);
356
357class CPjTimer : public CActive
358{
359public:
360 CPjTimer(const pj_time_val *delay, CPjTimer_cb cb, void *user_data) :
361 CActive(0), cb_(cb), user_data_(user_data)
362 {
363 CActiveScheduler::Add(this);
364
365 rtimer_.CreateLocal();
366 pj_int32_t interval = PJ_TIME_VAL_MSEC(*delay) * 1000;
367 if (interval < 0) {
368 interval = 0;
369 }
370 rtimer_.After(iStatus, interval);
371 SetActive();
372 }
373
374 ~CPjTimer() { Cancel(); }
375
376private:
377 RTimer rtimer_;
378 CPjTimer_cb cb_;
379 void *user_data_;
380
381 void RunL() { if (cb_) (*cb_)(user_data_); }
382 void DoCancel() { rtimer_.Cancel(); }
383};
384
385/*
386 * Structure of recv/read state.
387 */
388typedef struct read_state_t {
389 TPtr8 *read_buf;
390 TPtr8 *orig_buf;
391 pj_uint32_t flags;
392} read_state_t;
393
394/*
395 * Structure of send/write data.
396 */
397typedef struct write_data_t {
398 pj_size_t len;
399 pj_ioqueue_op_key_t *key;
400 pj_size_t data_len;
401 char data[1];
402} write_data_t;
403
404/*
405 * Structure of send/write state.
406 */
407typedef struct write_state_t {
408 char *buf;
409 pj_size_t max_len;
410 char *start;
411 pj_size_t len;
412 write_data_t *current_data;
413 TPtrC8 send_ptr;
414} write_state_t;
415
416/*
417 * Secure socket structure definition.
418 */
419struct pj_ssl_sock_t
420{
Nanang Izzuddin2fb937e2010-02-24 05:43:34 +0000421 pj_pool_t *pool;
Nanang Izzuddin6c62bf42009-08-27 19:55:13 +0000422 pj_ssl_sock_cb cb;
423 void *user_data;
424
425 pj_bool_t established;
426 write_state_t write_state;
427 read_state_t read_state;
428 CPjTimer *connect_timer;
429
430 CPjSSLSocket *sock;
431 int sock_af;
432 int sock_type;
433 pj_sockaddr local_addr;
434 pj_sockaddr rem_addr;
435
Benny Prijonoa25bc9d2009-11-09 08:51:34 +0000436 /* QoS settings */
437 pj_qos_type qos_type;
438 pj_qos_params qos_params;
439 pj_bool_t qos_ignore_error;
440
441
Nanang Izzuddin6c62bf42009-08-27 19:55:13 +0000442 pj_ssl_sock_proto proto;
443 pj_time_val timeout;
Nanang Izzuddin006cc012009-10-16 03:06:13 +0000444 unsigned ciphers_num;
445 pj_ssl_cipher *ciphers;
Nanang Izzuddin6c62bf42009-08-27 19:55:13 +0000446 pj_str_t servername;
Nanang Izzuddin2fb937e2010-02-24 05:43:34 +0000447 pj_ssl_cert_info remote_cert_info;
Nanang Izzuddin6c62bf42009-08-27 19:55:13 +0000448};
449
450
Nanang Izzuddin5e69da52010-02-25 11:58:19 +0000451static pj_str_t get_cert_name(char *buf, unsigned buf_len,
Nanang Izzuddin2fb937e2010-02-24 05:43:34 +0000452 const CX500DistinguishedName &name)
453{
454 TInt i;
Nanang Izzuddin2fb937e2010-02-24 05:43:34 +0000455 TUint8 *p;
Nanang Izzuddin5e69da52010-02-25 11:58:19 +0000456 TInt l = buf_len;
Nanang Izzuddin2fb937e2010-02-24 05:43:34 +0000457
458 p = (TUint8*)buf;
459 for(i = 0; i < name.Count(); ++i) {
460 const CX520AttributeTypeAndValue &attr = name.Element(i);
461
462 /* Print element separator */
463 *p++ = '/';
464 if (0 == --l) break;
465
466 /* Print the type. */
467 TPtr8 type(p, l);
468 type.Copy(attr.Type());
469 p += type.Length();
470 l -= type.Length();
471 if (0 >= --l) break;
472
473 /* Print equal sign */
474 *p++ = '=';
475 if (0 == --l) break;
476
477 /* Print the value. Let's just get the raw data here */
478 TPtr8 value(p, l);
479 value.Copy(attr.EncodedValue().Mid(2));
480 p += value.Length();
481 l -= value.Length();
482 if (0 >= --l) break;
483 }
484
Nanang Izzuddin5e69da52010-02-25 11:58:19 +0000485 pj_str_t src;
486 pj_strset(&src, buf, buf_len - l);
Nanang Izzuddin2fb937e2010-02-24 05:43:34 +0000487
Nanang Izzuddin5e69da52010-02-25 11:58:19 +0000488 return src;
Nanang Izzuddin2fb937e2010-02-24 05:43:34 +0000489}
490
491/* Get certificate info from CX509Certificate.
492 */
493static void get_cert_info(pj_pool_t *pool, pj_ssl_cert_info *ci,
494 const CX509Certificate *x)
495{
Nanang Izzuddin5e69da52010-02-25 11:58:19 +0000496 enum { tmp_buf_len = 512 };
497 char *tmp_buf;
Nanang Izzuddin2fb937e2010-02-24 05:43:34 +0000498 unsigned len;
499
500 pj_assert(pool && ci && x);
501
Nanang Izzuddin5e69da52010-02-25 11:58:19 +0000502 /* Init */
503 tmp_buf = new char[tmp_buf_len];
Nanang Izzuddin2fb937e2010-02-24 05:43:34 +0000504 pj_bzero(ci, sizeof(*ci));
505
506 /* Version */
507 ci->version = x->Version();
508
509 /* Serial number */
510 len = x->SerialNumber().Length();
511 if (len > sizeof(ci->serial_no))
512 len = sizeof(ci->serial_no);
513 pj_memcpy(ci->serial_no + sizeof(ci->serial_no) - len,
514 x->SerialNumber().Ptr(), len);
515
516 /* Subject */
517 {
518 HBufC *subject = NULL;
519 TRAPD(err, subject = x->SubjectL());
520 if (err == KErrNone) {
521 TPtr16 ptr16(subject->Des());
522 len = ptr16.Length();
523 TPtr8 ptr8((TUint8*)pj_pool_alloc(pool, len), len);
524 ptr8.Copy(ptr16);
525 pj_strset(&ci->subject.cn, (char*)ptr8.Ptr(), ptr8.Length());
526 }
Nanang Izzuddin5e69da52010-02-25 11:58:19 +0000527 pj_str_t tmp = get_cert_name(tmp_buf, tmp_buf_len,
528 x->SubjectName());
529 pj_strdup(pool, &ci->subject.info, &tmp);
Nanang Izzuddin2fb937e2010-02-24 05:43:34 +0000530 }
531
532 /* Issuer */
533 {
534 HBufC *issuer = NULL;
535 TRAPD(err, issuer = x->IssuerL());
536 if (err == KErrNone) {
537 TPtr16 ptr16(issuer->Des());
538 len = ptr16.Length();
539 TPtr8 ptr8((TUint8*)pj_pool_alloc(pool, len), len);
540 ptr8.Copy(ptr16);
541 pj_strset(&ci->issuer.cn, (char*)ptr8.Ptr(), ptr8.Length());
542 }
Nanang Izzuddin5e69da52010-02-25 11:58:19 +0000543 pj_str_t tmp = get_cert_name(tmp_buf, tmp_buf_len,
544 x->IssuerName());
545 pj_strdup(pool, &ci->issuer.info, &tmp);
Nanang Izzuddin2fb937e2010-02-24 05:43:34 +0000546 }
547
548 /* Validity */
549 const CValidityPeriod &valid_period = x->ValidityPeriod();
550 TTime base_time(TDateTime(1970, EJanuary, 0, 0, 0, 0, 0));
551 TTimeIntervalSeconds tmp_sec;
552 valid_period.Start().SecondsFrom(base_time, tmp_sec);
553 ci->validity.start.sec = tmp_sec.Int();
554 valid_period.Finish().SecondsFrom(base_time, tmp_sec);
555 ci->validity.end.sec = tmp_sec.Int();
Nanang Izzuddin5e69da52010-02-25 11:58:19 +0000556
557 /* Deinit */
558 delete [] tmp_buf;
Nanang Izzuddin2fb937e2010-02-24 05:43:34 +0000559}
560
561
562/* Update certificates info. This function should be called after handshake
563 * or renegotiation successfully completed.
564 */
565static void update_certs_info(pj_ssl_sock_t *ssock)
566{
567 const CX509Certificate *x;
568
569 pj_assert(ssock && ssock->sock &&
570 ssock->sock->GetState() == CPjSSLSocket::SSL_STATE_ESTABLISHED);
571
572 /* Active remote certificate */
573 x = ssock->sock->GetPeerCert();
574 if (x) {
575 get_cert_info(ssock->pool, &ssock->remote_cert_info, x);
576 } else {
577 pj_bzero(&ssock->remote_cert_info, sizeof(pj_ssl_cert_info));
578 }
579}
580
581
Nanang Izzuddin6c62bf42009-08-27 19:55:13 +0000582/*
Nanang Izzuddin006cc012009-10-16 03:06:13 +0000583 * Get cipher list supported by SSL/TLS backend.
584 */
585PJ_DEF(pj_status_t) pj_ssl_cipher_get_availables (pj_ssl_cipher ciphers[],
586 unsigned *cipher_num)
587{
588 /* Available ciphers */
589 static pj_ssl_cipher ciphers_[64];
590 static unsigned ciphers_num_ = 0;
591 unsigned i;
592
593 PJ_ASSERT_RETURN(ciphers && cipher_num, PJ_EINVAL);
594
595 if (ciphers_num_ == 0) {
596 RSocket sock;
597 CSecureSocket *secure_sock;
598 TPtrC16 proto(_L16("TLS1.0"));
599
600 secure_sock = CSecureSocket::NewL(sock, proto);
601 if (secure_sock) {
602 TBuf8<128> ciphers_buf(0);
603 secure_sock->AvailableCipherSuites(ciphers_buf);
604
605 ciphers_num_ = ciphers_buf.Length() / 2;
606 if (ciphers_num_ > PJ_ARRAY_SIZE(ciphers_))
607 ciphers_num_ = PJ_ARRAY_SIZE(ciphers_);
608 for (i = 0; i < ciphers_num_; ++i)
Nanang Izzuddineef9b8d2009-11-06 13:31:37 +0000609 ciphers_[i] = (pj_ssl_cipher)(ciphers_buf[i*2]*10 +
610 ciphers_buf[i*2+1]);
Nanang Izzuddin006cc012009-10-16 03:06:13 +0000611 }
612
613 delete secure_sock;
614 }
615
616 if (ciphers_num_ == 0) {
617 return PJ_ENOTFOUND;
618 }
619
620 *cipher_num = PJ_MIN(*cipher_num, ciphers_num_);
621 for (i = 0; i < *cipher_num; ++i)
622 ciphers[i] = ciphers_[i];
623
624 return PJ_SUCCESS;
625}
626
627/*
Nanang Izzuddin6c62bf42009-08-27 19:55:13 +0000628 * Create SSL socket instance.
629 */
630PJ_DEF(pj_status_t) pj_ssl_sock_create (pj_pool_t *pool,
631 const pj_ssl_sock_param *param,
632 pj_ssl_sock_t **p_ssock)
633{
634 pj_ssl_sock_t *ssock;
635
636 PJ_ASSERT_RETURN(param->async_cnt == 1, PJ_EINVAL);
637 PJ_ASSERT_RETURN(pool && param && p_ssock, PJ_EINVAL);
638
639 /* Allocate secure socket */
640 ssock = PJ_POOL_ZALLOC_T(pool, pj_ssl_sock_t);
641
642 /* Allocate write buffer */
643 ssock->write_state.buf = (char*)pj_pool_alloc(pool,
644 param->send_buffer_size);
645 ssock->write_state.max_len = param->send_buffer_size;
646 ssock->write_state.start = ssock->write_state.buf;
647
648 /* Init secure socket */
Nanang Izzuddin2fb937e2010-02-24 05:43:34 +0000649 ssock->pool = pool;
Nanang Izzuddin6c62bf42009-08-27 19:55:13 +0000650 ssock->sock_af = param->sock_af;
651 ssock->sock_type = param->sock_type;
652 ssock->cb = param->cb;
653 ssock->user_data = param->user_data;
Nanang Izzuddina7719d32010-03-06 02:04:52 +0000654 ssock->timeout = param->timeout;
Nanang Izzuddin006cc012009-10-16 03:06:13 +0000655 ssock->ciphers_num = param->ciphers_num;
656 if (param->ciphers_num > 0) {
657 unsigned i;
658 ssock->ciphers = (pj_ssl_cipher*)
659 pj_pool_calloc(pool, param->ciphers_num,
660 sizeof(pj_ssl_cipher));
661 for (i = 0; i < param->ciphers_num; ++i)
662 ssock->ciphers[i] = param->ciphers[i];
663 }
Nanang Izzuddinea6d3c42009-10-26 15:47:52 +0000664 pj_strdup_with_null(pool, &ssock->servername, &param->server_name);
Nanang Izzuddin6c62bf42009-08-27 19:55:13 +0000665
Benny Prijonoa25bc9d2009-11-09 08:51:34 +0000666 ssock->qos_type = param->qos_type;
667 ssock->qos_ignore_error = param->qos_ignore_error;
668 pj_memcpy(&ssock->qos_params, &param->qos_params,
669 sizeof(param->qos_params));
670
Nanang Izzuddin6c62bf42009-08-27 19:55:13 +0000671 /* Finally */
672 *p_ssock = ssock;
673
674 return PJ_SUCCESS;
675}
676
Nanang Izzuddin006cc012009-10-16 03:06:13 +0000677
678PJ_DEF(pj_status_t) pj_ssl_cert_load_from_files(pj_pool_t *pool,
679 const pj_str_t *CA_file,
680 const pj_str_t *cert_file,
681 const pj_str_t *privkey_file,
682 const pj_str_t *privkey_pass,
683 pj_ssl_cert_t **p_cert)
684{
685 PJ_UNUSED_ARG(pool);
686 PJ_UNUSED_ARG(CA_file);
687 PJ_UNUSED_ARG(cert_file);
688 PJ_UNUSED_ARG(privkey_file);
689 PJ_UNUSED_ARG(privkey_pass);
690 PJ_UNUSED_ARG(p_cert);
691 return PJ_ENOTSUP;
692}
693
Nanang Izzuddin6c62bf42009-08-27 19:55:13 +0000694/*
695 * Set SSL socket credential.
696 */
697PJ_DEF(pj_status_t) pj_ssl_sock_set_certificate(
698 pj_ssl_sock_t *ssock,
699 pj_pool_t *pool,
700 const pj_ssl_cert_t *cert)
701{
702 PJ_UNUSED_ARG(ssock);
703 PJ_UNUSED_ARG(pool);
704 PJ_UNUSED_ARG(cert);
705 return PJ_ENOTSUP;
706}
707
708/*
709 * Close the SSL socket.
710 */
711PJ_DEF(pj_status_t) pj_ssl_sock_close(pj_ssl_sock_t *ssock)
712{
713 PJ_ASSERT_RETURN(ssock, PJ_EINVAL);
714
715 delete ssock->connect_timer;
716 ssock->connect_timer = NULL;
717
718 delete ssock->sock;
719 ssock->sock = NULL;
720
721 delete ssock->read_state.read_buf;
722 delete ssock->read_state.orig_buf;
723 ssock->read_state.read_buf = NULL;
724 ssock->read_state.orig_buf = NULL;
725
726 return PJ_SUCCESS;
727}
728
729
730/*
731 * Associate arbitrary data with the SSL socket.
732 */
733PJ_DEF(pj_status_t) pj_ssl_sock_set_user_data (pj_ssl_sock_t *ssock,
734 void *user_data)
735{
736 PJ_ASSERT_RETURN(ssock, PJ_EINVAL);
737
738 ssock->user_data = user_data;
739
740 return PJ_SUCCESS;
741}
742
743
744/*
745 * Retrieve the user data previously associated with this SSL
746 * socket.
747 */
748PJ_DEF(void*) pj_ssl_sock_get_user_data(pj_ssl_sock_t *ssock)
749{
750 PJ_ASSERT_RETURN(ssock, NULL);
751
752 return ssock->user_data;
753}
754
755
756/*
757 * Retrieve the local address and port used by specified SSL socket.
758 */
759PJ_DEF(pj_status_t) pj_ssl_sock_get_info (pj_ssl_sock_t *ssock,
760 pj_ssl_sock_info *info)
761{
Nanang Izzuddin6c62bf42009-08-27 19:55:13 +0000762 PJ_ASSERT_RETURN(ssock && info, PJ_EINVAL);
763
764 pj_bzero(info, sizeof(*info));
765
766 info->established = ssock->established;
767
768 /* Local address */
769 if (ssock->sock) {
770 const TInetAddr* local_addr_ = ssock->sock->GetLocalAddr();
771 int addrlen = sizeof(pj_sockaddr);
772 pj_status_t status;
773
774 status = PjSymbianOS::Addr2pj(*local_addr_, info->local_addr, &addrlen);
775 if (status != PJ_SUCCESS)
776 return status;
777 } else {
778 pj_sockaddr_cp(&info->local_addr, &ssock->local_addr);
779 }
780
Nanang Izzuddin6c62bf42009-08-27 19:55:13 +0000781 if (info->established) {
Nanang Izzuddin006cc012009-10-16 03:06:13 +0000782 /* Cipher suite */
783 TBuf8<4> cipher;
Nanang Izzuddin6c62bf42009-08-27 19:55:13 +0000784 if (ssock->sock->GetCipher(cipher) == KErrNone) {
Nanang Izzuddin006cc012009-10-16 03:06:13 +0000785 info->cipher = (pj_ssl_cipher)cipher[1];
Nanang Izzuddin6c62bf42009-08-27 19:55:13 +0000786 }
Nanang Izzuddin006cc012009-10-16 03:06:13 +0000787
788 /* Remote address */
789 pj_sockaddr_cp((pj_sockaddr_t*)&info->remote_addr,
Nanang Izzuddin2fb937e2010-02-24 05:43:34 +0000790 (pj_sockaddr_t*)&ssock->rem_addr);
791
792 /* Certificates info */
793 info->remote_cert_info = &ssock->remote_cert_info;
Nanang Izzuddin6c62bf42009-08-27 19:55:13 +0000794 }
795
796 /* Protocol */
797 info->proto = ssock->proto;
798
799 return PJ_SUCCESS;
800}
801
802
803/*
804 * Starts read operation on this SSL socket.
805 */
806PJ_DEF(pj_status_t) pj_ssl_sock_start_read (pj_ssl_sock_t *ssock,
807 pj_pool_t *pool,
808 unsigned buff_size,
809 pj_uint32_t flags)
810{
811 PJ_ASSERT_RETURN(ssock && pool && buff_size, PJ_EINVAL);
812 PJ_ASSERT_RETURN(ssock->established, PJ_EINVALIDOP);
813
814 /* Reading is already started */
815 if (ssock->read_state.orig_buf) {
816 return PJ_SUCCESS;
817 }
818
819 void *readbuf[1];
820 readbuf[0] = pj_pool_alloc(pool, buff_size);
821 return pj_ssl_sock_start_read2(ssock, pool, buff_size, readbuf, flags);
822}
823
824static void read_cb(int err, void *key)
825{
826 pj_ssl_sock_t *ssock = (pj_ssl_sock_t*)key;
827 pj_status_t status;
828
829 status = (err == KErrNone)? PJ_SUCCESS : PJ_RETURN_OS_ERROR(err);
830
831 /* Check connection status */
832 if (err == KErrEof || !PjSymbianOS::Instance()->IsConnectionUp() ||
833 !ssock->established)
834 {
835 status = PJ_EEOF;
836 }
837
838 /* Notify data arrival */
839 if (ssock->cb.on_data_read) {
840 pj_size_t remainder = 0;
841 char *data = (char*)ssock->read_state.orig_buf->Ptr();
842 pj_size_t data_len = ssock->read_state.read_buf->Length() +
843 ssock->read_state.read_buf->Ptr() -
844 ssock->read_state.orig_buf->Ptr();
845
846 if (data_len > 0) {
847 /* Notify received data */
848 pj_bool_t ret = (*ssock->cb.on_data_read)(ssock, data, data_len,
849 status, &remainder);
850 if (!ret) {
851 /* We've been destroyed */
852 return;
853 }
854
855 /* Calculate available data for next READ operation */
856 if (remainder > 0) {
857 pj_size_t data_maxlen = ssock->read_state.orig_buf->MaxLength();
858
859 /* There is some data left unconsumed by application, we give
860 * smaller buffer for next READ operation.
861 */
862 ssock->read_state.read_buf->Set((TUint8*)data+remainder, 0,
863 data_maxlen - remainder);
864 } else {
865 /* Give all buffer for next READ operation.
866 */
867 ssock->read_state.read_buf->Set(*ssock->read_state.orig_buf);
868 }
869 }
870 }
871
872 if (status == PJ_SUCCESS) {
873 /* Perform the "next" READ operation */
874 CPjSSLSocketReader *reader = ssock->sock->GetReader();
875 ssock->read_state.read_buf->SetLength(0);
876 status = reader->Read(&read_cb, ssock, *ssock->read_state.read_buf,
877 ssock->read_state.flags);
Nanang Izzuddin6c62bf42009-08-27 19:55:13 +0000878 }
879
Nanang Izzuddin2fb937e2010-02-24 05:43:34 +0000880 /* Connection closed or something goes wrong */
Nanang Izzuddin6c62bf42009-08-27 19:55:13 +0000881 if (status != PJ_SUCCESS && status != PJ_EPENDING) {
Nanang Izzuddin2fb937e2010-02-24 05:43:34 +0000882 /* Notify error */
883 if (ssock->cb.on_data_read) {
884 pj_bool_t ret = (*ssock->cb.on_data_read)(ssock, NULL, 0,
885 status, NULL);
886 if (!ret) {
887 /* We've been destroyed */
888 return;
889 }
890 }
891
Nanang Izzuddin6c62bf42009-08-27 19:55:13 +0000892 delete ssock->read_state.read_buf;
893 delete ssock->read_state.orig_buf;
894 ssock->read_state.read_buf = NULL;
895 ssock->read_state.orig_buf = NULL;
896 ssock->established = PJ_FALSE;
897 }
898}
899
900/*
901 * Same as #pj_ssl_sock_start_read(), except that the application
902 * supplies the buffers for the read operation so that the acive socket
903 * does not have to allocate the buffers.
904 */
905PJ_DEF(pj_status_t) pj_ssl_sock_start_read2 (pj_ssl_sock_t *ssock,
906 pj_pool_t *pool,
907 unsigned buff_size,
908 void *readbuf[],
909 pj_uint32_t flags)
910{
911 PJ_ASSERT_RETURN(ssock && buff_size && readbuf, PJ_EINVAL);
912 PJ_ASSERT_RETURN(ssock->established, PJ_EINVALIDOP);
913
914 /* Return failure if access point is marked as down by app. */
915 PJ_SYMBIAN_CHECK_CONNECTION();
916
917 /* Reading is already started */
918 if (ssock->read_state.orig_buf) {
919 return PJ_SUCCESS;
920 }
921
922 PJ_UNUSED_ARG(pool);
923
924 /* Get reader instance */
925 CPjSSLSocketReader *reader = ssock->sock->GetReader();
926 if (!reader)
927 return PJ_ENOMEM;
928
929 /* We manage two buffer pointers here:
930 * 1. orig_buf keeps the orginal buffer address (and its max length).
931 * 2. read_buf provides buffer for READ operation, mind that there may be
932 * some remainder data left by application.
933 */
934 ssock->read_state.read_buf = new TPtr8((TUint8*)readbuf[0], 0, buff_size);
935 ssock->read_state.orig_buf = new TPtr8((TUint8*)readbuf[0], 0, buff_size);
936 ssock->read_state.flags = flags;
937
938 pj_status_t status;
939 status = reader->Read(&read_cb, ssock, *ssock->read_state.read_buf,
940 ssock->read_state.flags);
941
942 if (status != PJ_SUCCESS && status != PJ_EPENDING) {
943 delete ssock->read_state.read_buf;
944 delete ssock->read_state.orig_buf;
945 ssock->read_state.read_buf = NULL;
946 ssock->read_state.orig_buf = NULL;
947
948 return status;
949 }
950
951 return PJ_SUCCESS;
952}
953
954/*
955 * Same as pj_ssl_sock_start_read(), except that this function is used
956 * only for datagram sockets, and it will trigger \a on_data_recvfrom()
957 * callback instead.
958 */
959PJ_DEF(pj_status_t) pj_ssl_sock_start_recvfrom (pj_ssl_sock_t *ssock,
960 pj_pool_t *pool,
961 unsigned buff_size,
962 pj_uint32_t flags)
963{
964 PJ_UNUSED_ARG(ssock);
965 PJ_UNUSED_ARG(pool);
966 PJ_UNUSED_ARG(buff_size);
967 PJ_UNUSED_ARG(flags);
968 return PJ_ENOTSUP;
969}
970
971/*
972 * Same as #pj_ssl_sock_start_recvfrom() except that the recvfrom()
973 * operation takes the buffer from the argument rather than creating
974 * new ones.
975 */
976PJ_DEF(pj_status_t) pj_ssl_sock_start_recvfrom2 (pj_ssl_sock_t *ssock,
977 pj_pool_t *pool,
978 unsigned buff_size,
979 void *readbuf[],
980 pj_uint32_t flags)
981{
982 PJ_UNUSED_ARG(ssock);
983 PJ_UNUSED_ARG(pool);
984 PJ_UNUSED_ARG(buff_size);
985 PJ_UNUSED_ARG(readbuf);
986 PJ_UNUSED_ARG(flags);
987 return PJ_ENOTSUP;
988}
989
990static void send_cb(int err, void *key)
991{
992 pj_ssl_sock_t *ssock = (pj_ssl_sock_t*)key;
993 write_state_t *st = &ssock->write_state;
994
995 /* Check connection status */
996 if (err != KErrNone || !PjSymbianOS::Instance()->IsConnectionUp() ||
997 !ssock->established)
998 {
999 ssock->established = PJ_FALSE;
1000 return;
1001 }
1002
1003 /* Remove sent data from buffer */
1004 st->start += st->current_data->len;
1005 st->len -= st->current_data->len;
1006
1007 /* Reset current outstanding send */
1008 st->current_data = NULL;
1009
1010 /* Let's check if there is pending data to send */
1011 if (st->len) {
1012 write_data_t *wdata = (write_data_t*)st->start;
1013 pj_status_t status;
1014
1015 st->send_ptr.Set((TUint8*)wdata->data, (TInt)wdata->data_len);
1016 st->current_data = wdata;
1017 status = ssock->sock->Send(&send_cb, ssock, st->send_ptr, 0);
1018 if (status != PJ_EPENDING) {
1019 ssock->established = PJ_FALSE;
1020 st->len = 0;
1021 return;
1022 }
Nanang Izzuddin34fa0ec2010-11-12 07:42:58 +00001023 } else {
1024 /* Buffer empty, reset the start position */
1025 st->start = st->buf;
Nanang Izzuddin6c62bf42009-08-27 19:55:13 +00001026 }
1027}
1028
1029/*
1030 * Send data using the socket.
1031 */
1032PJ_DEF(pj_status_t) pj_ssl_sock_send (pj_ssl_sock_t *ssock,
1033 pj_ioqueue_op_key_t *send_key,
1034 const void *data,
1035 pj_ssize_t *size,
1036 unsigned flags)
1037{
1038 PJ_CHECK_STACK();
1039 PJ_ASSERT_RETURN(ssock && data && size, PJ_EINVAL);
1040 PJ_ASSERT_RETURN(ssock->write_state.max_len == 0 ||
1041 ssock->write_state.max_len >= (pj_size_t)*size,
1042 PJ_ETOOSMALL);
1043
1044 /* Check connection status */
1045 if (!PjSymbianOS::Instance()->IsConnectionUp() || !ssock->established)
1046 {
1047 ssock->established = PJ_FALSE;
1048 return PJ_ECANCELLED;
1049 }
1050
1051 write_state_t *st = &ssock->write_state;
1052
1053 /* Synchronous mode */
1054 if (st->max_len == 0) {
1055 st->send_ptr.Set((TUint8*)data, (TInt)*size);
1056 return ssock->sock->SendSync(st->send_ptr, flags);
1057 }
1058
1059 /* CSecureSocket only allows one outstanding send operation, so
1060 * we use buffering mechanism to allow application to perform send
1061 * operations at any time.
1062 */
1063
Nanang Izzuddin6c62bf42009-08-27 19:55:13 +00001064 pj_size_t needed_len = *size + sizeof(write_data_t) - 1;
1065
1066 /* Align needed_len to be multiplication of 4 */
1067 needed_len = ((needed_len + 3) >> 2) << 2;
1068
Nanang Izzuddin34fa0ec2010-11-12 07:42:58 +00001069 /* Block until there is buffer slot available and contiguous! */
1070 while (st->start + st->len + needed_len > st->buf + st->max_len) {
Nanang Izzuddin6c62bf42009-08-27 19:55:13 +00001071 pj_symbianos_poll(-1, -1);
Nanang Izzuddin6c62bf42009-08-27 19:55:13 +00001072 }
1073
Nanang Izzuddin6c62bf42009-08-27 19:55:13 +00001074 /* Push back the send data into the buffer */
1075 write_data_t *wdata = (write_data_t*)(st->start + st->len);
1076
1077 wdata->len = needed_len;
1078 wdata->key = send_key;
1079 wdata->data_len = (pj_size_t)*size;
1080 pj_memcpy(wdata->data, data, *size);
1081 st->len += needed_len;
1082
1083 /* If no outstanding send, send it */
1084 if (st->current_data == NULL) {
1085 pj_status_t status;
1086
1087 wdata = (write_data_t*)st->start;
1088 st->current_data = wdata;
1089 st->send_ptr.Set((TUint8*)wdata->data, (TInt)wdata->data_len);
1090 status = ssock->sock->Send(&send_cb, ssock, st->send_ptr, flags);
1091
1092 if (status != PJ_EPENDING) {
1093 *size = -status;
1094 return status;
1095 }
1096 }
1097
1098 return PJ_SUCCESS;
1099}
1100
1101/*
1102 * Send datagram using the socket.
1103 */
1104PJ_DEF(pj_status_t) pj_ssl_sock_sendto (pj_ssl_sock_t *ssock,
1105 pj_ioqueue_op_key_t *send_key,
1106 const void *data,
1107 pj_ssize_t *size,
1108 unsigned flags,
1109 const pj_sockaddr_t *addr,
1110 int addr_len)
1111{
1112 PJ_UNUSED_ARG(ssock);
1113 PJ_UNUSED_ARG(send_key);
1114 PJ_UNUSED_ARG(data);
1115 PJ_UNUSED_ARG(size);
1116 PJ_UNUSED_ARG(flags);
1117 PJ_UNUSED_ARG(addr);
1118 PJ_UNUSED_ARG(addr_len);
1119 return PJ_ENOTSUP;
1120}
1121
1122/*
1123 * Starts asynchronous socket accept() operations on this SSL socket.
1124 */
1125PJ_DEF(pj_status_t) pj_ssl_sock_start_accept (pj_ssl_sock_t *ssock,
1126 pj_pool_t *pool,
1127 const pj_sockaddr_t *local_addr,
1128 int addr_len)
1129{
1130 PJ_UNUSED_ARG(ssock);
1131 PJ_UNUSED_ARG(pool);
1132 PJ_UNUSED_ARG(local_addr);
1133 PJ_UNUSED_ARG(addr_len);
1134
1135 return PJ_ENOTSUP;
1136}
1137
1138static void connect_cb(int err, void *key)
1139{
1140 pj_ssl_sock_t *ssock = (pj_ssl_sock_t*)key;
1141 pj_status_t status;
1142
1143 if (ssock->connect_timer) {
1144 delete ssock->connect_timer;
1145 ssock->connect_timer = NULL;
1146 }
1147
1148 status = (err == KErrNone)? PJ_SUCCESS : PJ_RETURN_OS_ERROR(err);
1149 if (status == PJ_SUCCESS) {
1150 ssock->established = PJ_TRUE;
Nanang Izzuddin2fb937e2010-02-24 05:43:34 +00001151 update_certs_info(ssock);
Nanang Izzuddin6c62bf42009-08-27 19:55:13 +00001152 } else {
1153 delete ssock->sock;
1154 ssock->sock = NULL;
Nanang Izzuddina7719d32010-03-06 02:04:52 +00001155 if (err == KErrTimedOut) status = PJ_ETIMEDOUT;
Nanang Izzuddin6c62bf42009-08-27 19:55:13 +00001156 }
1157
1158 if (ssock->cb.on_connect_complete) {
1159 pj_bool_t ret = (*ssock->cb.on_connect_complete)(ssock, status);
1160 if (!ret) {
1161 /* We've been destroyed */
1162 return;
1163 }
1164 }
1165}
1166
1167static void connect_timer_cb(void *key)
1168{
1169 connect_cb(KErrTimedOut, key);
1170}
1171
1172/*
1173 * Starts asynchronous socket connect() operation and SSL/TLS handshaking
1174 * for this socket. Once the connection is done (either successfully or not),
1175 * the \a on_connect_complete() callback will be called.
1176 */
1177PJ_DEF(pj_status_t) pj_ssl_sock_start_connect (pj_ssl_sock_t *ssock,
1178 pj_pool_t *pool,
1179 const pj_sockaddr_t *localaddr,
1180 const pj_sockaddr_t *remaddr,
1181 int addr_len)
1182{
1183 CPjSSLSocket *sock = NULL;
1184 pj_status_t status;
1185
1186 PJ_ASSERT_RETURN(ssock && pool && localaddr && remaddr && addr_len,
1187 PJ_EINVAL);
1188
1189 /* Check connection status */
1190 PJ_SYMBIAN_CHECK_CONNECTION();
1191
1192 if (ssock->sock != NULL) {
1193 CPjSSLSocket::ssl_state state = ssock->sock->GetState();
1194 switch (state) {
1195 case CPjSSLSocket::SSL_STATE_ESTABLISHED:
1196 return PJ_SUCCESS;
1197 default:
1198 return PJ_EPENDING;
1199 }
1200 }
1201
1202 /* Set SSL protocol */
1203 TPtrC8 proto;
1204
1205 if (ssock->proto == PJ_SSL_SOCK_PROTO_DEFAULT)
1206 ssock->proto = PJ_SSL_SOCK_PROTO_TLS1;
1207
1208 /* CSecureSocket only support TLS1.0 and SSL3.0 */
1209 switch(ssock->proto) {
1210 case PJ_SSL_SOCK_PROTO_TLS1:
1211 proto.Set((const TUint8*)"TLS1.0", 6);
1212 break;
1213 case PJ_SSL_SOCK_PROTO_SSL3:
1214 proto.Set((const TUint8*)"SSL3.0", 6);
1215 break;
1216 default:
1217 return PJ_ENOTSUP;
1218 }
1219
1220 /* Prepare addresses */
1221 TInetAddr localaddr_, remaddr_;
1222 status = PjSymbianOS::pj2Addr(*(pj_sockaddr*)localaddr, addr_len,
1223 localaddr_);
1224 if (status != PJ_SUCCESS)
1225 return status;
1226
1227 status = PjSymbianOS::pj2Addr(*(pj_sockaddr*)remaddr, addr_len,
1228 remaddr_);
1229 if (status != PJ_SUCCESS)
1230 return status;
1231
1232 pj_sockaddr_cp((pj_sockaddr_t*)&ssock->rem_addr, remaddr);
1233
1234 /* Init SSL engine */
Benny Prijonoa25bc9d2009-11-09 08:51:34 +00001235 TRAPD(err, sock = CPjSSLSocket::NewL(proto, ssock->qos_type,
1236 ssock->qos_params));
Nanang Izzuddin6c62bf42009-08-27 19:55:13 +00001237 if (err != KErrNone)
1238 return PJ_ENOMEM;
1239
1240 if (ssock->timeout.sec != 0 || ssock->timeout.msec != 0) {
1241 ssock->connect_timer = new CPjTimer(&ssock->timeout,
1242 &connect_timer_cb, ssock);
1243 }
1244
1245 /* Convert server name to Symbian descriptor */
1246 TPtrC8 servername_((TUint8*)ssock->servername.ptr,
1247 ssock->servername.slen);
1248
1249 /* Try to connect */
1250 status = sock->Connect(&connect_cb, ssock, localaddr_, remaddr_,
1251 servername_);
1252 if (status != PJ_SUCCESS && status != PJ_EPENDING) {
1253 delete sock;
1254 return status;
1255 }
1256
1257 ssock->sock = sock;
1258 return status;
1259}
1260
Nanang Izzuddinea6d3c42009-10-26 15:47:52 +00001261
1262PJ_DEF(pj_status_t) pj_ssl_sock_renegotiate(pj_ssl_sock_t *ssock)
1263{
1264 PJ_UNUSED_ARG(ssock);
1265 return PJ_ENOTSUP;
1266}