source: cheroxy/trunk/src/CRXHttpResponse.cpp@ 24

Last change on this file since 24 was 24, checked in by cheese, 11 years ago

#1 change response, threading and proxy work-flow

File size: 4.7 KB
Line 
1/**
2 * CRXHttpResponse.cpp
3 */
4#ifdef _WIN32
5# pragma warning (disable:4996)
6#endif
7
8#include "CRXHttpResponse.h"
9
10#include <stdio.h>
11#include <stdlib.h>
12
13#define CRLF "\r\n"
14#define CRLF2 "\r\n\r\n"
15
16#define CONTENT_LENGTH "Content-Length: "
17#define TRANSFER_ENCODING "Transfer-Encoding: "
18
19CRXHttpResponse::CRXHttpResponse (void)
20 : mStatusCode (0),
21 mIsChunked (false),
22 mContentLength (0)
23{
24 memset (&mContent, 0x00, sizeof (mContent));
25}
26
27CRXHttpResponse::~CRXHttpResponse (void)
28{
29 ResetContent ();
30}
31
32void
33CRXHttpResponse::ResetContent (void)
34{
35 if (mContent.mBody)
36 free (mContent.mBody);
37
38 memset (&mContent, 0x00, sizeof (mContent));
39}
40
41int
42CRXHttpResponse::SetResponse (const char * aHttpResponse,
43 const int aResponseLength)
44{
45 int aResult = 0;
46
47 const char * aEndOfHeader = NULL;
48 std::string aHeader;
49
50 int aHeaderLength = 0;
51 int aBodyLength = 0;
52
53 /*----------------------------------------------------------------*/
54 if (aResponseLength <= 0)
55 return ERROR_HTTP_RESPONSE_INVALID_LENGTH;
56
57 if (GetHeader ().length () == 0)
58 {
59 aEndOfHeader = strstr (aHttpResponse, CRLF2);
60 if (aEndOfHeader == NULL)
61 return ERROR_HTTP_RESPONSE_INVALID_FORMAT;
62
63 aEndOfHeader += strlen (CRLF2);
64 aHeaderLength = aEndOfHeader - aHttpResponse;
65 aHeader.assign (aHttpResponse, aHeaderLength);
66
67 SetMessage (aHeader.c_str ());
68 }
69
70 aResult = ParseContent (aHttpResponse + aHeaderLength, aResponseLength - aHeaderLength);
71 if (aResult)
72 {
73 return ERROR_HTTP_RESPONSE_FAILED_TO_PARSE_CONTENT;
74 }
75 /*----------------------------------------------------------------*/
76
77 return aResult;
78}
79
80CRXHttpResponse &
81CRXHttpResponse::operator = (const char * aHttpMessage)
82{
83 SetMessage (aHttpMessage);
84 return *this;
85}
86
87std::string
88CRXHttpResponse::GetHeader (void) const
89{
90 return GetMessage ();
91}
92
93int
94CRXHttpResponse::GetStatusCode (void) const
95{
96 return mStatusCode;
97}
98
99int
100CRXHttpResponse::GetContentLength (void) const
101{
102 return mContentLength;
103}
104
105const char *
106CRXHttpResponse::GetContentBody (void) const
107{
108 return mContent.mBody;
109}
110
111void
112CRXHttpResponse::Parse (void)
113{
114 std::string aValue;
115
116 char aStatusCode[64] = {0x00, };
117 char aStatusName[64] = {0x00, };
118 char aHttpVersion[64] = {0x00, };
119
120 size_t aBegin = 0;
121 size_t aOffset = 0;
122 char aBuffer[12] = {0x00, };
123
124 /*----------------------------------------------------------------*/
125 aValue = GetHeader ().substr (0, GetHeader ().find (CRLF, 0));
126
127 /*----------------------------------------------------------------
128 * 1. separate first line to <METHOD>, <URL> and <VERSION>
129 *----------------------------------------------------------------*/
130 sscanf (aValue.c_str (), "%[^ ] %[^ ] %[^ ]\r\n", aHttpVersion, aStatusCode, aStatusName);
131 mHttpVersion.assign (aHttpVersion);
132 mStatusString.assign (aStatusName);
133 mStatusCode = atoi (aStatusCode);
134
135 /*----------------------------------------------------------------
136 * 2. get Content-Length or check is chunked
137 *----------------------------------------------------------------*/
138 aBegin = GetHeader ().find (CONTENT_LENGTH);
139 if (aBegin == std::string::npos)
140 {
141 /* is really chunked encoding ? */
142 aBegin = GetHeader ().find (TRANSFER_ENCODING);
143 if (aBegin == std::string::npos)
144 return ;
145
146 aBegin += strlen (TRANSFER_ENCODING);
147 aOffset = GetHeader ().find (CRLF, aBegin) - aBegin;
148
149 aValue = GetHeader ().substr (aBegin, aOffset);
150 if (aValue == "chunked")
151 {
152 mIsChunked = true;
153 return ;
154 }
155 }
156
157 aBegin += strlen (CONTENT_LENGTH);
158 aOffset = GetHeader ().find (CRLF, aBegin) - aBegin;
159
160 aValue = GetHeader ().substr (aBegin, aOffset);
161 mContentLength = atoi (aValue.c_str ());
162 /*----------------------------------------------------------------*/
163}
164
165int
166CRXHttpResponse::ParseContent (const char * aContent,
167 const int aLength)
168{
169 int aResult = 0;
170
171 char * aReallocPtr = NULL;
172
173 /*----------------------------------------------------------------*/
174
175 if (!mIsChunked)
176 {
177 if (mContentLength <= mContent.mLength)
178 return aResult;
179
180 if (mContent.mBody == NULL)
181 {
182 mContent.mBody = static_cast<char *> (calloc (mContentLength, 1));
183 if (mContent.mBody == NULL)
184 {
185 return ERROR_HTTP_RESPONSE_FAILED_TO_MEMORY_ALLOCATION;
186 }
187 }
188 }
189 else
190 {
191 mContentLength += aLength;
192 aReallocPtr = static_cast<char *> (realloc (mContent.mBody, mContentLength));
193 if (aReallocPtr == NULL)
194 {
195 return ERROR_HTTP_RESPONSE_FAILED_TO_MEMORY_ALLOCATION;
196 }
197 mContent.mBody = aReallocPtr;
198 }
199
200 memcpy (mContent.mBody + mContent.mLength, aContent, aLength);
201 mContent.mLength += aLength;
202 /*----------------------------------------------------------------*/
203
204 return aResult;
205}
Note: See TracBrowser for help on using the repository browser.