Browse code

Connection timeout cleanup

Change-Id: Ic177f19161c8a3f2447b7f1272d542ffbdbf15f9
Reviewed-on: http://photon-jenkins.eng.vmware.com:8082/4733
Tested-by: gerrit-photon <photon-checkins@vmware.com>
Reviewed-by: Kumar Kaushik <kaushikk@vmware.com>

Kumar Kaushik authored on 2018/02/01 07:32:49
Showing 3 changed files
... ...
@@ -1,7 +1,7 @@
1 1
 Name:          c-rest-engine
2 2
 Summary:       minimal http(s) server library
3 3
 Version:       1.1
4
-Release:       7%{?dist}
4
+Release:       8%{?dist}
5 5
 Group:         Applications/System
6 6
 Vendor:        VMware, Inc.
7 7
 License:       Apache 2.0
... ...
@@ -18,6 +18,8 @@ Patch2:        socket_logging.patch
18 18
 Patch3:        errno_init.patch
19 19
 Patch4:        ssl_shutdown.patch
20 20
 Patch5:        minimal_request_logging.patch
21
+Patch6:        connection_timeout.patch
22
+Patch7:        reqLine_parsing_check.patch
21 23
 %define sha1   c-rest-engine=a25927fd98ec92df5e210cc4941fa626604636f6
22 24
 
23 25
 %description
... ...
@@ -42,6 +44,9 @@ development libs and header files for c-rest-engine
42 42
 %patch3 -p1
43 43
 %patch4 -p1
44 44
 %patch5 -p1
45
+%patch6 -p1
46
+%patch7 -p1
47
+
45 48
 
46 49
 %build
47 50
 cd build
... ...
@@ -74,6 +79,8 @@ find %{buildroot} -name '*.la' -delete
74 74
 # %doc ChangeLog README COPYING
75 75
 
76 76
 %changelog
77
+*  Wed Jan 31 2018 Kumar Kaushik <kaushikk@vmware.com> 1.1-8
78
+-  Fixing timeout connection cleanup issue.
77 79
 *  Fri Dec 15 2017 Kumar Kaushik <kaushikk@vmware.com> 1.1-7
78 80
 -  Adding patch for minimal packet level logging.
79 81
 *  Wed Nov 29 2017 Kumar Kaushik <kaushikk@vmware.com> 1.1-6
80 82
new file mode 100644
... ...
@@ -0,0 +1,832 @@
0
+From 96a49b724295422ceb6465553fdf0da20e5a3b6d Mon Sep 17 00:00:00 2001
1
+From: Kumar Kaushik <kaushikk@vmware.com>
2
+Date: Mon, 29 Jan 2018 19:30:18 -0800
3
+Subject: [PATCH] Handling timeout events for faulty application callback
4
+
5
+Change-Id: I9a412f6d7cf2c3345c73f0581906829bd183e445
6
+---
7
+ common/sockinterface.c               |  26 ++-
8
+ include/public/vmrest.h              |   1 +
9
+ include/vmrestdefines.h              |   9 +
10
+ server/restengine/httpAllocStruct.c  |   4 +-
11
+ server/restengine/httpProtocolHead.c |   7 +-
12
+ transport/posix/socket.c             | 425 ++++++++++++++++++-----------------
13
+ transport/posix/structs.h            |   1 +
14
+ 7 files changed, 257 insertions(+), 216 deletions(-)
15
+
16
+diff --git a/common/sockinterface.c b/common/sockinterface.c
17
+index 403189c..9e7d404 100644
18
+--- a/common/sockinterface.c
19
+@@ -327,14 +327,13 @@ VmRESTHandleSocketEvent(
20
+             break;
21
+ 
22
+         case VM_SOCK_EVENT_TYPE_CONNECTION_TIMEOUT:
23
+-            /**** Free Associated memory ****/
24
+-            VMREST_LOG_DEBUG(pRESTHandle,"%s","EVENT-HANDLER: Connection timeout happened..Disconnecting client ...");
25
+-            dwError = VmRESTOnConnectionTimeout(
26
++             VMREST_LOG_DEBUG(pRESTHandle,"%s","EVENT-HANDLER: Connection timeout happened..Disconnecting client");
27
++             dwError = VmRESTOnConnectionTimeout(
28
+                           pRESTHandle,
29
+                           pSocket
30
+                           );
31
+-            BAIL_ON_VMREST_ERROR(dwError);
32
+-            break;
33
++             BAIL_ON_VMREST_ERROR(dwError);
34
++             break;
35
+ 
36
+         case VM_SOCK_EVENT_TYPE_UNKNOWN:
37
+              VMREST_LOG_DEBUG(pRESTHandle,"%s","EVENT-HANDLER: Unknown Socket Event, do nothing");
38
+@@ -436,6 +435,7 @@ VmRESTTcpReceiveNewData(
39
+     char*                            pszBuffer = NULL;
40
+     uint32_t                         nProcessed = 0;
41
+     uint32_t                         nBufLen = 0;
42
++    uint32_t                         ret = REST_ENGINE_SUCCESS;
43
+     BOOLEAN                          bNextIO = FALSE;
44
+ 
45
+     if (!pSocket || !pRESTHandle || !pQueue)
46
+@@ -517,7 +517,7 @@ VmRESTTcpReceiveNewData(
47
+ 
48
+ cleanup:
49
+ 
50
+-   if (!bNextIO)
51
++   if (!bNextIO && dwError != REST_ENGINE_ERROR_DOUBLE_FAILURE)
52
+    {
53
+        VMREST_LOG_DEBUG(pRESTHandle,"%s","Calling closed connection....");
54
+        /**** Close connection ****/ 
55
+@@ -542,6 +542,20 @@ VmRESTTcpReceiveNewData(
56
+ error:
57
+ 
58
+     VMREST_LOG_ERROR(pRESTHandle,"ERROR code %u", dwError);
59
++
60
++    if ((dwError == VMREST_TRANSPORT_DEFERRED_TIMEOUT_PROCESS) && (bNextIO))
61
++    {
62
++         ret = VmRESTOnConnectionTimeout(
63
++                     pRESTHandle,
64
++                     pSocket
65
++                     );
66
++
67
++         if (ret != REST_ENGINE_SUCCESS)
68
++         {
69
++            VMREST_LOG_ERROR(pRESTHandle,"Double failure on deferred timeout processing dwError, = %u", dwError);
70
++            dwError = REST_ENGINE_ERROR_DOUBLE_FAILURE;
71
++         }
72
++    }
73
+     goto cleanup;
74
+ }
75
+ 
76
+diff --git a/include/public/vmrest.h b/include/public/vmrest.h
77
+index 3988266..5219952 100644
78
+--- a/include/public/vmrest.h
79
+@@ -32,6 +32,7 @@
80
+ /**** REST ENGINE ERROR CODES ****/
81
+ #define     REST_ENGINE_SUCCESS                            0
82
+ #define     REST_ENGINE_FAILURE                            1
83
++#define     REST_ENGINE_ERROR_DOUBLE_FAILURE               99
84
+ #define     REST_ERROR_MISSING_CONFIG                      100
85
+ #define     REST_ERROR_INVALID_CONFIG                      101
86
+ #define     REST_ERROR_NO_MEMORY                           102
87
+diff --git a/include/vmrestdefines.h b/include/vmrestdefines.h
88
+index 914422a..8a37628 100644
89
+--- a/include/vmrestdefines.h
90
+@@ -63,6 +63,15 @@
91
+ #define VMREST_TRANSPORT_COND_INIT_FAILED               61125
92
+ #define VMREST_TRANSPORT_SERVER_THREAD_START_FAILED     61126
93
+ 
94
++
95
++#define VMREST_TRANSPORT_DEFERRED_TIMEOUT_PROCESS       61127
96
++#define VMREST_TRANSPORT_SOCK_READ_FAILED               61128
97
++#define VMREST_TRANSPORT_SOCK_WRITE_FAILED              61129
98
++#define VMREST_TRANSPORT_SOCK_GET_HANDLE_FAILED         61130
99
++#define VMREST_TRANSPORT_SOCK_SET_HANDLE_FAILED         61131
100
++#define VMREST_TRANSPORT_SOCK_DATA_OVER_LIMIT           61132
101
++#define VMREST_TRANSPORT_REMOTE_CONN_CLOSED             61133
102
++
103
+ #define ERROR_TRANSPORT_INVALID_PARAMS                  61040
104
+ #define ERROR_TRANSPORT_VALIDATION_FAILED               61041
105
+ 
106
+diff --git a/server/restengine/httpAllocStruct.c b/server/restengine/httpAllocStruct.c
107
+index 64cb846..27aa9ed 100644
108
+--- a/server/restengine/httpAllocStruct.c
109
+@@ -519,11 +519,13 @@ VmRESTAllocateMiscQueue(
110
+     PMISC_HEADER_QUEUE               pMiscQueue = NULL;
111
+ 
112
+     dwError = VmRESTAllocateMemory(
113
+-                  sizeof(VM_REST_HTTP_MESSAGE_BODY),
114
++                  sizeof(MISC_HEADER_QUEUE),
115
+                   (void**)&pMiscQueue
116
+                   );
117
+     BAIL_ON_VMREST_ERROR(dwError);
118
+ 
119
++    pMiscQueue->head = NULL;
120
++
121
+     *ppMiscHeaderQueue = pMiscQueue;
122
+ 
123
+ cleanup:
124
+diff --git a/server/restengine/httpProtocolHead.c b/server/restengine/httpProtocolHead.c
125
+index 18cff08..95089a3 100644
126
+--- a/server/restengine/httpProtocolHead.c
127
+@@ -1448,8 +1448,13 @@ VmRESTProcessBuffer(
128
+     if (ret != REST_ENGINE_SUCCESS)
129
+     {
130
+         VMREST_LOG_ERROR(pRESTHandle,"%s","Double Failure case detected ....");
131
++        VMREST_LOG_ERROR(pRESTHandle,"%s","possible memory leak");
132
++        dwError = REST_ENGINE_ERROR_DOUBLE_FAILURE;
133
++    }
134
++    else
135
++    {
136
++        dwError = REST_ENGINE_SUCCESS;
137
+     }
138
+-    dwError = REST_ENGINE_SUCCESS;
139
+     goto cleanup;
140
+ 
141
+ }
142
+diff --git a/transport/posix/socket.c b/transport/posix/socket.c
143
+index 6c0e14e..207075b 100644
144
+--- a/transport/posix/socket.c
145
+@@ -81,13 +81,6 @@ VmSockPosixReArmTimer(
146
+     int                              milliSec
147
+     );
148
+ 
149
+-static
150
+-BOOLEAN
151
+-VmSockPosixIsSafeToCloseConnOnTimeOut(
152
+-    PVMREST_HANDLE                   pRESTHandle,
153
+-    PVM_SOCKET                       pTimerSocket
154
+-    );
155
+-
156
+ static
157
+ uint32_t
158
+ VmRESTAcceptSSLContext(
159
+@@ -482,7 +475,9 @@ VmSockPosixWaitForEvent(
160
+     BOOLEAN                          bLocked = FALSE;
161
+     VM_SOCK_EVENT_TYPE               eventType = VM_SOCK_EVENT_TYPE_UNKNOWN;
162
+     PVM_SOCKET                       pSocket = NULL;
163
++    BOOLEAN                          bFound = FALSE;
164
+     BOOLEAN                          bFreeEventQueue = 0;
165
++    int                              i = 0;
166
+ 
167
+     if (!pQueue || !ppSocket || !pEventType)
168
+     {
169
+@@ -551,7 +546,7 @@ VmSockPosixWaitForEvent(
170
+                 BAIL_ON_VMREST_ERROR(dwError);
171
+                 pSocket = pEventSocket;
172
+             }
173
+-            else if (pEventSocket->type == VM_SOCK_TYPE_LISTENER)
174
++            else if (pEventSocket->type == VM_SOCK_TYPE_LISTENER)    // New connection request
175
+             {
176
+                 VMREST_LOG_INFO(pRESTHandle,"%s","C-REST-ENGINE: ========================  NEW REQUEST ==========================");
177
+                 dwError = VmSockPosixAcceptConnection(
178
+@@ -572,6 +567,7 @@ VmSockPosixWaitForEvent(
179
+                                    );
180
+                     BAIL_ON_VMREST_ERROR(dwError);
181
+ 
182
++                    /**** Try SSL Handshake ****/
183
+                     dwError  = VmRESTAcceptSSLContext(
184
+                                    pRESTHandle,
185
+                                    pSocket,
186
+@@ -580,6 +576,7 @@ VmSockPosixWaitForEvent(
187
+                     BAIL_ON_VMREST_ERROR(dwError);
188
+                 }
189
+ 
190
++                /**** Start watching new connection ****/
191
+                 dwError = VmSockPosixEventQueueAdd_inlock(
192
+                               pQueue,
193
+                               TRUE,
194
+@@ -593,9 +590,12 @@ VmSockPosixWaitForEvent(
195
+                               pSocket
196
+                               );
197
+                 BAIL_ON_VMREST_ERROR(dwError);
198
++
199
+                 eventType = VM_SOCK_EVENT_TYPE_TCP_NEW_CONNECTION;
200
++
201
++                VMREST_LOG_DEBUG(pRESTHandle,"Timer fd %d associated with socket fd %d", pSocket->pTimerSocket->fd ,pSocket->fd);
202
+             }
203
+-            else if (pEventSocket->type == VM_SOCK_TYPE_SIGNAL)
204
++            else if (pEventSocket->type == VM_SOCK_TYPE_SIGNAL) // Shutdown library
205
+             {
206
+                 if (pQueue->bShutdown)
207
+                 {
208
+@@ -614,58 +614,108 @@ VmSockPosixWaitForEvent(
209
+                     eventType = VM_SOCK_EVENT_TYPE_DATA_AVAILABLE;
210
+                 }
211
+             }
212
+-            else if (pEventSocket->type == VM_SOCK_TYPE_TIMER)
213
++            else if (pEventSocket->type == VM_SOCK_TYPE_TIMER) // Time out event
214
+             {
215
+-                /**** No activity on the socket watched by poller till timeout ****/
216
+-                if (VmSockPosixIsSafeToCloseConnOnTimeOut(pRESTHandle, pEventSocket))
217
++                eventType = VM_SOCK_EVENT_TYPE_UNKNOWN;
218
++                pSocket = pEventSocket;
219
++
220
++                VMREST_LOG_DEBUG(pRESTHandle, "Timeout event happened on timer fd %d", pSocket->fd);
221
++              
222
++                if (pSocket->pIoSocket != NULL)
223
+                 {
224
+-                    pSocket = pEventSocket;
225
++                    /*** Scan pQueue and look for IO event corresponding to this timer event ***/
226
++                    for ((i = (pQueue->iReady + 1)); i < pQueue->nReady ; i++)
227
++                    {
228
++                        struct epoll_event* pEventTemp = &pQueue->pEventArray[i];
229
++                        PVM_SOCKET pEventSocketTemp = (PVM_SOCKET)pEventTemp->data.ptr;
230
++                        if (pEventSocketTemp->fd == pEventSocket->pIoSocket->fd)
231
++                        {
232
++                            pEventSocket->pIoSocket->pTimerSocket = NULL;
233
++                            bFound = TRUE;
234
++                            break;
235
++                        }
236
++                    }
237
+ 
238
+-                    /**** Delete timer socket from poller ****/
239
+-                    dwError = VmSockPosixEventQueueDelete_inlock(
240
+-                                  pQueue,
241
+-                                  pSocket
242
+-                                  );
243
+-                    BAIL_ON_VMREST_ERROR(dwError);
244
++                    if (bFound)
245
++                    {
246
++                        VMREST_LOG_DEBUG(pRESTHandle,"Action: DEFERRED, IO sock found in queue(Succeeding),  Io Sock %d, timer %d", pSocket->pIoSocket->fd, pSocket->fd );
247
++                    }
248
++                    else
249
++                    {
250
++                        if (pSocket->pIoSocket->bInUse == TRUE)
251
++                        {
252
++                            VMREST_LOG_DEBUG(pRESTHandle,"Action: DEFERRED, IO Soc in use, IoSocket %d, timer %d", pSocket->pIoSocket->fd, pSocket->fd );
253
++                            pEventSocket->pIoSocket->pTimerSocket = NULL;
254
++                        }
255
++                        else
256
++                        {
257
++                             /**** We are good to close actual IO Socket here ****/
258
++                             VMREST_LOG_INFO(pRESTHandle,"Action: IO DELETION, IoSocket %d, timer %d", pSocket->pIoSocket->fd, pSocket->fd );
259
++                             eventType = VM_SOCK_EVENT_TYPE_CONNECTION_TIMEOUT;
260
++                             pSocket = pSocket->pIoSocket;
261
++                             
262
++                             /**** Delete IO from queue ****/
263
++                             VmSockPosixEventQueueDelete_inlock(
264
++                                           pQueue,
265
++                                           pSocket
266
++                                           );
267
++                        }
268
++                    }
269
++                }
270
+ 
271
+-                    /**** Delete actual IO socket from poller ****/
272
+-                    dwError = VmSockPosixEventQueueDelete_inlock(
273
+-                                  pQueue,
274
+-                                  pSocket->pIoSocket
275
+-                                  );
276
+-                    BAIL_ON_VMREST_ERROR(dwError);
277
++                /** Close and free the timer socket ****/
278
++                VmSockPosixCloseSocket(pRESTHandle,pEventSocket);
279
++                VmSockPosixReleaseSocket(pRESTHandle,pEventSocket);
280
+ 
281
+-                    pSocket = pEventSocket->pIoSocket;
282
+-                    eventType = VM_SOCK_EVENT_TYPE_CONNECTION_TIMEOUT;
283
++                if (eventType == VM_SOCK_EVENT_TYPE_UNKNOWN)
284
++                {
285
++                    pSocket = NULL;
286
+                 }
287
+             }
288
+-            else
289
++            else  // Data available on IO Socket
290
+             {
291
+-                /**** Data is available over the socket ****/
292
+-                pSocket = pEventSocket;
293
++                 pSocket = pEventSocket;
294
+ 
295
+-                /**** If SSL handshake is not yet complete, do the needful ****/
296
+-                if ((pRESTHandle->pSSLInfo->isSecure) && (!(pSocket->bSSLHandShakeCompleted)))
297
+-                {
298
+-                    dwError = VmRESTAcceptSSLContext(
299
+-                                  pRESTHandle,
300
+-                                  pSocket,
301
+-                                  TRUE
302
+-                                  );
303
+-                    BAIL_ON_VMREST_ERROR(dwError);
304
+-                }
305
+-                else
306
+-                {
307
+-                    eventType = VM_SOCK_EVENT_TYPE_DATA_AVAILABLE;
308
++                 /**** Mark IO socket in use - timer out event cannot modify IO till this is done ****/
309
++                 pSocket->bInUse = TRUE;
310
+ 
311
+-                    /**** Stop timer on the socket ****/
312
+-                    dwError = VmSockPosixReArmTimer(
313
+-                                   pRESTHandle,
314
+-                                   pSocket->pTimerSocket,
315
+-                                   0
316
+-                                   );
317
+-                    BAIL_ON_VMREST_ERROR(dwError);
318
+-                }
319
++                 if (pSocket->pTimerSocket == NULL)
320
++                 {
321
++                     /**** Time out already occurred on this socket.. request won't be processed ****/
322
++                     VmSockPosixCloseSocket(pRESTHandle,pSocket);
323
++                     VmSockPosixReleaseSocket(pRESTHandle,pSocket);
324
++                 }
325
++                 else
326
++                 {
327
++                      /**** Process data  ****/
328
++                      VMREST_LOG_DEBUG(pRESTHandle,"Data notification on socket fd %d", pSocket->fd);
329
++
330
++                      /**** If SSL handshake is not yet complete, do the needful ****/
331
++                      if ((pRESTHandle->pSSLInfo->isSecure) && (!(pSocket->bSSLHandShakeCompleted)))
332
++                      {
333
++                          dwError = VmRESTAcceptSSLContext(
334
++                                        pRESTHandle,
335
++                                        pSocket,
336
++                                        TRUE
337
++                                        );
338
++                          BAIL_ON_VMREST_ERROR(dwError);
339
++
340
++                          /**** We do not need IO any more ..mark as available for timer ****/
341
++                          pSocket->bInUse = FALSE;
342
++                      }
343
++                      else
344
++                      {
345
++                          eventType = VM_SOCK_EVENT_TYPE_DATA_AVAILABLE;
346
++
347
++                          /*** Disarm timer associated with this IO socket .. dont delete ***/
348
++                          dwError = VmSockPosixReArmTimer(
349
++                                        pRESTHandle,
350
++                                        pSocket->pTimerSocket,
351
++                                        0
352
++                                        );
353
++                          BAIL_ON_VMREST_ERROR(dwError);
354
++                      }
355
++                 }
356
+             }
357
+         }
358
+         pQueue->iReady++;
359
+@@ -696,7 +746,7 @@ VmSockPosixWaitForEvent(
360
+ 
361
+ error:
362
+ 
363
+-    VMREST_LOG_ERROR(pRESTHandle,"%s","Socket layer - wait for event error");
364
++    VMREST_LOG_ERROR(pRESTHandle,"Error while processing socket event, dwError = %u", dwError);
365
+     if (ppSocket)
366
+     {
367
+         *ppSocket = NULL;
368
+@@ -884,8 +934,8 @@ VmSockPosixRead(
369
+     if (nPrevBuf >= pRESTHandle->pRESTConfig->maxDataPerConnMB)
370
+     {
371
+         /**** Discard the request here itself. This might be the first read IO cycle ****/
372
+-        VMREST_LOG_ERROR(pRESTHandle,"Total Data in request %u bytes is over allowed limit of %u bytes, closing connection...", nPrevBuf, pRESTHandle->pRESTConfig->maxDataPerConnMB);
373
+-        dwError = REST_ENGINE_FAILURE;
374
++        VMREST_LOG_ERROR(pRESTHandle,"Total Data in request %u bytes is over allowed limit of %u bytes, closing connection with fd %d", nPrevBuf, pRESTHandle->pRESTConfig->maxDataPerConnMB, pSocket->fd);
375
++        dwError = VMREST_TRANSPORT_SOCK_DATA_OVER_LIMIT;
376
+     }
377
+     BAIL_ON_VMREST_ERROR(dwError);
378
+ 
379
+@@ -897,8 +947,8 @@ VmSockPosixRead(
380
+         }
381
+         else
382
+         {
383
+-            VMREST_LOG_ERROR(pRESTHandle,"Unknown socket read error: errno %u, errorCode %u, nRead %d", errno, errorCode, nRead);
384
+-            dwError = REST_ENGINE_FAILURE;
385
++            VMREST_LOG_ERROR(pRESTHandle,"Socket read error: errno %u, errorCode %u, nRead %d", errno, errorCode, nRead);
386
++            dwError = VMREST_TRANSPORT_SOCK_READ_FAILED;
387
+         }
388
+     }
389
+     else
390
+@@ -906,12 +956,12 @@ VmSockPosixRead(
391
+         if (nRead == 0)
392
+         {
393
+             VMREST_LOG_ERROR(pRESTHandle,"%s","Socket Read Failed: Remote has closed the connection");
394
+-            dwError = VM_SOCK_POSIX_ERROR_BROKEN_PIPE;
395
++            dwError = VMREST_TRANSPORT_SOCK_READ_FAILED;
396
+         }
397
+         else
398
+         {
399
+             VMREST_LOG_ERROR(pRESTHandle, "Socket read failed with error code %u", errorCode);
400
+-            dwError = errorCode;
401
++            dwError = VMREST_TRANSPORT_SOCK_READ_FAILED;
402
+         }
403
+     }
404
+     BAIL_ON_VMREST_ERROR(dwError);
405
+@@ -936,29 +986,37 @@ VmSockPosixRead(
406
+ 
407
+ error:
408
+ 
409
+-    if (pSocket)
410
+-    {
411
+-        VMREST_LOG_ERROR(pRESTHandle,"Socket read failed with Socket fd %d, dwError = %u, nRead = %d, errno = %u, errorCode = %u", pSocket->fd, dwError, nRead, errno, errorCode);
412
+-    }
413
+-    else
414
+-    {
415
+-        VMREST_LOG_ERROR(pRESTHandle,"Socket read failed with dwError = %u, nRead = %d, errno = %u, errorCode = %u", dwError, nRead, errno, errorCode);
416
+-    }
417
+-
418
+-    if (pszBufPrev && pSocket && pRESTHandle->pSockContext)
419
++    if (pSocket && pRESTHandle->pSockContext)
420
+     {
421
+         /**** Delete the socket from poller ****/
422
+-        
423
+-        VmSockPosixEventQueueDelete_inlock(
424
++            VmSockPosixEventQueueDelete_inlock(
425
+             pRESTHandle->pSockContext->pEventQueue,
426
+             pSocket
427
+             );
428
+-        
429
+-        VmRESTFreeMemory(pszBufPrev);
430
+-        pszBufPrev = NULL;
431
++
432
+         pSocket->pszBuffer = NULL;
433
+         pSocket->nProcessed = 0;
434
+         pSocket->nBufData = 0;
435
++
436
++        if (pSocket->pTimerSocket)
437
++        {
438
++            VmSockPosixReArmTimer(
439
++                pRESTHandle,
440
++                pSocket->pTimerSocket,
441
++                ((pRESTHandle->pRESTConfig->connTimeoutSec) * 1000)
442
++                );
443
++
444
++            write(pSocket->pTimerSocket->fd, "NotifyPQ", 8);
445
++            pSocket->pTimerSocket->pIoSocket = NULL;
446
++            
447
++        }
448
++
449
++    }
450
++
451
++    if (pszBufPrev)
452
++    {   
453
++        VmRESTFreeMemory(pszBufPrev);
454
++        pszBufPrev = NULL;
455
+     }
456
+ 
457
+     if (nBufLen)
458
+@@ -1080,8 +1138,8 @@ VmSockPosixWrite(
459
+ 
460
+ error:
461
+ 
462
+-    VMREST_LOG_ERROR(pRESTHandle,"%s", "Socket write failed");
463
+     goto cleanup;
464
++
465
+ }
466
+ 
467
+ VOID
468
+@@ -1092,10 +1150,6 @@ VmSockPosixReleaseSocket(
469
+ {
470
+     if (pSocket)
471
+     {
472
+-        if (pSocket->pTimerSocket)
473
+-        {
474
+-             VmSockPosixFreeSocket(pSocket->pTimerSocket);
475
+-        }
476
+         VmSockPosixFreeSocket(pSocket);
477
+     }
478
+ }
479
+@@ -1118,22 +1172,21 @@ VmSockPosixCloseSocket(
480
+     }
481
+     BAIL_ON_VMREST_ERROR(dwError);
482
+ 
483
+-    VMREST_LOG_INFO(pRESTHandle,"C-REST-ENGINE: Closing socket with fd %d", pSocket->fd);
484
++    VMREST_LOG_INFO(pRESTHandle,"C-REST-ENGINE: Closing socket with fd %d, Socket Type %u ( 2-Io / 5-Timer )", pSocket->fd, pSocket->type);
485
+ 
486
+     dwError = VmRESTLockMutex(pSocket->pMutex);
487
+     BAIL_ON_VMREST_ERROR(dwError);
488
+ 
489
+     bLocked = TRUE;
490
+ 
491
+-    if (pSocket->pTimerSocket && (pSocket->pTimerSocket->fd > 0))
492
++    if (pSocket->pTimerSocket)
493
+     {
494
+-        close(pSocket->pTimerSocket->fd);
495
+-        pSocket->pTimerSocket->fd = -1;
496
++        pSocket->pTimerSocket->pIoSocket = NULL;
497
+     }
498
+ 
499
+-    if (pRESTHandle->pSSLInfo->isSecure && pSocket->ssl)
500
++    if (pRESTHandle->pSSLInfo->isSecure && pSocket->ssl && (pSocket->type != VM_SOCK_TYPE_TIMER))
501
+     {
502
+-        ret = SSL_shutdown(pSocket->ssl);
503
++        ret =  SSL_shutdown(pSocket->ssl);
504
+         if (ret < 0)
505
+         {
506
+             errorCode = SSL_get_error(pSocket->ssl, ret);
507
+@@ -1149,7 +1202,6 @@ VmSockPosixCloseSocket(
508
+         pSocket->fd = -1;
509
+     }
510
+ 
511
+-
512
+ cleanup:
513
+ 
514
+     if (bLocked)
515
+@@ -1294,6 +1346,12 @@ VmSockPosixEventQueueDelete_inlock(
516
+     DWORD                            dwError = REST_ENGINE_SUCCESS;
517
+     struct                           epoll_event event = {0};
518
+ 
519
++    if (!pSocket || !pQueue)
520
++    {
521
++        dwError = REST_ERROR_INVALID_HANDLER;
522
++    }
523
++    BAIL_ON_VMREST_ERROR(dwError);
524
++
525
+     if (epoll_ctl(pQueue->epollFd, EPOLL_CTL_DEL, pSocket->fd, &event) < 0)
526
+     {
527
+         dwError = VM_SOCK_POSIX_ERROR_SYS_CALL_FAILED;
528
+@@ -1341,6 +1399,7 @@ VmSockPosixAcceptConnection(
529
+     pSocket->pTimerSocket = NULL;
530
+     pSocket->pIoSocket = NULL;
531
+     pSocket->bSSLHandShakeCompleted = FALSE;
532
++    pSocket->bInUse = FALSE;
533
+ 
534
+     *ppSocket = pSocket;
535
+ 
536
+@@ -1560,35 +1619,21 @@ VmSockPosixSetRequestHandle(
537
+ 
538
+     pSocket->nProcessed = nProcessed;
539
+ 
540
+-    /**** Rearm timer and add sockfd back to poller ****/
541
+-    if (!bCompleted)
542
++    if (bCompleted)
543
+     {
544
+-        dwError = VmSockPosixReArmTimer(
545
+-                      pRESTHandle,
546
+-                      pSocket->pTimerSocket,
547
+-                      ((pRESTHandle->pRESTConfig->connTimeoutSec) * 1000)
548
+-                      );
549
+-        BAIL_ON_VMREST_ERROR(dwError);
550
+-
551
+-        event.data.ptr = pSocket;
552
+-        event.events = EPOLLIN;
553
+-
554
+-        event.events = event.events | EPOLLONESHOT;
555
+-
556
+-        if (epoll_ctl(pQueue->epollFd, EPOLL_CTL_MOD, pSocket->fd, &event) < 0)
557
++        /**** We are done with request - no need to add back to poller *****/
558
++        if (pSocket->pTimerSocket != NULL)
559
+         {
560
+-            dwError = VM_SOCK_POSIX_ERROR_SYS_CALL_FAILED;
561
++            pSocket->pTimerSocket->pIoSocket = NULL;
562
++
563
++            /**** Give immediate notification to timer for cleanup ****/
564
++            dwError = VmSockPosixReArmTimer(
565
++                           pRESTHandle,
566
++                           pSocket->pTimerSocket,
567
++                           1
568
++                           );
569
+             BAIL_ON_VMREST_ERROR(dwError);
570
+         }
571
+-    }
572
+-    else
573
+-    {
574
+-        /**** Delete timerfd from poller ****/
575
+-        dwError = VmSockPosixEventQueueDelete_inlock(
576
+-                      pQueue,
577
+-                      pSocket->pTimerSocket
578
+-                      );
579
+-        BAIL_ON_VMREST_ERROR(dwError);
580
+ 
581
+         /**** Delete actual IO socket from poller ****/
582
+         dwError = VmSockPosixEventQueueDelete_inlock(
583
+@@ -1596,13 +1641,37 @@ VmSockPosixSetRequestHandle(
584
+                       pSocket
585
+                       );
586
+         BAIL_ON_VMREST_ERROR(dwError);
587
+-       
588
+-
589
+-        if (pSocket->pTimerSocket->fd > 0)
590
++    }
591
++    else
592
++    {
593
++        /***** Add back IO socket to poller for next IO cycle ****/
594
++        if (pSocket->pTimerSocket == NULL)
595
+         {
596
+-            close(pSocket->pTimerSocket->fd);
597
+-            pSocket->pTimerSocket->fd = -1;
598
+-        } 
599
++            /**** Timeout already happened. Notify HTTP layer to send 408 Req timeout - if possible ****/
600
++            dwError = VMREST_TRANSPORT_DEFERRED_TIMEOUT_PROCESS;
601
++        }
602
++        else
603
++        {
604
++            /*** Rearm timer and add IO socket to poller ****/
605
++            dwError = VmSockPosixReArmTimer(
606
++                           pRESTHandle,
607
++                           pSocket->pTimerSocket,
608
++                           ((pRESTHandle->pRESTConfig->connTimeoutSec) * 1000)
609
++                           );
610
++            BAIL_ON_VMREST_ERROR(dwError);
611
++
612
++            event.data.ptr = pSocket;
613
++            event.events = EPOLLIN;
614
++
615
++            event.events = event.events | EPOLLONESHOT;
616
++
617
++            if (epoll_ctl(pQueue->epollFd, EPOLL_CTL_MOD, pSocket->fd, &event) < 0)
618
++            {
619
++                dwError = VM_SOCK_POSIX_ERROR_SYS_CALL_FAILED;
620
++                BAIL_ON_VMREST_ERROR(dwError);
621
++            }
622
++        }
623
++        BAIL_ON_VMREST_ERROR(dwError);
624
+     }
625
+ 
626
+ cleanup:
627
+@@ -1611,6 +1680,10 @@ VmSockPosixSetRequestHandle(
628
+     {
629
+         VmRESTUnlockMutex(pSocket->pMutex);
630
+     }
631
++    if (!bCompleted && pSocket && (pSocket->pTimerSocket != NULL))
632
++    {
633
++        pSocket->bInUse = FALSE;
634
++    }
635
+ 
636
+     return dwError;
637
+ 
638
+@@ -1702,6 +1775,13 @@ VmSockPosixReArmTimer(
639
+     int                              nSec = 0;
640
+     int                              nNanoSec = 0;
641
+ 
642
++    if (!pRESTHandle || !pTimerSocket )
643
++    {
644
++        VMREST_LOG_ERROR(pRESTHandle,"%s","Invalid params");
645
++        dwError = ERROR_INVALID_PARAMETER;
646
++    }
647
++    BAIL_ON_VMREST_ERROR(dwError);
648
++
649
+     if (milliSec > 0)
650
+     {
651
+         nSec = milliSec / 1000;
652
+@@ -1733,96 +1813,6 @@ VmSockPosixReArmTimer(
653
+ 
654
+ }
655
+ 
656
+-static
657
+-BOOLEAN
658
+-VmSockPosixIsSafeToCloseConnOnTimeOut(
659
+-    PVMREST_HANDLE                   pRESTHandle,
660
+-    PVM_SOCKET                       pTimerSocket
661
+-    )
662
+-{
663
+-    uint32_t                         dwError = REST_ENGINE_SUCCESS;
664
+-    struct                           epoll_event event = {0};
665
+-    BOOLEAN                          bCloseConn = FALSE;
666
+-    ssize_t                          nRead = 0;
667
+-    uint32_t                         errorCode = 0;
668
+-    uint64_t                         res = 0;
669
+-    char                             pBuf = '\0';
670
+-    struct                           itimerspec ts = {0};
671
+-    PVM_SOCKET                       pSocket = NULL;
672
+-
673
+-    if (!pRESTHandle || !pTimerSocket)
674
+-    {
675
+-        VMREST_LOG_ERROR(pRESTHandle,"%s","Invalid params");
676
+-        dwError = ERROR_INVALID_PARAMETER;
677
+-    }
678
+-    BAIL_ON_VMREST_ERROR(dwError);
679
+-
680
+-    pSocket = pTimerSocket->pIoSocket;
681
+-    errno = 0;
682
+-
683
+-    if ((pRESTHandle->pSSLInfo->isSecure) && (pSocket->ssl))
684
+-    {
685
+-        nRead = SSL_read(pSocket->ssl, &pBuf, 0);
686
+-        errorCode = SSL_get_error(pSocket->ssl, nRead);
687
+-    }
688
+-    else if (pSocket->fd > 0)
689
+-    {
690
+-        nRead = read(pSocket->fd, &pBuf, 0);
691
+-        errorCode = errno;
692
+-    }
693
+-    VMREST_LOG_DEBUG(pRESTHandle, "IO socket read bytes %d, errorCode %u, at timer expiration", nRead, errorCode);
694
+-
695
+-    if (errorCode == EAGAIN || errorCode == EWOULDBLOCK || errorCode == SSL_ERROR_WANT_READ)
696
+-    {
697
+-        /**** Check for preceeding reset of timer due to valid IO ****/
698
+-        if (timerfd_gettime(pTimerSocket->fd, &ts) == 0)
699
+-        {
700
+-            if ((ts.it_value.tv_sec == 0) && (ts.it_value.tv_nsec == 0))
701
+-            {
702
+-                /**** timer is still disarmed ****/
703
+-                /**** It's safe to close connection ****/
704
+-                bCloseConn = TRUE;
705
+-            }
706
+-
707
+-            /**** Do a read on timer socket - dummy read ****/
708
+-            do
709
+-            {
710
+-                errorCode = 0;
711
+-                errno = 0;
712
+-                nRead = 0;
713
+-                nRead = read(pTimerSocket->fd, &res, sizeof(res));
714
+-                errorCode = errno;
715
+-                res = 0;
716
+-            }while(nRead > 0);
717
+-
718
+-            if (!bCloseConn)
719
+-            {
720
+-                /**** Add timer socket back to poller ****/
721
+-                event.data.ptr = pTimerSocket;
722
+-                event.events = EPOLLIN;
723
+-                event.events = event.events | EPOLLONESHOT;
724
+-
725
+-                if (epoll_ctl(pRESTHandle->pSockContext->pEventQueue->epollFd, EPOLL_CTL_MOD, pTimerSocket->fd, &event) < 0)
726
+-                {
727
+-                    dwError = VM_SOCK_POSIX_ERROR_SYS_CALL_FAILED;
728
+-                    BAIL_ON_VMREST_ERROR(dwError);
729
+-                }
730
+-            }
731
+-        }
732
+-    }
733
+-
734
+-cleanup:
735
+-
736
+-    return bCloseConn;
737
+-
738
+-error:
739
+-
740
+-    bCloseConn = FALSE;
741
+-
742
+-    goto cleanup;
743
+-
744
+-}
745
+-
746
+ static
747
+ uint32_t
748
+ VmSockPosixCreateTimer(
749
+@@ -1860,6 +1850,7 @@ VmSockPosixCreateTimer(
750
+ 
751
+     pTimerSocket->type = VM_SOCK_TYPE_TIMER;
752
+     pTimerSocket->fd = timerFd;
753
++    pTimerSocket->bInUse = FALSE;
754
+     pTimerSocket->pIoSocket = pSocket;
755
+     pTimerSocket->pRequest = NULL;
756
+     pTimerSocket->pszBuffer = NULL;
757
+@@ -1931,6 +1922,7 @@ VmRESTAcceptSSLContext(
758
+ 
759
+     if (ret == 1)
760
+     {
761
++        VMREST_LOG_DEBUG(pRESTHandle," SSL accept successful on socket %d, ret %d, errorCode %u", pSocket->fd, ret, errorCode);
762
+         pSocket->bSSLHandShakeCompleted = TRUE;
763
+         bReArm = TRUE;
764
+     }
765
+@@ -1940,15 +1932,22 @@ VmRESTAcceptSSLContext(
766
+        pSocket->bSSLHandShakeCompleted = FALSE;
767
+        bReArm = TRUE;
768
+     }
769
++    else if ((ret == 0) && (errorCode == SSL_ERROR_SYSCALL))
770
++    {
771
++         VMREST_LOG_ERROR(pRESTHandle," Client closed the connection during SSL handshake, socket fd %d, ret %d, errorCode %u, errno %d", pSocket->fd, ret, errorCode, errno);
772
++         dwError = VMREST_TRANSPORT_SSL_ACCEPT_FAILED;
773
++         BAIL_ON_VMREST_ERROR(dwError);
774
++    }
775
+     else
776
+     {
777
+-        VMREST_LOG_ERROR(pRESTHandle, "SSL handshake failed...connection will be closed for socket with fd %d, ret %d, errorCode %u", pSocket->fd, ret, errorCode);
778
++        VMREST_LOG_ERROR(pRESTHandle, "SSL handshake failed...connection will be closed for socket with fd %d, ret %d, errorCode %u, errno %d", pSocket->fd, ret, errorCode, errno);
779
+         dwError = VMREST_TRANSPORT_SSL_ACCEPT_FAILED;
780
+         BAIL_ON_VMREST_ERROR(dwError);
781
+     }
782
+ 
783
+      if (bReArm && bWatched)
784
+      {
785
++         /**** Rearm and add the socket ****/
786
+          dwError = VmSockPosixReArmTimer(
787
+                        pRESTHandle,
788
+                        pSocket->pTimerSocket,
789
+@@ -1974,13 +1973,23 @@ VmRESTAcceptSSLContext(
790
+ 
791
+ error:
792
+ 
793
+-    if (bWatched && pRESTHandle && pRESTHandle->pSockContext)
794
++    if (pRESTHandle && pRESTHandle->pSockContext)
795
+     {
796
+         /**** Delete from poller ****/
797
+         VmSockPosixEventQueueDelete_inlock(
798
+             pRESTHandle->pSockContext->pEventQueue,
799
+             pSocket
800
+             );
801
++
802
++        if (bWatched && pSocket && pSocket->pTimerSocket)
803
++        {
804
++            pSocket->pTimerSocket->pIoSocket = NULL;
805
++            VmSockPosixReArmTimer(
806
++                pRESTHandle,
807
++                pSocket->pTimerSocket,
808
++                1
809
++                );
810
++        }
811
+     }
812
+ 
813
+     goto cleanup;
814
+diff --git a/transport/posix/structs.h b/transport/posix/structs.h
815
+index ad5563e..369cfcb 100644
816
+--- a/transport/posix/structs.h
817
+@@ -20,6 +20,7 @@ typedef struct _VM_SOCKET
818
+     int                              fd;
819
+     SSL*                             ssl;
820
+     BOOLEAN                          bSSLHandShakeCompleted;
821
++    BOOLEAN                          bInUse;
822
+     char*                            pszBuffer;
823
+     uint32_t                         nBufData;
824
+     uint32_t                         nProcessed;
0 825
new file mode 100644
... ...
@@ -0,0 +1,57 @@
0
+From 36f7b88cfedf404ff8ef02ed2e2092ca963cb384 Mon Sep 17 00:00:00 2001
1
+From: Kumar Kaushik <kaushikk@vmware.com>
2
+Date: Tue, 30 Jan 2018 18:30:46 -0800
3
+Subject: [PATCH] Improper request line parsing check
4
+
5
+Change-Id: I606bfd18efe8fe9cd4d9cf7533e4991e81c74ae2
6
+---
7
+ server/restengine/httpProtocolHead.c | 14 ++++++++++----
8
+ 1 file changed, 10 insertions(+), 4 deletions(-)
9
+
10
+diff --git a/server/restengine/httpProtocolHead.c b/server/restengine/httpProtocolHead.c
11
+index 95089a3..a7ca54a 100644
12
+--- a/server/restengine/httpProtocolHead.c
13
+@@ -1001,7 +1001,7 @@ VmRESTProcessRequestLine(
14
+         {
15
+             /**** 1. Parsing HTTP METHOD ****/
16
+             pszFirstSpace = strchr(pszStartNewLine, ' ');
17
+-            if (pszFirstSpace != NULL && ((pszFirstSpace - pszStartNewLine) <= MAX_METHOD_LEN))
18
++            if (pszFirstSpace != NULL && ((pszFirstSpace - pszStartNewLine) <= MAX_METHOD_LEN) && ((pszFirstSpace - pszStartNewLine) > 0))
19
+             {
20
+                 strncpy(pRequest->requestLine->method, pszStartNewLine, (pszFirstSpace - pszStartNewLine));
21
+                 pRequest->requestLine->method[pszFirstSpace - pszStartNewLine] = '\0';
22
+@@ -1016,13 +1016,13 @@ VmRESTProcessRequestLine(
23
+                 /**** 2. Parse HTTP URI****/
24
+                 pszSecondSpace = strchr((pszFirstSpace + 1), ' ');
25
+              
26
+-                if (pszSecondSpace != NULL && ((pszSecondSpace - pszFirstSpace) < MAX_URI_LEN))
27
++                if (pszSecondSpace != NULL && ((pszSecondSpace - pszFirstSpace) < MAX_URI_LEN) && ((pszSecondSpace - pszFirstSpace) > 0))
28
+                 {
29
+                     strncpy(pRequest->requestLine->uri, (pszFirstSpace + 1), (pszSecondSpace - pszFirstSpace - 1));
30
+                     pRequest->requestLine->uri[pszSecondSpace - pszFirstSpace - 1] = '\0';
31
+ 
32
+                     /**** 3. Parse HTTP Version ****/
33
+-                    if ((pszEndNewLine - pszSecondSpace - 1) <= HTTP_VER_LEN)
34
++                    if (((pszEndNewLine - pszSecondSpace - 1) <= HTTP_VER_LEN) && ((pszEndNewLine - pszSecondSpace - 1) > 0))
35
+                     {
36
+                         strncpy(pRequest->requestLine->version, (pszSecondSpace + 1), (pszEndNewLine - pszSecondSpace - 1));
37
+                         pRequest->requestLine->version[pszEndNewLine - pszSecondSpace - 1] = '\0';
38
+@@ -1198,10 +1198,16 @@ VmRESTProcessHeaders(
39
+             BAIL_ON_VMREST_ERROR(dwError);
40
+         }
41
+     }
42
+-    else     /**** pszEndNewLine = NULL  ****/
43
++    else if (nBytes < MAX_REQ_LIN_LEN)    /**** pszEndNewLine = NULL  ****/
44
+     {
45
+         VMREST_LOG_DEBUG(pRESTHandle,"Incomplete line processing.. wait for IO.., bytesProcessed %u, nBytes %u", bytesProcessed, nBytes);
46
+     }
47
++    else
48
++    {
49
++        dwError = BAD_REQUEST;
50
++        BAIL_ON_VMREST_ERROR(dwError);
51
++    }
52
++    
53
+ 
54
+ cleanup:
55
+