http-message.c 6.47 KB
Newer Older
Simon Morlat's avatar
Simon Morlat committed
1 2
/*
	belle-sip - SIP (RFC3261) library.
3
	Copyright (C) 2010-2018  Belledonne Communications SARL
Simon Morlat's avatar
Simon Morlat committed
4

5 6 7 8
	This program is free software: you can redistribute it and/or modify
	it under the terms of the GNU General Public License as published by
	the Free Software Foundation, either version 2 of the License, or
	(at your option) any later version.
Simon Morlat's avatar
Simon Morlat committed
9

10 11 12 13
	This program is distributed in the hope that it will be useful,
	but WITHOUT ANY WARRANTY; without even the implied warranty of
	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
	GNU General Public License for more details.
Simon Morlat's avatar
Simon Morlat committed
14

15 16
	You should have received a copy of the GNU General Public License
	along with this program.  If not, see <http://www.gnu.org/licenses/>.
Simon Morlat's avatar
Simon Morlat committed
17
*/
18

19 20
#include "grammars/belle_sip_messageLexer.h"
#include "grammars/belle_sip_messageParser.h"
Simon Morlat's avatar
Simon Morlat committed
21 22 23 24
#include "belle_sip_internal.h"



jehan's avatar
jehan committed
25 26 27
static void belle_http_request_init(belle_http_request_t *req){
	/*nop*/
}
Simon Morlat's avatar
Simon Morlat committed
28 29 30 31 32
static void belle_http_request_listener_destroyed(belle_http_request_t *req){
	req->listener=NULL;
}

static void belle_http_request_destroy(belle_http_request_t *req){
jehan's avatar
jehan committed
33 34
	if (req->req_uri) belle_sip_object_unref(req->req_uri);
	DESTROY_STRING(req,method)
Simon Morlat's avatar
Simon Morlat committed
35
	belle_http_request_set_listener(req,NULL);
36
	belle_http_request_set_channel(req,NULL);
37
	SET_OBJECT_PROPERTY(req,orig_uri,NULL);
38
	SET_OBJECT_PROPERTY(req,response,NULL);
Simon Morlat's avatar
Simon Morlat committed
39 40 41
}

static void belle_http_request_clone(belle_http_request_t *obj, const belle_http_request_t *orig){
jehan's avatar
jehan committed
42 43 44
	if (orig->req_uri) obj->req_uri=(belle_generic_uri_t*)belle_sip_object_clone((belle_sip_object_t*)orig->req_uri);
	CLONE_STRING(belle_http_request,method,obj,orig)
}
Simon Morlat's avatar
Simon Morlat committed
45

jehan's avatar
jehan committed
46 47 48 49 50
static belle_sip_error_code belle_http_request_marshal(const belle_http_request_t* request, char* buff, size_t buff_size, size_t *offset) {
	belle_sip_error_code error=belle_sip_snprintf(buff,buff_size,offset,"%s ",belle_http_request_get_method(request));
	if (error!=BELLE_SIP_OK) return error;
	error=belle_generic_uri_marshal(belle_http_request_get_uri(request),buff,buff_size,offset);
	if (error!=BELLE_SIP_OK) return error;
Simon Morlat's avatar
Simon Morlat committed
51
	error=belle_sip_snprintf(buff,buff_size,offset," %s","HTTP/1.1\r\n");
jehan's avatar
jehan committed
52 53 54
	if (error!=BELLE_SIP_OK) return error;
	error=belle_sip_headers_marshal(BELLE_SIP_MESSAGE(request),buff,buff_size,offset);
	if (error!=BELLE_SIP_OK) return error;
55

jehan's avatar
jehan committed
56
	return error;
Simon Morlat's avatar
Simon Morlat committed
57
}
jehan's avatar
jehan committed
58 59 60
GET_SET_STRING(belle_http_request,method);
BELLE_NEW(belle_http_request,belle_sip_message)
BELLE_PARSE(belle_sip_messageParser,belle_,http_request)
Simon Morlat's avatar
Simon Morlat committed
61 62 63



Simon Morlat's avatar
Simon Morlat committed
64 65
belle_http_request_t *belle_http_request_create(const char *method, belle_generic_uri_t *url, ...){
	va_list vl;
66
	belle_http_request_t *obj;
Simon Morlat's avatar
Simon Morlat committed
67
	belle_sip_header_t *header;
68 69 70 71 72 73 74

	if (belle_generic_uri_get_host(url) == NULL) {
		belle_sip_error("%s: NULL host in url", __FUNCTION__);
		return NULL;
	}

	obj=belle_http_request_new();
Simon Morlat's avatar
Simon Morlat committed
75
	obj->method=belle_sip_strdup(method);
jehan's avatar
jehan committed
76
	obj->req_uri=(belle_generic_uri_t*)belle_sip_object_ref(url);
77

Simon Morlat's avatar
Simon Morlat committed
78 79 80 81 82
	va_start(vl,url);
	while((header=va_arg(vl,belle_sip_header_t*))!=NULL){
		belle_sip_message_add_header(BELLE_SIP_MESSAGE(obj),header);
	}
	va_end(vl);
Simon Morlat's avatar
Simon Morlat committed
83 84 85
	return obj;
}

86 87 88 89 90 91 92 93
int belle_http_request_is_cancelled(const belle_http_request_t *req) {
	return req->cancelled;
}

void belle_http_request_cancel(belle_http_request_t *req) {
	req->cancelled = TRUE;
}

Simon Morlat's avatar
Simon Morlat committed
94
void belle_http_request_set_listener(belle_http_request_t *req, belle_http_request_listener_t *l){
95 96 97 98 99 100
	/* FIXME: Temporary workaround for -Wcast-function-type. */
	#if __GNUC__ >= 8
		_Pragma("GCC diagnostic push")
		_Pragma("GCC diagnostic ignored \"-Wcast-function-type\"")
	#endif // if __GNUC__ >= 8

Simon Morlat's avatar
Simon Morlat committed
101
	if (req->listener){
102 103
		belle_sip_object_weak_unref(req->listener,(belle_sip_object_destroy_notify_t)belle_http_request_listener_destroyed,req);
		req->listener=NULL;
Simon Morlat's avatar
Simon Morlat committed
104
	}
Simon Morlat's avatar
Simon Morlat committed
105
	if (l){
Simon Morlat's avatar
Simon Morlat committed
106
		belle_sip_object_weak_ref(l,(belle_sip_object_destroy_notify_t)belle_http_request_listener_destroyed,req);
Simon Morlat's avatar
Simon Morlat committed
107 108
		req->listener=l;
	}
109 110 111 112

	#if __GNUC__ >= 8
		_Pragma("GCC diagnostic pop")
	#endif // if __GNUC__ >= 8
Simon Morlat's avatar
Simon Morlat committed
113
}
Simon Morlat's avatar
Simon Morlat committed
114

115 116 117 118 119 120 121 122 123 124 125 126 127 128 129
static void notify_http_request_of_channel_destruction(belle_http_request_t *obj, belle_sip_channel_t *chan_being_destroyed){
	obj->channel=NULL;
}

void belle_http_request_set_channel(belle_http_request_t *req, belle_sip_channel_t* chan){
	if (req->channel){
		belle_sip_object_weak_unref(req->channel, (belle_sip_object_destroy_notify_t)notify_http_request_of_channel_destruction, req);
		req->channel=NULL;
	}
	if (chan){
		belle_sip_object_weak_ref(chan, (belle_sip_object_destroy_notify_t)notify_http_request_of_channel_destruction, req);
		req->channel=chan;
	}
}

Simon Morlat's avatar
Simon Morlat committed
130 131 132 133
belle_http_request_listener_t * belle_http_request_get_listener(const belle_http_request_t *req){
	return req->listener;
}

jehan's avatar
jehan committed
134 135 136
belle_generic_uri_t *belle_http_request_get_uri(const belle_http_request_t *req){
	return req->req_uri;
}
Simon Morlat's avatar
Simon Morlat committed
137

jehan's avatar
jehan committed
138
void belle_http_request_set_uri(belle_http_request_t* request, belle_generic_uri_t* uri) {
139
	SET_OBJECT_PROPERTY(request,req_uri,uri);
Simon Morlat's avatar
Simon Morlat committed
140
}
jehan's avatar
jehan committed
141

Simon Morlat's avatar
Simon Morlat committed
142
void belle_http_request_set_response(belle_http_request_t *req, belle_http_response_t *resp){
143
	SET_OBJECT_PROPERTY(req,response,resp);
Simon Morlat's avatar
Simon Morlat committed
144
}
jehan's avatar
jehan committed
145

Simon Morlat's avatar
Simon Morlat committed
146 147 148
belle_http_response_t *belle_http_request_get_response(belle_http_request_t *req){
	return req->response;
}
jehan's avatar
jehan committed
149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180

/*response*/


struct belle_http_response{
	belle_sip_message_t base;
	char *http_version;
	int status_code;
	char *reason_phrase;
};


void belle_http_response_destroy(belle_http_response_t *resp){
	if (resp->http_version) belle_sip_free(resp->http_version);
	if (resp->reason_phrase) belle_sip_free(resp->reason_phrase);
}

static void belle_http_response_init(belle_http_response_t *resp){
}

static void belle_http_response_clone(belle_http_response_t *resp, const belle_http_response_t *orig){
	if (orig->http_version) resp->http_version=belle_sip_strdup(orig->http_version);
	resp->status_code=orig->status_code;
	if (orig->reason_phrase) resp->reason_phrase=belle_sip_strdup(orig->reason_phrase);
}

belle_sip_error_code belle_http_response_marshal(belle_http_response_t *resp, char* buff, size_t buff_size, size_t *offset) {
	belle_sip_error_code error=belle_sip_snprintf(	buff
													,buff_size
													,offset
													,"HTTP/1.1 %i %s\r\n"
													,belle_http_response_get_status_code(resp)
181
													,belle_http_response_get_reason_phrase(resp)?belle_http_response_get_reason_phrase(resp):"");
jehan's avatar
jehan committed
182 183 184
	if (error!=BELLE_SIP_OK) return error;
	error=belle_sip_headers_marshal(BELLE_SIP_MESSAGE(resp),buff,buff_size,offset);
	if (error!=BELLE_SIP_OK) return error;
185

jehan's avatar
jehan committed
186 187 188 189 190 191 192
	return error;
}

BELLE_NEW(belle_http_response,belle_sip_message)
BELLE_PARSE(belle_sip_messageParser,belle_,http_response)
GET_SET_STRING(belle_http_response,reason_phrase);
GET_SET_INT(belle_http_response,status_code,int)