14192
|
1 /*
|
|
2 * nmconn.c
|
|
3 *
|
|
4 * Copyright (c) 2004 Novell, Inc. All Rights Reserved.
|
|
5 *
|
|
6 * This program is free software; you can redistribute it and/or modify
|
|
7 * it under the terms of the GNU General Public License as published by
|
|
8 * the Free Software Foundation; version 2 of the License.
|
|
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 */
|
|
20
|
|
21 #include <glib.h>
|
|
22 #include <unistd.h>
|
|
23 #include <errno.h>
|
|
24 #include <string.h>
|
|
25 #include <ctype.h>
|
|
26 #include <time.h>
|
|
27 #include "nmconn.h"
|
|
28
|
|
29 #ifdef _WIN32
|
|
30 #include <windows.h>
|
|
31 #endif
|
|
32
|
|
33 #define NO_ESCAPE(ch) ((ch == 0x20) || (ch >= 0x30 && ch <= 0x39) || \
|
|
34 (ch >= 0x41 && ch <= 0x5a) || (ch >= 0x61 && ch <= 0x7a))
|
|
35
|
|
36 /* Read data from conn until the end of a line */
|
|
37 static NMERR_T
|
|
38 read_line(NMConn * conn, char *buff, int len)
|
|
39 {
|
|
40 NMERR_T rc = NM_OK;
|
|
41 int total_bytes = 0;
|
|
42
|
|
43 while ((rc == NM_OK) && (total_bytes < (len - 1))) {
|
|
44 rc = nm_read_all(conn, &buff[total_bytes], 1);
|
|
45 if (rc == NM_OK) {
|
|
46 total_bytes += 1;
|
|
47 if (buff[total_bytes - 1] == '\n') {
|
|
48 break;
|
|
49 }
|
|
50 }
|
|
51 }
|
|
52 buff[total_bytes] = '\0';
|
|
53
|
|
54 return rc;
|
|
55 }
|
|
56
|
|
57 static char *
|
|
58 url_escape_string(char *src)
|
|
59 {
|
|
60 guint32 escape = 0;
|
|
61 char *p;
|
|
62 char *q;
|
|
63 char *encoded = NULL;
|
|
64 int ch;
|
|
65
|
|
66 static const char hex_table[16] = "0123456789abcdef";
|
|
67
|
|
68 if (src == NULL) {
|
|
69 return NULL;
|
|
70 }
|
|
71
|
|
72 /* Find number of chars to escape */
|
|
73 for (p = src; *p != '\0'; p++) {
|
|
74 ch = (guchar) *p;
|
|
75 if (!NO_ESCAPE(ch)) {
|
|
76 escape++;
|
|
77 }
|
|
78 }
|
|
79
|
|
80 encoded = g_malloc((p - src) + (escape * 2) + 1);
|
|
81
|
|
82 /* Escape the string */
|
|
83 for (p = src, q = encoded; *p != '\0'; p++) {
|
|
84 ch = (guchar) * p;
|
|
85 if (NO_ESCAPE(ch)) {
|
|
86 if (ch != 0x20) {
|
|
87 *q = ch;
|
|
88 q++;
|
|
89 } else {
|
|
90 *q = '+';
|
|
91 q++;
|
|
92 }
|
|
93 } else {
|
|
94 *q = '%';
|
|
95 q++;
|
|
96
|
|
97 *q = hex_table[ch >> 4];
|
|
98 q++;
|
|
99
|
|
100 *q = hex_table[ch & 15];
|
|
101 q++;
|
|
102 }
|
|
103 }
|
|
104 *q = '\0';
|
|
105
|
|
106 return encoded;
|
|
107 }
|
|
108
|
|
109 static char *
|
|
110 encode_method(guint8 method)
|
|
111 {
|
|
112 char *str;
|
|
113
|
|
114 switch (method) {
|
|
115 case NMFIELD_METHOD_EQUAL:
|
|
116 str = "G";
|
|
117 break;
|
|
118 case NMFIELD_METHOD_UPDATE:
|
|
119 str = "F";
|
|
120 break;
|
|
121 case NMFIELD_METHOD_GTE:
|
|
122 str = "E";
|
|
123 break;
|
|
124 case NMFIELD_METHOD_LTE:
|
|
125 str = "D";
|
|
126 break;
|
|
127 case NMFIELD_METHOD_NE:
|
|
128 str = "C";
|
|
129 break;
|
|
130 case NMFIELD_METHOD_EXIST:
|
|
131 str = "B";
|
|
132 break;
|
|
133 case NMFIELD_METHOD_NOTEXIST:
|
|
134 str = "A";
|
|
135 break;
|
|
136 case NMFIELD_METHOD_SEARCH:
|
|
137 str = "9";
|
|
138 break;
|
|
139 case NMFIELD_METHOD_MATCHBEGIN:
|
|
140 str = "8";
|
|
141 break;
|
|
142 case NMFIELD_METHOD_MATCHEND:
|
|
143 str = "7";
|
|
144 break;
|
|
145 case NMFIELD_METHOD_NOT_ARRAY:
|
|
146 str = "6";
|
|
147 break;
|
|
148 case NMFIELD_METHOD_OR_ARRAY:
|
|
149 str = "5";
|
|
150 break;
|
|
151 case NMFIELD_METHOD_AND_ARRAY:
|
|
152 str = "4";
|
|
153 break;
|
|
154 case NMFIELD_METHOD_DELETE_ALL:
|
|
155 str = "3";
|
|
156 break;
|
|
157 case NMFIELD_METHOD_DELETE:
|
|
158 str = "2";
|
|
159 break;
|
|
160 case NMFIELD_METHOD_ADD:
|
|
161 str = "1";
|
|
162 break;
|
|
163 default: /* NMFIELD_METHOD_VALID */
|
|
164 str = "0";
|
|
165 break;
|
|
166 }
|
|
167
|
|
168 return str;
|
|
169 }
|
|
170
|
|
171 NMConn *
|
|
172 nm_create_conn(const char *addr, int port)
|
|
173 {
|
|
174 NMConn *conn = g_new0(NMConn, 1);
|
|
175 conn->addr = g_strdup(addr);
|
|
176 conn->port = port;
|
|
177 return conn;
|
|
178 }
|
|
179
|
|
180 void nm_release_conn(NMConn *conn)
|
|
181 {
|
|
182 if (conn) {
|
|
183 GSList *node;
|
|
184 for (node = conn->requests; node; node = node->next) {
|
|
185 if (node->data)
|
|
186 nm_release_request(node->data);
|
|
187 }
|
|
188 g_slist_free(conn->requests);
|
|
189 conn->requests = NULL;
|
|
190 if (conn->ssl_conn) {
|
|
191 g_free(conn->ssl_conn);
|
|
192 conn->ssl_conn = NULL;
|
|
193 }
|
|
194 g_free(conn->addr);
|
|
195 conn->addr = NULL;
|
|
196 g_free(conn);
|
|
197 }
|
|
198 }
|
|
199
|
|
200 int
|
|
201 nm_tcp_write(NMConn * conn, const void *buff, int len)
|
|
202 {
|
|
203 if (conn == NULL || buff == NULL)
|
|
204 return -1;
|
|
205
|
|
206 if (!conn->use_ssl)
|
|
207 return (write(conn->fd, buff, len));
|
|
208 else if (conn->ssl_conn && conn->ssl_conn->write)
|
|
209 return (conn->ssl_conn->write(conn->ssl_conn->data, buff, len));
|
|
210 else
|
|
211 return -1;
|
|
212 }
|
|
213
|
|
214 int
|
|
215 nm_tcp_read(NMConn * conn, void *buff, int len)
|
|
216 {
|
|
217 if (conn == NULL || buff == NULL)
|
|
218 return -1;
|
|
219
|
|
220 if (!conn->use_ssl)
|
|
221 return (read(conn->fd, buff, len));
|
|
222 else if (conn->ssl_conn && conn->ssl_conn->read)
|
|
223 return ((conn->ssl_conn->read)(conn->ssl_conn->data, buff, len));
|
|
224 else
|
|
225 return -1;
|
|
226 }
|
|
227
|
|
228 NMERR_T
|
|
229 nm_read_all(NMConn * conn, char *buff, int len)
|
|
230 {
|
|
231 NMERR_T rc = NM_OK;
|
|
232 int bytes_left = len;
|
|
233 int bytes_read;
|
|
234 int total_bytes = 0;
|
|
235 int retry = 10;
|
|
236
|
|
237 if (conn == NULL || buff == NULL)
|
|
238 return NMERR_BAD_PARM;
|
|
239
|
|
240 /* Keep reading until buffer is full */
|
|
241 while (bytes_left) {
|
|
242 bytes_read = nm_tcp_read(conn, &buff[total_bytes], bytes_left);
|
|
243 if (bytes_read > 0) {
|
|
244 bytes_left -= bytes_read;
|
|
245 total_bytes += bytes_read;
|
|
246 } else {
|
|
247 if (errno == EAGAIN) {
|
|
248 if (--retry == 0) {
|
|
249 rc = NMERR_TCP_READ;
|
|
250 break;
|
|
251 }
|
|
252 #ifdef _WIN32
|
|
253 Sleep(1000);
|
|
254 #else
|
|
255 usleep(1000);
|
|
256 #endif
|
|
257 } else {
|
|
258 rc = NMERR_TCP_READ;
|
|
259 break;
|
|
260 }
|
|
261 }
|
|
262 }
|
|
263 return rc;
|
|
264 }
|
|
265
|
|
266 NMERR_T
|
|
267 nm_read_uint32(NMConn *conn, guint32 *val)
|
|
268 {
|
|
269 NMERR_T rc = NM_OK;
|
|
270
|
|
271 rc = nm_read_all(conn, (char *)val, sizeof(*val));
|
|
272 if (rc == NM_OK) {
|
|
273 *val = GUINT32_FROM_LE(*val);
|
|
274 }
|
|
275
|
|
276 return rc;
|
|
277 }
|
|
278
|
|
279 NMERR_T
|
|
280 nm_read_uint16(NMConn *conn, guint16 *val)
|
|
281 {
|
|
282 NMERR_T rc = NM_OK;
|
|
283
|
|
284 rc = nm_read_all(conn, (char *)val, sizeof(*val));
|
|
285 if (rc == NM_OK) {
|
|
286 *val = GUINT16_FROM_LE(*val);
|
|
287 }
|
|
288
|
|
289 return rc;
|
|
290 }
|
|
291
|
|
292 NMERR_T
|
|
293 nm_write_fields(NMConn * conn, NMField * fields)
|
|
294 {
|
|
295 NMERR_T rc = NM_OK;
|
|
296 NMField *field;
|
|
297 char *value = NULL;
|
|
298 char *method = NULL;
|
|
299 char buffer[4096];
|
|
300 int ret;
|
|
301 int bytes_to_send;
|
|
302 int val = 0;
|
|
303
|
|
304 if (conn == NULL || fields == NULL) {
|
|
305 return NMERR_BAD_PARM;
|
|
306 }
|
|
307
|
|
308 /* Format each field as valid "post" data and write it out */
|
|
309 for (field = fields; (rc == NM_OK) && (field->tag); field++) {
|
|
310
|
|
311 /* We don't currently handle binary types */
|
|
312 if (field->method == NMFIELD_METHOD_IGNORE ||
|
|
313 field->type == NMFIELD_TYPE_BINARY) {
|
|
314 continue;
|
|
315 }
|
|
316
|
|
317 /* Write the field tag */
|
|
318 bytes_to_send = g_snprintf(buffer, sizeof(buffer), "&tag=%s", field->tag);
|
|
319 ret = nm_tcp_write(conn, buffer, bytes_to_send);
|
|
320 if (ret < 0) {
|
|
321 rc = NMERR_TCP_WRITE;
|
|
322 }
|
|
323
|
|
324 /* Write the field method */
|
|
325 if (rc == NM_OK) {
|
|
326 method = encode_method(field->method);
|
|
327 bytes_to_send = g_snprintf(buffer, sizeof(buffer), "&cmd=%s", method);
|
|
328 ret = nm_tcp_write(conn, buffer, bytes_to_send);
|
|
329 if (ret < 0) {
|
|
330 rc = NMERR_TCP_WRITE;
|
|
331 }
|
|
332 }
|
|
333
|
|
334 /* Write the field value */
|
|
335 if (rc == NM_OK) {
|
|
336 switch (field->type) {
|
|
337 case NMFIELD_TYPE_UTF8:
|
|
338 case NMFIELD_TYPE_DN:
|
|
339
|
|
340 value = url_escape_string((char *) field->ptr_value);
|
|
341 bytes_to_send = g_snprintf(buffer, sizeof(buffer),
|
|
342 "&val=%s", value);
|
|
343 if (bytes_to_send > (int)sizeof(buffer)) {
|
|
344 ret = nm_tcp_write(conn, buffer, sizeof(buffer));
|
|
345 } else {
|
|
346 ret = nm_tcp_write(conn, buffer, bytes_to_send);
|
|
347 }
|
|
348
|
|
349 if (ret < 0) {
|
|
350 rc = NMERR_TCP_WRITE;
|
|
351 }
|
|
352
|
|
353 g_free(value);
|
|
354
|
|
355 break;
|
|
356
|
|
357 case NMFIELD_TYPE_ARRAY:
|
|
358 case NMFIELD_TYPE_MV:
|
|
359
|
|
360 val = nm_count_fields((NMField *) field->ptr_value);
|
|
361 bytes_to_send = g_snprintf(buffer, sizeof(buffer),
|
|
362 "&val=%u", val);
|
|
363 ret = nm_tcp_write(conn, buffer, bytes_to_send);
|
|
364 if (ret < 0) {
|
|
365 rc = NMERR_TCP_WRITE;
|
|
366 }
|
|
367
|
|
368 break;
|
|
369
|
|
370 default:
|
|
371
|
|
372 bytes_to_send = g_snprintf(buffer, sizeof(buffer),
|
|
373 "&val=%u", field->value);
|
|
374 ret = nm_tcp_write(conn, buffer, bytes_to_send);
|
|
375 if (ret < 0) {
|
|
376 rc = NMERR_TCP_WRITE;
|
|
377 }
|
|
378
|
|
379 break;
|
|
380 }
|
|
381 }
|
|
382
|
|
383 /* Write the field type */
|
|
384 if (rc == NM_OK) {
|
|
385 bytes_to_send = g_snprintf(buffer, sizeof(buffer),
|
|
386 "&type=%u", field->type);
|
|
387 ret = nm_tcp_write(conn, buffer, bytes_to_send);
|
|
388 if (ret < 0) {
|
|
389 rc = NMERR_TCP_WRITE;
|
|
390 }
|
|
391 }
|
|
392
|
|
393 /* If the field is a sub array then post its fields */
|
|
394 if (rc == NM_OK && val > 0) {
|
|
395 if (field->type == NMFIELD_TYPE_ARRAY ||
|
|
396 field->type == NMFIELD_TYPE_MV) {
|
|
397
|
|
398 rc = nm_write_fields(conn, (NMField *) field->ptr_value);
|
|
399
|
|
400 }
|
|
401 }
|
|
402 }
|
|
403
|
|
404 return rc;
|
|
405 }
|
|
406
|
|
407 NMERR_T
|
|
408 nm_send_request(NMConn *conn, char *cmd, NMField *fields,
|
|
409 nm_response_cb cb, gpointer data, NMRequest **request)
|
|
410 {
|
|
411 NMERR_T rc = NM_OK;
|
|
412 char buffer[512];
|
|
413 int bytes_to_send;
|
|
414 int ret;
|
|
415 NMField *request_fields = NULL;
|
|
416 char *str = NULL;
|
|
417
|
|
418 if (conn == NULL || cmd == NULL)
|
|
419 return NMERR_BAD_PARM;
|
|
420
|
|
421 /* Write the post */
|
|
422 bytes_to_send = g_snprintf(buffer, sizeof(buffer),
|
|
423 "POST /%s HTTP/1.0\r\n", cmd);
|
|
424 ret = nm_tcp_write(conn, buffer, bytes_to_send);
|
|
425 if (ret < 0) {
|
|
426 rc = NMERR_TCP_WRITE;
|
|
427 }
|
|
428
|
|
429 /* Write headers */
|
|
430 if (rc == NM_OK) {
|
|
431 if (strcmp("login", cmd) == 0) {
|
|
432 bytes_to_send = g_snprintf(buffer, sizeof(buffer),
|
|
433 "Host: %s:%d\r\n\r\n", conn->addr, conn->port);
|
|
434 ret = nm_tcp_write(conn, buffer, bytes_to_send);
|
|
435 if (ret < 0) {
|
|
436 rc = NMERR_TCP_WRITE;
|
|
437 }
|
|
438 } else {
|
|
439 bytes_to_send = g_snprintf(buffer, sizeof(buffer), "\r\n");
|
|
440 ret = nm_tcp_write(conn, buffer, bytes_to_send);
|
|
441 if (ret < 0) {
|
|
442 rc = NMERR_TCP_WRITE;
|
|
443 }
|
|
444 }
|
|
445 }
|
|
446
|
|
447 /* Add the transaction id to the request fields */
|
|
448 if (rc == NM_OK) {
|
|
449 if (fields)
|
|
450 request_fields = nm_copy_field_array(fields);
|
|
451
|
|
452 str = g_strdup_printf("%d", ++(conn->trans_id));
|
|
453 request_fields = nm_field_add_pointer(request_fields, NM_A_SZ_TRANSACTION_ID, 0,
|
|
454 NMFIELD_METHOD_VALID, 0,
|
|
455 str, NMFIELD_TYPE_UTF8);
|
|
456 }
|
|
457
|
|
458 /* Send the request to the server */
|
|
459 if (rc == NM_OK) {
|
|
460 rc = nm_write_fields(conn, request_fields);
|
|
461 }
|
|
462
|
|
463 /* Write the CRLF to terminate the data */
|
|
464 if (rc == NM_OK) {
|
|
465 ret = nm_tcp_write(conn, "\r\n", strlen("\r\n"));
|
|
466 if (ret < 0) {
|
|
467 rc = NMERR_TCP_WRITE;
|
|
468 }
|
|
469 }
|
|
470
|
|
471 /* Create a request struct, add it to our queue, and return it */
|
|
472 if (rc == NM_OK) {
|
|
473 NMRequest *new_request = nm_create_request(cmd, conn->trans_id,
|
|
474 time(0), cb, NULL, data);
|
|
475 nm_conn_add_request_item(conn, new_request);
|
|
476
|
|
477 /* Set the out param if it was sent in, otherwise release the request */
|
|
478 if (request)
|
|
479 *request = new_request;
|
|
480 else
|
|
481 nm_release_request(new_request);
|
|
482 }
|
|
483
|
|
484 if (request_fields != NULL)
|
|
485 nm_free_fields(&request_fields);
|
|
486
|
|
487 return rc;
|
|
488 }
|
|
489
|
|
490 NMERR_T
|
|
491 nm_read_header(NMConn * conn)
|
|
492 {
|
|
493 NMERR_T rc = NM_OK;
|
|
494 char buffer[512];
|
|
495 char *ptr = NULL;
|
|
496 int i;
|
|
497 char rtn_buf[8];
|
|
498 int rtn_code = 0;
|
|
499
|
|
500 if (conn == NULL)
|
|
501 return NMERR_BAD_PARM;
|
|
502
|
|
503 *buffer = '\0';
|
|
504 rc = read_line(conn, buffer, sizeof(buffer));
|
|
505 if (rc == NM_OK) {
|
|
506
|
|
507 /* Find the return code */
|
|
508 ptr = strchr(buffer, ' ');
|
|
509 if (ptr != NULL) {
|
|
510 ptr++;
|
|
511
|
|
512 i = 0;
|
|
513 while (isdigit(*ptr) && (i < 3)) {
|
|
514 rtn_buf[i] = *ptr;
|
|
515 i++;
|
|
516 ptr++;
|
|
517 }
|
|
518 rtn_buf[i] = '\0';
|
|
519
|
|
520 if (i > 0)
|
|
521 rtn_code = atoi(rtn_buf);
|
|
522 }
|
|
523 }
|
|
524
|
|
525 /* Finish reading header, in the future we might want to do more processing here */
|
|
526 /* TODO: handle more general redirects in the future */
|
|
527 while ((rc == NM_OK) && (strcmp(buffer, "\r\n") != 0)) {
|
|
528 rc = read_line(conn, buffer, sizeof(buffer));
|
|
529 }
|
|
530
|
|
531 if (rc == NM_OK && rtn_code == 301)
|
|
532 rc = NMERR_SERVER_REDIRECT;
|
|
533
|
|
534 return rc;
|
|
535 }
|
|
536
|
|
537 NMERR_T
|
|
538 nm_read_fields(NMConn * conn, int count, NMField ** fields)
|
|
539 {
|
|
540 NMERR_T rc = NM_OK;
|
|
541 guint8 type;
|
|
542 guint8 method;
|
|
543 guint32 val;
|
|
544 char tag[64];
|
|
545 NMField *sub_fields = NULL;
|
|
546 char *str = NULL;
|
|
547
|
|
548 if (conn == NULL || fields == NULL)
|
|
549 return NMERR_BAD_PARM;
|
|
550
|
|
551 do {
|
|
552 if (count > 0) {
|
|
553 count--;
|
|
554 }
|
|
555
|
|
556 /* Read the field type, method, and tag */
|
|
557 rc = nm_read_all(conn, (char *)&type, sizeof(type));
|
|
558 if (rc != NM_OK || type == 0)
|
|
559 break;
|
|
560
|
|
561 rc = nm_read_all(conn, (char *)&method, sizeof(method));
|
|
562 if (rc != NM_OK)
|
|
563 break;
|
|
564
|
|
565 rc = nm_read_uint32(conn, &val);
|
|
566 if (rc != NM_OK)
|
|
567 break;
|
|
568
|
|
569 if (val > sizeof(tag)) {
|
|
570 rc = NMERR_PROTOCOL;
|
|
571 break;
|
|
572 }
|
|
573
|
|
574 rc = nm_read_all(conn, tag, val);
|
|
575 if (rc != NM_OK)
|
|
576 break;
|
|
577
|
|
578 if (type == NMFIELD_TYPE_MV || type == NMFIELD_TYPE_ARRAY) {
|
|
579
|
|
580 /* Read the subarray (first read the number of items in the array) */
|
|
581 rc = nm_read_uint32(conn, &val);
|
|
582 if (rc != NM_OK)
|
|
583 break;
|
|
584
|
|
585 if (val > 0) {
|
|
586 rc = nm_read_fields(conn, val, &sub_fields);
|
|
587 if (rc != NM_OK)
|
|
588 break;
|
|
589 }
|
|
590
|
|
591 *fields = nm_field_add_pointer(*fields, tag, 0, method,
|
|
592 0, sub_fields, type);
|
|
593
|
|
594 sub_fields = NULL;
|
|
595
|
|
596 } else if (type == NMFIELD_TYPE_UTF8 || type == NMFIELD_TYPE_DN) {
|
|
597
|
|
598 /* Read the string (first read the length) */
|
|
599 rc = nm_read_uint32(conn, &val);
|
|
600 if (rc != NM_OK)
|
|
601 break;
|
|
602
|
|
603 if (val >= NMFIELD_MAX_STR_LENGTH) {
|
|
604 rc = NMERR_PROTOCOL;
|
|
605 break;
|
|
606 }
|
|
607
|
|
608 if (val > 0) {
|
|
609 str = g_new0(char, val + 1);
|
|
610
|
|
611 rc = nm_read_all(conn, str, val);
|
|
612 if (rc != NM_OK)
|
|
613 break;
|
|
614
|
|
615 *fields = nm_field_add_pointer(*fields, tag, 0, method,
|
|
616 0, str, type);
|
|
617 str = NULL;
|
|
618 }
|
|
619
|
|
620 } else {
|
|
621
|
|
622 /* Read the numerical value */
|
|
623 rc = nm_read_uint32(conn, &val);
|
|
624 if (rc != NM_OK)
|
|
625 break;
|
|
626
|
|
627 *fields = nm_field_add_number(*fields, tag, 0, method,
|
|
628 0, val, type);
|
|
629 }
|
|
630
|
|
631 } while ((type != 0) && (count != 0));
|
|
632
|
|
633
|
|
634 if (str != NULL) {
|
|
635 g_free(str);
|
|
636 }
|
|
637
|
|
638 if (sub_fields != NULL) {
|
|
639 nm_free_fields(&sub_fields);
|
|
640 }
|
|
641
|
|
642 return rc;
|
|
643 }
|
|
644
|
|
645 void
|
|
646 nm_conn_add_request_item(NMConn * conn, NMRequest * request)
|
|
647 {
|
|
648 if (conn == NULL || request == NULL)
|
|
649 return;
|
|
650
|
|
651 nm_request_add_ref(request);
|
|
652 conn->requests = g_slist_append(conn->requests, request);
|
|
653 }
|
|
654
|
|
655 void
|
|
656 nm_conn_remove_request_item(NMConn * conn, NMRequest * request)
|
|
657 {
|
|
658 if (conn == NULL || request == NULL)
|
|
659 return;
|
|
660
|
|
661 conn->requests = g_slist_remove(conn->requests, request);
|
|
662 nm_release_request(request);
|
|
663 }
|
|
664
|
|
665 NMRequest *
|
|
666 nm_conn_find_request(NMConn * conn, int trans_id)
|
|
667 {
|
|
668 NMRequest *req = NULL;
|
|
669 GSList *itr = NULL;
|
|
670
|
|
671 if (conn == NULL)
|
|
672 return NULL;
|
|
673
|
|
674 itr = conn->requests;
|
|
675 while (itr) {
|
|
676 req = (NMRequest *) itr->data;
|
|
677 if (req != NULL && nm_request_get_trans_id(req) == trans_id) {
|
|
678 return req;
|
|
679 }
|
|
680 itr = g_slist_next(itr);
|
|
681 }
|
|
682 return NULL;
|
|
683 }
|
|
684
|
|
685 const char *
|
|
686 nm_conn_get_addr(NMConn * conn)
|
|
687 {
|
|
688 if (conn == NULL)
|
|
689 return NULL;
|
|
690 else
|
|
691 return conn->addr;
|
|
692 }
|
|
693
|
|
694 int
|
|
695 nm_conn_get_port(NMConn * conn)
|
|
696 {
|
|
697 if (conn == NULL)
|
|
698 return -1;
|
|
699 else
|
|
700 return conn->port;
|
|
701 }
|