PANCAKE_API Byte *PancakeNetworkGetInterfaceName(struct sockaddr *addr) { Byte *name; PancakeAssert(addr->sa_family == AF_INET || addr->sa_family == AF_INET6 || addr->sa_family == AF_UNIX); switch(addr->sa_family) { case AF_INET: { Byte textAddress[INET_ADDRSTRLEN + 1]; inet_ntop(AF_INET, &((struct sockaddr_in*) addr)->sin_addr, textAddress, INET_ADDRSTRLEN); // IPv4:<address>:<port> name = PancakeAllocate(sizeof("IPv4::12345") + INET_ADDRSTRLEN); sprintf(name, "IPv4:%s:%i", textAddress, (Int32) ntohs(((struct sockaddr_in*) addr)->sin_port)); } break; case AF_INET6: { Byte textAddress[INET6_ADDRSTRLEN + 1]; inet_ntop(AF_INET6, &((struct sockaddr_in6*) addr)->sin6_addr, textAddress, INET6_ADDRSTRLEN); // IPv6:[<address>]:<port> name = PancakeAllocate(sizeof("IPv6:[]:12345") + INET6_ADDRSTRLEN); sprintf(name, "IPv6:[%s]:%i", textAddress, (Int32) ntohs(((struct sockaddr_in6*) addr)->sin6_port)); } break; case AF_UNIX: { // UNIX:<address> name = PancakeAllocate(sizeof("UNIX:") + sizeof(((struct sockaddr_un*) addr)->sun_path)); sprintf(name, "UNIX:%s", ((struct sockaddr_un*) addr)->sun_path); } break; } return name; }
PANCAKE_API UByte PancakeNetworkInterfaceConfiguration(UByte step, config_setting_t *setting, PancakeConfigurationScope **scope) { switch(step) { case PANCAKE_CONFIGURATION_INIT: { PancakeSocket *socket = PancakeAllocate(sizeof(PancakeSocket)); /* Used for backlog storage */ socket->data = (void*) 0x1; socket->fd = -1; socket->localAddress = PancakeAllocate(sizeof(struct sockaddr)); socket->onRead = NULL; socket->onWrite = NULL; socket->onRemoteHangup = NULL; socket->flags = 0; socket->layer = NULL; socket->localAddress->sa_family = 0; memset(socket->localAddress->sa_data, 0, sizeof(socket->localAddress->sa_data)); setting->hook = (void*) socket; } break; case PANCAKE_CONFIGURATION_DTOR: { PancakeSocket *socket = (PancakeSocket*) setting->hook; if(socket->fd != -1) { close(socket->fd); } PancakeFree(socket->localAddress); PancakeFree(socket); // Make library happy setting->hook = NULL; } break; } return 1; }
STATIC UByte PancakeAuthenticationGroupConfiguration(UByte step, config_setting_t *setting, PancakeConfigurationScope **scope) { PancakeAuthenticationConfiguration *config; if(step == PANCAKE_CONFIGURATION_INIT) { config = PancakeAllocate(sizeof(PancakeAuthenticationConfiguration)); setting->hook = (void*) config; config->backend = NULL; config->backendData = NULL; } else { config = (PancakeAuthenticationConfiguration*) setting->hook; PancakeFree(config); } return 1; }
PANCAKE_API PancakeSchedulerEvent *PancakeSchedule(UNative time, PancakeSchedulerEventCallback callback, void *arg) { PancakeSchedulerEvent *event; if(unusedEvents) { // Use cached event instance event = unusedEvents; CDL_DELETE(unusedEvents, unusedEvents); } else { // Allocate new event event = PancakeAllocate(sizeof(PancakeSchedulerEvent)); } event->time = time; event->callback = callback; event->arg = arg; if(events) { if(events->prev->time <= time) { CDL_PREPEND_ELEM(events, events, event); events = event->next; } else if(events->time >= time) { CDL_PREPEND(events, event); } else { PancakeSchedulerEvent *ev; // Iterate through events and find place for new event CDL_FOREACH(events, ev) { if(ev->time == time) { CDL_PREPEND_ELEM(events, ev->next, event); break; } else if(ev->time < time && ev->next->time >= time) { CDL_PREPEND_ELEM(events, ev->next, event); break; } } } } else {
STATIC UByte PancakeHTTPBasicAuthenticate(PancakeSocket *sock) { // Check whether authentication framework is active if(PancakeAuthenticationActiveConfiguration) { PancakeHTTPRequest *request = (PancakeHTTPRequest*) sock->data; PancakeHTTPHeader *header; // Check credentials provided by client if(request->authorization.length > 6) { UByte *authorization = sock->readBuffer.value + request->authorization.offset; if(!memcmp(authorization, "Basic ", 6)) { UByte decoded[request->authorization.length - 6], *ptr; base64_decodestate state = {0}; PancakeAuthenticationUserPassword client; UInt32 length; // Decode base64 user and password length = base64_decode_block(authorization + 6, request->authorization.length - 6, decoded, &state); ptr = memchr(decoded, ':', length); if(ptr != NULL) { client.user.value = decoded; client.user.length = ptr - decoded; if(ptr - decoded < length) { client.password.value = ptr + 1; client.password.length = decoded + length - (ptr + 1); } else { client.password.value = ""; client.password.length = 0; } // Try authentication if(PancakeAuthenticate(PancakeAuthenticationActiveConfiguration, &client)) { return 1; } } } } // Build WWW-Authenticate header header = PancakeAllocate(sizeof(PancakeHTTPHeader)); header->name.value = PancakeAllocate(sizeof("WWW-Authenticate") - 1); header->name.length = sizeof("WWW-Authenticate") - 1; memcpy(header->name.value, "WWW-Authenticate", sizeof("WWW-Authenticate") - 1); if(activeRealm) { header->value.length = sizeof("Basic realm=\"\"") - 1 + activeRealm->length; header->value.value = PancakeAllocate(header->value.length); memcpy(header->value.value + 5, " realm=\"", sizeof(" realm=\"") - 1); memcpy(header->value.value + 5 + sizeof(" realm=\"") - 1, activeRealm->value, activeRealm->length); header->value.value[header->value.length - 1] = '"'; } else { header->value.length = sizeof("Basic") - 1; header->value.value = PancakeAllocate(sizeof("Basic") - 1); } memcpy(header->value.value, "Basic", 5); LL_APPEND(request->answerHeaders, header); // Throw 401 Unauthorized PancakeHTTPException(sock, 401); return 0; } return 1; }