1 /***************************************************************************
2 * Copyright (C) 2007,2008,2009 Øyvind Harboe *
3 * oyvind.harboe@zylin.com *
5 * This program is free software; you can redistribute it and/or modify *
6 * it under the terms of the GNU General Public License as published by *
7 * the Free Software Foundation; either version 2 of the License, or *
8 * (at your option) any later version. *
10 * This program is distributed in the hope that it will be useful, *
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
13 * GNU General Public License for more details. *
15 * You should have received a copy of the GNU General Public License *
16 * along with this program; if not, write to the *
17 * Free Software Foundation, Inc., *
18 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
19 ***************************************************************************/
21 /* some bits were copied from ahttpd which is under eCos license and
28 #include "telnet_server.h"
31 #include <microhttpd.h>
35 #define PAGE_NOT_FOUND "<html><head><title > File not found</title></head><body > File not found</body></html>"
37 int loadFile(const char *name
, void **data
, size_t *len
);
39 static const char *appendf(const char *prev
, const char *format
, ...)
43 char *string
= alloc_vprintf(format
, ap
);
49 string2
= alloc_printf("%s%s", (prev
== NULL
) ? "" : prev
, string
);
63 static const char *httpd_exec_cgi_tcl_error(Jim_Interp
*interp
)
68 t
= appendf(t
, "<html><body>\n");
70 t
= appendf(t
, "Runtime error, file \"%s\", line %d:<br>",
71 interp
->errorFileName
, interp
->errorLine
);
72 t
= appendf(t
, " %s < br>", Jim_GetString(interp
->result
, NULL
));
73 Jim_ListLength(interp
, interp
->stackTrace
, &len
);
74 for (i
= 0; i
< len
; i
+= 3)
77 const char *proc
, *file
, *line
;
79 Jim_ListIndex(interp
, interp
->stackTrace
, i
, &objPtr
, JIM_NONE
);
80 proc
= Jim_GetString(objPtr
, NULL
);
81 Jim_ListIndex(interp
, interp
->stackTrace
, i
+ 1, &objPtr
, JIM_NONE
);
82 file
= Jim_GetString(objPtr
, NULL
);
83 Jim_ListIndex(interp
, interp
->stackTrace
, i
+ 2, &objPtr
, JIM_NONE
);
84 line
= Jim_GetString(objPtr
, NULL
);
85 t
= appendf(t
, "In procedure '%s' called at file \"%s\", line %s < br>",
88 t
= appendf(t
, "</html></body>\n");
93 static int httpd_Jim_Command_writeform(Jim_Interp
*interp
, int argc
,
94 Jim_Obj
* const *argv
)
98 Jim_WrongNumArgs(interp
, 1, argv
, "method ?args ...?");
101 char *name
= (char*) Jim_GetString(argv
[1], NULL
);
102 char *file
= (char*) Jim_GetString(argv
[2], NULL
);
110 const char *script
= alloc_printf("set dummy_val $httppostdata(%s); set dummy_val",
112 retcode
= Jim_Eval_Named(interp
, script
, "httpd.c", __LINE__
);
113 free((void *) script
);
114 if (retcode
!= JIM_OK
)
117 data
= Jim_GetString(Jim_GetResult(interp
), &actual
);
119 FILE *f
= fopen(file
, "wb");
122 Jim_SetResultString(interp
, "Could not create file", -1);
126 int result
= fwrite(data
, 1, actual
, f
);
129 if (result
!= actual
)
131 Jim_SetResultString(interp
, "Could not write to file", -1);
139 httpd_Jim_Command_formfetch(Jim_Interp
*interp
,
141 Jim_Obj
*const *argv
)
145 Jim_WrongNumArgs(interp
, 1, argv
, "method ?args ...?");
148 char *name
= (char*)Jim_GetString(argv
[1], NULL
);
151 const char *script
= alloc_printf("set dummy_val $httppostdata(%s); set dummy_val",
153 int retcode
= Jim_Eval_Named(interp
, script
, "httpd.c", __LINE__
);
154 free((void *) script
);
155 if (retcode
!= JIM_OK
)
157 Jim_SetResult(interp
, Jim_NewEmptyStringObj(interp
));
160 Jim_SetResult(interp
, Jim_GetResult(interp
));
169 struct MHD_PostProcessor
*postprocessor
;
173 int complete
; /* did we receive the entire post ? */
177 static void request_completed(void *cls
, struct MHD_Connection
*connection
,
178 void **con_cls
, enum MHD_RequestTerminationCode toe
)
180 struct httpd_request
*r
= (struct httpd_request
*) *con_cls
;
185 if (r
->postprocessor
)
187 MHD_destroy_post_processor(r
->postprocessor
);
194 /* append to said key in dictonary */
195 static void append_key(struct httpd_request
*r
, const char *key
,
196 const char *data
, size_t off
, size_t size
)
198 Jim_Obj
*keyObj
= Jim_NewStringObj(interp
, key
, -1);
199 Jim_IncrRefCount(keyObj
);
200 Jim_Obj
*value
= NULL
;
202 Jim_Obj
*dict
= Jim_GetVariableStr(interp
, "httppostdata", 0);
206 if (Jim_DictKey(interp
, dict
, keyObj
, &value
, 0) != JIM_OK
)
212 Jim_IncrRefCount(value
);
218 value
= Jim_NewStringObj(interp
, "", -1);
219 Jim_IncrRefCount(value
);
223 /* create a new object we append to and insert into this location */
224 Jim_Obj
*newObj
= Jim_NewStringObj(interp
, "", -1);
225 Jim_IncrRefCount(newObj
);
226 Jim_AppendObj(interp
, newObj
, value
);
227 Jim_AppendString(interp
, newObj
, data
, size
);
228 /* uhh... use name here of dictionary */
229 dict
= Jim_NewStringObj(interp
, "httppostdata", -1);
230 Jim_IncrRefCount(dict
);
231 Jim_SetDictKeysVector(interp
, dict
, &keyObj
, 1, newObj
);
232 Jim_DecrRefCount(interp
, dict
);
233 Jim_DecrRefCount(interp
, value
);
234 Jim_DecrRefCount(interp
, newObj
);
235 Jim_DecrRefCount(interp
, keyObj
);
238 /* append data to each key */
239 static int iterate_post(void *con_cls
, enum MHD_ValueKind kind
,
240 const char *key
, const char *filename
, const char *content_type
,
241 const char *transfer_encoding
, const char *data
, uint64_t off
,
244 struct httpd_request
*r
= (struct httpd_request
*) con_cls
;
246 append_key(r
, key
, data
, off
, size
);
251 static int record_arg(void *cls
, enum MHD_ValueKind kind
, const char *key
,
254 struct httpd_request
*r
= (struct httpd_request
*) cls
;
255 append_key(r
, key
, value
, 0, strlen(value
));
260 int handle_request(struct MHD_Connection
* connection
, const char * url
)
262 struct MHD_Response
* response
;
266 suffix
= strrchr(url
, '.');
267 if ((suffix
!= NULL
) && (strcmp(suffix
, ".tcl") == 0))
269 printf("Run tcl %s\n", url
);
273 const char *script
= alloc_printf(
274 "global httpdata; source {%s}; set httpdata", url
);
275 retcode
= Jim_Eval_Named(interp
, script
, "httpd.c", __LINE__
);
276 free((void *) script
);
278 if (retcode
== JIM_ERR
)
280 printf("Tcl failed\n");
281 const char *t
= httpd_exec_cgi_tcl_error(interp
);
285 response
= MHD_create_response_from_data(strlen(t
), (void *) t
,
287 ret
= MHD_queue_response(connection
,
288 MHD_HTTP_INTERNAL_SERVER_ERROR
, response
);
289 MHD_destroy_response(response
);
295 /* FIX!!! how to handle mime types??? */
298 result
= Jim_GetString(Jim_GetResult(interp
), &reslen
);
300 response
= MHD_create_response_from_data(reslen
, (void *) result
,
302 ret
= MHD_queue_response(connection
,
303 MHD_HTTP_INTERNAL_SERVER_ERROR
, response
);
304 MHD_destroy_response(response
);
313 int retval
= loadFile(url
, &data
, &len
);
314 if (retval
!= ERROR_OK
)
316 printf("Did not find %s\n", url
);
318 response
= MHD_create_response_from_data(strlen(PAGE_NOT_FOUND
),
319 (void *) PAGE_NOT_FOUND
, MHD_NO
, MHD_NO
);
320 ret
= MHD_queue_response(connection
, MHD_HTTP_NOT_FOUND
, response
);
321 MHD_destroy_response(response
);
325 LOG_DEBUG("Serving %s length=%zu", url
, len
);
326 /* serve file directly */
327 response
= MHD_create_response_from_data(len
, data
, MHD_YES
, MHD_NO
);
328 MHD_add_response_header(response
, "Content-Type", "image/png");
330 ret
= MHD_queue_response(connection
, MHD_HTTP_OK
, response
);
331 MHD_destroy_response(response
);
338 static int ahc_echo(void * cls
, struct MHD_Connection
* connection
,
339 const char * url
, const char * method
, const char * version
,
340 const char * upload_data
, unsigned int * upload_data_size
, void ** ptr
)
344 if (0 == strcmp(method
, "POST"))
348 else if (0 == strcmp(method
, "GET"))
353 return MHD_NO
; /* unexpected method */
356 struct httpd_request
*r
;
359 /* The first time only the headers are valid,
360 do not respond in the first round... */
362 *ptr
= malloc(sizeof(struct httpd_request
));
365 memset(*ptr
, 0, sizeof(struct httpd_request
));
367 r
= (struct httpd_request
*) *ptr
;
370 Jim_SetVariableStr(interp
, "httppostdata", Jim_NewDictObj(interp
, NULL
, 0));
372 /* fill in url query strings in dictonary */
373 MHD_get_connection_values(connection
, MHD_GET_ARGUMENT_KIND
,
378 r
->postprocessor
= MHD_create_post_processor(connection
, 2048
379 * 1024, &iterate_post
, r
);
385 r
= (struct httpd_request
*) *ptr
;
389 /* consume post data */
390 if (*upload_data_size
)
392 MHD_post_process(r
->postprocessor
, upload_data
, *upload_data_size
);
393 *upload_data_size
= 0;
403 /* hand over to request who will be using it. */
407 /* FIX!!!! we need more advanced handling of url's to avoid them
408 * being subverted to evil purposes
411 const char *httpd_dir
= PKGDATADIR
"/httpd";
415 url
++; /* skip '/' */
420 const char *file_name
= alloc_printf("%s/%s", httpd_dir
, url
);
421 int result
= handle_request(connection
, file_name
);
422 free((void *)file_name
);
426 static struct MHD_Daemon
* d
;
427 static pthread_mutex_t mutex
;
430 int httpd_start(void)
432 pthread_mutexattr_t attr
;
433 pthread_mutexattr_init(&attr
);
434 pthread_mutex_init(&mutex
, &attr
);
437 LOG_USER("Launching httpd server on port %d", port
);
438 d
= MHD_start_daemon(MHD_USE_SELECT_INTERNALLY
, port
, NULL
, NULL
,
439 &ahc_echo
, NULL
, /* could be data for handler, but we only have a single handler, use global variables instead */
440 MHD_OPTION_NOTIFY_COMPLETED
, request_completed
, NULL
, /* Closure... what's that??? */
445 Jim_CreateCommand(interp
,
447 httpd_Jim_Command_formfetch
,
451 Jim_CreateCommand(interp
,
453 httpd_Jim_Command_writeform
,
461 void httpd_stop(void)
464 pthread_mutex_destroy(&mutex
);
467 void openocd_sleep_prelude(void)
469 pthread_mutex_unlock(&mutex
);
472 void openocd_sleep_postlude(void)
474 pthread_mutex_lock(&mutex
);
Linking to existing account procedure
If you already have an account and want to add another login method
you
MUST first sign in with your existing account and
then change URL to read
https://review.openocd.org/login/?link
to get to this page again but this time it'll work for linking. Thank you.
SSH host keys fingerprints
1024 SHA256:YKx8b7u5ZWdcbp7/4AeXNaqElP49m6QrwfXaqQGJAOk gerrit-code-review@openocd.zylin.com (DSA)
384 SHA256:jHIbSQa4REvwCFG4cq5LBlBLxmxSqelQPem/EXIrxjk gerrit-code-review@openocd.org (ECDSA)
521 SHA256:UAOPYkU9Fjtcao0Ul/Rrlnj/OsQvt+pgdYSZ4jOYdgs gerrit-code-review@openocd.org (ECDSA)
256 SHA256:A13M5QlnozFOvTllybRZH6vm7iSt0XLxbA48yfc2yfY gerrit-code-review@openocd.org (ECDSA)
256 SHA256:spYMBqEYoAOtK7yZBrcwE8ZpYt6b68Cfh9yEVetvbXg gerrit-code-review@openocd.org (ED25519)
+--[ED25519 256]--+
|=.. |
|+o.. . |
|*.o . . |
|+B . . . |
|Bo. = o S |
|Oo.+ + = |
|oB=.* = . o |
| =+=.+ + E |
|. .=o . o |
+----[SHA256]-----+
2048 SHA256:0Onrb7/PHjpo6iVZ7xQX2riKN83FJ3KGU0TvI0TaFG4 gerrit-code-review@openocd.zylin.com (RSA)