connection.c
来自「postgresql-odbc,跨平台应用」· C语言 代码 · 共 2,634 行 · 第 1/5 页
C
2,634 行
SOCK_get_string(sock, msgbuffer, sizeof(msgbuffer)); strncpy(conn->pg_version, msgbuffer, sizeof(conn->pg_version)); strcpy(szVersion, "0.0"); if (sscanf(conn->pg_version, "%d.%d", &major, &minor) >= 2) { snprintf(szVersion, sizeof(szVersion), "%d.%d", major, minor); conn->pg_version_major = major; conn->pg_version_minor = minor; } conn->pg_version_number = (float) atof(szVersion); if (PG_VERSION_GE(conn, 7.3)) conn->schema_support = 1; mylog("Got the PostgreSQL version string: '%s'\n", conn->pg_version); mylog("Extracted PostgreSQL version number: '%1.1f'\n", conn->pg_version_number); qlog(" [ PostgreSQL version string = '%s' ]\n", conn->pg_version); qlog(" [ PostgreSQL version number = '%1.1f' ]\n", conn->pg_version_number); } else SOCK_get_string(sock, msgbuffer, sizeof(msgbuffer));inolog("parameter value=%s\n", msgbuffer);}static int protocol3_opts_array(ConnectionClass *self, const char *opts[][2], BOOL libpqopt, int dim_opts){ ConnInfo *ci = &(self->connInfo); const char *enc = NULL; int cnt; cnt = 0; if (libpqopt && ci->server[0]) { opts[cnt][0] = "host"; opts[cnt++][1] = ci->server; } if (libpqopt && ci->port[0]) { opts[cnt][0] = "port"; opts[cnt++][1] = ci->port; } if (ci->database[0]) { if (libpqopt) { opts[cnt][0] = "dbname"; opts[cnt++][1] = ci->database; } else { opts[cnt][0] = "database"; opts[cnt++][1] = ci->database; } } if (ci->username[0]) { opts[cnt][0] = "user"; opts[cnt++][1] = ci->username; } if (libpqopt) { if (ci->sslmode[0]) { opts[cnt][0] = "sslmode"; opts[cnt++][1] = ci->sslmode; } if (ci->password[0]) { opts[cnt][0] = "password"; opts[cnt++][1] = ci->password; } } else { /* DateStyle */ opts[cnt][0] = "DateStyle"; opts[cnt++][1] = "ISO"; /* extra_float_digits */ opts[cnt][0] = "extra_float_digits"; opts[cnt++][1] = "2"; /* geqo */ opts[cnt][0] = "geqo"; if (ci->drivers.disable_optimizer) opts[cnt++][1] = "off"; else opts[cnt++][1] = "on"; /* client_encoding */ enc = get_environment_encoding(self, self->original_client_encoding, NULL, TRUE); if (enc) { mylog("startup client_encoding=%s\n", enc); opts[cnt][0] = "client_encoding"; opts[cnt++][1] = enc; } } return cnt;}static int protocol3_packet_build(ConnectionClass *self){ CSTR func = "protocol3_packet_build"; SocketClass *sock = self->sock; size_t slen; char *packet, *ppacket; ProtocolVersion pversion; const char *opts[20][2]; int cnt, i; cnt = protocol3_opts_array(self, opts, FALSE, sizeof(opts) / sizeof(opts[0])); slen = sizeof(ProtocolVersion); for (i = 0; i < cnt; i++) { slen += (strlen(opts[i][0]) + 1); slen += (strlen(opts[i][1]) + 1); } slen++; if (packet = malloc(slen), !packet) { CC_set_error(self, CONNECTION_SERVER_NOT_REACHED, "Could not allocate a startup packet", func); return 0; } mylog("sizeof startup packet = %d\n", slen); sock->pversion = PG_PROTOCOL_LATEST; /* Send length of Authentication Block */ SOCK_put_int(sock, (Int4) (slen + 4), 4); ppacket = packet; pversion = (ProtocolVersion) htonl(sock->pversion); memcpy(ppacket, &pversion, sizeof(pversion)); ppacket += sizeof(pversion); for (i = 0; i < cnt; i++) { strcpy(ppacket, opts[i][0]); ppacket += (strlen(opts[i][0]) + 1); strcpy(ppacket, opts[i][1]); ppacket += (strlen(opts[i][1]) + 1); } *ppacket = '\0'; SOCK_put_n_char(sock, packet, (Int4) slen); SOCK_flush_output(sock); free(packet); return 1;}CSTR l_login_timeout = "connect_timeout";static char *protocol3_opts_build(ConnectionClass *self){ CSTR func = "protocol3_opts_build"; size_t slen; char *conninfo, *ppacket; const char *opts[20][2]; int cnt, i; BOOL blankExist; cnt = protocol3_opts_array(self, opts, TRUE, sizeof(opts) / sizeof(opts[0])); slen = sizeof(ProtocolVersion); for (i = 0, slen = 0; i < cnt; i++) { slen += (strlen(opts[i][0]) + 2 + 2); /* add 2 bytes for safety (literal quotes) */ slen += strlen(opts[i][1]); } if (self->login_timeout > 0) { char tmout[16]; slen += (strlen(l_login_timeout) + 2 + 2); snprintf(tmout, sizeof(tmout), FORMAT_UINTEGER, self->login_timeout); slen += strlen(tmout); } slen++; if (conninfo = malloc(slen), !conninfo) { CC_set_error(self, CONNECTION_SERVER_NOT_REACHED, "Could not allocate a connectdb option", func); return 0; } mylog("sizeof connectdb option = %d\n", slen); for (i = 0, ppacket = conninfo; i < cnt; i++) { sprintf(ppacket, " %s=", opts[i][0]); ppacket += (strlen(opts[i][0]) + 2); blankExist = FALSE; if (strchr(opts[i][1], ' ')) blankExist = TRUE; if (blankExist) { *ppacket = '\''; ppacket++; } strcpy(ppacket, opts[i][1]); ppacket += strlen(opts[i][1]); if (blankExist) { *ppacket = '\''; ppacket++; } } if (self->login_timeout > 0) { sprintf(ppacket, " %s=", l_login_timeout); ppacket += (strlen(l_login_timeout) + 2); sprintf(ppacket, FORMAT_UINTEGER, self->login_timeout); ppacket = strchr(ppacket, '\0'); } *ppacket = '\0';inolog("return conninfo=%s(%d)\n", conninfo, strlen(conninfo)); return conninfo;}static char CC_initial_log(ConnectionClass *self, const char *func){ const ConnInfo *ci = &self->connInfo; char *encoding, vermsg[128]; snprintf(vermsg, sizeof(vermsg), "Driver Version='%s,%s'"#ifdef WIN32 " linking %d"#ifdef _MT#ifdef _DLL " dynamic"#else " static"#endif /* _DLL */ " Multithread"#else " Singlethread"#endif /* _MT */#ifdef _DEBUG " Debug"#endif /* DEBUG */ " library"#endif /* WIN32 */ "\n", POSTGRESDRIVERVERSION, PG_BUILD_VERSION#ifdef _MSC_VER , _MSC_VER#endif /* _MSC_VER */ ); qlog(vermsg); mylog(vermsg); qlog("Global Options: fetch=%d, socket=%d, unknown_sizes=%d, max_varchar_size=%d, max_longvarchar_size=%d\n", ci->drivers.fetch_max, ci->drivers.socket_buffersize, ci->drivers.unknown_sizes, ci->drivers.max_varchar_size, ci->drivers.max_longvarchar_size); qlog(" disable_optimizer=%d, ksqo=%d, unique_index=%d, use_declarefetch=%d\n", ci->drivers.disable_optimizer, ci->drivers.ksqo, ci->drivers.unique_index, ci->drivers.use_declarefetch); qlog(" text_as_longvarchar=%d, unknowns_as_longvarchar=%d, bools_as_char=%d NAMEDATALEN=%d\n", ci->drivers.text_as_longvarchar, ci->drivers.unknowns_as_longvarchar, ci->drivers.bools_as_char, TABLE_NAME_STORAGE_LEN); encoding = check_client_encoding(ci->conn_settings); if (encoding) self->original_client_encoding = encoding; else { encoding = check_client_encoding(ci->drivers.conn_settings); if (encoding) self->original_client_encoding = encoding; } if (self->original_client_encoding) self->ccsc = pg_CS_code(self->original_client_encoding); qlog(" extra_systable_prefixes='%s', conn_settings='%s' conn_encoding='%s'\n", ci->drivers.extra_systable_prefixes, ci->drivers.conn_settings, encoding ? encoding : ""); if (self->status != CONN_NOT_CONNECTED) { CC_set_error(self, CONN_OPENDB_ERROR, "Already connected.", func); return 0; } mylog("%s: DSN = '%s', server = '%s', port = '%s', database = '%s', username = '%s', password='%s'\n", func, ci->dsn, ci->server, ci->port, ci->database, ci->username, ci->password ? "xxxxx" : ""); if (ci->port[0] == '\0' ||#ifdef WIN32 ci->server[0] == '\0' ||#endif /* WIN32 */ ci->database[0] == '\0') { CC_set_error(self, CONN_INIREAD_ERROR, "Missing server name, port, or database name in call to CC_connect.", func); return 0; } return 1;}static char CC_setenv(ConnectionClass *self);static int LIBPQ_connect(ConnectionClass *self);static charLIBPQ_CC_connect(ConnectionClass *self, char password_req, char *salt_para){ int ret; CSTR func = "LIBPQ_CC_connect"; mylog("%s: entering...\n", func); if (password_req == AUTH_REQ_OK) /* not yet connected */ { if (0 == CC_initial_log(self, func)) return 0; } if (ret = LIBPQ_connect(self), ret <= 0) return ret; CC_setenv(self); return 1;}static charoriginal_CC_connect(ConnectionClass *self, char password_req, char *salt_para){ StartupPacket sp; StartupPacket6_2 sp62; QResultClass *res; SocketClass *sock; ConnInfo *ci = &(self->connInfo); int areq = -1; int beresp, sockerr; char msgbuffer[ERROR_MSG_LENGTH]; char salt[5], notice[512]; CSTR func = "original_CC_connect"; // char *encoding; BOOL startPacketReceived = FALSE; mylog("%s: entering...\n", func); if (password_req != AUTH_REQ_OK) { sock = self->sock; /* already connected, just authenticate */ CC_clear_error(self); } else { if (0 == CC_initial_log(self, func)) return 0;another_version_retry: /* * If the socket was closed for some reason (like a SQLDisconnect, * but no SQLFreeConnect then create a socket now. */ if (!self->sock) { self->sock = SOCK_Constructor(self); if (!self->sock) { CC_set_error(self, CONNECTION_SERVER_NOT_REACHED, "Could not construct a socket to the server", func); return 0; } } sock = self->sock; mylog("connecting to the server socket...\n"); SOCK_connect_to(sock, (short) atoi(ci->port), ci->server, self->login_timeout); if (SOCK_get_errcode(sock) != 0) { CC_set_error(self, CONNECTION_SERVER_NOT_REACHED, "Could not connect to the server", func); return 0; } mylog("connection to the server socket succeeded.\n");inolog("protocol=%s version=%d,%d\n", ci->protocol, self->pg_version_major, self->pg_version_minor); if (PROTOCOL_62(ci)) { sock->reverse = TRUE; /* make put_int and get_int work * for 6.2 */ memset(&sp62, 0, sizeof(StartupPacket6_2)); sock->pversion = PG_PROTOCOL_62; SOCK_put_int(sock, htonl(4 + sizeof(StartupPacket6_2)), 4); sp62.authtype = htonl(NO_AUTHENTICATION); strncpy(sp62.database, ci->database, PATH_SIZE); strncpy(sp62.user, ci->username, USRNAMEDATALEN); SOCK_put_n_char(sock, (char *) &sp62, sizeof(StartupPacket6_2)); SOCK_flush_output(sock); } else if (PROTOCOL_74(ci)) { if (!protocol3_packet_build(self)) return 0; } else { memset(&sp, 0, sizeof(StartupPacket)); mylog("sizeof startup packet = %d\n", sizeof(StartupPacket)); if (PROTOCOL_63(ci)) sock->pversion = PG_PROTOCOL_63; else sock->pversion = PG_PROTOCOL_64; /* Send length of Authentication Block */ SOCK_put_int(sock, 4 + sizeof(StartupPacket), 4); sp.protoVersion = (ProtocolVersion) htonl(sock->pversion); strncpy(sp.database, ci->database, SM_DATABASE); strncpy(sp.user, ci->username, SM_USER); SOCK_put_n_char(sock, (char *) &sp, sizeof(StartupPacket)); SOCK_flush_output(sock); } if (SOCK_get_errcode(sock) != 0) { CC_set_error(self, CONN_INVALID_AUTHENTICATION, "Failed to send the authentication packet", func); return 0; } mylog("sent the authentication block successfully.\n"); } mylog("gonna do authentication\n"); /* * Now get the authentication request from backend */ if (!PROTOCOL_62(ci)) { BOOL beforeV2 = PG_VERSION_LT(self, 6.4), ReadyForQuery = FALSE, retry = FALSE; uint32 leng; do { if (password_req != AUTH_REQ_OK) { beresp = 'R'; startPacketReceived = TRUE; } else { beresp = SOCK_get_id(sock); mylog("auth got '%c'\n", beresp); if (0 != SOCK_get_errcode(sock)) goto sockerr_proc; if (PROTOCOL_74(ci)) { if (beresp != 'E' || startPacketReceived) { leng = SOCK_get_response_length(sock);inolog("leng=%d\n", leng); if (0 != SOCK_get_errcode(sock)) goto sockerr_proc; } else strncpy(ci->protocol, PG74REJECTED, sizeof(ci->protocol));/* retry = TRUE; */ } startPacketReceived = TRUE; } switch (beresp) { case 'E':inolog("Ekita\n"); handle_error_message(self, msgbuffer, sizeof(msgbuffer), self->sqlstate, func, NULL); CC_set_error(self, CONN_INVALID_AUTHENTICATION, msgbuffer, func); qlog("ERROR from backend during authentication: '%s'\n", msgbuffer); if (strnicmp(msgbuffer, "Unsupported frontend protocol", 29) == 0) retry = TRUE; else if (strncmp(msgbuffer, "FATAL:", 6) == 0 && strnicmp(msgbuffer + 8, "unsupported frontend protocol", 29) == 0) retry = TRUE; if (retry) break; return 0; case 'R': if (password_req != AUTH_REQ_OK) { mylog("in 'R' password_req=%s\n", ci->password); areq = password_req; if (salt_para) memcpy(salt, salt_para, sizeof(salt)); password_req = AUTH_REQ_OK; mylog("salt=%02x%02x%02x%02x%02x\n", (UCHAR)salt[0], (UCHAR)salt[1], (UCHAR)salt[2], (UCHAR)salt[3], (UCHAR)salt[4]); } else { areq = SOCK_get_int(sock, 4); memset(salt, 0, sizeof(salt)); if (areq == AUTH_REQ_MD5) SOCK_get_n_char(sock, salt, 4); else if (areq == AUTH_REQ_CRYPT) SOCK_get_n_char(sock, salt, 2); mylog("areq = %d salt=%02x%02x%02x%02x%02x\n", areq, (UCHAR)salt[0], (UCHAR)salt[1], (UCHAR)salt[2], (UCHAR)salt[3], (UCHAR)salt[4]); } switch (areq) { case AUTH_REQ_OK: break; case AUTH_REQ_KRB4: CC_set_error(self, CONN_AUTH_TYPE_UNSUPPORTED, "Kerberos 4 authentication not supported", func); return 0; case AUTH_REQ_KRB5: CC_set_error(self, CONN_AUTH_TYPE_UNSUPPORTED, "Kerberos 5 authentication not supported", func); return 0; case AUTH_REQ_PASSWORD: mylog("in AUTH_REQ_PASSWORD\n"); if (ci->password[0] == '\0') { CC_set_error(self, CONNECTION_NEED_PASSWORD, "A password is required for this connection.", func); return -areq; /* need password */ } mylog("past need password\n");
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?