source: node_modules/pg/lib/connection.js@ 62b2964

finki-main main
Last change on this file since 62b2964 was 62b2964, checked in by Klimentina Efremova <klimentina08642@…>, 2 weeks ago

Project Handcraft Marketplace

  • Property mode set to 100644
File size: 5.8 KB
Line 
1'use strict'
2
3const EventEmitter = require('events').EventEmitter
4
5const { parse, serialize } = require('pg-protocol')
6const stream = require('./stream')
7const { getStream } = stream
8
9const flushBuffer = serialize.flush()
10const syncBuffer = serialize.sync()
11const endBuffer = serialize.end()
12
13// TODO(bmc) support binary mode at some point
14class Connection extends EventEmitter {
15 constructor(config) {
16 super()
17 config = config || {}
18
19 this.stream = config.stream || getStream(config.ssl)
20 if (typeof this.stream === 'function') {
21 this.stream = this.stream(config)
22 }
23
24 this._keepAlive = config.keepAlive
25 this._keepAliveInitialDelayMillis = config.keepAliveInitialDelayMillis
26 this.parsedStatements = {}
27 this.submittedNamedStatements = {}
28 this.ssl = config.ssl || false
29 this.sslNegotiation = config.sslNegotiation || 'postgres'
30 this._ending = false
31 this._emitMessage = false
32 const self = this
33 this.on('newListener', function (eventName) {
34 if (eventName === 'message') {
35 self._emitMessage = true
36 }
37 })
38 }
39
40 connect(port, host) {
41 const self = this
42
43 this._connecting = true
44 this.stream.setNoDelay(true)
45 this.stream.connect(port, host)
46
47 this.stream.once('connect', function () {
48 if (self._keepAlive) {
49 self.stream.setKeepAlive(true, self._keepAliveInitialDelayMillis)
50 }
51 self.emit('connect')
52 })
53
54 const reportStreamError = function (error) {
55 // errors about disconnections should be ignored during disconnect
56 if (self._ending && (error.code === 'ECONNRESET' || error.code === 'EPIPE')) {
57 return
58 }
59 self.emit('error', error)
60 }
61 this.stream.on('error', reportStreamError)
62
63 this.stream.on('close', function () {
64 self.emit('end')
65 })
66
67 if (!this.ssl) {
68 return this.attachListeners(this.stream)
69 }
70
71 // With direct SSL negotiation the TLS handshake starts immediately on the
72 // raw socket, skipping the SSLRequest packet and the server's 'S'/'N' reply.
73 if (this.sslNegotiation === 'direct') {
74 return this.stream.once('connect', function () {
75 self.upgradeToSSL(host, reportStreamError)
76 })
77 }
78
79 this.stream.once('data', function (buffer) {
80 const responseCode = buffer.toString('utf8')
81 switch (responseCode) {
82 case 'S': // Server supports SSL connections, continue with a secure connection
83 break
84 case 'N': // Server does not support SSL connections
85 self.stream.end()
86 return self.emit('error', new Error('The server does not support SSL connections'))
87 default:
88 // Any other response byte, including 'E' (ErrorResponse) indicating a server error
89 self.stream.end()
90 return self.emit('error', new Error('There was an error establishing an SSL connection'))
91 }
92 self.upgradeToSSL(host, reportStreamError)
93 })
94 }
95
96 upgradeToSSL(host, reportStreamError) {
97 const self = this
98 const options = {
99 socket: self.stream,
100 }
101
102 if (self.ssl !== true) {
103 Object.assign(options, self.ssl)
104
105 if ('key' in self.ssl) {
106 options.key = self.ssl.key
107 }
108 }
109
110 // Direct SSL negotiation requires ALPN so the server can confirm it is
111 // speaking the PostgreSQL protocol over the TLS connection.
112 if (self.sslNegotiation === 'direct') {
113 options.ALPNProtocols = ['postgresql']
114 }
115
116 const net = require('net')
117 if (net.isIP && net.isIP(host) === 0) {
118 options.servername = host
119 }
120 try {
121 self.stream = stream.getSecureStream(options)
122 } catch (err) {
123 return self.emit('error', err)
124 }
125 self.attachListeners(self.stream)
126 self.stream.on('error', reportStreamError)
127
128 self.emit('sslconnect')
129 }
130
131 attachListeners(stream) {
132 parse(stream, (msg) => {
133 const eventName = msg.name === 'error' ? 'errorMessage' : msg.name
134 if (this._emitMessage) {
135 this.emit('message', msg)
136 }
137 this.emit(eventName, msg)
138 })
139 }
140
141 requestSsl() {
142 this.stream.write(serialize.requestSsl())
143 }
144
145 startup(config) {
146 this.stream.write(serialize.startup(config))
147 }
148
149 cancel(processID, secretKey) {
150 this._send(serialize.cancel(processID, secretKey))
151 }
152
153 password(password) {
154 this._send(serialize.password(password))
155 }
156
157 sendSASLInitialResponseMessage(mechanism, initialResponse) {
158 this._send(serialize.sendSASLInitialResponseMessage(mechanism, initialResponse))
159 }
160
161 sendSCRAMClientFinalMessage(additionalData) {
162 this._send(serialize.sendSCRAMClientFinalMessage(additionalData))
163 }
164
165 _send(buffer) {
166 if (!this.stream.writable) {
167 return false
168 }
169 return this.stream.write(buffer)
170 }
171
172 query(text) {
173 this._send(serialize.query(text))
174 }
175
176 // send parse message
177 parse(query) {
178 this._send(serialize.parse(query))
179 }
180
181 // send bind message
182 bind(config) {
183 this._send(serialize.bind(config))
184 }
185
186 // send execute message
187 execute(config) {
188 this._send(serialize.execute(config))
189 }
190
191 flush() {
192 if (this.stream.writable) {
193 this.stream.write(flushBuffer)
194 }
195 }
196
197 sync() {
198 this._ending = true
199 this._send(syncBuffer)
200 }
201
202 ref() {
203 this.stream.ref()
204 }
205
206 unref() {
207 this.stream.unref()
208 }
209
210 end() {
211 // 0x58 = 'X'
212 this._ending = true
213 if (!this._connecting || !this.stream.writable) {
214 this.stream.end()
215 return
216 }
217 return this.stream.write(endBuffer, () => {
218 this.stream.end()
219 })
220 }
221
222 close(msg) {
223 this._send(serialize.close(msg))
224 }
225
226 describe(msg) {
227 this._send(serialize.describe(msg))
228 }
229
230 sendCopyFromChunk(chunk) {
231 this._send(serialize.copyData(chunk))
232 }
233
234 endCopyFrom() {
235 this._send(serialize.copyDone())
236 }
237
238 sendCopyFail(msg) {
239 this._send(serialize.copyFail(msg))
240 }
241}
242
243module.exports = Connection
Note: See TracBrowser for help on using the repository browser.