This is Webservice SDK for mbed. LPCXpresso1769/LPC1768/FRDM-K64F/LPC4088

Dependents:   MbedFileServer_1768MiniDK2 RedWireBridge IssueDebug_gcc MiMicRemoteMCU-for-Mbed ... more

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers NyLPC_cHttpClient.c Source File

NyLPC_cHttpClient.c

00001 /*
00002  * NyLPC_cHttpClient.c
00003  *
00004  *  Created on: 2013/08/24
00005  *      Author: nyatla
00006  */
00007 #include "NyLPC_cHttpClient.h"
00008 typedef NyLPC_TUInt8 NyLPC_TcHttpClient_ST;
00009 #define NyLPC_TcHttpClient_ST_CLOSED 0x00   //ソケット切断
00010 #define NyLPC_TcHttpClient_ST_IDLE   0x01   //メソッド選択待ち
00011 
00012 #define NyLPC_TcHttpClient_ST_SEND_REQ_BODY 0x21 //POSTリクエスト送信中
00013 #define NyLPC_TcHttpClient_ST_RECV_RES_HEAD 0x23
00014 #define NyLPC_TcHttpClient_ST_RECV_RES_BODY 0x24
00015 
00016 
00017 
00018 NyLPC_TBool NyLPC_cHttpClient_initialize(NyLPC_TcHttpClient_t* i_inst,void* i_rx_buf,NyLPC_TUInt16 i_rx_size)
00019 {
00020     i_inst->_sock=NyLPC_cNet_createTcpSocketEx(NyLPC_TSocketType_TCP_NORMAL);
00021     if(i_inst->_sock==NULL){
00022         return NyLPC_TBool_FALSE;
00023     }
00024     i_inst->_state=NyLPC_TcHttpClient_ST_CLOSED;
00025     return NyLPC_TBool_TRUE;
00026 }
00027 void NyLPC_cHttpClient_finalize(NyLPC_TcHttpClient_t* i_inst)
00028 {
00029     NyLPC_cHttpClient_close(i_inst);
00030     NyLPC_iTcpSocket_finalize(i_inst->_sock);
00031 }
00032 
00033 void NyLPC_cHttpClient_close(NyLPC_TcHttpClient_t* i_inst)
00034 {
00035     //ステータスをclosedへ遷移
00036     switch(i_inst->_state){
00037     case NyLPC_TcHttpClient_ST_RECV_RES_BODY:
00038         NyLPC_cHttpBodyParser_finalize(&i_inst->pw.body_parser);
00039         break;
00040     case NyLPC_TcHttpClient_ST_SEND_REQ_BODY:
00041         NyLPC_cHttpBodyWriter_finalize(&(i_inst->pw.body_writer));
00042         break;
00043     case NyLPC_TcHttpClient_ST_RECV_RES_HEAD:
00044         //開放するものとくにない
00045         break;
00046     case NyLPC_TcHttpClient_ST_IDLE:
00047         break;
00048     case NyLPC_TcHttpClient_ST_CLOSED:
00049         return;
00050     }
00051     NyLPC_iTcpSocket_close(i_inst->_sock,1000);
00052     i_inst->_state=NyLPC_TcHttpClient_ST_CLOSED;
00053 }
00054 
00055 /**
00056  * サーバに接続する。
00057  * 関数はステータスをIDLEへ遷移する。
00058  * インスタンスのステータスは何でも構わない。
00059  * @return
00060  * TRUE - ステータスはIDLEへ遷移する。
00061  * FALSE - ステータスはCLOSEDへ遷移する。
00062  */
00063 NyLPC_TBool NyLPC_cHttpClient_connect(NyLPC_TcHttpClient_t* i_inst,const struct NyLPC_TIPv4Addr* i_addr,NyLPC_TUInt16 i_port)
00064 {
00065     //ステータスをclosedへ遷移
00066     NyLPC_cHttpClient_close(i_inst);
00067     //接続
00068     if(!NyLPC_iTcpSocket_connect(i_inst->_sock,i_addr,i_port,3000)){
00069         return NyLPC_TBool_FALSE;
00070     }
00071     //streamの生成
00072     if(!NyLPC_cHttpStream_initialize(&i_inst->_stream,i_inst->_sock)){
00073         NyLPC_OnErrorGoto(ERROR);
00074     }
00075     //ステータス遷移
00076     i_inst->_state=NyLPC_TcHttpClient_ST_IDLE;
00077     return NyLPC_TBool_TRUE;
00078 ERROR:
00079     return NyLPC_TBool_FALSE;
00080 }
00081 
00082 
00083 
00084 /**
00085  * POSTリクエストを送信する。
00086  * @return
00087  * 引き続き処理が可能かを返す。
00088  */
00089 NyLPC_TBool NyLPC_cHttpClient_sendMethod(
00090     NyLPC_TcHttpClient_t* i_inst,
00091     NyLPC_THttpMethodType i_method,
00092     const NyLPC_TChar* i_path,
00093     NyLPC_TUInt32 i_content_length,
00094     const NyLPC_TChar* i_mime_type,
00095     const NyLPC_TChar* i_additional_header)
00096 {
00097     //ステータスチェック
00098     if(i_inst->_state!=NyLPC_TcHttpClient_ST_IDLE){
00099         NyLPC_OnErrorGoto(Error_0);
00100     }
00101     //POSTリクエストの送信
00102     if(!NyLPC_cHttpHeaderWriter_initialize(&i_inst->pw.head_writer,&i_inst->_stream.super,NULL)){
00103         NyLPC_OnErrorGoto(Error_0);
00104     }
00105     //ヘッダを送信
00106     NyLPC_cHttpHeaderWriter_setConnectionClose(&i_inst->pw.head_writer,NyLPC_TBool_TRUE);//Connection closeを強制
00107     if(i_content_length==NyLPC_cHttpHeaderWriter_CONTENT_LENGTH_UNLIMITED){
00108         NyLPC_cHttpHeaderWriter_setChunked(&i_inst->pw.head_writer);
00109     }else{
00110         NyLPC_cHttpHeaderWriter_setContentLength(&i_inst->pw.head_writer,i_content_length);
00111     }
00112     if(!NyLPC_cHttpHeaderWriter_writeRequestHeader(
00113         &i_inst->pw.head_writer,
00114         i_method,
00115         NyLPC_iTcpSocket_getPeerAddr((i_inst->_sock)),
00116         NyLPC_iTcpSocket_getPeerPort((i_inst->_sock)),i_path)){
00117         NyLPC_OnErrorGoto(Error_1);
00118     }
00119     //MimeType
00120     if(i_mime_type!=NULL){
00121         if(!NyLPC_cHttpHeaderWriter_writeMessage(&i_inst->pw.head_writer,"Content-type",i_mime_type)){
00122             NyLPC_OnErrorGoto(Error_1);
00123         }
00124     }
00125     if(i_additional_header!=NULL){
00126         if(!NyLPC_cHttpHeaderWriter_writeRawMessage(&i_inst->pw.head_writer,i_additional_header)){
00127             NyLPC_OnErrorGoto(Error_1);
00128         }
00129     }
00130     NyLPC_cHttpHeaderWriter_close(&i_inst->pw.head_writer);
00131     NyLPC_cHttpHeaderWriter_finalize(&i_inst->pw.head_writer);
00132 
00133     //BodyWriter生成
00134     NyLPC_cHttpBodyWriter_initialize(&(i_inst->pw.body_writer),&(i_inst->_stream));
00135     //bodyのchunkedもセット
00136     if(i_content_length==0xffffffff){
00137         NyLPC_cHttpBodyWriter_setChunked(&(i_inst->pw.body_writer));
00138     }else{
00139         NyLPC_cHttpBodyWriter_setContentLength(&(i_inst->pw.body_writer),i_content_length);
00140     }
00141     i_inst->_state=NyLPC_TcHttpClient_ST_SEND_REQ_BODY;
00142     return NyLPC_TBool_TRUE;
00143 Error_0:
00144     return NyLPC_TBool_FALSE;
00145 Error_1:
00146     NyLPC_cHttpHeaderWriter_finalize(&i_inst->pw.head_writer);
00147     return NyLPC_TBool_FALSE;
00148 }
00149 
00150 /**
00151  * POSTリクエストのデータを送信する。
00152  * @return
00153  * 0:EOF
00154  */
00155 NyLPC_TBool NyLPC_cHttpClient_write(NyLPC_TcHttpClient_t* i_inst,const void* i_buf,NyLPC_TUInt32 i_buf_size)
00156 {
00157     if(i_inst->_state!=NyLPC_TcHttpClient_ST_SEND_REQ_BODY){
00158         return NyLPC_TBool_FALSE;
00159     }
00160     if(!NyLPC_cHttpBodyWriter_write(&i_inst->pw.body_writer,i_buf,i_buf_size)){
00161         //ERROR
00162         NyLPC_cHttpClient_close(i_inst);
00163         NyLPC_OnErrorGoto(Error);
00164     }
00165     return NyLPC_TBool_TRUE;
00166 Error:
00167     return NyLPC_TBool_FALSE;
00168 }
00169 
00170 NyLPC_TBool NyLPC_cHttpClient_writeFormat(NyLPC_TcHttpClient_t* i_inst,const NyLPC_TChar* i_fmt,...)
00171 {
00172     NyLPC_TBool ret;
00173     va_list a;
00174     if(i_inst->_state!=NyLPC_TcHttpClient_ST_SEND_REQ_BODY){
00175         return NyLPC_TBool_FALSE;
00176     }
00177     va_start(a,i_fmt);
00178     ret=NyLPC_cHttpBodyWriter_formatV(&i_inst->pw.body_writer,i_fmt,a);
00179     va_end(a);
00180     if(!ret){
00181         NyLPC_cHttpClient_close(i_inst);
00182     }
00183     return ret;
00184 }
00185 NyLPC_TBool NyLPC_cHttpClient_writeFormatV(NyLPC_TcHttpClient_t* i_inst,const NyLPC_TChar* i_fmt,va_list i_args)
00186 {
00187     NyLPC_TBool ret;
00188     if(i_inst->_state!=NyLPC_TcHttpClient_ST_SEND_REQ_BODY){
00189         return NyLPC_TBool_FALSE;
00190     }
00191     ret=NyLPC_cHttpBodyWriter_formatV(&i_inst->pw.body_writer,i_fmt,i_args);
00192     if(!ret){
00193         NyLPC_cHttpClient_close(i_inst);
00194     }
00195     return ret;
00196 }
00197 
00198 
00199 /**
00200  * ステータスコードを返す。
00201  * @return
00202  * ステータスコード
00203  */
00204 NyLPC_TUInt16 NyLPC_cHttpClient_getStatus(NyLPC_TcHttpClient_t* i_inst)
00205 {
00206     struct NyLPC_THttpBasicHeader header;
00207     if(i_inst->_state!=NyLPC_TcHttpClient_ST_SEND_REQ_BODY){
00208         return 0;
00209     }
00210     //
00211     if(!NyLPC_cHttpBodyWriter_close(&i_inst->pw.body_writer)){
00212         NyLPC_OnErrorGoto(Error_1);
00213     }
00214     i_inst->_state=NyLPC_TcHttpClient_ST_RECV_RES_HEAD;
00215     //100を無視してHTTPヘッダをパース
00216     //@todo POSTの時だけに制限したら?
00217     do{
00218         NyLPC_cHttpBasicHeaderParser_initialize(&i_inst->pw.head_parser,NULL);
00219         NyLPC_cHttpBasicHeaderParser_parseInit(&i_inst->pw.head_parser,&header);
00220         if(!NyLPC_cHttpBasicHeaderParser_parseStream(&i_inst->pw.head_parser,&i_inst->_stream.super,&header)){
00221             NyLPC_OnErrorGoto(Error_2);
00222         }
00223         if(!NyLPC_cHttpBasicHeaderParser_parseFinish(&i_inst->pw.head_parser,&header)){
00224             NyLPC_OnErrorGoto(Error_2);
00225         }
00226         NyLPC_cHttpBasicHeaderParser_finalize(&i_inst->pw.head_parser);
00227         //レスポンスヘッダか確認
00228         if(header.type!=NyLPC_THttpHeaderType_RESPONSE){
00229             NyLPC_OnErrorGoto(Error_1);
00230         }
00231     }while(header.startline.res.status==100);
00232     //BodyParserを起動
00233     NyLPC_cHttpBodyParser_initialize(&i_inst->pw.body_parser);
00234     NyLPC_cHttpBodyParser_parseInit(&i_inst->pw.body_parser,&header);
00235     i_inst->_state=NyLPC_TcHttpClient_ST_RECV_RES_BODY;
00236     return header.startline.res.status;
00237 Error_1:
00238     NyLPC_cHttpClient_close(i_inst);
00239     return 0;
00240 Error_2:
00241     NyLPC_cHttpBasicHeaderParser_finalize(&i_inst->pw.head_parser);
00242     NyLPC_cHttpClient_close(i_inst);
00243     return 0;
00244 }
00245 
00246 
00247 /**
00248  * GET/POSTリクエストで受信したデータを読み出す。
00249  * @param o_read_len
00250  * 戻り値TRUEの場合のみ有効。
00251  * 終端の場合は0
00252  * @return
00253  * TRUE:正常読み出し。o_read_lenの値で終端判定
00254  * FALSE:失敗。コネクションはクローズされる。
00255  */
00256 NyLPC_TBool NyLPC_cHttpClient_read(NyLPC_TcHttpClient_t* i_inst,void* i_buf,NyLPC_TUInt32 i_buf_size,NyLPC_TInt16* o_read_len)
00257 {
00258     if(i_inst->_state!=NyLPC_TcHttpClient_ST_RECV_RES_BODY){
00259         return NyLPC_TBool_FALSE;
00260     }
00261     if(!NyLPC_cHttpBodyParser_parseStream(&i_inst->pw.body_parser,&i_inst->_stream.super,i_buf,i_buf_size,o_read_len)){
00262         NyLPC_cHttpClient_close(i_inst);
00263         return NyLPC_TBool_FALSE;
00264     }
00265     return NyLPC_TBool_TRUE;
00266 }
00267