publish final code

Fork of Pubnub_c_core by Srdjan Veljkovic

Committer:
sveljko
Date:
Thu Nov 10 22:20:11 2016 +0000
Revision:
0:d13755cfb705
Initial commit of Pubnub C-core

Who changed what in which revision?

UserRevisionLine numberNew contents of line
sveljko 0:d13755cfb705 1 /* -*- c-file-style:"stroustrup"; indent-tabs-mode: nil -*- */
sveljko 0:d13755cfb705 2 #include "pubnub_internal.h"
sveljko 0:d13755cfb705 3
sveljko 0:d13755cfb705 4 #include "pubnub_assert.h"
sveljko 0:d13755cfb705 5 #include "pubnub_log.h"
sveljko 0:d13755cfb705 6 #include "pubnub_ccore.h"
sveljko 0:d13755cfb705 7 #include "pbpal.h"
sveljko 0:d13755cfb705 8
sveljko 0:d13755cfb705 9 #include <string.h>
sveljko 0:d13755cfb705 10
sveljko 0:d13755cfb705 11
sveljko 0:d13755cfb705 12 static void outcome_detected(struct pubnub_ *pb, enum pubnub_res rslt)
sveljko 0:d13755cfb705 13 {
sveljko 0:d13755cfb705 14 pb->core.last_result = rslt;
sveljko 0:d13755cfb705 15 if (pbpal_close(pb) <= 0) {
sveljko 0:d13755cfb705 16 pbpal_forget(pb);
sveljko 0:d13755cfb705 17 pbntf_trans_outcome(pb);
sveljko 0:d13755cfb705 18 }
sveljko 0:d13755cfb705 19 else {
sveljko 0:d13755cfb705 20 pb->state = PBS_WAIT_CLOSE;
sveljko 0:d13755cfb705 21 }
sveljko 0:d13755cfb705 22 }
sveljko 0:d13755cfb705 23
sveljko 0:d13755cfb705 24
sveljko 0:d13755cfb705 25 static enum pubnub_res parse_pubnub_result(struct pubnub_ *pb)
sveljko 0:d13755cfb705 26 {
sveljko 0:d13755cfb705 27 enum pubnub_res pbres = PNR_OK;
sveljko 0:d13755cfb705 28 switch (pb->trans) {
sveljko 0:d13755cfb705 29 case PBTT_SUBSCRIBE:
sveljko 0:d13755cfb705 30 if (pbcc_parse_subscribe_response(&pb->core) != 0) {
sveljko 0:d13755cfb705 31 PUBNUB_LOG_WARNING("parse_subscribe failed\n");
sveljko 0:d13755cfb705 32 pbres = PNR_FORMAT_ERROR;
sveljko 0:d13755cfb705 33 }
sveljko 0:d13755cfb705 34 break;
sveljko 0:d13755cfb705 35 case PBTT_PUBLISH:
sveljko 0:d13755cfb705 36 pbres = pbcc_parse_publish_response(&pb->core);
sveljko 0:d13755cfb705 37 if (pbres != PNR_OK) {
sveljko 0:d13755cfb705 38 PUBNUB_LOG_WARNING("parse_publish failed\n");
sveljko 0:d13755cfb705 39 }
sveljko 0:d13755cfb705 40 break;
sveljko 0:d13755cfb705 41 case PBTT_TIME:
sveljko 0:d13755cfb705 42 if (pbcc_parse_time_response(&pb->core) != 0) {
sveljko 0:d13755cfb705 43 PUBNUB_LOG_WARNING("parse_time failed\n");
sveljko 0:d13755cfb705 44 pbres = PNR_FORMAT_ERROR;
sveljko 0:d13755cfb705 45 }
sveljko 0:d13755cfb705 46 break;
sveljko 0:d13755cfb705 47 case PBTT_HISTORY:
sveljko 0:d13755cfb705 48 if (pbcc_parse_history_response(&pb->core) != 0) {
sveljko 0:d13755cfb705 49 PUBNUB_LOG_WARNING("parse_history failed\n");
sveljko 0:d13755cfb705 50 pbres = PNR_FORMAT_ERROR;
sveljko 0:d13755cfb705 51 }
sveljko 0:d13755cfb705 52 break;
sveljko 0:d13755cfb705 53 case PBTT_LEAVE:
sveljko 0:d13755cfb705 54 case PBTT_HERENOW:
sveljko 0:d13755cfb705 55 case PBTT_GLOBAL_HERENOW:
sveljko 0:d13755cfb705 56 case PBTT_WHERENOW:
sveljko 0:d13755cfb705 57 case PBTT_SET_STATE:
sveljko 0:d13755cfb705 58 case PBTT_STATE_GET:
sveljko 0:d13755cfb705 59 case PBTT_HEARTBEAT:
sveljko 0:d13755cfb705 60 if (pbcc_parse_presence_response(&pb->core) != 0) {
sveljko 0:d13755cfb705 61 PUBNUB_LOG_WARNING("parse_presence failed\n");
sveljko 0:d13755cfb705 62 pbres = PNR_FORMAT_ERROR;
sveljko 0:d13755cfb705 63 }
sveljko 0:d13755cfb705 64 break;
sveljko 0:d13755cfb705 65 case PBTT_REMOVE_CHANNEL_GROUP:
sveljko 0:d13755cfb705 66 case PBTT_REMOVE_CHANNEL_FROM_GROUP:
sveljko 0:d13755cfb705 67 case PBTT_ADD_CHANNEL_TO_GROUP:
sveljko 0:d13755cfb705 68 case PBTT_LIST_CHANNEL_GROUP:
sveljko 0:d13755cfb705 69 pbres = pbcc_parse_channel_registry_response(&pb->core);
sveljko 0:d13755cfb705 70 if (pbres != PNR_OK) {
sveljko 0:d13755cfb705 71 PUBNUB_LOG_WARNING("parse_channel_registry failed\n");
sveljko 0:d13755cfb705 72 }
sveljko 0:d13755cfb705 73 break;
sveljko 0:d13755cfb705 74 default:
sveljko 0:d13755cfb705 75 break;
sveljko 0:d13755cfb705 76 }
sveljko 0:d13755cfb705 77
sveljko 0:d13755cfb705 78 return pbres;
sveljko 0:d13755cfb705 79 }
sveljko 0:d13755cfb705 80
sveljko 0:d13755cfb705 81
sveljko 0:d13755cfb705 82 static void finish(struct pubnub_ *pb)
sveljko 0:d13755cfb705 83 {
sveljko 0:d13755cfb705 84 enum pubnub_res pbres;
sveljko 0:d13755cfb705 85
sveljko 0:d13755cfb705 86 #if PUBNUB_PROXY_API
sveljko 0:d13755cfb705 87 if (pb->proxy_type == pbproxyHTTP_CONNECT) {
sveljko 0:d13755cfb705 88 if (!pb->proxy_tunnel_established) {
sveljko 0:d13755cfb705 89 if ((pb->http_code / 100) != 2) {
sveljko 0:d13755cfb705 90 outcome_detected(pb, PNR_HTTP_ERROR);
sveljko 0:d13755cfb705 91 }
sveljko 0:d13755cfb705 92 else {
sveljko 0:d13755cfb705 93 pb->proxy_tunnel_established = true;
sveljko 0:d13755cfb705 94 pb->state = PBS_CONNECTED;
sveljko 0:d13755cfb705 95 }
sveljko 0:d13755cfb705 96
sveljko 0:d13755cfb705 97 return;
sveljko 0:d13755cfb705 98 }
sveljko 0:d13755cfb705 99 else {
sveljko 0:d13755cfb705 100 pb->proxy_tunnel_established = false;
sveljko 0:d13755cfb705 101 }
sveljko 0:d13755cfb705 102 }
sveljko 0:d13755cfb705 103 #endif
sveljko 0:d13755cfb705 104
sveljko 0:d13755cfb705 105 pb->core.http_reply[pb->core.http_buf_len] = '\0';
sveljko 0:d13755cfb705 106 PUBNUB_LOG_TRACE("finish('%s')\n", pb->core.http_reply);
sveljko 0:d13755cfb705 107
sveljko 0:d13755cfb705 108 pbres = parse_pubnub_result(pb);
sveljko 0:d13755cfb705 109 if ((PNR_OK == pbres) && ((pb->http_code / 100) != 2)) {
sveljko 0:d13755cfb705 110 pbres = PNR_HTTP_ERROR;
sveljko 0:d13755cfb705 111 }
sveljko 0:d13755cfb705 112
sveljko 0:d13755cfb705 113 outcome_detected(pb, pbres);
sveljko 0:d13755cfb705 114 }
sveljko 0:d13755cfb705 115
sveljko 0:d13755cfb705 116
sveljko 0:d13755cfb705 117 int pbnc_fsm(struct pubnub_ *pb)
sveljko 0:d13755cfb705 118 {
sveljko 0:d13755cfb705 119 enum pubnub_res pbrslt;
sveljko 0:d13755cfb705 120 int i;
sveljko 0:d13755cfb705 121
sveljko 0:d13755cfb705 122 PUBNUB_LOG_TRACE("pbnc_fsm()\t");
sveljko 0:d13755cfb705 123
sveljko 0:d13755cfb705 124 next_state:
sveljko 0:d13755cfb705 125 WATCH_ENUM(pb->state);
sveljko 0:d13755cfb705 126 switch (pb->state) {
sveljko 0:d13755cfb705 127 case PBS_NULL:
sveljko 0:d13755cfb705 128 break;
sveljko 0:d13755cfb705 129 case PBS_IDLE:
sveljko 0:d13755cfb705 130 pb->state = PBS_READY;
sveljko 0:d13755cfb705 131 switch (pbntf_enqueue_for_processing(pb)) {
sveljko 0:d13755cfb705 132 case -1:
sveljko 0:d13755cfb705 133 pb->core.last_result = PNR_INTERNAL_ERROR;
sveljko 0:d13755cfb705 134 pbntf_trans_outcome(pb);
sveljko 0:d13755cfb705 135 return 0;
sveljko 0:d13755cfb705 136 case 0:
sveljko 0:d13755cfb705 137 goto next_state;
sveljko 0:d13755cfb705 138 case +1:
sveljko 0:d13755cfb705 139 break;
sveljko 0:d13755cfb705 140 }
sveljko 0:d13755cfb705 141 break;
sveljko 0:d13755cfb705 142 case PBS_READY:
sveljko 0:d13755cfb705 143 {
sveljko 0:d13755cfb705 144 enum pbpal_resolv_n_connect_result rslv = pbpal_resolv_and_connect(pb);
sveljko 0:d13755cfb705 145 WATCH_ENUM(rslv);
sveljko 0:d13755cfb705 146 switch (rslv) {
sveljko 0:d13755cfb705 147 case pbpal_resolv_send_wouldblock:
sveljko 0:d13755cfb705 148 pb->state = PBS_WAIT_DNS_SEND;
sveljko 0:d13755cfb705 149 break;
sveljko 0:d13755cfb705 150 case pbpal_resolv_sent:
sveljko 0:d13755cfb705 151 case pbpal_resolv_rcv_wouldblock:
sveljko 0:d13755cfb705 152 pb->state = PBS_WAIT_DNS_RCV;
sveljko 0:d13755cfb705 153 pbntf_watch_in_events(pb);
sveljko 0:d13755cfb705 154 break;
sveljko 0:d13755cfb705 155 case pbpal_connect_wouldblock:
sveljko 0:d13755cfb705 156 pb->state = PBS_WAIT_CONNECT;
sveljko 0:d13755cfb705 157 break;
sveljko 0:d13755cfb705 158 case pbpal_connect_success:
sveljko 0:d13755cfb705 159 pb->state = PBS_CONNECTED;
sveljko 0:d13755cfb705 160 break;
sveljko 0:d13755cfb705 161 default:
sveljko 0:d13755cfb705 162 pb->core.last_result = PNR_ADDR_RESOLUTION_FAILED;
sveljko 0:d13755cfb705 163 pbntf_trans_outcome(pb);
sveljko 0:d13755cfb705 164 return 0;
sveljko 0:d13755cfb705 165 }
sveljko 0:d13755cfb705 166 i = pbntf_got_socket(pb, pb->pal.socket);
sveljko 0:d13755cfb705 167 if (0 == i) {
sveljko 0:d13755cfb705 168 goto next_state;
sveljko 0:d13755cfb705 169 }
sveljko 0:d13755cfb705 170 else if (i < 0) {
sveljko 0:d13755cfb705 171 pb->core.last_result = PNR_CONNECT_FAILED;
sveljko 0:d13755cfb705 172 pbntf_trans_outcome(pb);
sveljko 0:d13755cfb705 173 }
sveljko 0:d13755cfb705 174 break;
sveljko 0:d13755cfb705 175 }
sveljko 0:d13755cfb705 176 case PBS_WAIT_DNS_SEND:
sveljko 0:d13755cfb705 177 {
sveljko 0:d13755cfb705 178 enum pbpal_resolv_n_connect_result rslv = pbpal_check_resolv_and_connect(pb);
sveljko 0:d13755cfb705 179 WATCH_ENUM(rslv);
sveljko 0:d13755cfb705 180 switch (rslv) {
sveljko 0:d13755cfb705 181 case pbpal_resolv_send_wouldblock:
sveljko 0:d13755cfb705 182 break;
sveljko 0:d13755cfb705 183 case pbpal_resolv_sent:
sveljko 0:d13755cfb705 184 case pbpal_resolv_rcv_wouldblock:
sveljko 0:d13755cfb705 185 pbntf_update_socket(pb, pb->pal.socket);
sveljko 0:d13755cfb705 186 pb->state = PBS_WAIT_DNS_RCV;
sveljko 0:d13755cfb705 187 pbntf_watch_in_events(pb);
sveljko 0:d13755cfb705 188 break;
sveljko 0:d13755cfb705 189 case pbpal_connect_wouldblock:
sveljko 0:d13755cfb705 190 pbntf_update_socket(pb, pb->pal.socket);
sveljko 0:d13755cfb705 191 pb->state = PBS_WAIT_CONNECT;
sveljko 0:d13755cfb705 192 break;
sveljko 0:d13755cfb705 193 case pbpal_connect_success:
sveljko 0:d13755cfb705 194 pb->state = PBS_CONNECTED;
sveljko 0:d13755cfb705 195 goto next_state;
sveljko 0:d13755cfb705 196 default:
sveljko 0:d13755cfb705 197 outcome_detected(pb, PNR_ADDR_RESOLUTION_FAILED);
sveljko 0:d13755cfb705 198 break;
sveljko 0:d13755cfb705 199 }
sveljko 0:d13755cfb705 200 break;
sveljko 0:d13755cfb705 201 }
sveljko 0:d13755cfb705 202 case PBS_WAIT_DNS_RCV:
sveljko 0:d13755cfb705 203 {
sveljko 0:d13755cfb705 204 enum pbpal_resolv_n_connect_result rslv = pbpal_check_resolv_and_connect(pb);
sveljko 0:d13755cfb705 205 WATCH_ENUM(rslv);
sveljko 0:d13755cfb705 206 switch (rslv) {
sveljko 0:d13755cfb705 207 case pbpal_resolv_send_wouldblock:
sveljko 0:d13755cfb705 208 case pbpal_resolv_sent:
sveljko 0:d13755cfb705 209 outcome_detected(pb, PNR_INTERNAL_ERROR);
sveljko 0:d13755cfb705 210 break;
sveljko 0:d13755cfb705 211 case pbpal_resolv_rcv_wouldblock:
sveljko 0:d13755cfb705 212 break;
sveljko 0:d13755cfb705 213 case pbpal_connect_wouldblock:
sveljko 0:d13755cfb705 214 pbntf_update_socket(pb, pb->pal.socket);
sveljko 0:d13755cfb705 215 pb->state = PBS_WAIT_CONNECT;
sveljko 0:d13755cfb705 216 pbntf_watch_out_events(pb);
sveljko 0:d13755cfb705 217 break;
sveljko 0:d13755cfb705 218 case pbpal_connect_success:
sveljko 0:d13755cfb705 219 pb->state = PBS_CONNECTED;
sveljko 0:d13755cfb705 220 pbntf_watch_out_events(pb);
sveljko 0:d13755cfb705 221 goto next_state;
sveljko 0:d13755cfb705 222 default:
sveljko 0:d13755cfb705 223 outcome_detected(pb, PNR_ADDR_RESOLUTION_FAILED);
sveljko 0:d13755cfb705 224 break;
sveljko 0:d13755cfb705 225 }
sveljko 0:d13755cfb705 226 break;
sveljko 0:d13755cfb705 227 }
sveljko 0:d13755cfb705 228 case PBS_WAIT_CONNECT:
sveljko 0:d13755cfb705 229 {
sveljko 0:d13755cfb705 230 enum pbpal_resolv_n_connect_result rslv = pbpal_check_connect(pb);
sveljko 0:d13755cfb705 231 WATCH_ENUM(rslv);
sveljko 0:d13755cfb705 232 switch (rslv) {
sveljko 0:d13755cfb705 233 case pbpal_resolv_send_wouldblock:
sveljko 0:d13755cfb705 234 case pbpal_resolv_sent:
sveljko 0:d13755cfb705 235 case pbpal_resolv_rcv_wouldblock:
sveljko 0:d13755cfb705 236 pb->core.last_result = PNR_INTERNAL_ERROR;
sveljko 0:d13755cfb705 237 pbntf_trans_outcome(pb);
sveljko 0:d13755cfb705 238 break;
sveljko 0:d13755cfb705 239 case pbpal_connect_wouldblock:
sveljko 0:d13755cfb705 240 break;
sveljko 0:d13755cfb705 241 case pbpal_connect_success:
sveljko 0:d13755cfb705 242 pb->state = PBS_CONNECTED;
sveljko 0:d13755cfb705 243 goto next_state;
sveljko 0:d13755cfb705 244 default:
sveljko 0:d13755cfb705 245 outcome_detected(pb, PNR_CONNECT_FAILED);
sveljko 0:d13755cfb705 246 break;
sveljko 0:d13755cfb705 247 }
sveljko 0:d13755cfb705 248 break;
sveljko 0:d13755cfb705 249 }
sveljko 0:d13755cfb705 250 case PBS_CONNECTED:
sveljko 0:d13755cfb705 251 #if PUBNUB_PROXY_API
sveljko 0:d13755cfb705 252 if ((pb->proxy_type == pbproxyHTTP_CONNECT) && (!pb->proxy_tunnel_established)) {
sveljko 0:d13755cfb705 253 pbpal_send_literal_str(pb, "CONNECT ");
sveljko 0:d13755cfb705 254 }
sveljko 0:d13755cfb705 255 else {
sveljko 0:d13755cfb705 256 pbpal_send_literal_str(pb, "GET ");
sveljko 0:d13755cfb705 257 }
sveljko 0:d13755cfb705 258 #else
sveljko 0:d13755cfb705 259 pbpal_send_literal_str(pb, "GET ");
sveljko 0:d13755cfb705 260 #endif
sveljko 0:d13755cfb705 261 pb->state = PBS_TX_GET;
sveljko 0:d13755cfb705 262 goto next_state;
sveljko 0:d13755cfb705 263 case PBS_TX_GET:
sveljko 0:d13755cfb705 264 i = pbpal_send_status(pb);
sveljko 0:d13755cfb705 265 if (i <= 0) {
sveljko 0:d13755cfb705 266 #if PUBNUB_PROXY_API
sveljko 0:d13755cfb705 267 switch (pb->proxy_type) {
sveljko 0:d13755cfb705 268 case pbproxyHTTP_GET:
sveljko 0:d13755cfb705 269 pb->state = PBS_TX_SCHEME;
sveljko 0:d13755cfb705 270 if (i < 0) {
sveljko 0:d13755cfb705 271 outcome_detected(pb, PNR_IO_ERROR);
sveljko 0:d13755cfb705 272 break;
sveljko 0:d13755cfb705 273 }
sveljko 0:d13755cfb705 274 pbpal_send_literal_str(pb, "http://");
sveljko 0:d13755cfb705 275 break;
sveljko 0:d13755cfb705 276 case pbproxyHTTP_CONNECT:
sveljko 0:d13755cfb705 277 pb->state = PBS_TX_SCHEME;
sveljko 0:d13755cfb705 278 if (i < 0) {
sveljko 0:d13755cfb705 279 outcome_detected(pb, PNR_IO_ERROR);
sveljko 0:d13755cfb705 280 break;
sveljko 0:d13755cfb705 281 }
sveljko 0:d13755cfb705 282 if (!pb->proxy_tunnel_established) {
sveljko 0:d13755cfb705 283 strcpy(pb->proxy_saved_path, pb->core.http_buf);
sveljko 0:d13755cfb705 284 }
sveljko 0:d13755cfb705 285 else {
sveljko 0:d13755cfb705 286 strcpy(pb->core.http_buf, pb->proxy_saved_path);
sveljko 0:d13755cfb705 287 }
sveljko 0:d13755cfb705 288 break;
sveljko 0:d13755cfb705 289 case pbproxyNONE:
sveljko 0:d13755cfb705 290 pb->state = PBS_TX_PATH;
sveljko 0:d13755cfb705 291 if ((i < 0) || (-1 == pbpal_send_str(pb, pb->core.http_buf))) {
sveljko 0:d13755cfb705 292 outcome_detected(pb, PNR_IO_ERROR);
sveljko 0:d13755cfb705 293 }
sveljko 0:d13755cfb705 294 break;
sveljko 0:d13755cfb705 295 default:
sveljko 0:d13755cfb705 296 outcome_detected(pb, PNR_INTERNAL_ERROR);
sveljko 0:d13755cfb705 297 break;
sveljko 0:d13755cfb705 298 }
sveljko 0:d13755cfb705 299 #else
sveljko 0:d13755cfb705 300 pb->state = PBS_TX_PATH;
sveljko 0:d13755cfb705 301 if ((i < 0) || (-1 == pbpal_send_str(pb, pb->core.http_buf))) {
sveljko 0:d13755cfb705 302 outcome_detected(pb, PNR_IO_ERROR);
sveljko 0:d13755cfb705 303 break;
sveljko 0:d13755cfb705 304 }
sveljko 0:d13755cfb705 305 #endif /* PUBNUB_PROXY_API */
sveljko 0:d13755cfb705 306 goto next_state;
sveljko 0:d13755cfb705 307 }
sveljko 0:d13755cfb705 308 break;
sveljko 0:d13755cfb705 309 #if PUBNUB_PROXY_API
sveljko 0:d13755cfb705 310 case PBS_TX_SCHEME:
sveljko 0:d13755cfb705 311 i = pbpal_send_status(pb);
sveljko 0:d13755cfb705 312 if (i <= 0) {
sveljko 0:d13755cfb705 313 if ((pb->proxy_type == pbproxyHTTP_CONNECT) && pb->proxy_tunnel_established) {
sveljko 0:d13755cfb705 314 pb->state = PBS_TX_HOST;
sveljko 0:d13755cfb705 315 }
sveljko 0:d13755cfb705 316 else {
sveljko 0:d13755cfb705 317 char const* o = PUBNUB_ORIGIN_SETTABLE ? pb->origin : PUBNUB_ORIGIN;
sveljko 0:d13755cfb705 318 pb->state = PBS_TX_HOST;
sveljko 0:d13755cfb705 319 if ((i < 0) || (-1 == pbpal_send_str(pb, o))) {
sveljko 0:d13755cfb705 320 outcome_detected(pb, PNR_IO_ERROR);
sveljko 0:d13755cfb705 321 break;
sveljko 0:d13755cfb705 322 }
sveljko 0:d13755cfb705 323 }
sveljko 0:d13755cfb705 324 goto next_state;
sveljko 0:d13755cfb705 325 }
sveljko 0:d13755cfb705 326 break;
sveljko 0:d13755cfb705 327 case PBS_TX_HOST:
sveljko 0:d13755cfb705 328 i = pbpal_send_status(pb);
sveljko 0:d13755cfb705 329 if (i <= 0) {
sveljko 0:d13755cfb705 330 if ((pb->proxy_type == pbproxyHTTP_CONNECT) && !pb->proxy_tunnel_established) {
sveljko 0:d13755cfb705 331 char port_num[20];
sveljko 0:d13755cfb705 332 snprintf(port_num, sizeof port_num, ":%d", 80);
sveljko 0:d13755cfb705 333 pbpal_send_str(pb, port_num);
sveljko 0:d13755cfb705 334 pb->state = PBS_TX_PORT_NUM;
sveljko 0:d13755cfb705 335 goto next_state;
sveljko 0:d13755cfb705 336 }
sveljko 0:d13755cfb705 337 else {
sveljko 0:d13755cfb705 338 pb->state = PBS_TX_PATH;
sveljko 0:d13755cfb705 339 if ((i < 0) || (-1 == pbpal_send_str(pb, pb->core.http_buf))) {
sveljko 0:d13755cfb705 340 outcome_detected(pb, PNR_IO_ERROR);
sveljko 0:d13755cfb705 341 break;
sveljko 0:d13755cfb705 342 }
sveljko 0:d13755cfb705 343 }
sveljko 0:d13755cfb705 344 goto next_state;
sveljko 0:d13755cfb705 345 }
sveljko 0:d13755cfb705 346 break;
sveljko 0:d13755cfb705 347 case PBS_TX_PORT_NUM:
sveljko 0:d13755cfb705 348 i = pbpal_send_status(pb);
sveljko 0:d13755cfb705 349 if (i <= 0) {
sveljko 0:d13755cfb705 350 pb->state = PBS_TX_PATH;
sveljko 0:d13755cfb705 351 if (i < 0) {
sveljko 0:d13755cfb705 352 outcome_detected(pb, PNR_IO_ERROR);
sveljko 0:d13755cfb705 353 break;
sveljko 0:d13755cfb705 354 }
sveljko 0:d13755cfb705 355 goto next_state;
sveljko 0:d13755cfb705 356 }
sveljko 0:d13755cfb705 357 break;
sveljko 0:d13755cfb705 358 #endif /* PUBNUB_PROXY_API */
sveljko 0:d13755cfb705 359 case PBS_TX_PATH:
sveljko 0:d13755cfb705 360 i = pbpal_send_status(pb);
sveljko 0:d13755cfb705 361 if (i < 0) {
sveljko 0:d13755cfb705 362 outcome_detected(pb, PNR_IO_ERROR);
sveljko 0:d13755cfb705 363 }
sveljko 0:d13755cfb705 364 else if (0 == i) {
sveljko 0:d13755cfb705 365 pbpal_send_literal_str(pb, " HTTP/1.1\r\nHost: ");
sveljko 0:d13755cfb705 366 pb->state = PBS_TX_VER;
sveljko 0:d13755cfb705 367 goto next_state;
sveljko 0:d13755cfb705 368 }
sveljko 0:d13755cfb705 369 break;
sveljko 0:d13755cfb705 370 case PBS_TX_VER:
sveljko 0:d13755cfb705 371 i = pbpal_send_status(pb);
sveljko 0:d13755cfb705 372 if (i <= 0) {
sveljko 0:d13755cfb705 373 char const* o = PUBNUB_ORIGIN_SETTABLE ? pb->origin : PUBNUB_ORIGIN;
sveljko 0:d13755cfb705 374 pb->state = PBS_TX_ORIGIN;
sveljko 0:d13755cfb705 375 if ((i < 0) || (-1 == pbpal_send_str(pb, o))) {
sveljko 0:d13755cfb705 376 outcome_detected(pb, PNR_IO_ERROR);
sveljko 0:d13755cfb705 377 break;
sveljko 0:d13755cfb705 378 }
sveljko 0:d13755cfb705 379 goto next_state;
sveljko 0:d13755cfb705 380 }
sveljko 0:d13755cfb705 381 break;
sveljko 0:d13755cfb705 382 case PBS_TX_ORIGIN:
sveljko 0:d13755cfb705 383 i = pbpal_send_status(pb);
sveljko 0:d13755cfb705 384 if (i < 0) {
sveljko 0:d13755cfb705 385 outcome_detected(pb, PNR_IO_ERROR);
sveljko 0:d13755cfb705 386 }
sveljko 0:d13755cfb705 387 else if (0 == i) {
sveljko 0:d13755cfb705 388 pbpal_send_literal_str(pb, "\r\nUser-Agent: PubNub-C-core/2.1\r\nConnection: Keep-Alive\r\n\r\n");
sveljko 0:d13755cfb705 389 pb->state = PBS_TX_FIN_HEAD;
sveljko 0:d13755cfb705 390 goto next_state;
sveljko 0:d13755cfb705 391 }
sveljko 0:d13755cfb705 392 break;
sveljko 0:d13755cfb705 393 case PBS_TX_FIN_HEAD:
sveljko 0:d13755cfb705 394 i = pbpal_send_status(pb);
sveljko 0:d13755cfb705 395 if (i < 0) {
sveljko 0:d13755cfb705 396 outcome_detected(pb, PNR_IO_ERROR);
sveljko 0:d13755cfb705 397 }
sveljko 0:d13755cfb705 398 else if (0 == i) {
sveljko 0:d13755cfb705 399 pbpal_start_read_line(pb);
sveljko 0:d13755cfb705 400 pb->state = PBS_RX_HTTP_VER;
sveljko 0:d13755cfb705 401 pbntf_watch_in_events(pb);
sveljko 0:d13755cfb705 402 goto next_state;
sveljko 0:d13755cfb705 403 }
sveljko 0:d13755cfb705 404 break;
sveljko 0:d13755cfb705 405 case PBS_RX_HTTP_VER:
sveljko 0:d13755cfb705 406 pbrslt = pbpal_line_read_status(pb);
sveljko 0:d13755cfb705 407 switch (pbrslt) {
sveljko 0:d13755cfb705 408 case PNR_IN_PROGRESS:
sveljko 0:d13755cfb705 409 break;
sveljko 0:d13755cfb705 410 case PNR_OK:
sveljko 0:d13755cfb705 411 if (strncmp(pb->core.http_buf, "HTTP/1.", 7) != 0) {
sveljko 0:d13755cfb705 412 outcome_detected(pb, PNR_IO_ERROR);
sveljko 0:d13755cfb705 413 break;
sveljko 0:d13755cfb705 414 }
sveljko 0:d13755cfb705 415 pb->http_code = atoi(pb->core.http_buf + 9);
sveljko 0:d13755cfb705 416 WATCH_USHORT(pb->http_code);
sveljko 0:d13755cfb705 417 pb->core.http_content_len = 0;
sveljko 0:d13755cfb705 418 pb->http_chunked = false;
sveljko 0:d13755cfb705 419 pb->state = PBS_RX_HEADERS;
sveljko 0:d13755cfb705 420 goto next_state;
sveljko 0:d13755cfb705 421 default:
sveljko 0:d13755cfb705 422 outcome_detected(pb, pbrslt);
sveljko 0:d13755cfb705 423 break;
sveljko 0:d13755cfb705 424 }
sveljko 0:d13755cfb705 425 break;
sveljko 0:d13755cfb705 426 case PBS_RX_HEADERS:
sveljko 0:d13755cfb705 427 PUBNUB_LOG_TRACE("PBS_RX_HEADERS\n");
sveljko 0:d13755cfb705 428 pbpal_start_read_line(pb);
sveljko 0:d13755cfb705 429 pb->state = PBS_RX_HEADER_LINE;
sveljko 0:d13755cfb705 430 goto next_state;
sveljko 0:d13755cfb705 431 case PBS_RX_HEADER_LINE:
sveljko 0:d13755cfb705 432 PUBNUB_LOG_TRACE("PBS_RX_HEADER_LINE\n");
sveljko 0:d13755cfb705 433 pbrslt = pbpal_line_read_status(pb);
sveljko 0:d13755cfb705 434 switch (pbrslt) {
sveljko 0:d13755cfb705 435 case PNR_IN_PROGRESS:
sveljko 0:d13755cfb705 436 break;
sveljko 0:d13755cfb705 437 case PNR_OK:
sveljko 0:d13755cfb705 438 {
sveljko 0:d13755cfb705 439 char h_chunked[] = "Transfer-Encoding: chunked";
sveljko 0:d13755cfb705 440 char h_length[] = "Content-Length: ";
sveljko 0:d13755cfb705 441 int read_len = pbpal_read_len(pb);
sveljko 0:d13755cfb705 442 PUBNUB_LOG_TRACE("header line was read: %.*s\n", read_len, pb->core.http_buf);
sveljko 0:d13755cfb705 443 WATCH_INT(read_len);
sveljko 0:d13755cfb705 444 if (read_len <= 2) {
sveljko 0:d13755cfb705 445 pb->core.http_buf_len = 0;
sveljko 0:d13755cfb705 446 if (!pb->http_chunked) {
sveljko 0:d13755cfb705 447 if (0 == pb->core.http_content_len) {
sveljko 0:d13755cfb705 448 #if PUBNUB_PROXY_API
sveljko 0:d13755cfb705 449 if ((pb->proxy_type == pbproxyHTTP_CONNECT) && !pb->proxy_tunnel_established) {
sveljko 0:d13755cfb705 450 finish(pb);
sveljko 0:d13755cfb705 451 break;
sveljko 0:d13755cfb705 452 }
sveljko 0:d13755cfb705 453 #endif
sveljko 0:d13755cfb705 454 outcome_detected(pb, PNR_IO_ERROR);
sveljko 0:d13755cfb705 455 break;
sveljko 0:d13755cfb705 456 }
sveljko 0:d13755cfb705 457 pb->state = PBS_RX_BODY;
sveljko 0:d13755cfb705 458 }
sveljko 0:d13755cfb705 459 else {
sveljko 0:d13755cfb705 460 pb->state = PBS_RX_CHUNK_LEN;
sveljko 0:d13755cfb705 461 }
sveljko 0:d13755cfb705 462 goto next_state;
sveljko 0:d13755cfb705 463 }
sveljko 0:d13755cfb705 464 if (strncmp(pb->core.http_buf, h_chunked, sizeof h_chunked - 1) == 0) {
sveljko 0:d13755cfb705 465 pb->http_chunked = true;
sveljko 0:d13755cfb705 466 }
sveljko 0:d13755cfb705 467 else if (strncmp(pb->core.http_buf, h_length, sizeof h_length - 1) == 0) {
sveljko 0:d13755cfb705 468 size_t len = atoi(pb->core.http_buf + sizeof h_length - 1);
sveljko 0:d13755cfb705 469 if (0 != pbcc_realloc_reply_buffer(&pb->core, len)) {
sveljko 0:d13755cfb705 470 outcome_detected(pb, PNR_REPLY_TOO_BIG);
sveljko 0:d13755cfb705 471 break;
sveljko 0:d13755cfb705 472 }
sveljko 0:d13755cfb705 473 pb->core.http_content_len = len;
sveljko 0:d13755cfb705 474 }
sveljko 0:d13755cfb705 475 pb->state = PBS_RX_HEADERS;
sveljko 0:d13755cfb705 476 goto next_state;
sveljko 0:d13755cfb705 477 }
sveljko 0:d13755cfb705 478 default:
sveljko 0:d13755cfb705 479 outcome_detected(pb, pbrslt);
sveljko 0:d13755cfb705 480 break;
sveljko 0:d13755cfb705 481 }
sveljko 0:d13755cfb705 482 break;
sveljko 0:d13755cfb705 483 case PBS_RX_BODY:
sveljko 0:d13755cfb705 484 PUBNUB_LOG_TRACE("PBS_RX_BODY\n");
sveljko 0:d13755cfb705 485 if (pb->core.http_buf_len < pb->core.http_content_len) {
sveljko 0:d13755cfb705 486 pbpal_start_read(pb, pb->core.http_content_len - pb->core.http_buf_len);
sveljko 0:d13755cfb705 487 pb->state = PBS_RX_BODY_WAIT;
sveljko 0:d13755cfb705 488 goto next_state;
sveljko 0:d13755cfb705 489 }
sveljko 0:d13755cfb705 490 else {
sveljko 0:d13755cfb705 491 finish(pb);
sveljko 0:d13755cfb705 492 }
sveljko 0:d13755cfb705 493 break;
sveljko 0:d13755cfb705 494 case PBS_RX_BODY_WAIT:
sveljko 0:d13755cfb705 495 PUBNUB_LOG_TRACE("PBS_RX_BODY_WAIT\n");
sveljko 0:d13755cfb705 496 if (pbpal_read_over(pb)) {
sveljko 0:d13755cfb705 497 unsigned len = pbpal_read_len(pb);
sveljko 0:d13755cfb705 498 WATCH_UINT(len);
sveljko 0:d13755cfb705 499 WATCH_UINT(pb->core.http_buf_len);
sveljko 0:d13755cfb705 500 memcpy(
sveljko 0:d13755cfb705 501 pb->core.http_reply + pb->core.http_buf_len,
sveljko 0:d13755cfb705 502 pb->core.http_buf,
sveljko 0:d13755cfb705 503 len
sveljko 0:d13755cfb705 504 );
sveljko 0:d13755cfb705 505 pb->core.http_buf_len += len;
sveljko 0:d13755cfb705 506 pb->state = PBS_RX_BODY;
sveljko 0:d13755cfb705 507 goto next_state;
sveljko 0:d13755cfb705 508 }
sveljko 0:d13755cfb705 509 break;
sveljko 0:d13755cfb705 510 case PBS_RX_CHUNK_LEN:
sveljko 0:d13755cfb705 511 PUBNUB_LOG_TRACE("PBS_RX_CHUNK_LEN\n");
sveljko 0:d13755cfb705 512 pbpal_start_read_line(pb);
sveljko 0:d13755cfb705 513 pb->state = PBS_RX_CHUNK_LEN_LINE;
sveljko 0:d13755cfb705 514 goto next_state;
sveljko 0:d13755cfb705 515 case PBS_RX_CHUNK_LEN_LINE:
sveljko 0:d13755cfb705 516 pbrslt = pbpal_line_read_status(pb);
sveljko 0:d13755cfb705 517 PUBNUB_LOG_TRACE("PBS_RX_CHUNK_LEN_LINE: pbrslt=%d\n", pbrslt);
sveljko 0:d13755cfb705 518 switch (pbrslt) {
sveljko 0:d13755cfb705 519 case PNR_IN_PROGRESS:
sveljko 0:d13755cfb705 520 break;
sveljko 0:d13755cfb705 521 case PNR_OK:
sveljko 0:d13755cfb705 522 {
sveljko 0:d13755cfb705 523 unsigned chunk_length = strtoul(pb->core.http_buf, NULL, 16);
sveljko 0:d13755cfb705 524
sveljko 0:d13755cfb705 525 PUBNUB_LOG_TRACE("About to read a chunk w/length: %d\n", chunk_length);
sveljko 0:d13755cfb705 526 if (chunk_length == 0) {
sveljko 0:d13755cfb705 527 finish(pb);
sveljko 0:d13755cfb705 528 }
sveljko 0:d13755cfb705 529 else if (chunk_length > sizeof pb->core.http_buf) {
sveljko 0:d13755cfb705 530 outcome_detected(pb, PNR_IO_ERROR);
sveljko 0:d13755cfb705 531 }
sveljko 0:d13755cfb705 532 else if (0 != pbcc_realloc_reply_buffer(&pb->core, pb->core.http_buf_len + chunk_length)) {
sveljko 0:d13755cfb705 533 outcome_detected(pb, PNR_REPLY_TOO_BIG);
sveljko 0:d13755cfb705 534 }
sveljko 0:d13755cfb705 535 else {
sveljko 0:d13755cfb705 536 pb->core.http_content_len = chunk_length + 2;
sveljko 0:d13755cfb705 537 pb->state = PBS_RX_BODY_CHUNK;
sveljko 0:d13755cfb705 538 goto next_state;
sveljko 0:d13755cfb705 539 }
sveljko 0:d13755cfb705 540 break;
sveljko 0:d13755cfb705 541 }
sveljko 0:d13755cfb705 542 default:
sveljko 0:d13755cfb705 543 outcome_detected(pb, pbrslt);
sveljko 0:d13755cfb705 544 break;
sveljko 0:d13755cfb705 545 }
sveljko 0:d13755cfb705 546 break;
sveljko 0:d13755cfb705 547 case PBS_RX_BODY_CHUNK:
sveljko 0:d13755cfb705 548 PUBNUB_LOG_TRACE("PBS_RX_BODY_CHUNK\n");
sveljko 0:d13755cfb705 549 if (pb->core.http_content_len > 0) {
sveljko 0:d13755cfb705 550 pbpal_start_read(pb, pb->core.http_content_len);
sveljko 0:d13755cfb705 551 pb->state = PBS_RX_BODY_CHUNK_WAIT;
sveljko 0:d13755cfb705 552 }
sveljko 0:d13755cfb705 553 else {
sveljko 0:d13755cfb705 554 pb->state = PBS_RX_CHUNK_LEN;
sveljko 0:d13755cfb705 555 }
sveljko 0:d13755cfb705 556 goto next_state;
sveljko 0:d13755cfb705 557 case PBS_RX_BODY_CHUNK_WAIT:
sveljko 0:d13755cfb705 558 PUBNUB_LOG_TRACE("PBS_RX_BODY_CHUNK_WAIT\n");
sveljko 0:d13755cfb705 559 if (pbpal_read_over(pb)) {
sveljko 0:d13755cfb705 560 unsigned len = pbpal_read_len(pb);
sveljko 0:d13755cfb705 561
sveljko 0:d13755cfb705 562 PUBNUB_ASSERT_OPT(pb->core.http_content_len >= len);
sveljko 0:d13755cfb705 563 PUBNUB_ASSERT_OPT(len > 0);
sveljko 0:d13755cfb705 564
sveljko 0:d13755cfb705 565 if (pb->core.http_content_len > 2) {
sveljko 0:d13755cfb705 566 unsigned to_copy = pb->core.http_content_len - 2;
sveljko 0:d13755cfb705 567 if (len < to_copy) {
sveljko 0:d13755cfb705 568 to_copy = len;
sveljko 0:d13755cfb705 569 }
sveljko 0:d13755cfb705 570 memcpy(
sveljko 0:d13755cfb705 571 pb->core.http_reply + pb->core.http_buf_len,
sveljko 0:d13755cfb705 572 pb->core.http_buf,
sveljko 0:d13755cfb705 573 to_copy
sveljko 0:d13755cfb705 574 );
sveljko 0:d13755cfb705 575 pb->core.http_buf_len += to_copy;
sveljko 0:d13755cfb705 576 }
sveljko 0:d13755cfb705 577 pb->core.http_content_len -= len;
sveljko 0:d13755cfb705 578 pb->state = PBS_RX_BODY_CHUNK;
sveljko 0:d13755cfb705 579 goto next_state;
sveljko 0:d13755cfb705 580 }
sveljko 0:d13755cfb705 581 break;
sveljko 0:d13755cfb705 582 case PBS_WAIT_CLOSE:
sveljko 0:d13755cfb705 583 if (pbpal_closed(pb)) {
sveljko 0:d13755cfb705 584 pbpal_forget(pb);
sveljko 0:d13755cfb705 585 pbntf_trans_outcome(pb);
sveljko 0:d13755cfb705 586 }
sveljko 0:d13755cfb705 587 break;
sveljko 0:d13755cfb705 588 case PBS_WAIT_CANCEL:
sveljko 0:d13755cfb705 589 pb->state = PBS_WAIT_CANCEL_CLOSE;
sveljko 0:d13755cfb705 590 if (pbpal_close(pb) <= 0) {
sveljko 0:d13755cfb705 591 goto next_state;
sveljko 0:d13755cfb705 592 }
sveljko 0:d13755cfb705 593 break;
sveljko 0:d13755cfb705 594 case PBS_WAIT_CANCEL_CLOSE:
sveljko 0:d13755cfb705 595 if (pbpal_closed(pb)) {
sveljko 0:d13755cfb705 596 pbpal_forget(pb);
sveljko 0:d13755cfb705 597 pb->core.msg_ofs = pb->core.msg_end = 0;
sveljko 0:d13755cfb705 598 pbntf_trans_outcome(pb);
sveljko 0:d13755cfb705 599 }
sveljko 0:d13755cfb705 600 break;
sveljko 0:d13755cfb705 601 }
sveljko 0:d13755cfb705 602 return 0;
sveljko 0:d13755cfb705 603 }
sveljko 0:d13755cfb705 604
sveljko 0:d13755cfb705 605
sveljko 0:d13755cfb705 606 void pbnc_stop(struct pubnub_ *pb, enum pubnub_res outcome_to_report)
sveljko 0:d13755cfb705 607 {
sveljko 0:d13755cfb705 608 pb->core.last_result = outcome_to_report;
sveljko 0:d13755cfb705 609 switch (pb->state) {
sveljko 0:d13755cfb705 610 case PBS_WAIT_CANCEL:
sveljko 0:d13755cfb705 611 case PBS_WAIT_CANCEL_CLOSE:
sveljko 0:d13755cfb705 612 break;
sveljko 0:d13755cfb705 613 case PBS_IDLE:
sveljko 0:d13755cfb705 614 case PBS_NULL:
sveljko 0:d13755cfb705 615 pbntf_trans_outcome(pb);
sveljko 0:d13755cfb705 616 break;
sveljko 0:d13755cfb705 617 default:
sveljko 0:d13755cfb705 618 pb->state = PBS_WAIT_CANCEL;
sveljko 0:d13755cfb705 619 pbntf_requeue_for_processing(pb);
sveljko 0:d13755cfb705 620 break;
sveljko 0:d13755cfb705 621 }
sveljko 0:d13755cfb705 622 }