00001 /*------------------------------------------------------------------------- 00002 * 00003 * pqformat.c 00004 * Routines for formatting and parsing frontend/backend messages 00005 * 00006 * Outgoing messages are built up in a StringInfo buffer (which is expansible) 00007 * and then sent in a single call to pq_putmessage. This module provides data 00008 * formatting/conversion routines that are needed to produce valid messages. 00009 * Note in particular the distinction between "raw data" and "text"; raw data 00010 * is message protocol characters and binary values that are not subject to 00011 * character set conversion, while text is converted by character encoding 00012 * rules. 00013 * 00014 * Incoming messages are similarly read into a StringInfo buffer, via 00015 * pq_getmessage, and then parsed and converted from that using the routines 00016 * in this module. 00017 * 00018 * These same routines support reading and writing of external binary formats 00019 * (typsend/typreceive routines). The conversion routines for individual 00020 * data types are exactly the same, only initialization and completion 00021 * are different. 00022 * 00023 * 00024 * Portions Copyright (c) 1996-2013, PostgreSQL Global Development Group 00025 * Portions Copyright (c) 1994, Regents of the University of California 00026 * 00027 * src/backend/libpq/pqformat.c 00028 * 00029 *------------------------------------------------------------------------- 00030 */ 00031 /* 00032 * INTERFACE ROUTINES 00033 * Message assembly and output: 00034 * pq_beginmessage - initialize StringInfo buffer 00035 * pq_sendbyte - append a raw byte to a StringInfo buffer 00036 * pq_sendint - append a binary integer to a StringInfo buffer 00037 * pq_sendint64 - append a binary 8-byte int to a StringInfo buffer 00038 * pq_sendfloat4 - append a float4 to a StringInfo buffer 00039 * pq_sendfloat8 - append a float8 to a StringInfo buffer 00040 * pq_sendbytes - append raw data to a StringInfo buffer 00041 * pq_sendcountedtext - append a counted text string (with character set conversion) 00042 * pq_sendtext - append a text string (with conversion) 00043 * pq_sendstring - append a null-terminated text string (with conversion) 00044 * pq_send_ascii_string - append a null-terminated text string (without conversion) 00045 * pq_endmessage - send the completed message to the frontend 00046 * Note: it is also possible to append data to the StringInfo buffer using 00047 * the regular StringInfo routines, but this is discouraged since required 00048 * character set conversion may not occur. 00049 * 00050 * typsend support (construct a bytea value containing external binary data): 00051 * pq_begintypsend - initialize StringInfo buffer 00052 * pq_endtypsend - return the completed string as a "bytea*" 00053 * 00054 * Special-case message output: 00055 * pq_puttextmessage - generate a character set-converted message in one step 00056 * pq_putemptymessage - convenience routine for message with empty body 00057 * 00058 * Message parsing after input: 00059 * pq_getmsgbyte - get a raw byte from a message buffer 00060 * pq_getmsgint - get a binary integer from a message buffer 00061 * pq_getmsgint64 - get a binary 8-byte int from a message buffer 00062 * pq_getmsgfloat4 - get a float4 from a message buffer 00063 * pq_getmsgfloat8 - get a float8 from a message buffer 00064 * pq_getmsgbytes - get raw data from a message buffer 00065 * pq_copymsgbytes - copy raw data from a message buffer 00066 * pq_getmsgtext - get a counted text string (with conversion) 00067 * pq_getmsgstring - get a null-terminated text string (with conversion) 00068 * pq_getmsgend - verify message fully consumed 00069 */ 00070 00071 #include "postgres.h" 00072 00073 #include <sys/param.h> 00074 #include <netinet/in.h> 00075 #include <arpa/inet.h> 00076 00077 #include "libpq/libpq.h" 00078 #include "libpq/pqformat.h" 00079 #include "mb/pg_wchar.h" 00080 00081 00082 /* -------------------------------- 00083 * pq_beginmessage - initialize for sending a message 00084 * -------------------------------- 00085 */ 00086 void 00087 pq_beginmessage(StringInfo buf, char msgtype) 00088 { 00089 initStringInfo(buf); 00090 00091 /* 00092 * We stash the message type into the buffer's cursor field, expecting 00093 * that the pq_sendXXX routines won't touch it. We could alternatively 00094 * make it the first byte of the buffer contents, but this seems easier. 00095 */ 00096 buf->cursor = msgtype; 00097 } 00098 00099 /* -------------------------------- 00100 * pq_sendbyte - append a raw byte to a StringInfo buffer 00101 * -------------------------------- 00102 */ 00103 void 00104 pq_sendbyte(StringInfo buf, int byt) 00105 { 00106 appendStringInfoCharMacro(buf, byt); 00107 } 00108 00109 /* -------------------------------- 00110 * pq_sendbytes - append raw data to a StringInfo buffer 00111 * -------------------------------- 00112 */ 00113 void 00114 pq_sendbytes(StringInfo buf, const char *data, int datalen) 00115 { 00116 appendBinaryStringInfo(buf, data, datalen); 00117 } 00118 00119 /* -------------------------------- 00120 * pq_sendcountedtext - append a counted text string (with character set conversion) 00121 * 00122 * The data sent to the frontend by this routine is a 4-byte count field 00123 * followed by the string. The count includes itself or not, as per the 00124 * countincludesself flag (pre-3.0 protocol requires it to include itself). 00125 * The passed text string need not be null-terminated, and the data sent 00126 * to the frontend isn't either. 00127 * -------------------------------- 00128 */ 00129 void 00130 pq_sendcountedtext(StringInfo buf, const char *str, int slen, 00131 bool countincludesself) 00132 { 00133 int extra = countincludesself ? 4 : 0; 00134 char *p; 00135 00136 p = pg_server_to_client(str, slen); 00137 if (p != str) /* actual conversion has been done? */ 00138 { 00139 slen = strlen(p); 00140 pq_sendint(buf, slen + extra, 4); 00141 appendBinaryStringInfo(buf, p, slen); 00142 pfree(p); 00143 } 00144 else 00145 { 00146 pq_sendint(buf, slen + extra, 4); 00147 appendBinaryStringInfo(buf, str, slen); 00148 } 00149 } 00150 00151 /* -------------------------------- 00152 * pq_sendtext - append a text string (with conversion) 00153 * 00154 * The passed text string need not be null-terminated, and the data sent 00155 * to the frontend isn't either. Note that this is not actually useful 00156 * for direct frontend transmissions, since there'd be no way for the 00157 * frontend to determine the string length. But it is useful for binary 00158 * format conversions. 00159 * -------------------------------- 00160 */ 00161 void 00162 pq_sendtext(StringInfo buf, const char *str, int slen) 00163 { 00164 char *p; 00165 00166 p = pg_server_to_client(str, slen); 00167 if (p != str) /* actual conversion has been done? */ 00168 { 00169 slen = strlen(p); 00170 appendBinaryStringInfo(buf, p, slen); 00171 pfree(p); 00172 } 00173 else 00174 appendBinaryStringInfo(buf, str, slen); 00175 } 00176 00177 /* -------------------------------- 00178 * pq_sendstring - append a null-terminated text string (with conversion) 00179 * 00180 * NB: passed text string must be null-terminated, and so is the data 00181 * sent to the frontend. 00182 * -------------------------------- 00183 */ 00184 void 00185 pq_sendstring(StringInfo buf, const char *str) 00186 { 00187 int slen = strlen(str); 00188 char *p; 00189 00190 p = pg_server_to_client(str, slen); 00191 if (p != str) /* actual conversion has been done? */ 00192 { 00193 slen = strlen(p); 00194 appendBinaryStringInfo(buf, p, slen + 1); 00195 pfree(p); 00196 } 00197 else 00198 appendBinaryStringInfo(buf, str, slen + 1); 00199 } 00200 00201 /* -------------------------------- 00202 * pq_send_ascii_string - append a null-terminated text string (without conversion) 00203 * 00204 * This function intentionally bypasses encoding conversion, instead just 00205 * silently replacing any non-7-bit-ASCII characters with question marks. 00206 * It is used only when we are having trouble sending an error message to 00207 * the client with normal localization and encoding conversion. The caller 00208 * should already have taken measures to ensure the string is just ASCII; 00209 * the extra work here is just to make certain we don't send a badly encoded 00210 * string to the client (which might or might not be robust about that). 00211 * 00212 * NB: passed text string must be null-terminated, and so is the data 00213 * sent to the frontend. 00214 * -------------------------------- 00215 */ 00216 void 00217 pq_send_ascii_string(StringInfo buf, const char *str) 00218 { 00219 while (*str) 00220 { 00221 char ch = *str++; 00222 00223 if (IS_HIGHBIT_SET(ch)) 00224 ch = '?'; 00225 appendStringInfoCharMacro(buf, ch); 00226 } 00227 appendStringInfoChar(buf, '\0'); 00228 } 00229 00230 /* -------------------------------- 00231 * pq_sendint - append a binary integer to a StringInfo buffer 00232 * -------------------------------- 00233 */ 00234 void 00235 pq_sendint(StringInfo buf, int i, int b) 00236 { 00237 unsigned char n8; 00238 uint16 n16; 00239 uint32 n32; 00240 00241 switch (b) 00242 { 00243 case 1: 00244 n8 = (unsigned char) i; 00245 appendBinaryStringInfo(buf, (char *) &n8, 1); 00246 break; 00247 case 2: 00248 n16 = htons((uint16) i); 00249 appendBinaryStringInfo(buf, (char *) &n16, 2); 00250 break; 00251 case 4: 00252 n32 = htonl((uint32) i); 00253 appendBinaryStringInfo(buf, (char *) &n32, 4); 00254 break; 00255 default: 00256 elog(ERROR, "unsupported integer size %d", b); 00257 break; 00258 } 00259 } 00260 00261 /* -------------------------------- 00262 * pq_sendint64 - append a binary 8-byte int to a StringInfo buffer 00263 * 00264 * It is tempting to merge this with pq_sendint, but we'd have to make the 00265 * argument int64 for all data widths --- that could be a big performance 00266 * hit on machines where int64 isn't efficient. 00267 * -------------------------------- 00268 */ 00269 void 00270 pq_sendint64(StringInfo buf, int64 i) 00271 { 00272 uint32 n32; 00273 00274 /* High order half first, since we're doing MSB-first */ 00275 n32 = (uint32) (i >> 32); 00276 n32 = htonl(n32); 00277 appendBinaryStringInfo(buf, (char *) &n32, 4); 00278 00279 /* Now the low order half */ 00280 n32 = (uint32) i; 00281 n32 = htonl(n32); 00282 appendBinaryStringInfo(buf, (char *) &n32, 4); 00283 } 00284 00285 /* -------------------------------- 00286 * pq_sendfloat4 - append a float4 to a StringInfo buffer 00287 * 00288 * The point of this routine is to localize knowledge of the external binary 00289 * representation of float4, which is a component of several datatypes. 00290 * 00291 * We currently assume that float4 should be byte-swapped in the same way 00292 * as int4. This rule is not perfect but it gives us portability across 00293 * most IEEE-float-using architectures. 00294 * -------------------------------- 00295 */ 00296 void 00297 pq_sendfloat4(StringInfo buf, float4 f) 00298 { 00299 union 00300 { 00301 float4 f; 00302 uint32 i; 00303 } swap; 00304 00305 swap.f = f; 00306 swap.i = htonl(swap.i); 00307 00308 appendBinaryStringInfo(buf, (char *) &swap.i, 4); 00309 } 00310 00311 /* -------------------------------- 00312 * pq_sendfloat8 - append a float8 to a StringInfo buffer 00313 * 00314 * The point of this routine is to localize knowledge of the external binary 00315 * representation of float8, which is a component of several datatypes. 00316 * 00317 * We currently assume that float8 should be byte-swapped in the same way 00318 * as int8. This rule is not perfect but it gives us portability across 00319 * most IEEE-float-using architectures. 00320 * -------------------------------- 00321 */ 00322 void 00323 pq_sendfloat8(StringInfo buf, float8 f) 00324 { 00325 union 00326 { 00327 float8 f; 00328 int64 i; 00329 } swap; 00330 00331 swap.f = f; 00332 pq_sendint64(buf, swap.i); 00333 } 00334 00335 /* -------------------------------- 00336 * pq_endmessage - send the completed message to the frontend 00337 * 00338 * The data buffer is pfree()d, but if the StringInfo was allocated with 00339 * makeStringInfo then the caller must still pfree it. 00340 * -------------------------------- 00341 */ 00342 void 00343 pq_endmessage(StringInfo buf) 00344 { 00345 /* msgtype was saved in cursor field */ 00346 (void) pq_putmessage(buf->cursor, buf->data, buf->len); 00347 /* no need to complain about any failure, since pqcomm.c already did */ 00348 pfree(buf->data); 00349 buf->data = NULL; 00350 } 00351 00352 00353 /* -------------------------------- 00354 * pq_begintypsend - initialize for constructing a bytea result 00355 * -------------------------------- 00356 */ 00357 void 00358 pq_begintypsend(StringInfo buf) 00359 { 00360 initStringInfo(buf); 00361 /* Reserve four bytes for the bytea length word */ 00362 appendStringInfoCharMacro(buf, '\0'); 00363 appendStringInfoCharMacro(buf, '\0'); 00364 appendStringInfoCharMacro(buf, '\0'); 00365 appendStringInfoCharMacro(buf, '\0'); 00366 } 00367 00368 /* -------------------------------- 00369 * pq_endtypsend - finish constructing a bytea result 00370 * 00371 * The data buffer is returned as the palloc'd bytea value. (We expect 00372 * that it will be suitably aligned for this because it has been palloc'd.) 00373 * We assume the StringInfoData is just a local variable in the caller and 00374 * need not be pfree'd. 00375 * -------------------------------- 00376 */ 00377 bytea * 00378 pq_endtypsend(StringInfo buf) 00379 { 00380 bytea *result = (bytea *) buf->data; 00381 00382 /* Insert correct length into bytea length word */ 00383 Assert(buf->len >= VARHDRSZ); 00384 SET_VARSIZE(result, buf->len); 00385 00386 return result; 00387 } 00388 00389 00390 /* -------------------------------- 00391 * pq_puttextmessage - generate a character set-converted message in one step 00392 * 00393 * This is the same as the pqcomm.c routine pq_putmessage, except that 00394 * the message body is a null-terminated string to which encoding 00395 * conversion applies. 00396 * -------------------------------- 00397 */ 00398 void 00399 pq_puttextmessage(char msgtype, const char *str) 00400 { 00401 int slen = strlen(str); 00402 char *p; 00403 00404 p = pg_server_to_client(str, slen); 00405 if (p != str) /* actual conversion has been done? */ 00406 { 00407 (void) pq_putmessage(msgtype, p, strlen(p) + 1); 00408 pfree(p); 00409 return; 00410 } 00411 (void) pq_putmessage(msgtype, str, slen + 1); 00412 } 00413 00414 00415 /* -------------------------------- 00416 * pq_putemptymessage - convenience routine for message with empty body 00417 * -------------------------------- 00418 */ 00419 void 00420 pq_putemptymessage(char msgtype) 00421 { 00422 (void) pq_putmessage(msgtype, NULL, 0); 00423 } 00424 00425 00426 /* -------------------------------- 00427 * pq_getmsgbyte - get a raw byte from a message buffer 00428 * -------------------------------- 00429 */ 00430 int 00431 pq_getmsgbyte(StringInfo msg) 00432 { 00433 if (msg->cursor >= msg->len) 00434 ereport(ERROR, 00435 (errcode(ERRCODE_PROTOCOL_VIOLATION), 00436 errmsg("no data left in message"))); 00437 return (unsigned char) msg->data[msg->cursor++]; 00438 } 00439 00440 /* -------------------------------- 00441 * pq_getmsgint - get a binary integer from a message buffer 00442 * 00443 * Values are treated as unsigned. 00444 * -------------------------------- 00445 */ 00446 unsigned int 00447 pq_getmsgint(StringInfo msg, int b) 00448 { 00449 unsigned int result; 00450 unsigned char n8; 00451 uint16 n16; 00452 uint32 n32; 00453 00454 switch (b) 00455 { 00456 case 1: 00457 pq_copymsgbytes(msg, (char *) &n8, 1); 00458 result = n8; 00459 break; 00460 case 2: 00461 pq_copymsgbytes(msg, (char *) &n16, 2); 00462 result = ntohs(n16); 00463 break; 00464 case 4: 00465 pq_copymsgbytes(msg, (char *) &n32, 4); 00466 result = ntohl(n32); 00467 break; 00468 default: 00469 elog(ERROR, "unsupported integer size %d", b); 00470 result = 0; /* keep compiler quiet */ 00471 break; 00472 } 00473 return result; 00474 } 00475 00476 /* -------------------------------- 00477 * pq_getmsgint64 - get a binary 8-byte int from a message buffer 00478 * 00479 * It is tempting to merge this with pq_getmsgint, but we'd have to make the 00480 * result int64 for all data widths --- that could be a big performance 00481 * hit on machines where int64 isn't efficient. 00482 * -------------------------------- 00483 */ 00484 int64 00485 pq_getmsgint64(StringInfo msg) 00486 { 00487 int64 result; 00488 uint32 h32; 00489 uint32 l32; 00490 00491 pq_copymsgbytes(msg, (char *) &h32, 4); 00492 pq_copymsgbytes(msg, (char *) &l32, 4); 00493 h32 = ntohl(h32); 00494 l32 = ntohl(l32); 00495 00496 result = h32; 00497 result <<= 32; 00498 result |= l32; 00499 00500 return result; 00501 } 00502 00503 /* -------------------------------- 00504 * pq_getmsgfloat4 - get a float4 from a message buffer 00505 * 00506 * See notes for pq_sendfloat4. 00507 * -------------------------------- 00508 */ 00509 float4 00510 pq_getmsgfloat4(StringInfo msg) 00511 { 00512 union 00513 { 00514 float4 f; 00515 uint32 i; 00516 } swap; 00517 00518 swap.i = pq_getmsgint(msg, 4); 00519 return swap.f; 00520 } 00521 00522 /* -------------------------------- 00523 * pq_getmsgfloat8 - get a float8 from a message buffer 00524 * 00525 * See notes for pq_sendfloat8. 00526 * -------------------------------- 00527 */ 00528 float8 00529 pq_getmsgfloat8(StringInfo msg) 00530 { 00531 union 00532 { 00533 float8 f; 00534 int64 i; 00535 } swap; 00536 00537 swap.i = pq_getmsgint64(msg); 00538 return swap.f; 00539 } 00540 00541 /* -------------------------------- 00542 * pq_getmsgbytes - get raw data from a message buffer 00543 * 00544 * Returns a pointer directly into the message buffer; note this 00545 * may not have any particular alignment. 00546 * -------------------------------- 00547 */ 00548 const char * 00549 pq_getmsgbytes(StringInfo msg, int datalen) 00550 { 00551 const char *result; 00552 00553 if (datalen < 0 || datalen > (msg->len - msg->cursor)) 00554 ereport(ERROR, 00555 (errcode(ERRCODE_PROTOCOL_VIOLATION), 00556 errmsg("insufficient data left in message"))); 00557 result = &msg->data[msg->cursor]; 00558 msg->cursor += datalen; 00559 return result; 00560 } 00561 00562 /* -------------------------------- 00563 * pq_copymsgbytes - copy raw data from a message buffer 00564 * 00565 * Same as above, except data is copied to caller's buffer. 00566 * -------------------------------- 00567 */ 00568 void 00569 pq_copymsgbytes(StringInfo msg, char *buf, int datalen) 00570 { 00571 if (datalen < 0 || datalen > (msg->len - msg->cursor)) 00572 ereport(ERROR, 00573 (errcode(ERRCODE_PROTOCOL_VIOLATION), 00574 errmsg("insufficient data left in message"))); 00575 memcpy(buf, &msg->data[msg->cursor], datalen); 00576 msg->cursor += datalen; 00577 } 00578 00579 /* -------------------------------- 00580 * pq_getmsgtext - get a counted text string (with conversion) 00581 * 00582 * Always returns a pointer to a freshly palloc'd result. 00583 * The result has a trailing null, *and* we return its strlen in *nbytes. 00584 * -------------------------------- 00585 */ 00586 char * 00587 pq_getmsgtext(StringInfo msg, int rawbytes, int *nbytes) 00588 { 00589 char *str; 00590 char *p; 00591 00592 if (rawbytes < 0 || rawbytes > (msg->len - msg->cursor)) 00593 ereport(ERROR, 00594 (errcode(ERRCODE_PROTOCOL_VIOLATION), 00595 errmsg("insufficient data left in message"))); 00596 str = &msg->data[msg->cursor]; 00597 msg->cursor += rawbytes; 00598 00599 p = pg_client_to_server(str, rawbytes); 00600 if (p != str) /* actual conversion has been done? */ 00601 *nbytes = strlen(p); 00602 else 00603 { 00604 p = (char *) palloc(rawbytes + 1); 00605 memcpy(p, str, rawbytes); 00606 p[rawbytes] = '\0'; 00607 *nbytes = rawbytes; 00608 } 00609 return p; 00610 } 00611 00612 /* -------------------------------- 00613 * pq_getmsgstring - get a null-terminated text string (with conversion) 00614 * 00615 * May return a pointer directly into the message buffer, or a pointer 00616 * to a palloc'd conversion result. 00617 * -------------------------------- 00618 */ 00619 const char * 00620 pq_getmsgstring(StringInfo msg) 00621 { 00622 char *str; 00623 int slen; 00624 00625 str = &msg->data[msg->cursor]; 00626 00627 /* 00628 * It's safe to use strlen() here because a StringInfo is guaranteed to 00629 * have a trailing null byte. But check we found a null inside the 00630 * message. 00631 */ 00632 slen = strlen(str); 00633 if (msg->cursor + slen >= msg->len) 00634 ereport(ERROR, 00635 (errcode(ERRCODE_PROTOCOL_VIOLATION), 00636 errmsg("invalid string in message"))); 00637 msg->cursor += slen + 1; 00638 00639 return pg_client_to_server(str, slen); 00640 } 00641 00642 /* -------------------------------- 00643 * pq_getmsgend - verify message fully consumed 00644 * -------------------------------- 00645 */ 00646 void 00647 pq_getmsgend(StringInfo msg) 00648 { 00649 if (msg->cursor != msg->len) 00650 ereport(ERROR, 00651 (errcode(ERRCODE_PROTOCOL_VIOLATION), 00652 errmsg("invalid message format"))); 00653 }