1 /* $Id$ */
2 /*
3  * Copyright (C) 2013 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 <pjsua2/types.hpp>
20 #include <pjsua2/siptypes.hpp>
21 #include "util.hpp"
22 
23 using namespace pj;
24 using namespace std;
25 
26 #define THIS_FILE	"siptypes.cpp"
27 
28 ///////////////////////////////////////////////////////////////////////////////
29 namespace pj
30 {
readIntVector(ContainerNode & node,const string & array_name,IntVector & v)31 void readIntVector( ContainerNode &node,
32                     const string &array_name,
33                     IntVector &v) PJSUA2_THROW(Error)
34 {
35     ContainerNode array_node = node.readArray(array_name);
36     v.resize(0);
37     while (array_node.hasUnread()) {
38 	v.push_back((int)array_node.readNumber());
39     }
40 }
41 
writeIntVector(ContainerNode & node,const string & array_name,const IntVector & v)42 void writeIntVector(ContainerNode &node,
43                     const string &array_name,
44                     const IntVector &v) PJSUA2_THROW(Error)
45 {
46     ContainerNode array_node = node.writeNewArray(array_name);
47     for (unsigned i=0; i<v.size(); ++i) {
48 	array_node.writeNumber("", (float)v[i]);
49     }
50 }
51 
readQosParams(ContainerNode & node,pj_qos_params & qos)52 void readQosParams( ContainerNode &node,
53                     pj_qos_params &qos) PJSUA2_THROW(Error)
54 {
55     ContainerNode this_node = node.readContainer("qosParams");
56 
57     NODE_READ_NUM_T( this_node, pj_uint8_t, qos.flags);
58     NODE_READ_NUM_T( this_node, pj_uint8_t, qos.dscp_val);
59     NODE_READ_NUM_T( this_node, pj_uint8_t, qos.so_prio);
60     NODE_READ_NUM_T( this_node, pj_qos_wmm_prio, qos.wmm_prio);
61 }
62 
writeQosParams(ContainerNode & node,const pj_qos_params & qos)63 void writeQosParams( ContainerNode &node,
64                      const pj_qos_params &qos) PJSUA2_THROW(Error)
65 {
66     ContainerNode this_node = node.writeNewContainer("qosParams");
67 
68     NODE_WRITE_NUM_T( this_node, pj_uint8_t, qos.flags);
69     NODE_WRITE_NUM_T( this_node, pj_uint8_t, qos.dscp_val);
70     NODE_WRITE_NUM_T( this_node, pj_uint8_t, qos.so_prio);
71     NODE_WRITE_NUM_T( this_node, pj_qos_wmm_prio, qos.wmm_prio);
72 }
73 
readSipHeaders(const ContainerNode & node,const string & array_name,SipHeaderVector & headers)74 void readSipHeaders( const ContainerNode &node,
75                      const string &array_name,
76                      SipHeaderVector &headers) PJSUA2_THROW(Error)
77 {
78     ContainerNode headers_node = node.readArray(array_name);
79     headers.resize(0);
80     while (headers_node.hasUnread()) {
81 	SipHeader hdr;
82 
83 	ContainerNode header_node = headers_node.readContainer("header");
84 	hdr.hName = header_node.readString("hname");
85 	hdr.hValue = header_node.readString("hvalue");
86 	headers.push_back(hdr);
87     }
88 }
89 
writeSipHeaders(ContainerNode & node,const string & array_name,const SipHeaderVector & headers)90 void writeSipHeaders(ContainerNode &node,
91                      const string &array_name,
92                      const SipHeaderVector &headers) PJSUA2_THROW(Error)
93 {
94     ContainerNode headers_node = node.writeNewArray(array_name);
95     for (unsigned i=0; i<headers.size(); ++i) {
96 	ContainerNode header_node = headers_node.writeNewContainer("header");
97 	header_node.writeString("hname", headers[i].hName);
98 	header_node.writeString("hvalue", headers[i].hValue);
99     }
100 }
101 
102 } // namespace
103 ///////////////////////////////////////////////////////////////////////////////
104 
AuthCredInfo()105 AuthCredInfo::AuthCredInfo()
106 : scheme("digest"), realm("*"), dataType(0)
107 {
108 }
109 
AuthCredInfo(const string & param_scheme,const string & param_realm,const string & param_user_name,const int param_data_type,const string param_data)110 AuthCredInfo::AuthCredInfo(const string &param_scheme,
111 			   const string &param_realm,
112 			   const string &param_user_name,
113 			   const int param_data_type,
114 			   const string param_data)
115 : scheme(param_scheme), realm(param_realm), username(param_user_name),
116   dataType(param_data_type), data(param_data)
117 {
118 }
119 
readObject(const ContainerNode & node)120 void AuthCredInfo::readObject(const ContainerNode &node) PJSUA2_THROW(Error)
121 {
122     ContainerNode this_node = node.readContainer("AuthCredInfo");
123 
124     NODE_READ_STRING( this_node, scheme);
125     NODE_READ_STRING( this_node, realm);
126     NODE_READ_STRING( this_node, username);
127     NODE_READ_INT   ( this_node, dataType);
128     NODE_READ_STRING( this_node, data);
129     NODE_READ_STRING( this_node, akaK);
130     NODE_READ_STRING( this_node, akaOp);
131     NODE_READ_STRING( this_node, akaAmf);
132 }
133 
writeObject(ContainerNode & node) const134 void AuthCredInfo::writeObject(ContainerNode &node) const PJSUA2_THROW(Error)
135 {
136     ContainerNode this_node = node.writeNewContainer("AuthCredInfo");
137 
138     NODE_WRITE_STRING( this_node, scheme);
139     NODE_WRITE_STRING( this_node, realm);
140     NODE_WRITE_STRING( this_node, username);
141     NODE_WRITE_INT   ( this_node, dataType);
142     NODE_WRITE_STRING( this_node, data);
143     NODE_WRITE_STRING( this_node, akaK);
144     NODE_WRITE_STRING( this_node, akaOp);
145     NODE_WRITE_STRING( this_node, akaAmf);
146 }
147 
148 ///////////////////////////////////////////////////////////////////////////////
149 
TlsConfig()150 TlsConfig::TlsConfig() : method(PJSIP_SSL_UNSPECIFIED_METHOD),
151 			 qosType(PJ_QOS_TYPE_BEST_EFFORT)
152 {
153     pjsip_tls_setting ts;
154     pjsip_tls_setting_default(&ts);
155     this->fromPj(ts);
156 }
157 
toPj() const158 pjsip_tls_setting TlsConfig::toPj() const
159 {
160     pjsip_tls_setting ts;
161     pjsip_tls_setting_default(&ts);
162 
163     ts.ca_list_file	= str2Pj(this->CaListFile);
164     ts.cert_file	= str2Pj(this->certFile);
165     ts.privkey_file	= str2Pj(this->privKeyFile);
166     ts.password		= str2Pj(this->password);
167     ts.ca_buf		= str2Pj(this->CaBuf);
168     ts.cert_buf		= str2Pj(this->certBuf);
169     ts.privkey_buf	= str2Pj(this->privKeyBuf);
170     ts.method		= this->method;
171     ts.ciphers_num	= (unsigned)this->ciphers.size();
172     ts.proto		= this->proto;
173     // The following will only work if sizeof(enum)==sizeof(int)
174     pj_assert(sizeof(ts.ciphers[0]) == sizeof(int));
175     ts.ciphers		= ts.ciphers_num?
176 			    (pj_ssl_cipher*)&this->ciphers[0] : NULL;
177     ts.verify_server	= this->verifyServer;
178     ts.verify_client	= this->verifyClient;
179     ts.require_client_cert = this->requireClientCert;
180     ts.timeout.sec 	= this->msecTimeout / 1000;
181     ts.timeout.msec	= this->msecTimeout % 1000;
182     ts.qos_type		= this->qosType;
183     ts.qos_params	= this->qosParams;
184     ts.qos_ignore_error	= this->qosIgnoreError;
185 
186     return ts;
187 }
188 
fromPj(const pjsip_tls_setting & prm)189 void TlsConfig::fromPj(const pjsip_tls_setting &prm)
190 {
191     this->CaListFile 	= pj2Str(prm.ca_list_file);
192     this->certFile 	= pj2Str(prm.cert_file);
193     this->privKeyFile 	= pj2Str(prm.privkey_file);
194     this->password 	= pj2Str(prm.password);
195     this->CaBuf		= pj2Str(prm.ca_buf);
196     this->certBuf	= pj2Str(prm.cert_buf);
197     this->privKeyBuf	= pj2Str(prm.privkey_buf);
198     this->method 	= (pjsip_ssl_method)prm.method;
199     this->proto 	= prm.proto;
200     // The following will only work if sizeof(enum)==sizeof(int)
201     pj_assert(sizeof(prm.ciphers[0]) == sizeof(int));
202     this->ciphers 	= IntVector(prm.ciphers, prm.ciphers+prm.ciphers_num);
203     this->verifyServer 	= PJ2BOOL(prm.verify_server);
204     this->verifyClient 	= PJ2BOOL(prm.verify_client);
205     this->requireClientCert = PJ2BOOL(prm.require_client_cert);
206     this->msecTimeout 	= PJ_TIME_VAL_MSEC(prm.timeout);
207     this->qosType 	= prm.qos_type;
208     this->qosParams 	= prm.qos_params;
209     this->qosIgnoreError = PJ2BOOL(prm.qos_ignore_error);
210 }
211 
readObject(const ContainerNode & node)212 void TlsConfig::readObject(const ContainerNode &node) PJSUA2_THROW(Error)
213 {
214     ContainerNode this_node = node.readContainer("TlsConfig");
215 
216     NODE_READ_STRING  ( this_node, CaListFile);
217     NODE_READ_STRING  ( this_node, certFile);
218     NODE_READ_STRING  ( this_node, privKeyFile);
219     NODE_READ_STRING  ( this_node, password);
220     NODE_READ_STRING  ( this_node, CaBuf);
221     NODE_READ_STRING  ( this_node, certBuf);
222     NODE_READ_STRING  ( this_node, privKeyBuf);
223     NODE_READ_NUM_T   ( this_node, pjsip_ssl_method, method);
224     readIntVector     ( this_node, "ciphers", ciphers);
225     NODE_READ_BOOL    ( this_node, verifyServer);
226     NODE_READ_BOOL    ( this_node, verifyClient);
227     NODE_READ_BOOL    ( this_node, requireClientCert);
228     NODE_READ_UNSIGNED( this_node, msecTimeout);
229     NODE_READ_NUM_T   ( this_node, pj_qos_type, qosType);
230     readQosParams     ( this_node, qosParams);
231     NODE_READ_BOOL    ( this_node, qosIgnoreError);
232 }
233 
writeObject(ContainerNode & node) const234 void TlsConfig::writeObject(ContainerNode &node) const PJSUA2_THROW(Error)
235 {
236     ContainerNode this_node = node.writeNewContainer("TlsConfig");
237 
238     NODE_WRITE_STRING  ( this_node, CaListFile);
239     NODE_WRITE_STRING  ( this_node, certFile);
240     NODE_WRITE_STRING  ( this_node, privKeyFile);
241     NODE_WRITE_STRING  ( this_node, password);
242     NODE_WRITE_STRING  ( this_node, CaBuf);
243     NODE_WRITE_STRING  ( this_node, certBuf);
244     NODE_WRITE_STRING  ( this_node, privKeyBuf);
245     NODE_WRITE_NUM_T   ( this_node, pjsip_ssl_method, method);
246     writeIntVector     ( this_node, "ciphers", ciphers);
247     NODE_WRITE_BOOL    ( this_node, verifyServer);
248     NODE_WRITE_BOOL    ( this_node, verifyClient);
249     NODE_WRITE_BOOL    ( this_node, requireClientCert);
250     NODE_WRITE_UNSIGNED( this_node, msecTimeout);
251     NODE_WRITE_NUM_T   ( this_node, pj_qos_type, qosType);
252     writeQosParams     ( this_node, qosParams);
253     NODE_WRITE_BOOL    ( this_node, qosIgnoreError);
254 }
255 
256 ///////////////////////////////////////////////////////////////////////////////
257 
TransportConfig()258 TransportConfig::TransportConfig() : qosType(PJ_QOS_TYPE_BEST_EFFORT)
259 {
260     pjsua_transport_config tc;
261     pjsua_transport_config_default(&tc);
262     this->fromPj(tc);
263 }
264 
fromPj(const pjsua_transport_config & prm)265 void TransportConfig::fromPj(const pjsua_transport_config &prm)
266 {
267     this->port 		= prm.port;
268     this->portRange	= prm.port_range;
269     this->publicAddress = pj2Str(prm.public_addr);
270     this->boundAddress	= pj2Str(prm.bound_addr);
271     this->tlsConfig.fromPj(prm.tls_setting);
272     this->qosType	= prm.qos_type;
273     this->qosParams	= prm.qos_params;
274 }
275 
toPj() const276 pjsua_transport_config TransportConfig::toPj() const
277 {
278     pjsua_transport_config tc;
279     pjsua_transport_config_default(&tc);
280 
281     tc.port		= this->port;
282     tc.port_range	= this->portRange;
283     tc.public_addr	= str2Pj(this->publicAddress);
284     tc.bound_addr	= str2Pj(this->boundAddress);
285     tc.tls_setting	= this->tlsConfig.toPj();
286     tc.qos_type		= this->qosType;
287     tc.qos_params	= this->qosParams;
288 
289     return tc;
290 }
291 
readObject(const ContainerNode & node)292 void TransportConfig::readObject(const ContainerNode &node) PJSUA2_THROW(Error)
293 {
294     ContainerNode this_node = node.readContainer("TransportConfig");
295 
296     NODE_READ_UNSIGNED  ( this_node, port);
297     NODE_READ_UNSIGNED  ( this_node, portRange);
298     NODE_READ_STRING    ( this_node, publicAddress);
299     NODE_READ_STRING    ( this_node, boundAddress);
300     NODE_READ_NUM_T     ( this_node, pj_qos_type, qosType);
301     readQosParams       ( this_node, qosParams);
302     NODE_READ_OBJ       ( this_node, tlsConfig);
303 }
304 
writeObject(ContainerNode & node) const305 void TransportConfig::writeObject(ContainerNode &node) const
306 				  PJSUA2_THROW(Error)
307 {
308     ContainerNode this_node = node.writeNewContainer("TransportConfig");
309 
310     NODE_WRITE_UNSIGNED  ( this_node, port);
311     NODE_WRITE_UNSIGNED  ( this_node, portRange);
312     NODE_WRITE_STRING    ( this_node, publicAddress);
313     NODE_WRITE_STRING    ( this_node, boundAddress);
314     NODE_WRITE_NUM_T     ( this_node, pj_qos_type, qosType);
315     writeQosParams       ( this_node, qosParams);
316     NODE_WRITE_OBJ       ( this_node, tlsConfig);
317 }
318 
319 ///////////////////////////////////////////////////////////////////////////////
320 
TransportInfo()321 TransportInfo::TransportInfo()
322 : id(), type(PJSIP_TRANSPORT_UNSPECIFIED), flags(), usageCount()
323 {
324 }
325 
fromPj(const pjsua_transport_info & tinfo)326 void TransportInfo::fromPj(const pjsua_transport_info &tinfo)
327 {
328     this->id = tinfo.id;
329     this->type = tinfo.type;
330     this->typeName = pj2Str(tinfo.type_name);
331     this->info = pj2Str(tinfo.info);
332     this->flags = tinfo.flag;
333 
334     char straddr[PJ_INET6_ADDRSTRLEN+10];
335     pj_sockaddr_print(&tinfo.local_addr, straddr, sizeof(straddr), 3);
336     this->localAddress = straddr;
337 
338     pj_ansi_snprintf(straddr, sizeof(straddr), "%.*s:%d",
339                      (int)tinfo.local_name.host.slen,
340                      tinfo.local_name.host.ptr,
341                      tinfo.local_name.port);
342     this->localName = straddr;
343     this->usageCount = tinfo.usage_count;
344 }
345 
346 ///////////////////////////////////////////////////////////////////////////////
347 
SipRxData()348 SipRxData::SipRxData()
349 : pjRxData(NULL)
350 {
351 }
352 
fromPj(pjsip_rx_data & rdata)353 void SipRxData::fromPj(pjsip_rx_data &rdata)
354 {
355     char straddr[PJ_INET6_ADDRSTRLEN+10];
356 
357     info	= pjsip_rx_data_get_info(&rdata);
358     wholeMsg	= string(rdata.msg_info.msg_buf, rdata.msg_info.len);
359     pj_sockaddr_print(&rdata.pkt_info.src_addr, straddr, sizeof(straddr), 3);
360     srcAddress  = straddr;
361     pjRxData    = (void *)&rdata;
362 }
363 
364 ///////////////////////////////////////////////////////////////////////////////
365 
fromPj(const pjsip_media_type & prm)366 void SipMediaType::fromPj(const pjsip_media_type &prm)
367 {
368     type	= pj2Str(prm.type);
369     subType	= pj2Str(prm.subtype);
370 }
371 
toPj() const372 pjsip_media_type SipMediaType::toPj() const
373 {
374     pjsip_media_type pj_mt;
375     pj_bzero(&pj_mt, sizeof(pj_mt));
376     pj_mt.type	    = str2Pj(type);
377     pj_mt.subtype   = str2Pj(subType);
378     return pj_mt;
379 }
380 
381 ///////////////////////////////////////////////////////////////////////////////
382 
fromPj(const pjsip_hdr * hdr)383 void SipHeader::fromPj(const pjsip_hdr *hdr) PJSUA2_THROW(Error)
384 {
385     char *buf = NULL;
386     int len = 0;
387     unsigned buf_size = 256>>1;
388 
389     /* Print header to a 256 bytes buffer first.
390      * If buffer is not sufficient, try 512, 1024, soon
391      * until > PJSIP_MAX_PKT_LEN
392      */
393     do {
394         buf_size <<= 1;
395 	buf = (char*)malloc(buf_size);
396 	if (!buf)
397 	    PJSUA2_RAISE_ERROR(PJ_ENOMEM);
398 
399 	len = pjsip_hdr_print_on((void*)hdr, buf, buf_size-1);
400         if (len < 0)
401             free(buf);
402 
403     } while ((buf_size < PJSIP_MAX_PKT_LEN) && (len < 0));
404 
405     if (len < 0)
406 	PJSUA2_RAISE_ERROR(PJ_ETOOSMALL);
407 
408     buf[len] = '\0';
409 
410     char *pos = strchr(buf, ':');
411     if (!pos) {
412 	free(buf);
413 	PJSUA2_RAISE_ERROR(PJSIP_EINVALIDHDR);
414     }
415 
416     // Trim white space after header name
417     char *end_name = pos;
418     while (end_name>buf && pj_isspace(*(end_name-1))) --end_name;
419 
420     // Trim whitespaces after colon
421     char *start_val = pos+1;
422     while (*start_val && pj_isspace(*start_val)) ++start_val;
423 
424     hName = string(buf, end_name);
425     hValue = string(start_val);
426     free(buf);
427 }
428 
toPj() const429 pjsip_generic_string_hdr &SipHeader::toPj() const
430 {
431     pj_str_t hname  = str2Pj(hName);
432     pj_str_t hvalue = str2Pj(hValue);
433 
434     pjsip_generic_string_hdr_init2(&pjHdr, &hname, &hvalue);
435     return pjHdr;
436 }
437 
438 ///////////////////////////////////////////////////////////////////////////////
439 
fromPj(const pjsip_multipart_part & prm)440 void SipMultipartPart::fromPj(const pjsip_multipart_part &prm)
441 			      PJSUA2_THROW(Error)
442 {
443     headers.clear();
444     pjsip_hdr* pj_hdr = prm.hdr.next;
445     while (pj_hdr != &prm.hdr) {
446 	SipHeader sh;
447 	sh.fromPj(pj_hdr);
448 	headers.push_back(sh);
449 	pj_hdr = pj_hdr->next;
450     }
451 
452     if (!prm.body)
453 	PJSUA2_RAISE_ERROR(PJ_EINVAL);
454 
455     contentType.fromPj(prm.body->content_type);
456     body = string((char*)prm.body->data, prm.body->len);
457 }
458 
toPj() const459 pjsip_multipart_part& SipMultipartPart::toPj() const
460 {
461     pj_list_init(&pjMpp.hdr);
462     for (unsigned i = 0; i < headers.size(); i++) {
463 	pjsip_generic_string_hdr& pj_hdr = headers[i].toPj();
464 	pj_list_push_back(&pjMpp.hdr, &pj_hdr);
465     }
466 
467     pj_bzero(&pjMsgBody, sizeof(pjMsgBody));
468     pjMsgBody.content_type  = contentType.toPj();
469     pjMsgBody.print_body    = &pjsip_print_text_body;
470     pjMsgBody.clone_data    = &pjsip_clone_text_data;
471     pjMsgBody.data	    = (void*)body.c_str();
472     pjMsgBody.len	    = (unsigned)body.size();
473     pjMpp.body = &pjMsgBody;
474 
475     return pjMpp;
476 }
477 
478 ///////////////////////////////////////////////////////////////////////////////
479 
SipEvent()480 SipEvent::SipEvent()
481 : type(PJSIP_EVENT_UNKNOWN), pjEvent(NULL)
482 {
483 }
484 
fromPj(const pjsip_event & ev)485 void SipEvent::fromPj(const pjsip_event &ev)
486 {
487     type = ev.type;
488     if (type == PJSIP_EVENT_TIMER) {
489         body.timer.entry = ev.body.timer.entry;
490     } else if (type == PJSIP_EVENT_TSX_STATE) {
491         body.tsxState.prevState = (pjsip_tsx_state_e)
492         ev.body.tsx_state.prev_state;
493         body.tsxState.tsx.fromPj(*ev.body.tsx_state.tsx);
494         body.tsxState.type = ev.body.tsx_state.type;
495         if (body.tsxState.type == PJSIP_EVENT_TX_MSG) {
496             if (ev.body.tsx_state.src.tdata)
497         	body.tsxState.src.tdata.fromPj(*ev.body.tsx_state.src.tdata);
498         } else if (body.tsxState.type == PJSIP_EVENT_RX_MSG) {
499             if (ev.body.tsx_state.src.rdata)
500         	body.tsxState.src.rdata.fromPj(*ev.body.tsx_state.src.rdata);
501         } else if (body.tsxState.type == PJSIP_EVENT_TRANSPORT_ERROR) {
502             body.tsxState.src.status = ev.body.tsx_state.src.status;
503         } else if (body.tsxState.type == PJSIP_EVENT_TIMER) {
504             body.tsxState.src.timer = ev.body.tsx_state.src.timer;
505         } else if (body.tsxState.type == PJSIP_EVENT_USER) {
506             body.tsxState.src.data = ev.body.tsx_state.src.data;
507         }
508     } else if (type == PJSIP_EVENT_TX_MSG) {
509 	if (ev.body.tx_msg.tdata)
510 	    body.txMsg.tdata.fromPj(*ev.body.tx_msg.tdata);
511     } else if (type == PJSIP_EVENT_RX_MSG) {
512 	if (ev.body.rx_msg.rdata)
513 	    body.rxMsg.rdata.fromPj(*ev.body.rx_msg.rdata);
514     } else if (type == PJSIP_EVENT_TRANSPORT_ERROR) {
515 	if (ev.body.tx_error.tdata)
516 	    body.txError.tdata.fromPj(*ev.body.tx_error.tdata);
517 	if (ev.body.tx_error.tsx)
518 	    body.txError.tsx.fromPj(*ev.body.tx_error.tsx);
519     } else if (type == PJSIP_EVENT_USER) {
520         body.user.user1 = ev.body.user.user1;
521         body.user.user2 = ev.body.user.user2;
522         body.user.user3 = ev.body.user.user3;
523         body.user.user4 = ev.body.user.user4;
524     }
525     pjEvent = (void *)&ev;
526 }
527 
SipTxData()528 SipTxData::SipTxData()
529 : pjTxData(NULL)
530 {
531 }
532 
fromPj(pjsip_tx_data & tdata)533 void SipTxData::fromPj(pjsip_tx_data &tdata)
534 {
535     char straddr[PJ_INET6_ADDRSTRLEN+10];
536 
537     info	= pjsip_tx_data_get_info(&tdata);
538     pjsip_tx_data_encode(&tdata);
539     wholeMsg	= string(tdata.buf.start, tdata.buf.cur - tdata.buf.start);
540     if (pj_sockaddr_has_addr(&tdata.tp_info.dst_addr)) {
541 	pj_sockaddr_print(&tdata.tp_info.dst_addr, straddr, sizeof(straddr), 3);
542 	dstAddress  = straddr;
543     } else {
544 	dstAddress = "";
545     }
546     pjTxData    = (void *)&tdata;
547 }
548 
SipTransaction()549 SipTransaction::SipTransaction()
550 : role(PJSIP_ROLE_UAC), statusCode(PJSIP_SC_NULL),
551   state(PJSIP_TSX_STATE_NULL), pjTransaction(NULL)
552 {
553 }
554 
fromPj(pjsip_transaction & tsx)555 void SipTransaction::fromPj(pjsip_transaction &tsx)
556 {
557     this->role          = tsx.role;
558     this->method        = pj2Str(tsx.method.name);
559     this->statusCode    = tsx.status_code;
560     this->statusText    = pj2Str(tsx.status_text);
561     this->state		= tsx.state;
562     if (tsx.last_tx)
563 	this->lastTx.fromPj(*tsx.last_tx);
564     else
565 	this->lastTx.pjTxData = NULL;
566     this->pjTransaction = (void *)&tsx;
567 }
568 
TsxStateEvent()569 TsxStateEvent::TsxStateEvent()
570 : prevState(PJSIP_TSX_STATE_NULL), type(PJSIP_EVENT_UNKNOWN)
571 {
572 }
573 
isEmpty() const574 bool SipTxOption::isEmpty() const
575 {
576     return (targetUri == "" && headers.size() == 0 && contentType == "" &&
577             msgBody == "" && multipartContentType.type == "" &&
578             multipartContentType.subType == "" && multipartParts.size() == 0);
579 }
580 
fromPj(const pjsua_msg_data & prm)581 void SipTxOption::fromPj(const pjsua_msg_data &prm) PJSUA2_THROW(Error)
582 {
583     targetUri = pj2Str(prm.target_uri);
584 
585     headers.clear();
586     pjsip_hdr* pj_hdr = prm.hdr_list.next;
587     while (pj_hdr != &prm.hdr_list) {
588 	SipHeader sh;
589 	sh.fromPj(pj_hdr);
590 	headers.push_back(sh);
591 	pj_hdr = pj_hdr->next;
592     }
593 
594     contentType = pj2Str(prm.content_type);
595     msgBody = pj2Str(prm.msg_body);
596     multipartContentType.fromPj(prm.multipart_ctype);
597 
598     multipartParts.clear();
599     pjsip_multipart_part* pj_mp = prm.multipart_parts.next;
600     while (pj_mp != &prm.multipart_parts) {
601 	SipMultipartPart smp;
602 	smp.fromPj(*pj_mp);
603 	multipartParts.push_back(smp);
604 	pj_mp = pj_mp->next;
605     }
606 }
607 
toPj(pjsua_msg_data & msg_data) const608 void SipTxOption::toPj(pjsua_msg_data &msg_data) const
609 {
610     unsigned i;
611 
612     pjsua_msg_data_init(&msg_data);
613 
614     msg_data.target_uri = str2Pj(targetUri);
615 
616     pj_list_init(&msg_data.hdr_list);
617     for (i = 0; i < headers.size(); i++) {
618 	pjsip_generic_string_hdr& pj_hdr = headers[i].toPj();
619 	pj_list_push_back(&msg_data.hdr_list, &pj_hdr);
620     }
621 
622     msg_data.content_type = str2Pj(contentType);
623     msg_data.msg_body = str2Pj(msgBody);
624     msg_data.multipart_ctype = multipartContentType.toPj();
625 
626     pj_list_init(&msg_data.multipart_parts);
627     for (i = 0; i < multipartParts.size(); i++) {
628 	pjsip_multipart_part& pj_part = multipartParts[i].toPj();
629 	pj_list_push_back(&msg_data.multipart_parts, &pj_part);
630     }
631 }
632 
633 //////////////////////////////////////////////////////////////////////////////
634 
SendInstantMessageParam()635 SendInstantMessageParam::SendInstantMessageParam()
636 : contentType("text/plain"), content(""), userData(NULL)
637 {
638 }
639 
SendTypingIndicationParam()640 SendTypingIndicationParam::SendTypingIndicationParam()
641 : isTyping(false)
642 {
643 }
644