Browse code

c-rest-engine: Supporting persistent connection

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

Kumar Kaushik authored on 2018/03/23 11:10:10
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.2
4
-Release:       3%{?dist}
4
+Release:       4%{?dist}
5 5
 Group:         Applications/System
6 6
 Vendor:        VMware, Inc.
7 7
 License:       Apache 2.0
... ...
@@ -15,6 +15,8 @@ Source0:       %{name}-%{version}.tar.gz
15 15
 Patch0:        log-file-name.patch
16 16
 Patch1:        preprocess-timeout.patch
17 17
 Patch2:        typo_fixes.patch
18
+Patch3:        ssl_read_error.patch
19
+Patch4:        persistent_connection.patch
18 20
 %define sha1   c-rest-engine=25aa9d1f2680e26114dee18365c510692552f8e4
19 21
 
20 22
 %description
... ...
@@ -36,6 +38,8 @@ development libs and header files for c-rest-engine
36 36
 %patch0 -p1
37 37
 %patch1 -p1
38 38
 %patch2 -p1
39
+%patch3 -p1
40
+%patch4 -p1
39 41
 
40 42
 %build
41 43
 cd build
... ...
@@ -68,6 +72,8 @@ find %{buildroot} -name '*.la' -delete
68 68
 # %doc ChangeLog README COPYING
69 69
 
70 70
 %changelog
71
+*  Thu Mar 22 2018 Kumar Kaushik <kaushikk@vmware.com> 1.2-4
72
+-  Adding support for persistent connection.
71 73
 *  Mon Mar 05 2018 Kumar Kaushik <kaushikk@vmware.com> 1.2-3
72 74
 -  Appying patch for some typo in code.
73 75
 *  Fri Feb 23 2018 Kumar Kaushik <kaushikk@vmware.com> 1.2-2
74 76
new file mode 100644
... ...
@@ -0,0 +1,603 @@
0
+From f8320a22d54e51052478ce6421a9cfc454a4255e Mon Sep 17 00:00:00 2001
1
+From: Kumar Kaushik <kaushikk@vmware.com>
2
+Date: Tue, 20 Mar 2018 16:36:00 -0700
3
+Subject: [PATCH] Support persistent connection
4
+
5
+Change-Id: I05d60c56f5f9e62e5c7b0bd6c10b7fad9e0e329a
6
+---
7
+ common/sockinterface.c                             |  55 +++++---
8
+ include/vmrestcommon.h                             |   7 +
9
+ include/vmsock.h                                   |   4 +-
10
+ server/restengine/httpProtocolHead.c               | 145 +++++++++++----------
11
+ server/restengine/libmain.c                        |   2 +-
12
+ server/restengine/prototype.h                      |   5 -
13
+ test/scripts/BUGS_TC/BUG-2076723/README            |  26 ++++
14
+ .../BUGS_TC/BUG-2076723/persistentConnection.c     | 121 +++++++++++++++++
15
+ transport/api/api.c                                |   4 +-
16
+ transport/posix/prototypes.h                       |   2 +-
17
+ transport/posix/socket.c                           |  27 +++-
18
+ 11 files changed, 288 insertions(+), 110 deletions(-)
19
+ create mode 100644 test/scripts/BUGS_TC/BUG-2076723/README
20
+ create mode 100644 test/scripts/BUGS_TC/BUG-2076723/persistentConnection.c
21
+
22
+diff --git a/common/sockinterface.c b/common/sockinterface.c
23
+index 197dd48..103c69c 100644
24
+--- a/common/sockinterface.c
25
+@@ -476,6 +476,7 @@ VmRESTTcpReceiveNewData(
26
+     uint32_t                         nProcessed = 0;
27
+     uint32_t                         nBufLen = 0;
28
+     BOOLEAN                          bNextIO = FALSE;
29
++    BOOLEAN                          bKeepConnOpen = FALSE;
30
+ 
31
+     if (!pSocket || !pRESTHandle || !pQueue)
32
+     {
33
+@@ -543,6 +544,16 @@ VmRESTTcpReceiveNewData(
34
+     {
35
+         pSetReq = pRequest;
36
+     }
37
++    else
38
++    {
39
++        /**** Verify and act on persistent connection requests ****/
40
++        dwError = VmRESTEntertainPersistentConn(
41
++                      pRESTHandle,
42
++                      pRequest,
43
++                      &bKeepConnOpen
44
++                      );
45
++        BAIL_ON_VMREST_ERROR(dwError);
46
++    }
47
+ 
48
+     /**** Save state of request processing in socket context ****/
49
+     dwError = VmwSockSetRequestHandle(
50
+@@ -550,31 +561,35 @@ VmRESTTcpReceiveNewData(
51
+                   pSocket,
52
+                   pSetReq,
53
+                   nProcessed,
54
+-                  pQueue
55
++                  bKeepConnOpen
56
+                   );
57
+     BAIL_ON_VMREST_ERROR(dwError);
58
+ 
59
+ cleanup:
60
+ 
61
+-   if (!bNextIO && dwError != REST_ENGINE_ERROR_DOUBLE_FAILURE)
62
+-   {
63
+-       VMREST_LOG_DEBUG(pRESTHandle,"%s","Calling closed connection....");
64
+-       /**** Close connection ****/ 
65
+-       VmRESTDisconnectClient(
66
+-           pRESTHandle,
67
+-           pSocket
68
+-           );
69
+-
70
+-       /****  free request object memory ****/
71
+-       if (pRequest)
72
+-       {
73
+-           VmRESTFreeRequestHandle(
74
+-               pRESTHandle,
75
+-               pRequest
76
+-               );
77
+-           pRequest = NULL;
78
+-       }
79
+-   }
80
++    if (!bNextIO && dwError != REST_ENGINE_ERROR_DOUBLE_FAILURE)
81
++    {
82
++
83
++        if (!bKeepConnOpen)
84
++        {
85
++            VMREST_LOG_DEBUG(pRESTHandle,"%s","Calling closed connection....");
86
++            /**** Close connection ****/
87
++            VmRESTDisconnectClient(
88
++                pRESTHandle,
89
++                pSocket
90
++                );
91
++        }
92
++
93
++        /****  free request object memory ****/
94
++        if (pRequest)
95
++        {
96
++            VmRESTFreeRequestHandle(
97
++                pRESTHandle,
98
++                pRequest
99
++                );
100
++            pRequest = NULL;
101
++        }
102
++    }
103
+ 
104
+     return dwError;
105
+ 
106
+diff --git a/include/vmrestcommon.h b/include/vmrestcommon.h
107
+index 3b7f17c..16f90ad 100644
108
+--- a/include/vmrestcommon.h
109
+@@ -350,6 +350,13 @@ VmRESTProcessBuffer(
110
+     uint32_t*                        nProcessed
111
+     );
112
+ 
113
++uint32_t
114
++VmRESTEntertainPersistentConn(
115
++    PVMREST_HANDLE                   pRESTHandle,
116
++    PREST_REQUEST                    pRequest,
117
++    BOOLEAN*                         bKeepOpen
118
++    );
119
++
120
+ uint32_t
121
+ VmRESTSendFailureResponse(
122
+      PVMREST_HANDLE                  pRESTHandle,
123
+diff --git a/include/vmsock.h b/include/vmsock.h
124
+index 5075aa7..5213e67 100644
125
+--- a/include/vmsock.h
126
+@@ -265,7 +265,7 @@ VmwSockSetRequestHandle(
127
+     PVM_SOCKET                       pSocket,
128
+     PREST_REQUEST                    pRequest,
129
+     uint32_t                         nProcessed,
130
+-    PVM_SOCK_EVENT_QUEUE             pQueue
131
++    BOOLEAN                          bPersistentConn
132
+     );
133
+ 
134
+ DWORD
135
+@@ -368,7 +368,7 @@ typedef DWORD(*PFN_SET_REQUEST_HANDLE)(
136
+                     PVM_SOCKET            pSocket,
137
+                     PREST_REQUEST         pRequest,
138
+                     uint32_t              nProcessed,
139
+-                    PVM_SOCK_EVENT_QUEUE  pQueue
140
++                    BOOLEAN               bPersistentConn
141
+                     );
142
+ 
143
+ typedef DWORD(*PFN_GET_PEER_INFO)(
144
+diff --git a/server/restengine/httpProtocolHead.c b/server/restengine/httpProtocolHead.c
145
+index c5b9f3c..be3ff09 100644
146
+--- a/server/restengine/httpProtocolHead.c
147
+@@ -783,77 +783,6 @@ VmRESTSendHeaderAndPayload(
148
+     goto cleanup;
149
+ }
150
+ 
151
+-uint32_t
152
+-VmRESTCloseClient(
153
+-    PVM_REST_HTTP_RESPONSE_PACKET    pResPacket
154
+-    )
155
+-{
156
+-    uint32_t                         dwError = REST_ENGINE_SUCCESS;
157
+-    char*                            connection = NULL;
158
+-    uint32_t                         closeSocket = 1;
159
+-    char*                            statusStartChar = NULL;
160
+-
161
+-    if (!pResPacket)
162
+-    {
163
+-        dwError = VMREST_HTTP_INVALID_PARAMS;
164
+-    }
165
+-    BAIL_ON_VMREST_ERROR(dwError);
166
+-
167
+-    /**** Look for response status ****/
168
+-    statusStartChar = pResPacket->statusLine->statusCode;
169
+-
170
+-    if(statusStartChar != NULL && (*statusStartChar == '4' || *statusStartChar == '5'))
171
+-    {
172
+-        /**** Failure response sent, must close client ****/
173
+-        closeSocket = 1;
174
+-    }
175
+-    else
176
+-    {
177
+-        /**** Non failure response sent, respect client say on connection close ****/
178
+-        if (pResPacket->requestPacket != NULL)
179
+-        {
180
+-            dwError = VmRESTGetHttpHeader(
181
+-                          pResPacket->requestPacket,
182
+-                          "Connection",
183
+-                          &connection
184
+-                          );
185
+-        }
186
+-
187
+-        if ((connection != NULL) && (strcmp(connection, " keep-alive") == 0))
188
+-        {
189
+-            closeSocket = 0;
190
+-        }
191
+-    }
192
+-    if (closeSocket == 1)
193
+-    {
194
+-        /**** TODO: Inform transport to close connection else MUST NOT close it****/
195
+-    }
196
+-
197
+-    /**** Free all associcated request and response object memory ****/
198
+-    if (pResPacket->requestPacket)
199
+-    {
200
+-        VmRESTFreeHTTPRequestPacket(
201
+-            &(pResPacket->requestPacket)
202
+-            );
203
+-        pResPacket->requestPacket = NULL;
204
+-    }
205
+-        
206
+-    VmRESTFreeHTTPResponsePacket(
207
+-        &pResPacket
208
+-        );
209
+-    BAIL_ON_VMREST_ERROR(dwError);
210
+-
211
+-cleanup:
212
+-    if (connection != NULL)
213
+-    {
214
+-        VmRESTFreeMemory(connection);
215
+-        connection = NULL;
216
+-    }
217
+-    return dwError;
218
+-error:
219
+-    goto cleanup;
220
+-}
221
+-
222
+ uint32_t
223
+ VmRESTGetRequestHandle(
224
+     PVMREST_HANDLE                   pRESTHandle,
225
+@@ -1360,7 +1289,6 @@ VmRESTProcessBuffer(
226
+     }
227
+     BAIL_ON_VMREST_ERROR(dwError);
228
+ 
229
+-
230
+     /**** Get the request processing state ****/
231
+     currState = pRequest->state;
232
+     *nBytesProcessed = 0;
233
+@@ -1692,3 +1620,76 @@ VmRESTSetHttpPayloadZeroCopy(
234
+     VMREST_LOG_ERROR(pRESTHandle,"%s","Set Zero copy payload Failed");
235
+     goto cleanup;
236
+ }
237
++
238
++uint32_t
239
++VmRESTEntertainPersistentConn(
240
++    PVMREST_HANDLE                   pRESTHandle,
241
++    PREST_REQUEST                    pRequest,
242
++    BOOLEAN*                         bKeepOpen
243
++    )
244
++{
245
++    uint32_t                         dwError = REST_ENGINE_SUCCESS;
246
++    char*                            pszKeepAliveRequest = NULL;
247
++    char*                            pszKeepAliveResponse = NULL;
248
++    BOOLEAN                          bKeepConnOpen = FALSE;
249
++
250
++    if (!pRESTHandle || !pRequest || !bKeepOpen || !pRequest->pResponse)
251
++    {
252
++        VMREST_LOG_ERROR(pRESTHandle,"%s","Invalid params");
253
++        dwError = VMREST_HTTP_INVALID_PARAMS;
254
++    }
255
++
256
++    /**** Get client's say on persistent connection ****/
257
++    dwError = VmRESTGetHttpHeader(
258
++                  pRequest,
259
++                  "Connection",
260
++                  &pszKeepAliveRequest
261
++                  );
262
++    BAIL_ON_VMREST_ERROR(dwError);
263
++
264
++    if ((pszKeepAliveRequest != NULL) && (strncmp(pszKeepAliveRequest, "keep-alive", strlen("keep-alive")) == 0))
265
++    {
266
++        bKeepConnOpen = TRUE;
267
++    }
268
++
269
++    /**** Inspect application response on connection (set from application callback) ****/
270
++    if (bKeepConnOpen)
271
++    {
272
++        dwError = VmRESTGetHttpResponseHeader(
273
++                      pRequest->pResponse,
274
++                      "Connection",
275
++                      &pszKeepAliveResponse
276
++                      );
277
++        BAIL_ON_VMREST_ERROR(dwError);
278
++
279
++        if (!((pszKeepAliveResponse != NULL) && (strncmp(pszKeepAliveResponse, "keep-alive", strlen("keep-alive")) == 0)))
280
++        {
281
++            VMREST_LOG_WARNING(pRESTHandle,"%s","Client's request for persistent connection not entertained by server");
282
++            bKeepConnOpen = FALSE;
283
++        }
284
++    }
285
++
286
++    *bKeepOpen = bKeepConnOpen;
287
++
288
++cleanup:
289
++
290
++    if (pszKeepAliveRequest)
291
++    {
292
++        VmRESTFreeMemory(
293
++            pszKeepAliveRequest
294
++            );
295
++        pszKeepAliveRequest = NULL;
296
++    }
297
++
298
++    return dwError;
299
++
300
++error:
301
++
302
++    if (bKeepOpen)
303
++    {
304
++        *bKeepOpen = FALSE;
305
++    }
306
++
307
++    goto cleanup;
308
++}    
309
++
310
+diff --git a/server/restengine/libmain.c b/server/restengine/libmain.c
311
+index 3992b76..e227a76 100644
312
+--- a/server/restengine/libmain.c
313
+@@ -612,7 +612,7 @@ VmRESTSetSuccessResponse(
314
+                   );
315
+     BAIL_ON_VMREST_ERROR(dwError);
316
+ 
317
+-    if ((connection != NULL) && (strcmp(connection, " keep-alive") == 0))
318
++    if ((connection != NULL) && ((strncmp(connection, "keep-alive", strlen("keep-alive")) == 0)))
319
+     {
320
+         dwError = VmRESTSetHttpHeader(
321
+                       ppResponse,
322
+diff --git a/server/restengine/prototype.h b/server/restengine/prototype.h
323
+index dfb8bda..d4dcf51 100644
324
+--- a/server/restengine/prototype.h
325
+@@ -116,11 +116,6 @@ VmRESTTriggerAppCb(
326
+     PVM_REST_HTTP_RESPONSE_PACKET*   ppResponse
327
+     );
328
+ 
329
+-uint32_t
330
+-VmRESTCloseClient(
331
+-    PVM_REST_HTTP_RESPONSE_PACKET    pResPacket
332
+-    );
333
+-
334
+ uint32_t
335
+ VmRESTSetHttpPayloadZeroCopy(
336
+     PVMREST_HANDLE                   pRESTHandle,
337
+diff --git a/test/scripts/BUGS_TC/BUG-2076723/README b/test/scripts/BUGS_TC/BUG-2076723/README
338
+new file mode 100644
339
+index 0000000..79cf1a2
340
+--- /dev/null
341
+@@ -0,0 +1,26 @@
342
++Bugzilla Id: 2076723
343
++
344
++Category: New feature/Critical
345
++
346
++Description:
347
++In secure version (HTTPS) of c-rest-engine, all connection requests are transactional. 
348
++This means each request is served via new connection. This introduces steps involving 
349
++openssl handshake which is known to cause significant performance delays.
350
++
351
++Requirements:
352
++1. Re-use TCP connections originating from same host and port to server.
353
++2. Support HTTP header "connection: keep-alive"
354
++
355
++Feature Testing:
356
++Use available libcurl based client to open one single connection and send multiple
357
++HTTP(S) request.
358
++
359
++Steps to test.
360
++1. Compile the persistentConnection.c file with the following command.
361
++   "gcc -o persistentConnection persistentConnection.c -lcurl"
362
++2. Run the test with following command.
363
++   "./persistentConnection https://<SERVER_IP>:<PORT>/v1/pkg?x=y 2>/dev/null"
364
++
365
++   Example:
366
++   "./persistentConnection https://172.16.127.131:81/v1/pkg?x=y 2>/dev/null"
367
++
368
+diff --git a/test/scripts/BUGS_TC/BUG-2076723/persistentConnection.c b/test/scripts/BUGS_TC/BUG-2076723/persistentConnection.c
369
+new file mode 100644
370
+index 0000000..e0f83e6
371
+--- /dev/null
372
+@@ -0,0 +1,121 @@
373
++/**************************************************************************
374
++* This test client uses libcurl to open connection to server and re-uses
375
++* the same connection to send multiple HTTPS requests.
376
++**************************************************************************/
377
++
378
++
379
++#include <stdio.h>
380
++#include <unistd.h>
381
++#include <curl/curl.h>
382
++#include <stdlib.h>
383
++#include <string.h>
384
++
385
++
386
++struct string
387
++{
388
++    char                            *ptr;
389
++    size_t                          len;
390
++};
391
++
392
++void init_string(struct string *s)
393
++{
394
++      s->len = 0;
395
++      s->ptr = malloc(s->len+1);
396
++      if (s->ptr == NULL)
397
++      {
398
++          fprintf(stderr, "malloc() failed\n");
399
++          exit(EXIT_FAILURE);
400
++      }
401
++      s->ptr[0] = '\0';
402
++}
403
++
404
++size_t writefunc(void *ptr, size_t size, size_t nmemb, struct string *s)
405
++{
406
++    size_t                           new_len = s->len + size*nmemb;
407
++    s->ptr = realloc(s->ptr, new_len+1);
408
++    if (s->ptr == NULL)
409
++    {
410
++        fprintf(stderr, "realloc() failed\n");
411
++        exit(EXIT_FAILURE);
412
++    }
413
++    memcpy(s->ptr+s->len, ptr, size*nmemb);
414
++    s->ptr[new_len] = '\0';
415
++    s->len = new_len;
416
++    return size*nmemb;
417
++}
418
++
419
++int main (int argc, char *argv[])
420
++{
421
++    CURL*                            curl = NULL;
422
++    CURLcode                         res = 0;
423
++    int                              ct = 0;
424
++    char                             expected[512] = {0};
425
++
426
++    if (argc != 2) {
427
++        printf("Wrong number of arguments supplied to test program\n");
428
++        exit(1);
429
++    }
430
++
431
++    struct string s;
432
++    curl_global_init(CURL_GLOBAL_ALL);
433
++
434
++    curl = curl_easy_init();
435
++    if(curl)
436
++    {
437
++try:
438
++        init_string(&s);
439
++        struct curl_slist *chunk = NULL;
440
++
441
++        curl_easy_setopt(curl, CURLOPT_VERBOSE, 1L);
442
++        curl_easy_setopt(curl, CURLOPT_HEADER, 1L);
443
++        curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0L);
444
++        curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 0L);
445
++        curl_easy_setopt(curl, CURLOPT_TCP_KEEPALIVE, 1L);
446
++
447
++        if (ct == 500)
448
++        {
449
++            chunk = curl_slist_append(chunk, "Connection:close");
450
++            strcpy(expected,"HTTP/1.1 200 OK\r\nConnection:close\r\nContent-Length:13\r\n\r\nKumar Kaushik");
451
++        }
452
++        else
453
++        {
454
++            chunk = curl_slist_append(chunk, "Connection:keep-alive");
455
++            strcpy(expected,"HTTP/1.1 200 OK\r\nConnection:keep-alive\r\nContent-Length:13\r\n\r\nKumar Kaushik");
456
++        }
457
++        curl_easy_setopt(curl, CURLOPT_HTTPHEADER, chunk);
458
++
459
++        curl_easy_setopt(curl, CURLOPT_POSTFIELDS, "Kumar Kaushik");
460
++        curl_easy_setopt(curl, CURLOPT_URL, argv[1]);
461
++
462
++        curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, writefunc);
463
++        curl_easy_setopt(curl, CURLOPT_WRITEDATA, &s);
464
++        res = curl_easy_perform(curl);
465
++        if(res != CURLE_OK)
466
++        {
467
++            fprintf(stderr, "curl_easy_perform() failed: %s\n", curl_easy_strerror(res));
468
++        }
469
++
470
++        if (strcmp(expected, s.ptr) == 0)
471
++        {
472
++            printf("Test passed, iteration %d\n", ct);
473
++        }
474
++        else
475
++        {
476
++           printf("Test failed, iteration %d\n", ct);
477
++        }
478
++        //printf("\n===============\n%s\n==========\n", s.ptr);
479
++        free(s.ptr);
480
++
481
++        ct++;
482
++
483
++        if (ct <= 500)
484
++        {
485
++            goto try;
486
++        }
487
++
488
++        curl_easy_cleanup(curl);
489
++    }
490
++
491
++  return 0;
492
++}
493
++
494
+diff --git a/transport/api/api.c b/transport/api/api.c
495
+index cc2c930..5389ff0 100644
496
+--- a/transport/api/api.c
497
+@@ -268,12 +268,12 @@ VmwSockSetRequestHandle(
498
+     PVM_SOCKET                       pSocket,
499
+     PREST_REQUEST                    pRequest,
500
+     uint32_t                         nProcessed,
501
+-    PVM_SOCK_EVENT_QUEUE             pQueue
502
++    BOOLEAN                          bPersistentConn
503
+     )
504
+ {
505
+      DWORD                            dwError = REST_ENGINE_SUCCESS;
506
+ 
507
+-     dwError = pRESTHandle->pPackage->pfnSetRequestHandle(pRESTHandle,pSocket,pRequest, nProcessed, pQueue);
508
++     dwError = pRESTHandle->pPackage->pfnSetRequestHandle(pRESTHandle,pSocket,pRequest, nProcessed, bPersistentConn);
509
+ 
510
+      return dwError;
511
+ }
512
+diff --git a/transport/posix/prototypes.h b/transport/posix/prototypes.h
513
+index d60e5e2..b1e4b57 100644
514
+--- a/transport/posix/prototypes.h
515
+@@ -101,7 +101,7 @@ VmSockPosixSetRequestHandle(
516
+     PVM_SOCKET                       pSocket,
517
+     PREST_REQUEST                    pRequest,
518
+     uint32_t                         nProcessed,
519
+-    PVM_SOCK_EVENT_QUEUE             pQueue
520
++    BOOLEAN                          bKeepAlive
521
+     );
522
+ 
523
+ DWORD
524
+diff --git a/transport/posix/socket.c b/transport/posix/socket.c
525
+index 982ae5c..f50356d 100644
526
+--- a/transport/posix/socket.c
527
+@@ -1592,7 +1592,7 @@ VmSockPosixSetRequestHandle(
528
+     PVM_SOCKET                       pSocket,
529
+     PREST_REQUEST                    pRequest,
530
+     uint32_t                         nProcessed,
531
+-    PVM_SOCK_EVENT_QUEUE             pQueue
532
++    BOOLEAN                          bPersistentConn
533
+     )
534
+ {
535
+     uint32_t                         dwError = REST_ENGINE_SUCCESS;
536
+@@ -1600,7 +1600,7 @@ VmSockPosixSetRequestHandle(
537
+     BOOLEAN                          bCompleted = FALSE;
538
+     struct                           epoll_event event = {0};
539
+ 
540
+-    if (!pSocket || !pRESTHandle || !pQueue)
541
++    if (!pSocket || !pRESTHandle || !pRESTHandle->pSockContext || !pRESTHandle->pSockContext->pEventQueue)
542
+     {
543
+         VMREST_LOG_ERROR(pRESTHandle, "%s", "Invalid params ...");
544
+         dwError = ERROR_INVALID_PARAMETER;
545
+@@ -1615,14 +1615,28 @@ VmSockPosixSetRequestHandle(
546
+     if (pRequest)
547
+     {
548
+         pSocket->pRequest = pRequest;
549
++        pSocket->nProcessed = nProcessed;
550
+     }
551
+     else
552
+     {
553
+         pSocket->pRequest = NULL;
554
+-        bCompleted = TRUE;
555
+-    }
556
+ 
557
+-    pSocket->nProcessed = nProcessed;
558
++        if (bPersistentConn)
559
++        {
560
++            /**** reset the socket object for new request *****/
561
++            if (pSocket->pszBuffer)
562
++            {
563
++                VmRESTFreeMemory(pSocket->pszBuffer);
564
++                pSocket->pszBuffer = NULL;
565
++            }
566
++            pSocket->nProcessed = 0;
567
++            pSocket->nBufData = 0;
568
++        }
569
++        else
570
++        {
571
++            bCompleted = TRUE;
572
++        }
573
++    }
574
+ 
575
+     if (!bCompleted)
576
+     {
577
+@@ -1639,7 +1653,7 @@ VmSockPosixSetRequestHandle(
578
+ 
579
+         event.events = event.events | EPOLLONESHOT;
580
+ 
581
+-        if (epoll_ctl(pQueue->epollFd, EPOLL_CTL_MOD, pSocket->fd, &event) < 0)
582
++        if (epoll_ctl(pRESTHandle->pSockContext->pEventQueue->epollFd, EPOLL_CTL_MOD, pSocket->fd, &event) < 0)
583
+         {
584
+             dwError = VM_SOCK_POSIX_ERROR_SYS_CALL_FAILED;
585
+         }
586
+@@ -1659,7 +1673,6 @@ VmSockPosixSetRequestHandle(
587
+ 
588
+     goto cleanup;
589
+     
590
+-
591
+ }
0 592
new file mode 100644
... ...
@@ -0,0 +1,25 @@
0
+From ce1e44ec82c5725e03f1e7f811cffe2c4c163094 Mon Sep 17 00:00:00 2001
1
+From: Kumar Kaushik <kaushikk@vmware.com>
2
+Date: Fri, 16 Mar 2018 12:05:35 -0700
3
+Subject: [PATCH] Extra SSL_read error case handling
4
+
5
+Change-Id: I39cb4beca2c82f8ad46eaf452ac6a09727c2e583
6
+---
7
+ transport/posix/socket.c | 4 +++-
8
+ 1 file changed, 3 insertions(+), 1 deletion(-)
9
+
10
+diff --git a/transport/posix/socket.c b/transport/posix/socket.c
11
+index 355610f..982ae5c 100644
12
+--- a/transport/posix/socket.c
13
+@@ -940,7 +940,9 @@ VmSockPosixRead(
14
+ 
15
+     if (nRead == -1)
16
+     {
17
+-        if (((pSocket->fd > 0) && (errorCode == EAGAIN || errorCode == EWOULDBLOCK)) || ((pRESTHandle->pSSLInfo->isSecure) && (errorCode == SSL_ERROR_WANT_READ)))
18
++        if (((pSocket->fd > 0) && (errorCode == EAGAIN || errorCode == EWOULDBLOCK)) || 
19
++           ((pRESTHandle->pSSLInfo->isSecure) && 
20
++           ((errorCode == SSL_ERROR_WANT_READ) || ((errorCode == SSL_ERROR_SSL) && (errno == EAGAIN)))))
21
+         {
22
+             dwError = REST_ENGINE_SUCCESS;
23
+         }