Mercurial > pidgin
annotate src/protocols/novell/nmconn.c @ 13253:87a7c3077c19
[gaim-migrate @ 15619]
More cleaning up of oscar. Renamed some functions to be more clear.
Got rid of some stuff that wasn't used. Inlined some small things
in conn.c that were only used once.
The goals of all this are
1. Non-blocking I/O for all connections
2. p2p stuff won't use the same struct as oscar connections, because
that's stupid
3. The oscar PRPL should be less scary
committer: Tailor Script <tailor@pidgin.im>
| author | Mark Doliner <mark@kingant.net> |
|---|---|
| date | Sun, 12 Feb 2006 21:27:04 +0000 |
| parents | 4b3a952b395e |
| children |
| rev | line source |
|---|---|
| 8675 | 1 /* |
| 2 * nmconn.c | |
| 3 * | |
| 8933 | 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. | |
| 8675 | 9 * |
| 8933 | 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. | |
|
8684
046dd8ef2920
[gaim-migrate @ 9437]
Christian Hammond <chipx86@chipx86.com>
parents:
8675
diff
changeset
|
14 * |
| 8933 | 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 | |
| 8675 | 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++; | |
|
8684
046dd8ef2920
[gaim-migrate @ 9437]
Christian Hammond <chipx86@chipx86.com>
parents:
8675
diff
changeset
|
96 |
| 8675 | 97 *q = hex_table[ch >> 4]; |
| 98 q++; | |
|
8684
046dd8ef2920
[gaim-migrate @ 9437]
Christian Hammond <chipx86@chipx86.com>
parents:
8675
diff
changeset
|
99 |
| 8675 | 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 } | |
|
8684
046dd8ef2920
[gaim-migrate @ 9437]
Christian Hammond <chipx86@chipx86.com>
parents:
8675
diff
changeset
|
167 |
| 8675 | 168 return str; |
| 169 } | |
| 170 | |
| 9360 | 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 | |
| 8675 | 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) | |
| 10660 | 223 return ((conn->ssl_conn->read)(conn->ssl_conn->data, buff, len)); |
| 8675 | 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 | |
| 8874 | 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 | |
| 8675 | 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; | |
| 8874 | 299 char buffer[4096]; |
| 8675 | 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: | |
|
8684
046dd8ef2920
[gaim-migrate @ 9437]
Christian Hammond <chipx86@chipx86.com>
parents:
8675
diff
changeset
|
339 |
| 8933 | 340 value = url_escape_string((char *) field->ptr_value); |
| 8675 | 341 bytes_to_send = g_snprintf(buffer, sizeof(buffer), |
| 342 "&val=%s", value); | |
| 8874 | 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 | |
| 8675 | 349 if (ret < 0) { |
| 350 rc = NMERR_TCP_WRITE; | |
| 351 } | |
|
8684
046dd8ef2920
[gaim-migrate @ 9437]
Christian Hammond <chipx86@chipx86.com>
parents:
8675
diff
changeset
|
352 |
| 8675 | 353 g_free(value); |
|
8684
046dd8ef2920
[gaim-migrate @ 9437]
Christian Hammond <chipx86@chipx86.com>
parents:
8675
diff
changeset
|
354 |
| 8675 | 355 break; |
|
8684
046dd8ef2920
[gaim-migrate @ 9437]
Christian Hammond <chipx86@chipx86.com>
parents:
8675
diff
changeset
|
356 |
| 8675 | 357 case NMFIELD_TYPE_ARRAY: |
| 358 case NMFIELD_TYPE_MV: | |
|
8684
046dd8ef2920
[gaim-migrate @ 9437]
Christian Hammond <chipx86@chipx86.com>
parents:
8675
diff
changeset
|
359 |
| 8933 | 360 val = nm_count_fields((NMField *) field->ptr_value); |
| 8675 | 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 } | |
|
8684
046dd8ef2920
[gaim-migrate @ 9437]
Christian Hammond <chipx86@chipx86.com>
parents:
8675
diff
changeset
|
367 |
| 8675 | 368 break; |
|
8684
046dd8ef2920
[gaim-migrate @ 9437]
Christian Hammond <chipx86@chipx86.com>
parents:
8675
diff
changeset
|
369 |
| 8675 | 370 default: |
|
8684
046dd8ef2920
[gaim-migrate @ 9437]
Christian Hammond <chipx86@chipx86.com>
parents:
8675
diff
changeset
|
371 |
| 8675 | 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 } | |
|
8684
046dd8ef2920
[gaim-migrate @ 9437]
Christian Hammond <chipx86@chipx86.com>
parents:
8675
diff
changeset
|
378 |
| 8675 | 379 break; |
| 380 } | |
| 381 } | |
|
8684
046dd8ef2920
[gaim-migrate @ 9437]
Christian Hammond <chipx86@chipx86.com>
parents:
8675
diff
changeset
|
382 |
| 8675 | 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 | |
| 8933 | 398 rc = nm_write_fields(conn, (NMField *) field->ptr_value); |
| 8675 | 399 |
| 400 } | |
| 401 } | |
| 402 } | |
| 403 | |
| 404 return rc; | |
| 405 } | |
| 406 | |
| 407 NMERR_T | |
| 9360 | 408 nm_send_request(NMConn *conn, char *cmd, NMField *fields, |
| 409 nm_response_cb cb, gpointer data, NMRequest **request) | |
| 8675 | 410 { |
| 411 NMERR_T rc = NM_OK; | |
| 412 char buffer[512]; | |
| 413 int bytes_to_send; | |
| 414 int ret; | |
| 9360 | 415 NMField *request_fields = NULL; |
| 9268 | 416 char *str = NULL; |
| 8675 | 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) { | |
| 9268 | 449 if (fields) |
| 9360 | 450 request_fields = nm_copy_field_array(fields); |
|
8684
046dd8ef2920
[gaim-migrate @ 9437]
Christian Hammond <chipx86@chipx86.com>
parents:
8675
diff
changeset
|
451 |
| 9268 | 452 str = g_strdup_printf("%d", ++(conn->trans_id)); |
| 9360 | 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); | |
| 8675 | 456 } |
| 457 | |
| 458 /* Send the request to the server */ | |
| 459 if (rc == NM_OK) { | |
| 9360 | 460 rc = nm_write_fields(conn, request_fields); |
| 8675 | 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 | |
| 9360 | 471 /* Create a request struct, add it to our queue, and return it */ |
| 8675 | 472 if (rc == NM_OK) { |
| 9360 | 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); | |
| 8675 | 482 } |
| 483 | |
| 9360 | 484 if (request_fields != NULL) |
| 485 nm_free_fields(&request_fields); | |
| 8675 | 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'; | |
|
8684
046dd8ef2920
[gaim-migrate @ 9437]
Christian Hammond <chipx86@chipx86.com>
parents:
8675
diff
changeset
|
519 |
| 8675 | 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 | |
| 8933 | 531 if (rc == NM_OK && rtn_code == 301) |
| 532 rc = NMERR_SERVER_REDIRECT; | |
| 8675 | 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 { | |
| 8753 | 552 if (count > 0) { |
| 8675 | 553 count--; |
| 554 } | |
| 555 | |
| 556 /* Read the field type, method, and tag */ | |
| 8933 | 557 rc = nm_read_all(conn, (char *)&type, sizeof(type)); |
| 8675 | 558 if (rc != NM_OK || type == 0) |
| 559 break; | |
| 560 | |
| 8933 | 561 rc = nm_read_all(conn, (char *)&method, sizeof(method)); |
| 8675 | 562 if (rc != NM_OK) |
| 563 break; | |
| 564 | |
| 8874 | 565 rc = nm_read_uint32(conn, &val); |
| 8675 | 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) */ | |
| 8874 | 581 rc = nm_read_uint32(conn, &val); |
| 8675 | 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 | |
| 8933 | 591 *fields = nm_field_add_pointer(*fields, tag, 0, method, |
| 592 0, sub_fields, type); | |
| 8675 | 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) */ | |
| 8874 | 599 rc = nm_read_uint32(conn, &val); |
| 8675 | 600 if (rc != NM_OK) |
| 601 break; | |
| 602 | |
| 8753 | 603 if (val >= NMFIELD_MAX_STR_LENGTH) { |
| 604 rc = NMERR_PROTOCOL; | |
| 605 break; | |
| 606 } | |
| 607 | |
| 8675 | 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; | |
| 8753 | 614 |
| 8933 | 615 *fields = nm_field_add_pointer(*fields, tag, 0, method, |
| 616 0, str, type); | |
| 8753 | 617 str = NULL; |
| 8675 | 618 } |
| 619 | |
| 620 } else { | |
| 621 | |
| 622 /* Read the numerical value */ | |
| 8874 | 623 rc = nm_read_uint32(conn, &val); |
| 8675 | 624 if (rc != NM_OK) |
| 625 break; | |
| 626 | |
| 8933 | 627 *fields = nm_field_add_number(*fields, tag, 0, method, |
| 628 0, val, type); | |
| 8675 | 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 } |
