diff --git a/src/java/nxt_jni.c b/src/java/nxt_jni.c index 02ec1e376..35a29749b 100644 --- a/src/java/nxt_jni.c +++ b/src/java/nxt_jni.c @@ -11,165 +11,137 @@ #include "nxt_jni.h" - -static jclass nxt_java_NoSuchElementException_class; -static jclass nxt_java_IOException_class; -static jclass nxt_java_IllegalStateException_class; -static jclass nxt_java_File_class; -static jmethodID nxt_java_File_ctor; +static jclass nxt_java_NoSuchElementException_class; +static jclass nxt_java_IOException_class; +static jclass nxt_java_IllegalStateException_class; +static jclass nxt_java_File_class; +static jmethodID nxt_java_File_ctor; static inline char nxt_java_lowcase(char c); - -int -nxt_java_jni_init(JNIEnv *env) -{ - jclass cls; - - cls = (*env)->FindClass(env, "java/util/NoSuchElementException"); - if (cls == NULL) { - return NXT_UNIT_ERROR; - } - - nxt_java_NoSuchElementException_class = (*env)->NewGlobalRef(env, cls); - (*env)->DeleteLocalRef(env, cls); - - - cls = (*env)->FindClass(env, "java/io/IOException"); - if (cls == NULL) { - (*env)->DeleteGlobalRef(env, nxt_java_NoSuchElementException_class); - return NXT_UNIT_ERROR; - } - - nxt_java_IOException_class = (*env)->NewGlobalRef(env, cls); - (*env)->DeleteLocalRef(env, cls); - - - cls = (*env)->FindClass(env, "java/lang/IllegalStateException"); - if (cls == NULL) { - (*env)->DeleteGlobalRef(env, nxt_java_NoSuchElementException_class); - (*env)->DeleteGlobalRef(env, nxt_java_IOException_class); - return NXT_UNIT_ERROR; - } - - nxt_java_IllegalStateException_class = (*env)->NewGlobalRef(env, cls); - (*env)->DeleteLocalRef(env, cls); - - - cls = (*env)->FindClass(env, "java/io/File"); - if (cls == NULL) { - (*env)->DeleteGlobalRef(env, nxt_java_NoSuchElementException_class); - (*env)->DeleteGlobalRef(env, nxt_java_IOException_class); - (*env)->DeleteGlobalRef(env, nxt_java_IllegalStateException_class); - return NXT_UNIT_ERROR; - } - - nxt_java_File_class = (*env)->NewGlobalRef(env, cls); - (*env)->DeleteLocalRef(env, cls); - - - nxt_java_File_ctor = (*env)->GetMethodID(env, nxt_java_File_class, "", - "(Ljava/lang/String;)V"); - if (nxt_java_File_ctor == NULL) { - (*env)->DeleteGlobalRef(env, nxt_java_NoSuchElementException_class); - (*env)->DeleteGlobalRef(env, nxt_java_IOException_class); - (*env)->DeleteGlobalRef(env, nxt_java_IllegalStateException_class); - (*env)->DeleteGlobalRef(env, nxt_java_File_class); - return NXT_UNIT_ERROR; - } - - return NXT_UNIT_OK; +int nxt_java_jni_init(JNIEnv *env) { + jclass cls; + + cls = (*env)->FindClass(env, "java/util/NoSuchElementException"); + if (cls == NULL) { + return NXT_UNIT_ERROR; + } + + nxt_java_NoSuchElementException_class = (*env)->NewGlobalRef(env, cls); + (*env)->DeleteLocalRef(env, cls); + + cls = (*env)->FindClass(env, "java/io/IOException"); + if (cls == NULL) { + (*env)->DeleteGlobalRef(env, nxt_java_NoSuchElementException_class); + return NXT_UNIT_ERROR; + } + + nxt_java_IOException_class = (*env)->NewGlobalRef(env, cls); + (*env)->DeleteLocalRef(env, cls); + + cls = (*env)->FindClass(env, "java/lang/IllegalStateException"); + if (cls == NULL) { + (*env)->DeleteGlobalRef(env, nxt_java_NoSuchElementException_class); + (*env)->DeleteGlobalRef(env, nxt_java_IOException_class); + return NXT_UNIT_ERROR; + } + + nxt_java_IllegalStateException_class = (*env)->NewGlobalRef(env, cls); + (*env)->DeleteLocalRef(env, cls); + + cls = (*env)->FindClass(env, "java/io/File"); + if (cls == NULL) { + (*env)->DeleteGlobalRef(env, nxt_java_NoSuchElementException_class); + (*env)->DeleteGlobalRef(env, nxt_java_IOException_class); + (*env)->DeleteGlobalRef(env, nxt_java_IllegalStateException_class); + return NXT_UNIT_ERROR; + } + + nxt_java_File_class = (*env)->NewGlobalRef(env, cls); + (*env)->DeleteLocalRef(env, cls); + + nxt_java_File_ctor = (*env)->GetMethodID(env, nxt_java_File_class, "", + "(Ljava/lang/String;)V"); + if (nxt_java_File_ctor == NULL) { + (*env)->DeleteGlobalRef(env, nxt_java_NoSuchElementException_class); + (*env)->DeleteGlobalRef(env, nxt_java_IOException_class); + (*env)->DeleteGlobalRef(env, nxt_java_IllegalStateException_class); + (*env)->DeleteGlobalRef(env, nxt_java_File_class); + return NXT_UNIT_ERROR; + } + + return NXT_UNIT_OK; } - -void -nxt_java_throw_NoSuchElementException(JNIEnv *env, const char *msg) -{ - (*env)->ThrowNew(env, nxt_java_NoSuchElementException_class, msg); +void nxt_java_throw_NoSuchElementException(JNIEnv *env, const char *msg) { + (*env)->ThrowNew(env, nxt_java_NoSuchElementException_class, msg); } - -void -nxt_java_throw_IOException(JNIEnv *env, const char *msg) -{ - (*env)->ThrowNew(env, nxt_java_IOException_class, msg); +void nxt_java_throw_IOException(JNIEnv *env, const char *msg) { + (*env)->ThrowNew(env, nxt_java_IOException_class, msg); } - -void -nxt_java_throw_IllegalStateException(JNIEnv *env, const char *msg) -{ - (*env)->ThrowNew(env, nxt_java_IllegalStateException_class, msg); +void nxt_java_throw_IllegalStateException(JNIEnv *env, const char *msg) { + (*env)->ThrowNew(env, nxt_java_IllegalStateException_class, msg); } +nxt_unit_field_t *nxt_java_findHeader(nxt_unit_field_t *f, + nxt_unit_field_t *end, const char *name, + uint8_t name_len) { + const char *field_name; -nxt_unit_field_t * -nxt_java_findHeader(nxt_unit_field_t *f, nxt_unit_field_t *end, - const char *name, uint8_t name_len) -{ - const char *field_name; - - for (/* void */ ; f < end; f++) { - if (f->skip != 0 || f->name_length != name_len) { - continue; - } + for (/* void */; f < end; f++) { + if (f->skip != 0 || f->name_length != name_len) { + continue; + } - field_name = nxt_unit_sptr_get(&f->name); + field_name = nxt_unit_sptr_get(&f->name); - if (nxt_java_strcaseeq(name, field_name, name_len)) { - return f; - } + if (nxt_java_strcaseeq(name, field_name, name_len)) { + return f; } + } - return NULL; + return NULL; } +int nxt_java_strcaseeq(const char *str1, const char *str2, int len) { + char c1, c2; + const char *end1; -int -nxt_java_strcaseeq(const char *str1, const char *str2, int len) -{ - char c1, c2; - const char *end1; + end1 = str1 + len; - end1 = str1 + len; + while (str1 < end1) { + c1 = nxt_java_lowcase(*str1++); + c2 = nxt_java_lowcase(*str2++); - while (str1 < end1) { - c1 = nxt_java_lowcase(*str1++); - c2 = nxt_java_lowcase(*str2++); - - if (c1 != c2) { - return 0; - } + if (c1 != c2) { + return 0; } + } - return 1; + return 1; } - -static inline char -nxt_java_lowcase(char c) -{ - return (c >= 'A' && c <= 'Z') ? c | 0x20 : c; +static inline char nxt_java_lowcase(char c) { + return (c >= 'A' && c <= 'Z') ? c | 0x20 : c; } +jstring nxt_java_newString(JNIEnv *env, char *str, uint32_t len) { + char tmp; + jstring res; -jstring -nxt_java_newString(JNIEnv *env, char *str, uint32_t len) -{ - char tmp; - jstring res; + tmp = str[len]; - tmp = str[len]; + if (tmp != '\0') { + str[len] = '\0'; + } - if (tmp != '\0') { - str[len] = '\0'; - } - - res = (*env)->NewStringUTF(env, str); + res = (*env)->NewStringUTF(env, str); - if (tmp != '\0') { - str[len] = tmp; - } + if (tmp != '\0') { + str[len] = tmp; + } - return res; + return res; } diff --git a/src/java/nxt_jni.h b/src/java/nxt_jni.h index 62acb7522..7a31a1a80 100644 --- a/src/java/nxt_jni.h +++ b/src/java/nxt_jni.h @@ -6,11 +6,9 @@ #ifndef _NXT_JAVA_JNI_H_INCLUDED_ #define _NXT_JAVA_JNI_H_INCLUDED_ - #include #include - int nxt_java_jni_init(JNIEnv *env); void nxt_java_throw_NoSuchElementException(JNIEnv *env, const char *msg); @@ -20,36 +18,26 @@ void nxt_java_throw_IOException(JNIEnv *env, const char *msg); void nxt_java_throw_IllegalStateException(JNIEnv *env, const char *msg); nxt_unit_field_t *nxt_java_findHeader(nxt_unit_field_t *f, nxt_unit_field_t *e, - const char *name, uint8_t name_len); + const char *name, uint8_t name_len); int nxt_java_strcaseeq(const char *str1, const char *str2, int len); jstring nxt_java_newString(JNIEnv *env, char *str, uint32_t len); - typedef struct { - uint32_t header_size; - uint32_t buf_size; + uint32_t header_size; + uint32_t buf_size; - jobject jreq; - jobject jresp; + jobject jreq; + jobject jresp; - nxt_unit_buf_t *first; - nxt_unit_buf_t *buf; + nxt_unit_buf_t *first; + nxt_unit_buf_t *buf; } nxt_java_request_data_t; +static inline jlong nxt_ptr2jlong(void *ptr) { return (jlong)(intptr_t)ptr; } -static inline jlong -nxt_ptr2jlong(void *ptr) -{ - return (jlong) (intptr_t) ptr; -} - -static inline void * -nxt_jlong2ptr(jlong l) -{ - return (void *) (intptr_t) l; -} +static inline void *nxt_jlong2ptr(jlong l) { return (void *)(intptr_t)l; } -#endif /* _NXT_JAVA_JNI_H_INCLUDED_ */ +#endif /* _NXT_JAVA_JNI_H_INCLUDED_ */ diff --git a/src/java/nxt_jni_Context.c b/src/java/nxt_jni_Context.c index 589e1c5bf..60cf09cc2 100644 --- a/src/java/nxt_jni_Context.c +++ b/src/java/nxt_jni_Context.c @@ -12,153 +12,134 @@ #include "nxt_jni_Context.h" #include "nxt_jni_URLClassLoader.h" +static jclass nxt_java_Context_class; +static jmethodID nxt_java_Context_start; +static jmethodID nxt_java_Context_service; +static jmethodID nxt_java_Context_stop; -static jclass nxt_java_Context_class; -static jmethodID nxt_java_Context_start; -static jmethodID nxt_java_Context_service; -static jmethodID nxt_java_Context_stop; - -static void JNICALL nxt_java_Context_log(JNIEnv *env, jclass cls, - jlong ctx_ptr, jstring msg, jint msg_len); +static void JNICALL nxt_java_Context_log(JNIEnv *env, jclass cls, jlong ctx_ptr, + jstring msg, jint msg_len); static void JNICALL nxt_java_Context_trace(JNIEnv *env, jclass cls, - jlong ctx_ptr, jstring msg, jint msg_len); - - -int -nxt_java_initContext(JNIEnv *env, jobject cl) -{ - int res; - jclass cls; - - cls = nxt_java_loadClass(env, cl, "nginx.unit.Context"); - if (cls == NULL) { - nxt_unit_warn(NULL, "nginx.unit.Context not found"); - return NXT_UNIT_ERROR; - } - - nxt_java_Context_class = (*env)->NewGlobalRef(env, cls); - (*env)->DeleteLocalRef(env, cls); - cls = nxt_java_Context_class; - - nxt_java_Context_start = (*env)->GetStaticMethodID(env, cls, "start", - "(Ljava/lang/String;[Ljava/net/URL;)Lnginx/unit/Context;"); - if (nxt_java_Context_start == NULL) { - nxt_unit_warn(NULL, "nginx.unit.Context.start() not found"); - goto failed; - } - - nxt_java_Context_service = (*env)->GetMethodID(env, cls, "service", - "(Lnginx/unit/Request;Lnginx/unit/Response;)V"); - if (nxt_java_Context_service == NULL) { - nxt_unit_warn(NULL, "nginx.unit.Context.service() not found"); - goto failed; - } - - nxt_java_Context_stop = (*env)->GetMethodID(env, cls, "stop", "()V"); - if (nxt_java_Context_stop == NULL) { - nxt_unit_warn(NULL, "nginx.unit.Context.stop() not found"); - goto failed; - } - - JNINativeMethod context_methods[] = { - { (char *) "log", - (char *) "(JLjava/lang/String;I)V", - nxt_java_Context_log }, - - { (char *) "trace", - (char *) "(JLjava/lang/String;I)V", - nxt_java_Context_trace }, - - }; - - res = (*env)->RegisterNatives(env, nxt_java_Context_class, - context_methods, - sizeof(context_methods) - / sizeof(context_methods[0])); - - nxt_unit_debug(NULL, "registered Context methods: %d", res); - - if (res != 0) { - nxt_unit_warn(NULL, "registering natives for Context failed"); - goto failed; - } - - return NXT_UNIT_OK; + jlong ctx_ptr, jstring msg, + jint msg_len); -failed: +int nxt_java_initContext(JNIEnv *env, jobject cl) { + int res; + jclass cls; - (*env)->DeleteGlobalRef(env, cls); + cls = nxt_java_loadClass(env, cl, "nginx.unit.Context"); + if (cls == NULL) { + nxt_unit_warn(NULL, "nginx.unit.Context not found"); return NXT_UNIT_ERROR; -} + } + nxt_java_Context_class = (*env)->NewGlobalRef(env, cls); + (*env)->DeleteLocalRef(env, cls); + cls = nxt_java_Context_class; -jobject -nxt_java_startContext(JNIEnv *env, const char *webapp, jobject classpaths) -{ - jstring webapp_str; + nxt_java_Context_start = (*env)->GetStaticMethodID( + env, cls, "start", + "(Ljava/lang/String;[Ljava/net/URL;)Lnginx/unit/Context;"); + if (nxt_java_Context_start == NULL) { + nxt_unit_warn(NULL, "nginx.unit.Context.start() not found"); + goto failed; + } - webapp_str = (*env)->NewStringUTF(env, webapp); - if (webapp_str == NULL) { - return NULL; - } + nxt_java_Context_service = (*env)->GetMethodID( + env, cls, "service", "(Lnginx/unit/Request;Lnginx/unit/Response;)V"); + if (nxt_java_Context_service == NULL) { + nxt_unit_warn(NULL, "nginx.unit.Context.service() not found"); + goto failed; + } - return (*env)->CallStaticObjectMethod(env, nxt_java_Context_class, - nxt_java_Context_start, webapp_str, - classpaths); -} + nxt_java_Context_stop = (*env)->GetMethodID(env, cls, "stop", "()V"); + if (nxt_java_Context_stop == NULL) { + nxt_unit_warn(NULL, "nginx.unit.Context.stop() not found"); + goto failed; + } + + JNINativeMethod context_methods[] = { + {(char *)"log", (char *)"(JLjava/lang/String;I)V", nxt_java_Context_log}, + + {(char *)"trace", (char *)"(JLjava/lang/String;I)V", + nxt_java_Context_trace}, + + }; + + res = (*env)->RegisterNatives(env, nxt_java_Context_class, context_methods, + sizeof(context_methods) / + sizeof(context_methods[0])); + + nxt_unit_debug(NULL, "registered Context methods: %d", res); + if (res != 0) { + nxt_unit_warn(NULL, "registering natives for Context failed"); + goto failed; + } -void -nxt_java_service(JNIEnv *env, jobject ctx, jobject jreq, jobject jresp) -{ - (*env)->CallVoidMethod(env, ctx, nxt_java_Context_service, jreq, jresp); + return NXT_UNIT_OK; + +failed: + + (*env)->DeleteGlobalRef(env, cls); + return NXT_UNIT_ERROR; } +jobject nxt_java_startContext(JNIEnv *env, const char *webapp, + jobject classpaths) { + jstring webapp_str; -void -nxt_java_stopContext(JNIEnv *env, jobject ctx) -{ - (*env)->CallVoidMethod(env, ctx, nxt_java_Context_stop); + webapp_str = (*env)->NewStringUTF(env, webapp); + if (webapp_str == NULL) { + return NULL; + } + + return (*env)->CallStaticObjectMethod(env, nxt_java_Context_class, + nxt_java_Context_start, webapp_str, + classpaths); } +void nxt_java_service(JNIEnv *env, jobject ctx, jobject jreq, jobject jresp) { + (*env)->CallVoidMethod(env, ctx, nxt_java_Context_service, jreq, jresp); +} -static void JNICALL -nxt_java_Context_log(JNIEnv *env, jclass cls, jlong ctx_ptr, jstring msg, - jint msg_len) -{ - const char *msg_str; - nxt_unit_ctx_t *ctx; +void nxt_java_stopContext(JNIEnv *env, jobject ctx) { + (*env)->CallVoidMethod(env, ctx, nxt_java_Context_stop); +} - ctx = nxt_jlong2ptr(ctx_ptr); +static void JNICALL nxt_java_Context_log(JNIEnv *env, jclass cls, jlong ctx_ptr, + jstring msg, jint msg_len) { + const char *msg_str; + nxt_unit_ctx_t *ctx; - msg_str = (*env)->GetStringUTFChars(env, msg, NULL); - if (msg_str == NULL) { - return; - } + ctx = nxt_jlong2ptr(ctx_ptr); - nxt_unit_log(ctx, NXT_UNIT_LOG_INFO, "%.*s", msg_len, msg_str); + msg_str = (*env)->GetStringUTFChars(env, msg, NULL); + if (msg_str == NULL) { + return; + } - (*env)->ReleaseStringUTFChars(env, msg, msg_str); -} + nxt_unit_log(ctx, NXT_UNIT_LOG_INFO, "%.*s", msg_len, msg_str); + (*env)->ReleaseStringUTFChars(env, msg, msg_str); +} -static void JNICALL -nxt_java_Context_trace(JNIEnv *env, jclass cls, jlong ctx_ptr, jstring msg, - jint msg_len) -{ +static void JNICALL nxt_java_Context_trace(JNIEnv *env, jclass cls, + jlong ctx_ptr, jstring msg, + jint msg_len) { #if (NXT_DEBUG) - const char *msg_str; - nxt_unit_ctx_t *ctx; + const char *msg_str; + nxt_unit_ctx_t *ctx; - ctx = nxt_jlong2ptr(ctx_ptr); + ctx = nxt_jlong2ptr(ctx_ptr); - msg_str = (*env)->GetStringUTFChars(env, msg, NULL); - if (msg_str == NULL) { - return; - } + msg_str = (*env)->GetStringUTFChars(env, msg, NULL); + if (msg_str == NULL) { + return; + } - nxt_unit_debug(ctx, "%.*s", msg_len, msg_str); + nxt_unit_debug(ctx, "%.*s", msg_len, msg_str); - (*env)->ReleaseStringUTFChars(env, msg, msg_str); + (*env)->ReleaseStringUTFChars(env, msg, msg_str); #endif } diff --git a/src/java/nxt_jni_Context.h b/src/java/nxt_jni_Context.h index 976c36cf6..44a4ba814 100644 --- a/src/java/nxt_jni_Context.h +++ b/src/java/nxt_jni_Context.h @@ -6,18 +6,15 @@ #ifndef _NXT_JAVA_CONTEXT_H_INCLUDED_ #define _NXT_JAVA_CONTEXT_H_INCLUDED_ - #include - int nxt_java_initContext(JNIEnv *env, jobject cl); jobject nxt_java_startContext(JNIEnv *env, const char *webapp, - jobject classpaths); + jobject classpaths); void nxt_java_service(JNIEnv *env, jobject ctx, jobject jreq, jobject jresp); void nxt_java_stopContext(JNIEnv *env, jobject ctx); -#endif /* _NXT_JAVA_CONTEXT_H_INCLUDED_ */ - +#endif /* _NXT_JAVA_CONTEXT_H_INCLUDED_ */ diff --git a/src/java/nxt_jni_HeaderNamesEnumeration.c b/src/java/nxt_jni_HeaderNamesEnumeration.c index eea0c387e..b93366517 100644 --- a/src/java/nxt_jni_HeaderNamesEnumeration.c +++ b/src/java/nxt_jni_HeaderNamesEnumeration.c @@ -14,140 +14,118 @@ #include "nxt_jni_URLClassLoader.h" #include "nxt_jni_HeaderNamesEnumeration.h" - -static jlong JNICALL nxt_java_HeaderNamesEnumeration_nextElementPos(JNIEnv *env, - jclass cls, jlong headers_ptr, jlong size, jlong pos); -static jstring JNICALL nxt_java_HeaderNamesEnumeration_nextElement(JNIEnv *env, - jclass cls, jlong headers_ptr, jlong size, jlong pos); - - -static jclass nxt_java_HeaderNamesEnumeration_class; -static jmethodID nxt_java_HeaderNamesEnumeration_ctor; - - -int -nxt_java_initHeaderNamesEnumeration(JNIEnv *env, jobject cl) -{ - int res; - jclass cls; - - cls = nxt_java_loadClass(env, cl, "nginx.unit.HeaderNamesEnumeration"); - if (cls == NULL) { - return NXT_UNIT_ERROR; - } - - nxt_java_HeaderNamesEnumeration_class = (*env)->NewGlobalRef(env, cls); - (*env)->DeleteLocalRef(env, cls); - cls = nxt_java_HeaderNamesEnumeration_class; - - nxt_java_HeaderNamesEnumeration_ctor = (*env)->GetMethodID(env, cls, - "", "(JJ)V"); - if (nxt_java_HeaderNamesEnumeration_ctor == NULL) { - (*env)->DeleteGlobalRef(env, cls); - return NXT_UNIT_ERROR; - } - - JNINativeMethod hnenum_methods[] = { - { (char *) "nextElementPos", - (char *) "(JJJ)J", - nxt_java_HeaderNamesEnumeration_nextElementPos }, - - { (char *) "nextElement", - (char *) "(JJJ)Ljava/lang/String;", - nxt_java_HeaderNamesEnumeration_nextElement }, - }; - - res = (*env)->RegisterNatives(env, nxt_java_HeaderNamesEnumeration_class, - hnenum_methods, - sizeof(hnenum_methods) - / sizeof(hnenum_methods[0])); - - nxt_unit_debug(NULL, "registered HeaderNamesEnumeration methods: %d", res); - - if (res != 0) { - (*env)->DeleteGlobalRef(env, cls); - return NXT_UNIT_ERROR; - } - - return NXT_UNIT_OK; +static jlong JNICALL nxt_java_HeaderNamesEnumeration_nextElementPos( + JNIEnv *env, jclass cls, jlong headers_ptr, jlong size, jlong pos); +static jstring JNICALL nxt_java_HeaderNamesEnumeration_nextElement( + JNIEnv *env, jclass cls, jlong headers_ptr, jlong size, jlong pos); + +static jclass nxt_java_HeaderNamesEnumeration_class; +static jmethodID nxt_java_HeaderNamesEnumeration_ctor; + +int nxt_java_initHeaderNamesEnumeration(JNIEnv *env, jobject cl) { + int res; + jclass cls; + + cls = nxt_java_loadClass(env, cl, "nginx.unit.HeaderNamesEnumeration"); + if (cls == NULL) { + return NXT_UNIT_ERROR; + } + + nxt_java_HeaderNamesEnumeration_class = (*env)->NewGlobalRef(env, cls); + (*env)->DeleteLocalRef(env, cls); + cls = nxt_java_HeaderNamesEnumeration_class; + + nxt_java_HeaderNamesEnumeration_ctor = + (*env)->GetMethodID(env, cls, "", "(JJ)V"); + if (nxt_java_HeaderNamesEnumeration_ctor == NULL) { + (*env)->DeleteGlobalRef(env, cls); + return NXT_UNIT_ERROR; + } + + JNINativeMethod hnenum_methods[] = { + {(char *)"nextElementPos", (char *)"(JJJ)J", + nxt_java_HeaderNamesEnumeration_nextElementPos}, + + {(char *)"nextElement", (char *)"(JJJ)Ljava/lang/String;", + nxt_java_HeaderNamesEnumeration_nextElement}, + }; + + res = (*env)->RegisterNatives( + env, nxt_java_HeaderNamesEnumeration_class, hnenum_methods, + sizeof(hnenum_methods) / sizeof(hnenum_methods[0])); + + nxt_unit_debug(NULL, "registered HeaderNamesEnumeration methods: %d", res); + + if (res != 0) { + (*env)->DeleteGlobalRef(env, cls); + return NXT_UNIT_ERROR; + } + + return NXT_UNIT_OK; } - -jobject -nxt_java_newHeaderNamesEnumeration(JNIEnv *env, nxt_unit_field_t *f, - uint32_t fields_count) -{ - return (*env)->NewObject(env, - nxt_java_HeaderNamesEnumeration_class, - nxt_java_HeaderNamesEnumeration_ctor, nxt_ptr2jlong(f), - (jlong) fields_count); +jobject nxt_java_newHeaderNamesEnumeration(JNIEnv *env, nxt_unit_field_t *f, + uint32_t fields_count) { + return (*env)->NewObject(env, nxt_java_HeaderNamesEnumeration_class, + nxt_java_HeaderNamesEnumeration_ctor, + nxt_ptr2jlong(f), (jlong)fields_count); } +static jlong JNICALL nxt_java_HeaderNamesEnumeration_nextElementPos( + JNIEnv *env, jclass cls, jlong headers_ptr, jlong size, jlong pos) { + nxt_unit_field_t *f; -static jlong JNICALL -nxt_java_HeaderNamesEnumeration_nextElementPos(JNIEnv *env, jclass cls, - jlong headers_ptr, jlong size, jlong pos) -{ - nxt_unit_field_t *f; + f = nxt_jlong2ptr(headers_ptr); - f = nxt_jlong2ptr(headers_ptr); + if (pos >= size) { + return size; + } - if (pos >= size) { - return size; + if (pos > 0) { + while (pos < size && f[pos].hash == f[pos - 1].hash && + f[pos].name_length == f[pos - 1].name_length) { + pos++; } + } - if (pos > 0) { - while (pos < size - && f[pos].hash == f[pos - 1].hash - && f[pos].name_length == f[pos - 1].name_length) - { - pos++; - } - } - - return pos; + return pos; } +static jstring JNICALL nxt_java_HeaderNamesEnumeration_nextElement( + JNIEnv *env, jclass cls, jlong headers_ptr, jlong size, jlong pos) { + char *name, tmp; + jstring res; + nxt_unit_field_t *f; -static jstring JNICALL -nxt_java_HeaderNamesEnumeration_nextElement(JNIEnv *env, jclass cls, - jlong headers_ptr, jlong size, jlong pos) -{ - char *name, tmp; - jstring res; - nxt_unit_field_t *f; - - f = nxt_jlong2ptr(headers_ptr); + f = nxt_jlong2ptr(headers_ptr); - if (pos > 0) { - while (pos < size - && f[pos].hash == f[pos - 1].hash - && f[pos].name_length == f[pos - 1].name_length) - { - pos++; - } + if (pos > 0) { + while (pos < size && f[pos].hash == f[pos - 1].hash && + f[pos].name_length == f[pos - 1].name_length) { + pos++; } + } - if (pos >= size) { - nxt_java_throw_NoSuchElementException(env, "pos >= size"); + if (pos >= size) { + nxt_java_throw_NoSuchElementException(env, "pos >= size"); - return NULL; - } + return NULL; + } - f += pos; + f += pos; - name = nxt_unit_sptr_get(&f->name); - tmp = name[f->name_length]; + name = nxt_unit_sptr_get(&f->name); + tmp = name[f->name_length]; - if (tmp != '\0') { - name[f->name_length] = '\0'; - } + if (tmp != '\0') { + name[f->name_length] = '\0'; + } - res = (*env)->NewStringUTF(env, name); + res = (*env)->NewStringUTF(env, name); - if (tmp != '\0') { - name[f->name_length] = tmp; - } + if (tmp != '\0') { + name[f->name_length] = tmp; + } - return res; + return res; } diff --git a/src/java/nxt_jni_HeaderNamesEnumeration.h b/src/java/nxt_jni_HeaderNamesEnumeration.h index 90df8f542..86a39f155 100644 --- a/src/java/nxt_jni_HeaderNamesEnumeration.h +++ b/src/java/nxt_jni_HeaderNamesEnumeration.h @@ -6,14 +6,12 @@ #ifndef _NXT_JAVA_HEADERNAMESENUMERATION_H_INCLUDED_ #define _NXT_JAVA_HEADERNAMESENUMERATION_H_INCLUDED_ - #include #include - int nxt_java_initHeaderNamesEnumeration(JNIEnv *env, jobject cl); jobject nxt_java_newHeaderNamesEnumeration(JNIEnv *env, nxt_unit_field_t *f, - uint32_t fields_count); + uint32_t fields_count); -#endif /* _NXT_JAVA_HEADERNAMESENUMERATION_H_INCLUDED_ */ +#endif /* _NXT_JAVA_HEADERNAMESENUMERATION_H_INCLUDED_ */ diff --git a/src/java/nxt_jni_HeadersEnumeration.c b/src/java/nxt_jni_HeadersEnumeration.c index aaea710db..ebf2c294d 100644 --- a/src/java/nxt_jni_HeadersEnumeration.c +++ b/src/java/nxt_jni_HeadersEnumeration.c @@ -14,135 +14,117 @@ #include "nxt_jni_URLClassLoader.h" #include "nxt_jni_HeadersEnumeration.h" +static jclass nxt_java_HeadersEnumeration_class; +static jmethodID nxt_java_HeadersEnumeration_ctor; -static jclass nxt_java_HeadersEnumeration_class; -static jmethodID nxt_java_HeadersEnumeration_ctor; +static jlong JNICALL nxt_java_HeadersEnumeration_nextElementPos( + JNIEnv *env, jclass cls, jlong headers_ptr, jlong size, jlong ipos, + jlong pos); +static jstring JNICALL nxt_java_HeadersEnumeration_nextElement( + JNIEnv *env, jclass cls, jlong headers_ptr, jlong size, jlong ipos, + jlong pos); -static jlong JNICALL nxt_java_HeadersEnumeration_nextElementPos(JNIEnv *env, - jclass cls, jlong headers_ptr, jlong size, jlong ipos, jlong pos); +int nxt_java_initHeadersEnumeration(JNIEnv *env, jobject cl) { + int res; + jclass cls; -static jstring JNICALL nxt_java_HeadersEnumeration_nextElement(JNIEnv *env, - jclass cls, jlong headers_ptr, jlong size, jlong ipos, jlong pos); + cls = nxt_java_loadClass(env, cl, "nginx.unit.HeadersEnumeration"); + if (cls == NULL) { + return NXT_UNIT_ERROR; + } + nxt_java_HeadersEnumeration_class = (*env)->NewGlobalRef(env, cls); + (*env)->DeleteLocalRef(env, cls); + cls = nxt_java_HeadersEnumeration_class; -int -nxt_java_initHeadersEnumeration(JNIEnv *env, jobject cl) -{ - int res; - jclass cls; + nxt_java_HeadersEnumeration_ctor = + (*env)->GetMethodID(env, cls, "", "(JJJ)V"); + if (nxt_java_HeadersEnumeration_ctor == NULL) { + (*env)->DeleteGlobalRef(env, cls); + return NXT_UNIT_ERROR; + } - cls = nxt_java_loadClass(env, cl, "nginx.unit.HeadersEnumeration"); - if (cls == NULL) { - return NXT_UNIT_ERROR; - } + JNINativeMethod methods[] = { + {(char *)"nextElementPos", (char *)"(JJJJ)J", + nxt_java_HeadersEnumeration_nextElementPos}, - nxt_java_HeadersEnumeration_class = (*env)->NewGlobalRef(env, cls); - (*env)->DeleteLocalRef(env, cls); - cls = nxt_java_HeadersEnumeration_class; + {(char *)"nextElement", (char *)"(JJJJ)Ljava/lang/String;", + nxt_java_HeadersEnumeration_nextElement}, + }; - nxt_java_HeadersEnumeration_ctor = (*env)->GetMethodID(env, cls, - "", "(JJJ)V"); - if (nxt_java_HeadersEnumeration_ctor == NULL) { - (*env)->DeleteGlobalRef(env, cls); - return NXT_UNIT_ERROR; - } + res = (*env)->RegisterNatives(env, nxt_java_HeadersEnumeration_class, methods, + sizeof(methods) / sizeof(methods[0])); - JNINativeMethod methods[] = { - { (char *) "nextElementPos", - (char *) "(JJJJ)J", - nxt_java_HeadersEnumeration_nextElementPos }, + nxt_unit_debug(NULL, "registered HeadersEnumeration methods: %d", res); - { (char *) "nextElement", - (char *) "(JJJJ)Ljava/lang/String;", - nxt_java_HeadersEnumeration_nextElement }, - }; + if (res != 0) { + (*env)->DeleteGlobalRef(env, cls); + return NXT_UNIT_ERROR; + } - res = (*env)->RegisterNatives(env, nxt_java_HeadersEnumeration_class, - methods, - sizeof(methods) / sizeof(methods[0])); - - nxt_unit_debug(NULL, "registered HeadersEnumeration methods: %d", res); - - if (res != 0) { - (*env)->DeleteGlobalRef(env, cls); - return NXT_UNIT_ERROR; - } - - return NXT_UNIT_OK; + return NXT_UNIT_OK; } - -jobject -nxt_java_newHeadersEnumeration(JNIEnv *env, nxt_unit_field_t *f, - uint32_t fields_count, uint32_t pos) -{ - return (*env)->NewObject(env, - nxt_java_HeadersEnumeration_class, - nxt_java_HeadersEnumeration_ctor, nxt_ptr2jlong(f), - (jlong) fields_count, (jlong) pos); +jobject nxt_java_newHeadersEnumeration(JNIEnv *env, nxt_unit_field_t *f, + uint32_t fields_count, uint32_t pos) { + return (*env)->NewObject(env, nxt_java_HeadersEnumeration_class, + nxt_java_HeadersEnumeration_ctor, nxt_ptr2jlong(f), + (jlong)fields_count, (jlong)pos); } +static jlong JNICALL nxt_java_HeadersEnumeration_nextElementPos( + JNIEnv *env, jclass cls, jlong headers_ptr, jlong size, jlong ipos, + jlong pos) { + nxt_unit_field_t *f, *init_field; -static jlong JNICALL -nxt_java_HeadersEnumeration_nextElementPos(JNIEnv *env, jclass cls, - jlong headers_ptr, jlong size, jlong ipos, jlong pos) -{ - nxt_unit_field_t *f, *init_field; - - f = nxt_jlong2ptr(headers_ptr); + f = nxt_jlong2ptr(headers_ptr); - init_field = f + ipos; + init_field = f + ipos; - if (pos >= size) { - return size; - } + if (pos >= size) { + return size; + } - f += pos; + f += pos; - if (f->hash != init_field->hash - || f->name_length != init_field->name_length) - { - return size; - } + if (f->hash != init_field->hash || + f->name_length != init_field->name_length) { + return size; + } - if (!nxt_java_strcaseeq(nxt_unit_sptr_get(&f->name), - nxt_unit_sptr_get(&init_field->name), - init_field->name_length)) - { - return size; - } + if (!nxt_java_strcaseeq(nxt_unit_sptr_get(&f->name), + nxt_unit_sptr_get(&init_field->name), + init_field->name_length)) { + return size; + } - return pos; + return pos; } +static jstring JNICALL nxt_java_HeadersEnumeration_nextElement( + JNIEnv *env, jclass cls, jlong headers_ptr, jlong size, jlong ipos, + jlong pos) { + nxt_unit_field_t *f, *init_field; -static jstring JNICALL -nxt_java_HeadersEnumeration_nextElement(JNIEnv *env, jclass cls, - jlong headers_ptr, jlong size, jlong ipos, jlong pos) -{ - nxt_unit_field_t *f, *init_field; - - f = nxt_jlong2ptr(headers_ptr); + f = nxt_jlong2ptr(headers_ptr); - init_field = f + ipos; + init_field = f + ipos; - if (pos >= size) { - nxt_java_throw_IOException(env, "pos >= size"); + if (pos >= size) { + nxt_java_throw_IOException(env, "pos >= size"); - return NULL; - } + return NULL; + } - f += pos; + f += pos; - if (f->hash != init_field->hash - || f->name_length != init_field->name_length) - { - nxt_java_throw_IOException(env, "f->hash != hash"); + if (f->hash != init_field->hash || + f->name_length != init_field->name_length) { + nxt_java_throw_IOException(env, "f->hash != hash"); - return NULL; - } + return NULL; + } - return nxt_java_newString(env, nxt_unit_sptr_get(&f->value), - f->value_length); + return nxt_java_newString(env, nxt_unit_sptr_get(&f->value), f->value_length); } diff --git a/src/java/nxt_jni_HeadersEnumeration.h b/src/java/nxt_jni_HeadersEnumeration.h index 10f9393c6..6e4222c03 100644 --- a/src/java/nxt_jni_HeadersEnumeration.h +++ b/src/java/nxt_jni_HeadersEnumeration.h @@ -6,14 +6,12 @@ #ifndef _NXT_JAVA_HEADERSENUMERATION_H_INCLUDED_ #define _NXT_JAVA_HEADERSENUMERATION_H_INCLUDED_ - #include #include - int nxt_java_initHeadersEnumeration(JNIEnv *env, jobject cl); jobject nxt_java_newHeadersEnumeration(JNIEnv *env, nxt_unit_field_t *f, - uint32_t fields_count, uint32_t pos); + uint32_t fields_count, uint32_t pos); -#endif /* _NXT_JAVA_HEADERSENUMERATION_H_INCLUDED_ */ +#endif /* _NXT_JAVA_HEADERSENUMERATION_H_INCLUDED_ */ diff --git a/src/java/nxt_jni_InputStream.c b/src/java/nxt_jni_InputStream.c index fabff685e..2e693ceaf 100644 --- a/src/java/nxt_jni_InputStream.c +++ b/src/java/nxt_jni_InputStream.c @@ -13,198 +13,171 @@ #include "nxt_jni_InputStream.h" #include "nxt_jni_URLClassLoader.h" - static jint JNICALL nxt_java_InputStream_readLine(JNIEnv *env, jclass cls, - jlong req_info_ptr, jarray b, jint off, jint len); + jlong req_info_ptr, jarray b, + jint off, jint len); static jboolean JNICALL nxt_java_InputStream_isFinished(JNIEnv *env, jclass cls, - jlong req_info_ptr); + jlong req_info_ptr); static jint JNICALL nxt_java_InputStream_readByte(JNIEnv *env, jclass cls, - jlong req_info_ptr); + jlong req_info_ptr); static jint JNICALL nxt_java_InputStream_read(JNIEnv *env, jclass cls, - jlong req_info_ptr, jarray b, jint off, jint len); + jlong req_info_ptr, jarray b, + jint off, jint len); static jlong JNICALL nxt_java_InputStream_skip(JNIEnv *env, jclass cls, - jlong req_info_ptr, jlong n); + jlong req_info_ptr, jlong n); static jint JNICALL nxt_java_InputStream_available(JNIEnv *env, jclass cls, - jlong req_info_ptr); - - -static jclass nxt_java_InputStream_class; + jlong req_info_ptr); +static jclass nxt_java_InputStream_class; -int -nxt_java_initInputStream(JNIEnv *env, jobject cl) -{ - int res; - jclass cls; +int nxt_java_initInputStream(JNIEnv *env, jobject cl) { + int res; + jclass cls; - cls = nxt_java_loadClass(env, cl, "nginx.unit.InputStream"); - if (cls == NULL) { - return NXT_UNIT_ERROR; - } + cls = nxt_java_loadClass(env, cl, "nginx.unit.InputStream"); + if (cls == NULL) { + return NXT_UNIT_ERROR; + } - nxt_java_InputStream_class = (*env)->NewGlobalRef(env, cls); - (*env)->DeleteLocalRef(env, cls); + nxt_java_InputStream_class = (*env)->NewGlobalRef(env, cls); + (*env)->DeleteLocalRef(env, cls); - JNINativeMethod is_methods[] = { - { (char *) "readLine", - (char *) "(J[BII)I", - nxt_java_InputStream_readLine }, + JNINativeMethod is_methods[] = { + {(char *)"readLine", (char *)"(J[BII)I", nxt_java_InputStream_readLine}, - { (char *) "isFinished", - (char *) "(J)Z", - nxt_java_InputStream_isFinished }, + {(char *)"isFinished", (char *)"(J)Z", nxt_java_InputStream_isFinished}, - { (char *) "read", - (char *) "(J)I", - nxt_java_InputStream_readByte }, + {(char *)"read", (char *)"(J)I", nxt_java_InputStream_readByte}, - { (char *) "read", - (char *) "(J[BII)I", - nxt_java_InputStream_read }, + {(char *)"read", (char *)"(J[BII)I", nxt_java_InputStream_read}, - { (char *) "skip", - (char *) "(JJ)J", - nxt_java_InputStream_skip }, + {(char *)"skip", (char *)"(JJ)J", nxt_java_InputStream_skip}, - { (char *) "available", - (char *) "(J)I", - nxt_java_InputStream_available }, - }; + {(char *)"available", (char *)"(J)I", nxt_java_InputStream_available}, + }; - res = (*env)->RegisterNatives(env, nxt_java_InputStream_class, - is_methods, - sizeof(is_methods) / sizeof(is_methods[0])); + res = (*env)->RegisterNatives(env, nxt_java_InputStream_class, is_methods, + sizeof(is_methods) / sizeof(is_methods[0])); - nxt_unit_debug(NULL, "registered InputStream methods: %d", res); + nxt_unit_debug(NULL, "registered InputStream methods: %d", res); - if (res != 0) { - (*env)->DeleteGlobalRef(env, cls); - return NXT_UNIT_ERROR; - } + if (res != 0) { + (*env)->DeleteGlobalRef(env, cls); + return NXT_UNIT_ERROR; + } - return NXT_UNIT_OK; + return NXT_UNIT_OK; } +static jint JNICALL nxt_java_InputStream_readLine(JNIEnv *env, jclass cls, + jlong req_info_ptr, + jarray out, jint off, + jint len) { + uint8_t *data; + ssize_t res; + nxt_unit_request_info_t *req; -static jint JNICALL -nxt_java_InputStream_readLine(JNIEnv *env, jclass cls, - jlong req_info_ptr, jarray out, jint off, jint len) -{ - uint8_t *data; - ssize_t res; - nxt_unit_request_info_t *req; - - req = nxt_jlong2ptr(req_info_ptr); + req = nxt_jlong2ptr(req_info_ptr); - data = (*env)->GetPrimitiveArrayCritical(env, out, NULL); + data = (*env)->GetPrimitiveArrayCritical(env, out, NULL); - res = nxt_unit_request_readline_size(req, len); + res = nxt_unit_request_readline_size(req, len); - if (res > 0) { - res = nxt_unit_request_read(req, data + off, res); - } + if (res > 0) { + res = nxt_unit_request_read(req, data + off, res); + } - nxt_unit_req_debug(req, "readLine '%.*s'", (int) res, (char *) data + off); + nxt_unit_req_debug(req, "readLine '%.*s'", (int)res, (char *)data + off); - (*env)->ReleasePrimitiveArrayCritical(env, out, data, 0); + (*env)->ReleasePrimitiveArrayCritical(env, out, data, 0); - return res > 0 ? res : -1; + return res > 0 ? res : -1; } +static jboolean JNICALL nxt_java_InputStream_isFinished(JNIEnv *env, jclass cls, + jlong req_info_ptr) { + nxt_unit_request_info_t *req; -static jboolean JNICALL -nxt_java_InputStream_isFinished(JNIEnv *env, jclass cls, jlong req_info_ptr) -{ - nxt_unit_request_info_t *req; - - req = nxt_jlong2ptr(req_info_ptr); + req = nxt_jlong2ptr(req_info_ptr); - return req->content_length == 0; + return req->content_length == 0; } +static jint JNICALL nxt_java_InputStream_readByte(JNIEnv *env, jclass cls, + jlong req_info_ptr) { + uint8_t b; + ssize_t size; + nxt_unit_request_info_t *req; -static jint JNICALL -nxt_java_InputStream_readByte(JNIEnv *env, jclass cls, jlong req_info_ptr) -{ - uint8_t b; - ssize_t size; - nxt_unit_request_info_t *req; - - req = nxt_jlong2ptr(req_info_ptr); + req = nxt_jlong2ptr(req_info_ptr); - size = nxt_unit_request_read(req, &b, 1); + size = nxt_unit_request_read(req, &b, 1); - return size == 1 ? b : -1; + return size == 1 ? b : -1; } +static jint JNICALL nxt_java_InputStream_read(JNIEnv *env, jclass cls, + jlong req_info_ptr, jarray b, + jint off, jint len) { + uint8_t *data; + ssize_t res; + nxt_unit_request_info_t *req; -static jint JNICALL -nxt_java_InputStream_read(JNIEnv *env, jclass cls, jlong req_info_ptr, - jarray b, jint off, jint len) -{ - uint8_t *data; - ssize_t res; - nxt_unit_request_info_t *req; - - req = nxt_jlong2ptr(req_info_ptr); + req = nxt_jlong2ptr(req_info_ptr); - data = (*env)->GetPrimitiveArrayCritical(env, b, NULL); + data = (*env)->GetPrimitiveArrayCritical(env, b, NULL); - res = nxt_unit_request_read(req, data + off, len); + res = nxt_unit_request_read(req, data + off, len); - nxt_unit_req_debug(req, "read '%.*s'", (int) res, (char *) data + off); + nxt_unit_req_debug(req, "read '%.*s'", (int)res, (char *)data + off); - (*env)->ReleasePrimitiveArrayCritical(env, b, data, 0); + (*env)->ReleasePrimitiveArrayCritical(env, b, data, 0); - return res > 0 ? res : -1; + return res > 0 ? res : -1; } +static jlong JNICALL nxt_java_InputStream_skip(JNIEnv *env, jclass cls, + jlong req_info_ptr, jlong n) { + size_t rest, b_size; + nxt_unit_buf_t *buf; + nxt_unit_request_info_t *req; -static jlong JNICALL -nxt_java_InputStream_skip(JNIEnv *env, jclass cls, jlong req_info_ptr, jlong n) -{ - size_t rest, b_size; - nxt_unit_buf_t *buf; - nxt_unit_request_info_t *req; - - req = nxt_jlong2ptr(req_info_ptr); - - rest = n; - - buf = req->content_buf; + req = nxt_jlong2ptr(req_info_ptr); - while (buf != NULL) { - b_size = buf->end - buf->free; - b_size = rest < b_size ? rest : b_size; + rest = n; - buf->free += b_size; - rest -= b_size; + buf = req->content_buf; - if (rest == 0) { - if (buf->end == buf->free) { - buf = nxt_unit_buf_next(buf); - } + while (buf != NULL) { + b_size = buf->end - buf->free; + b_size = rest < b_size ? rest : b_size; - break; - } + buf->free += b_size; + rest -= b_size; + if (rest == 0) { + if (buf->end == buf->free) { buf = nxt_unit_buf_next(buf); + } + + break; } - n = n < (jlong) req->content_length ? n : (jlong) req->content_length; + buf = nxt_unit_buf_next(buf); + } - req->content_length -= n; + n = n < (jlong)req->content_length ? n : (jlong)req->content_length; - return n; -} + req->content_length -= n; + return n; +} -static jint JNICALL -nxt_java_InputStream_available(JNIEnv *env, jclass cls, jlong req_info_ptr) -{ - nxt_unit_request_info_t *req; +static jint JNICALL nxt_java_InputStream_available(JNIEnv *env, jclass cls, + jlong req_info_ptr) { + nxt_unit_request_info_t *req; - req = nxt_jlong2ptr(req_info_ptr); + req = nxt_jlong2ptr(req_info_ptr); - return req->content_length; + return req->content_length; } diff --git a/src/java/nxt_jni_InputStream.h b/src/java/nxt_jni_InputStream.h index b20b262a4..7441b1f98 100644 --- a/src/java/nxt_jni_InputStream.h +++ b/src/java/nxt_jni_InputStream.h @@ -6,10 +6,8 @@ #ifndef _NXT_JAVA_INPUTSTREAM_H_INCLUDED_ #define _NXT_JAVA_INPUTSTREAM_H_INCLUDED_ - #include - int nxt_java_initInputStream(JNIEnv *env, jobject cl); -#endif /* _NXT_JAVA_INPUTSTREAM_H_INCLUDED_ */ +#endif /* _NXT_JAVA_INPUTSTREAM_H_INCLUDED_ */ diff --git a/src/java/nxt_jni_OutputStream.c b/src/java/nxt_jni_OutputStream.c index 170b33ba9..a1072afde 100644 --- a/src/java/nxt_jni_OutputStream.c +++ b/src/java/nxt_jni_OutputStream.c @@ -12,225 +12,199 @@ #include "nxt_jni_OutputStream.h" #include "nxt_jni_URLClassLoader.h" - static void JNICALL nxt_java_OutputStream_writeByte(JNIEnv *env, jclass cls, - jlong req_info_ptr, jint b); -static nxt_unit_buf_t *nxt_java_OutputStream_req_buf(JNIEnv *env, - nxt_unit_request_info_t *req); + jlong req_info_ptr, jint b); +static nxt_unit_buf_t * +nxt_java_OutputStream_req_buf(JNIEnv *env, nxt_unit_request_info_t *req); static void JNICALL nxt_java_OutputStream_write(JNIEnv *env, jclass cls, - jlong req_info_ptr, jarray b, jint off, jint len); + jlong req_info_ptr, jarray b, + jint off, jint len); static void JNICALL nxt_java_OutputStream_flush(JNIEnv *env, jclass cls, - jlong req_info_ptr); + jlong req_info_ptr); static void JNICALL nxt_java_OutputStream_close(JNIEnv *env, jclass cls, - jlong req_info_ptr); - - -static jclass nxt_java_OutputStream_class; + jlong req_info_ptr); +static jclass nxt_java_OutputStream_class; -int -nxt_java_initOutputStream(JNIEnv *env, jobject cl) -{ - int res; - jclass cls; +int nxt_java_initOutputStream(JNIEnv *env, jobject cl) { + int res; + jclass cls; - cls = nxt_java_loadClass(env, cl, "nginx.unit.OutputStream"); - if (cls == NULL) { - return NXT_UNIT_ERROR; - } + cls = nxt_java_loadClass(env, cl, "nginx.unit.OutputStream"); + if (cls == NULL) { + return NXT_UNIT_ERROR; + } - nxt_java_OutputStream_class = (*env)->NewGlobalRef(env, cls); - (*env)->DeleteLocalRef(env, cls); + nxt_java_OutputStream_class = (*env)->NewGlobalRef(env, cls); + (*env)->DeleteLocalRef(env, cls); - cls = nxt_java_OutputStream_class; + cls = nxt_java_OutputStream_class; - JNINativeMethod os_methods[] = { - { (char *) "write", - (char *) "(JI)V", - nxt_java_OutputStream_writeByte }, + JNINativeMethod os_methods[] = { + {(char *)"write", (char *)"(JI)V", nxt_java_OutputStream_writeByte}, - { (char *) "write", - (char *) "(J[BII)V", - nxt_java_OutputStream_write }, + {(char *)"write", (char *)"(J[BII)V", nxt_java_OutputStream_write}, - { (char *) "flush", - (char *) "(J)V", - nxt_java_OutputStream_flush }, + {(char *)"flush", (char *)"(J)V", nxt_java_OutputStream_flush}, - { (char *) "close", - (char *) "(J)V", - nxt_java_OutputStream_close }, - }; + {(char *)"close", (char *)"(J)V", nxt_java_OutputStream_close}, + }; - res = (*env)->RegisterNatives(env, nxt_java_OutputStream_class, - os_methods, - sizeof(os_methods) / sizeof(os_methods[0])); + res = (*env)->RegisterNatives(env, nxt_java_OutputStream_class, os_methods, + sizeof(os_methods) / sizeof(os_methods[0])); - nxt_unit_debug(NULL, "registered OutputStream methods: %d", res); + nxt_unit_debug(NULL, "registered OutputStream methods: %d", res); - if (res != 0) { - (*env)->DeleteGlobalRef(env, cls); - return NXT_UNIT_ERROR; - } + if (res != 0) { + (*env)->DeleteGlobalRef(env, cls); + return NXT_UNIT_ERROR; + } - return NXT_UNIT_OK; + return NXT_UNIT_OK; } +static void JNICALL nxt_java_OutputStream_writeByte(JNIEnv *env, jclass cls, + jlong req_info_ptr, + jint b) { + nxt_unit_buf_t *buf; + nxt_unit_request_info_t *req; + nxt_java_request_data_t *data; -static void JNICALL -nxt_java_OutputStream_writeByte(JNIEnv *env, jclass cls, jlong req_info_ptr, - jint b) -{ - nxt_unit_buf_t *buf; - nxt_unit_request_info_t *req; - nxt_java_request_data_t *data; + req = nxt_jlong2ptr(req_info_ptr); + data = req->data; - req = nxt_jlong2ptr(req_info_ptr); - data = req->data; + buf = nxt_java_OutputStream_req_buf(env, req); + if (buf == NULL) { + return; + } - buf = nxt_java_OutputStream_req_buf(env, req); - if (buf == NULL) { - return; - } + *buf->free++ = b; - *buf->free++ = b; - - if ((uint32_t) (buf->free - buf->start) >= data->buf_size) { - nxt_java_OutputStream_flush_buf(env, req); - } + if ((uint32_t)(buf->free - buf->start) >= data->buf_size) { + nxt_java_OutputStream_flush_buf(env, req); + } } +int nxt_java_OutputStream_flush_buf(JNIEnv *env, nxt_unit_request_info_t *req) { + int rc; + nxt_java_request_data_t *data; -int -nxt_java_OutputStream_flush_buf(JNIEnv *env, nxt_unit_request_info_t *req) -{ - int rc; - nxt_java_request_data_t *data; + data = req->data; - data = req->data; + if (!nxt_unit_response_is_init(req)) { + rc = nxt_unit_response_init(req, 200, 0, 0); + if (rc != NXT_UNIT_OK) { + nxt_java_throw_IOException(env, "Failed to allocate response"); - if (!nxt_unit_response_is_init(req)) { - rc = nxt_unit_response_init(req, 200, 0, 0); - if (rc != NXT_UNIT_OK) { - nxt_java_throw_IOException(env, "Failed to allocate response"); - - return rc; - } + return rc; } + } - if (!nxt_unit_response_is_sent(req)) { - rc = nxt_unit_response_send(req); - if (rc != NXT_UNIT_OK) { - nxt_java_throw_IOException(env, "Failed to send response headers"); + if (!nxt_unit_response_is_sent(req)) { + rc = nxt_unit_response_send(req); + if (rc != NXT_UNIT_OK) { + nxt_java_throw_IOException(env, "Failed to send response headers"); - return rc; - } + return rc; } + } - if (data->buf != NULL) { - rc = nxt_unit_buf_send(data->buf); - if (rc != NXT_UNIT_OK) { - nxt_java_throw_IOException(env, "Failed to send buffer"); - - } else { - data->buf = NULL; - } + if (data->buf != NULL) { + rc = nxt_unit_buf_send(data->buf); + if (rc != NXT_UNIT_OK) { + nxt_java_throw_IOException(env, "Failed to send buffer"); } else { - rc = NXT_UNIT_OK; + data->buf = NULL; } - return rc; -} + } else { + rc = NXT_UNIT_OK; + } + return rc; +} static nxt_unit_buf_t * -nxt_java_OutputStream_req_buf(JNIEnv *env, nxt_unit_request_info_t *req) -{ - uint32_t size; - nxt_unit_buf_t *buf; - nxt_java_request_data_t *data; - - data = req->data; - buf = data->buf; +nxt_java_OutputStream_req_buf(JNIEnv *env, nxt_unit_request_info_t *req) { + uint32_t size; + nxt_unit_buf_t *buf; + nxt_java_request_data_t *data; - if (buf == NULL || buf->free >= buf->end) { - size = data->buf_size == 0 ? nxt_unit_buf_min() : data->buf_size; + data = req->data; + buf = data->buf; - buf = nxt_unit_response_buf_alloc(req, size); - if (buf == NULL) { - nxt_java_throw_IOException(env, "Failed to allocate buffer"); + if (buf == NULL || buf->free >= buf->end) { + size = data->buf_size == 0 ? nxt_unit_buf_min() : data->buf_size; - return NULL; - } + buf = nxt_unit_response_buf_alloc(req, size); + if (buf == NULL) { + nxt_java_throw_IOException(env, "Failed to allocate buffer"); - data->buf = buf; + return NULL; } - return buf; -} + data->buf = buf; + } + return buf; +} -static void JNICALL -nxt_java_OutputStream_write(JNIEnv *env, jclass cls, jlong req_info_ptr, - jarray b, jint off, jint len) -{ - int rc; - jint copy; - uint8_t *ptr; - nxt_unit_buf_t *buf; - nxt_unit_request_info_t *req; - nxt_java_request_data_t *data; +static void JNICALL nxt_java_OutputStream_write(JNIEnv *env, jclass cls, + jlong req_info_ptr, jarray b, + jint off, jint len) { + int rc; + jint copy; + uint8_t *ptr; + nxt_unit_buf_t *buf; + nxt_unit_request_info_t *req; + nxt_java_request_data_t *data; - req = nxt_jlong2ptr(req_info_ptr); - data = req->data; + req = nxt_jlong2ptr(req_info_ptr); + data = req->data; - ptr = (*env)->GetPrimitiveArrayCritical(env, b, NULL); + ptr = (*env)->GetPrimitiveArrayCritical(env, b, NULL); - while (len > 0) { - buf = nxt_java_OutputStream_req_buf(env, req); - if (buf == NULL) { - return; - } + while (len > 0) { + buf = nxt_java_OutputStream_req_buf(env, req); + if (buf == NULL) { + return; + } - copy = buf->end - buf->free; - copy = copy < len ? copy : len; + copy = buf->end - buf->free; + copy = copy < len ? copy : len; - memcpy(buf->free, ptr + off, copy); - buf->free += copy; + memcpy(buf->free, ptr + off, copy); + buf->free += copy; - len -= copy; - off += copy; + len -= copy; + off += copy; - if ((uint32_t) (buf->free - buf->start) >= data->buf_size) { - rc = nxt_java_OutputStream_flush_buf(env, req); - if (rc != NXT_UNIT_OK) { - break; - } - } + if ((uint32_t)(buf->free - buf->start) >= data->buf_size) { + rc = nxt_java_OutputStream_flush_buf(env, req); + if (rc != NXT_UNIT_OK) { + break; + } } + } - (*env)->ReleasePrimitiveArrayCritical(env, b, ptr, 0); + (*env)->ReleasePrimitiveArrayCritical(env, b, ptr, 0); } +static void JNICALL nxt_java_OutputStream_flush(JNIEnv *env, jclass cls, + jlong req_info_ptr) { + nxt_unit_request_info_t *req; + nxt_java_request_data_t *data; -static void JNICALL -nxt_java_OutputStream_flush(JNIEnv *env, jclass cls, jlong req_info_ptr) -{ - nxt_unit_request_info_t *req; - nxt_java_request_data_t *data; - - req = nxt_jlong2ptr(req_info_ptr); - data = req->data; + req = nxt_jlong2ptr(req_info_ptr); + data = req->data; - if (data->buf != NULL && data->buf->free > data->buf->start) { - nxt_java_OutputStream_flush_buf(env, req); - } + if (data->buf != NULL && data->buf->free > data->buf->start) { + nxt_java_OutputStream_flush_buf(env, req); + } } - -static void JNICALL -nxt_java_OutputStream_close(JNIEnv *env, jclass cls, jlong req_info_ptr) -{ - nxt_java_OutputStream_flush_buf(env, nxt_jlong2ptr(req_info_ptr)); +static void JNICALL nxt_java_OutputStream_close(JNIEnv *env, jclass cls, + jlong req_info_ptr) { + nxt_java_OutputStream_flush_buf(env, nxt_jlong2ptr(req_info_ptr)); } diff --git a/src/java/nxt_jni_OutputStream.h b/src/java/nxt_jni_OutputStream.h index 0c3c9989d..10891c47f 100644 --- a/src/java/nxt_jni_OutputStream.h +++ b/src/java/nxt_jni_OutputStream.h @@ -6,12 +6,10 @@ #ifndef _NXT_JAVA_OUTPUTSTREAM_H_INCLUDED_ #define _NXT_JAVA_OUTPUTSTREAM_H_INCLUDED_ - #include - int nxt_java_initOutputStream(JNIEnv *env, jobject cl); int nxt_java_OutputStream_flush_buf(JNIEnv *env, nxt_unit_request_info_t *req); -#endif /* _NXT_JAVA_OUTPUTSTREAM_H_INCLUDED_ */ +#endif /* _NXT_JAVA_OUTPUTSTREAM_H_INCLUDED_ */ diff --git a/src/java/nxt_jni_Request.c b/src/java/nxt_jni_Request.c index 980a26b68..782d29a20 100644 --- a/src/java/nxt_jni_Request.c +++ b/src/java/nxt_jni_Request.c @@ -17,807 +17,720 @@ #include "nxt_jni_HeadersEnumeration.h" #include "nxt_jni_HeaderNamesEnumeration.h" - static jstring JNICALL nxt_java_Request_getHeader(JNIEnv *env, jclass cls, - jlong req_ptr, jstring name, jint name_len); + jlong req_ptr, jstring name, + jint name_len); static jobject JNICALL nxt_java_Request_getHeaderNames(JNIEnv *env, jclass cls, - jlong req_ptr); + jlong req_ptr); static jobject JNICALL nxt_java_Request_getHeaders(JNIEnv *env, jclass cls, - jlong req_ptr, jstring name, jint name_len); + jlong req_ptr, jstring name, + jint name_len); static jint JNICALL nxt_java_Request_getIntHeader(JNIEnv *env, jclass cls, - jlong req_ptr, jstring name, jint name_len); + jlong req_ptr, jstring name, + jint name_len); static jstring JNICALL nxt_java_Request_getMethod(JNIEnv *env, jclass cls, - jlong req_ptr); + jlong req_ptr); static jstring JNICALL nxt_java_Request_getQueryString(JNIEnv *env, jclass cls, - jlong req_ptr); + jlong req_ptr); static jstring JNICALL nxt_java_Request_getRequestURI(JNIEnv *env, jclass cls, - jlong req_ptr); + jlong req_ptr); static jlong JNICALL nxt_java_Request_getContentLength(JNIEnv *env, jclass cls, - jlong req_ptr); + jlong req_ptr); static jstring JNICALL nxt_java_Request_getContentType(JNIEnv *env, jclass cls, - jlong req_ptr); + jlong req_ptr); static jstring JNICALL nxt_java_Request_getLocalAddr(JNIEnv *env, jclass cls, - jlong req_ptr); + jlong req_ptr); static jstring JNICALL nxt_java_Request_getLocalName(JNIEnv *env, jclass cls, - jlong req_ptr); + jlong req_ptr); static jint JNICALL nxt_java_Request_getLocalPort(JNIEnv *env, jclass cls, - jlong req_ptr); + jlong req_ptr); static jstring JNICALL nxt_java_Request_getProtocol(JNIEnv *env, jclass cls, - jlong req_ptr); + jlong req_ptr); static jstring JNICALL nxt_java_Request_getRemoteAddr(JNIEnv *env, jclass cls, - jlong req_ptr); + jlong req_ptr); static jstring JNICALL nxt_java_Request_getRemoteHost(JNIEnv *env, jclass cls, - jlong req_ptr); + jlong req_ptr); static jint JNICALL nxt_java_Request_getRemotePort(JNIEnv *env, jclass cls, - jlong req_ptr); + jlong req_ptr); static jstring JNICALL nxt_java_Request_getScheme(JNIEnv *env, jclass cls, - jlong req_ptr); + jlong req_ptr); static jstring JNICALL nxt_java_Request_getServerName(JNIEnv *env, jclass cls, - jlong req_ptr); + jlong req_ptr); static jint JNICALL nxt_java_Request_getServerPort(JNIEnv *env, jclass cls, - jlong req_ptr); + jlong req_ptr); static jboolean JNICALL nxt_java_Request_isSecure(JNIEnv *env, jclass cls, - jlong req_ptr); + jlong req_ptr); static void JNICALL nxt_java_Request_upgrade(JNIEnv *env, jclass cls, - jlong req_info_ptr); + jlong req_info_ptr); static jboolean JNICALL nxt_java_Request_isUpgrade(JNIEnv *env, jclass cls, - jlong req_info_ptr); + jlong req_info_ptr); static void JNICALL nxt_java_Request_log(JNIEnv *env, jclass cls, - jlong req_info_ptr, jstring msg, jint msg_len); + jlong req_info_ptr, jstring msg, + jint msg_len); static void JNICALL nxt_java_Request_trace(JNIEnv *env, jclass cls, - jlong req_info_ptr, jstring msg, jint msg_len); + jlong req_info_ptr, jstring msg, + jint msg_len); static jobject JNICALL nxt_java_Request_getResponse(JNIEnv *env, jclass cls, - jlong req_info_ptr); + jlong req_info_ptr); static void JNICALL nxt_java_Request_sendWsFrameBuf(JNIEnv *env, jclass cls, - jlong req_info_ptr, jobject buf, jint pos, jint len, jbyte opCode, jboolean last); + jlong req_info_ptr, + jobject buf, jint pos, + jint len, jbyte opCode, + jboolean last); static void JNICALL nxt_java_Request_sendWsFrameArr(JNIEnv *env, jclass cls, - jlong req_info_ptr, jarray arr, jint pos, jint len, jbyte opCode, jboolean last); + jlong req_info_ptr, + jarray arr, jint pos, + jint len, jbyte opCode, + jboolean last); static void JNICALL nxt_java_Request_closeWs(JNIEnv *env, jclass cls, - jlong req_info_ptr); - - -static jclass nxt_java_Request_class; -static jmethodID nxt_java_Request_ctor; -static jmethodID nxt_java_Request_processWsFrame; -static jmethodID nxt_java_Request_closeWsSession; + jlong req_info_ptr); +static jclass nxt_java_Request_class; +static jmethodID nxt_java_Request_ctor; +static jmethodID nxt_java_Request_processWsFrame; +static jmethodID nxt_java_Request_closeWsSession; -int -nxt_java_initRequest(JNIEnv *env, jobject cl) -{ - int res; - jclass cls; +int nxt_java_initRequest(JNIEnv *env, jobject cl) { + int res; + jclass cls; - cls = nxt_java_loadClass(env, cl, "nginx.unit.Request"); - if (cls == NULL) { - return NXT_UNIT_ERROR; - } + cls = nxt_java_loadClass(env, cl, "nginx.unit.Request"); + if (cls == NULL) { + return NXT_UNIT_ERROR; + } - nxt_java_Request_class = (*env)->NewGlobalRef(env, cls); - (*env)->DeleteLocalRef(env, cls); - cls = nxt_java_Request_class; + nxt_java_Request_class = (*env)->NewGlobalRef(env, cls); + (*env)->DeleteLocalRef(env, cls); + cls = nxt_java_Request_class; - nxt_java_Request_ctor = (*env)->GetMethodID(env, cls, "", "(Lnginx/unit/Context;JJ)V"); - if (nxt_java_Request_ctor == NULL) { - (*env)->DeleteGlobalRef(env, cls); - return NXT_UNIT_ERROR; - } + nxt_java_Request_ctor = + (*env)->GetMethodID(env, cls, "", "(Lnginx/unit/Context;JJ)V"); + if (nxt_java_Request_ctor == NULL) { + (*env)->DeleteGlobalRef(env, cls); + return NXT_UNIT_ERROR; + } - nxt_java_Request_processWsFrame = (*env)->GetMethodID(env, cls, "processWsFrame", "(Ljava/nio/ByteBuffer;BZ)V"); - if (nxt_java_Request_processWsFrame == NULL) { - (*env)->DeleteGlobalRef(env, cls); - return NXT_UNIT_ERROR; - } + nxt_java_Request_processWsFrame = (*env)->GetMethodID( + env, cls, "processWsFrame", "(Ljava/nio/ByteBuffer;BZ)V"); + if (nxt_java_Request_processWsFrame == NULL) { + (*env)->DeleteGlobalRef(env, cls); + return NXT_UNIT_ERROR; + } - nxt_java_Request_closeWsSession = (*env)->GetMethodID(env, cls, "closeWsSession", "()V"); - if (nxt_java_Request_closeWsSession == NULL) { - (*env)->DeleteGlobalRef(env, cls); - return NXT_UNIT_ERROR; - } + nxt_java_Request_closeWsSession = + (*env)->GetMethodID(env, cls, "closeWsSession", "()V"); + if (nxt_java_Request_closeWsSession == NULL) { + (*env)->DeleteGlobalRef(env, cls); + return NXT_UNIT_ERROR; + } - JNINativeMethod request_methods[] = { - { (char *) "getHeader", - (char *) "(JLjava/lang/String;I)Ljava/lang/String;", - nxt_java_Request_getHeader }, + JNINativeMethod request_methods[] = { + {(char *)"getHeader", (char *)"(JLjava/lang/String;I)Ljava/lang/String;", + nxt_java_Request_getHeader}, - { (char *) "getHeaderNames", - (char *) "(J)Ljava/util/Enumeration;", - nxt_java_Request_getHeaderNames }, + {(char *)"getHeaderNames", (char *)"(J)Ljava/util/Enumeration;", + nxt_java_Request_getHeaderNames}, - { (char *) "getHeaders", - (char *) "(JLjava/lang/String;I)Ljava/util/Enumeration;", - nxt_java_Request_getHeaders }, + {(char *)"getHeaders", + (char *)"(JLjava/lang/String;I)Ljava/util/Enumeration;", + nxt_java_Request_getHeaders}, - { (char *) "getIntHeader", - (char *) "(JLjava/lang/String;I)I", - nxt_java_Request_getIntHeader }, + {(char *)"getIntHeader", (char *)"(JLjava/lang/String;I)I", + nxt_java_Request_getIntHeader}, - { (char *) "getMethod", - (char *) "(J)Ljava/lang/String;", - nxt_java_Request_getMethod }, + {(char *)"getMethod", (char *)"(J)Ljava/lang/String;", + nxt_java_Request_getMethod}, - { (char *) "getQueryString", - (char *) "(J)Ljava/lang/String;", - nxt_java_Request_getQueryString }, + {(char *)"getQueryString", (char *)"(J)Ljava/lang/String;", + nxt_java_Request_getQueryString}, - { (char *) "getRequestURI", - (char *) "(J)Ljava/lang/String;", - nxt_java_Request_getRequestURI }, + {(char *)"getRequestURI", (char *)"(J)Ljava/lang/String;", + nxt_java_Request_getRequestURI}, - { (char *) "getContentLength", - (char *) "(J)J", - nxt_java_Request_getContentLength }, + {(char *)"getContentLength", (char *)"(J)J", + nxt_java_Request_getContentLength}, - { (char *) "getContentType", - (char *) "(J)Ljava/lang/String;", - nxt_java_Request_getContentType }, + {(char *)"getContentType", (char *)"(J)Ljava/lang/String;", + nxt_java_Request_getContentType}, - { (char *) "getLocalAddr", - (char *) "(J)Ljava/lang/String;", - nxt_java_Request_getLocalAddr }, + {(char *)"getLocalAddr", (char *)"(J)Ljava/lang/String;", + nxt_java_Request_getLocalAddr}, - { (char *) "getLocalName", - (char *) "(J)Ljava/lang/String;", - nxt_java_Request_getLocalName }, + {(char *)"getLocalName", (char *)"(J)Ljava/lang/String;", + nxt_java_Request_getLocalName}, - { (char *) "getLocalPort", - (char *) "(J)I", - nxt_java_Request_getLocalPort }, + {(char *)"getLocalPort", (char *)"(J)I", nxt_java_Request_getLocalPort}, - { (char *) "getProtocol", - (char *) "(J)Ljava/lang/String;", - nxt_java_Request_getProtocol }, + {(char *)"getProtocol", (char *)"(J)Ljava/lang/String;", + nxt_java_Request_getProtocol}, - { (char *) "getRemoteAddr", - (char *) "(J)Ljava/lang/String;", - nxt_java_Request_getRemoteAddr }, + {(char *)"getRemoteAddr", (char *)"(J)Ljava/lang/String;", + nxt_java_Request_getRemoteAddr}, - { (char *) "getRemoteHost", - (char *) "(J)Ljava/lang/String;", - nxt_java_Request_getRemoteHost }, + {(char *)"getRemoteHost", (char *)"(J)Ljava/lang/String;", + nxt_java_Request_getRemoteHost}, - { (char *) "getRemotePort", - (char *) "(J)I", - nxt_java_Request_getRemotePort }, + {(char *)"getRemotePort", (char *)"(J)I", nxt_java_Request_getRemotePort}, - { (char *) "getScheme", - (char *) "(J)Ljava/lang/String;", - nxt_java_Request_getScheme }, + {(char *)"getScheme", (char *)"(J)Ljava/lang/String;", + nxt_java_Request_getScheme}, - { (char *) "getServerName", - (char *) "(J)Ljava/lang/String;", - nxt_java_Request_getServerName }, + {(char *)"getServerName", (char *)"(J)Ljava/lang/String;", + nxt_java_Request_getServerName}, - { (char *) "getServerPort", - (char *) "(J)I", - nxt_java_Request_getServerPort }, + {(char *)"getServerPort", (char *)"(J)I", nxt_java_Request_getServerPort}, - { (char *) "isSecure", - (char *) "(J)Z", - nxt_java_Request_isSecure }, + {(char *)"isSecure", (char *)"(J)Z", nxt_java_Request_isSecure}, - { (char *) "upgrade", - (char *) "(J)V", - nxt_java_Request_upgrade }, + {(char *)"upgrade", (char *)"(J)V", nxt_java_Request_upgrade}, - { (char *) "isUpgrade", - (char *) "(J)Z", - nxt_java_Request_isUpgrade }, + {(char *)"isUpgrade", (char *)"(J)Z", nxt_java_Request_isUpgrade}, - { (char *) "log", - (char *) "(JLjava/lang/String;I)V", - nxt_java_Request_log }, + {(char *)"log", (char *)"(JLjava/lang/String;I)V", nxt_java_Request_log}, - { (char *) "trace", - (char *) "(JLjava/lang/String;I)V", - nxt_java_Request_trace }, + {(char *)"trace", (char *)"(JLjava/lang/String;I)V", + nxt_java_Request_trace}, - { (char *) "getResponse", - (char *) "(J)Lnginx/unit/Response;", - nxt_java_Request_getResponse }, + {(char *)"getResponse", (char *)"(J)Lnginx/unit/Response;", + nxt_java_Request_getResponse}, - { (char *) "sendWsFrame", - (char *) "(JLjava/nio/ByteBuffer;IIBZ)V", - nxt_java_Request_sendWsFrameBuf }, + {(char *)"sendWsFrame", (char *)"(JLjava/nio/ByteBuffer;IIBZ)V", + nxt_java_Request_sendWsFrameBuf}, - { (char *) "sendWsFrame", - (char *) "(J[BIIBZ)V", - nxt_java_Request_sendWsFrameArr }, + {(char *)"sendWsFrame", (char *)"(J[BIIBZ)V", + nxt_java_Request_sendWsFrameArr}, - { (char *) "closeWs", - (char *) "(J)V", - nxt_java_Request_closeWs }, + {(char *)"closeWs", (char *)"(J)V", nxt_java_Request_closeWs}, - }; + }; - res = (*env)->RegisterNatives(env, nxt_java_Request_class, - request_methods, - sizeof(request_methods) / sizeof(request_methods[0])); + res = (*env)->RegisterNatives(env, nxt_java_Request_class, request_methods, + sizeof(request_methods) / + sizeof(request_methods[0])); - nxt_unit_debug(NULL, "registered Request methods: %d", res); + nxt_unit_debug(NULL, "registered Request methods: %d", res); - if (res != 0) { - nxt_unit_warn(NULL, "registering natives for Request failed"); - goto failed; - } + if (res != 0) { + nxt_unit_warn(NULL, "registering natives for Request failed"); + goto failed; + } - res = nxt_java_initHeadersEnumeration(env, cl); - if (res != NXT_UNIT_OK) { - goto failed; - } + res = nxt_java_initHeadersEnumeration(env, cl); + if (res != NXT_UNIT_OK) { + goto failed; + } - res = nxt_java_initHeaderNamesEnumeration(env, cl); - if (res != NXT_UNIT_OK) { - goto failed; - } + res = nxt_java_initHeaderNamesEnumeration(env, cl); + if (res != NXT_UNIT_OK) { + goto failed; + } - return NXT_UNIT_OK; + return NXT_UNIT_OK; failed: - (*env)->DeleteGlobalRef(env, cls); - return NXT_UNIT_ERROR; + (*env)->DeleteGlobalRef(env, cls); + return NXT_UNIT_ERROR; } - -jobject -nxt_java_newRequest(JNIEnv *env, jobject ctx, nxt_unit_request_info_t *req) -{ - return (*env)->NewObject(env, nxt_java_Request_class, - nxt_java_Request_ctor, ctx, nxt_ptr2jlong(req), - nxt_ptr2jlong(req->request)); +jobject nxt_java_newRequest(JNIEnv *env, jobject ctx, + nxt_unit_request_info_t *req) { + return (*env)->NewObject(env, nxt_java_Request_class, nxt_java_Request_ctor, + ctx, nxt_ptr2jlong(req), + nxt_ptr2jlong(req->request)); } +static jstring JNICALL nxt_java_Request_getHeader(JNIEnv *env, jclass cls, + jlong req_ptr, jstring name, + jint name_len) { + const char *name_str; + nxt_unit_field_t *f; + nxt_unit_request_t *r; + + name_str = (*env)->GetStringUTFChars(env, name, NULL); + if (name_str == NULL) { + return NULL; + } -static jstring JNICALL -nxt_java_Request_getHeader(JNIEnv *env, jclass cls, jlong req_ptr, - jstring name, jint name_len) -{ - const char *name_str; - nxt_unit_field_t *f; - nxt_unit_request_t *r; - - name_str = (*env)->GetStringUTFChars(env, name, NULL); - if (name_str == NULL) { - return NULL; - } - - r = nxt_jlong2ptr(req_ptr); + r = nxt_jlong2ptr(req_ptr); - f = nxt_java_findHeader(r->fields, r->fields + r->fields_count, - name_str, name_len); + f = nxt_java_findHeader(r->fields, r->fields + r->fields_count, name_str, + name_len); - (*env)->ReleaseStringUTFChars(env, name, name_str); + (*env)->ReleaseStringUTFChars(env, name, name_str); - if (f == NULL) { - return NULL; - } + if (f == NULL) { + return NULL; + } - return (*env)->NewStringUTF(env, nxt_unit_sptr_get(&f->value)); + return (*env)->NewStringUTF(env, nxt_unit_sptr_get(&f->value)); } +static jobject JNICALL nxt_java_Request_getHeaderNames(JNIEnv *env, jclass cls, + jlong req_ptr) { + nxt_unit_request_t *r; -static jobject JNICALL -nxt_java_Request_getHeaderNames(JNIEnv *env, jclass cls, jlong req_ptr) -{ - nxt_unit_request_t *r; - - r = nxt_jlong2ptr(req_ptr); + r = nxt_jlong2ptr(req_ptr); - return nxt_java_newHeaderNamesEnumeration(env, r->fields, r->fields_count); + return nxt_java_newHeaderNamesEnumeration(env, r->fields, r->fields_count); } +static jobject JNICALL nxt_java_Request_getHeaders(JNIEnv *env, jclass cls, + jlong req_ptr, jstring name, + jint name_len) { + const char *name_str; + nxt_unit_field_t *f; + nxt_unit_request_t *r; + + name_str = (*env)->GetStringUTFChars(env, name, NULL); + if (name_str == NULL) { + return NULL; + } -static jobject JNICALL -nxt_java_Request_getHeaders(JNIEnv *env, jclass cls, jlong req_ptr, - jstring name, jint name_len) -{ - const char *name_str; - nxt_unit_field_t *f; - nxt_unit_request_t *r; - - name_str = (*env)->GetStringUTFChars(env, name, NULL); - if (name_str == NULL) { - return NULL; - } - - r = nxt_jlong2ptr(req_ptr); + r = nxt_jlong2ptr(req_ptr); - f = nxt_java_findHeader(r->fields, r->fields + r->fields_count, - name_str, name_len); + f = nxt_java_findHeader(r->fields, r->fields + r->fields_count, name_str, + name_len); - (*env)->ReleaseStringUTFChars(env, name, name_str); + (*env)->ReleaseStringUTFChars(env, name, name_str); - if (f == NULL) { - f = r->fields + r->fields_count; - } + if (f == NULL) { + f = r->fields + r->fields_count; + } - return nxt_java_newHeadersEnumeration(env, r->fields, r->fields_count, - f - r->fields); + return nxt_java_newHeadersEnumeration(env, r->fields, r->fields_count, + f - r->fields); } +static jint JNICALL nxt_java_Request_getIntHeader(JNIEnv *env, jclass cls, + jlong req_ptr, jstring name, + jint name_len) { + jint res; + char *value, *end; + const char *name_str; + nxt_unit_field_t *f; + nxt_unit_request_t *r; + + res = -1; + + name_str = (*env)->GetStringUTFChars(env, name, NULL); + if (name_str == NULL) { + return res; + } -static jint JNICALL -nxt_java_Request_getIntHeader(JNIEnv *env, jclass cls, jlong req_ptr, - jstring name, jint name_len) -{ - jint res; - char *value, *end; - const char *name_str; - nxt_unit_field_t *f; - nxt_unit_request_t *r; - - res = -1; - - name_str = (*env)->GetStringUTFChars(env, name, NULL); - if (name_str == NULL) { - return res; - } - - r = nxt_jlong2ptr(req_ptr); + r = nxt_jlong2ptr(req_ptr); - f = nxt_java_findHeader(r->fields, r->fields + r->fields_count, - name_str, name_len); + f = nxt_java_findHeader(r->fields, r->fields + r->fields_count, name_str, + name_len); - (*env)->ReleaseStringUTFChars(env, name, name_str); + (*env)->ReleaseStringUTFChars(env, name, name_str); - if (f == NULL) { - return res; - } + if (f == NULL) { + return res; + } - value = nxt_unit_sptr_get(&f->value); - end = value + f->value_length; + value = nxt_unit_sptr_get(&f->value); + end = value + f->value_length; - res = strtol(value, &end, 10); + res = strtol(value, &end, 10); - if (end < value + f->value_length) { - // TODO throw NumberFormatException.forInputString(value) - } + if (end < value + f->value_length) { + // TODO throw NumberFormatException.forInputString(value) + } - return res; + return res; } +static jstring JNICALL nxt_java_Request_getMethod(JNIEnv *env, jclass cls, + jlong req_ptr) { + nxt_unit_request_t *r; -static jstring JNICALL -nxt_java_Request_getMethod(JNIEnv *env, jclass cls, jlong req_ptr) -{ - nxt_unit_request_t *r; - - r = nxt_jlong2ptr(req_ptr); + r = nxt_jlong2ptr(req_ptr); - return (*env)->NewStringUTF(env, nxt_unit_sptr_get(&r->method)); + return (*env)->NewStringUTF(env, nxt_unit_sptr_get(&r->method)); } +static jstring JNICALL nxt_java_Request_getQueryString(JNIEnv *env, jclass cls, + jlong req_ptr) { + char *query; + nxt_unit_request_t *r; -static jstring JNICALL -nxt_java_Request_getQueryString(JNIEnv *env, jclass cls, jlong req_ptr) -{ - char *query; - nxt_unit_request_t *r; - - r = nxt_jlong2ptr(req_ptr); + r = nxt_jlong2ptr(req_ptr); - if (r->query.offset != 0) { - query = nxt_unit_sptr_get(&r->query); - return (*env)->NewStringUTF(env, query); - } + if (r->query.offset != 0) { + query = nxt_unit_sptr_get(&r->query); + return (*env)->NewStringUTF(env, query); + } - return NULL; + return NULL; } +static jstring JNICALL nxt_java_Request_getRequestURI(JNIEnv *env, jclass cls, + jlong req_ptr) { + char *target, *query; + nxt_unit_request_t *r; -static jstring JNICALL -nxt_java_Request_getRequestURI(JNIEnv *env, jclass cls, jlong req_ptr) -{ - char *target, *query; - nxt_unit_request_t *r; - - r = nxt_jlong2ptr(req_ptr); + r = nxt_jlong2ptr(req_ptr); - target = nxt_unit_sptr_get(&r->target); + target = nxt_unit_sptr_get(&r->target); - if (r->query.offset != 0) { - query = nxt_unit_sptr_get(&r->query); - return nxt_java_newString(env, target, query - target - 1); - } + if (r->query.offset != 0) { + query = nxt_unit_sptr_get(&r->query); + return nxt_java_newString(env, target, query - target - 1); + } - return (*env)->NewStringUTF(env, target); + return (*env)->NewStringUTF(env, target); } +static jlong JNICALL nxt_java_Request_getContentLength(JNIEnv *env, jclass cls, + jlong req_ptr) { + nxt_unit_request_t *r; -static jlong JNICALL -nxt_java_Request_getContentLength(JNIEnv *env, jclass cls, jlong req_ptr) -{ - nxt_unit_request_t *r; - - r = nxt_jlong2ptr(req_ptr); + r = nxt_jlong2ptr(req_ptr); - return r->content_length; + return r->content_length; } +static jstring JNICALL nxt_java_Request_getContentType(JNIEnv *env, jclass cls, + jlong req_ptr) { + nxt_unit_field_t *f; + nxt_unit_request_t *r; -static jstring JNICALL -nxt_java_Request_getContentType(JNIEnv *env, jclass cls, jlong req_ptr) -{ - nxt_unit_field_t *f; - nxt_unit_request_t *r; - - r = nxt_jlong2ptr(req_ptr); + r = nxt_jlong2ptr(req_ptr); - if (r->content_type_field != NXT_UNIT_NONE_FIELD) { - f = r->fields + r->content_type_field; + if (r->content_type_field != NXT_UNIT_NONE_FIELD) { + f = r->fields + r->content_type_field; - return (*env)->NewStringUTF(env, nxt_unit_sptr_get(&f->value)); - } + return (*env)->NewStringUTF(env, nxt_unit_sptr_get(&f->value)); + } - return NULL; + return NULL; } +static jstring JNICALL nxt_java_Request_getLocalAddr(JNIEnv *env, jclass cls, + jlong req_ptr) { + nxt_unit_request_t *r; -static jstring JNICALL -nxt_java_Request_getLocalAddr(JNIEnv *env, jclass cls, jlong req_ptr) -{ - nxt_unit_request_t *r; - - r = nxt_jlong2ptr(req_ptr); + r = nxt_jlong2ptr(req_ptr); - return nxt_java_newString(env, nxt_unit_sptr_get(&r->local_addr), - r->local_addr_length); + return nxt_java_newString(env, nxt_unit_sptr_get(&r->local_addr), + r->local_addr_length); } +static jstring JNICALL nxt_java_Request_getLocalName(JNIEnv *env, jclass cls, + jlong req_ptr) { + char *local, *colon; + nxt_unit_request_t *r; -static jstring JNICALL -nxt_java_Request_getLocalName(JNIEnv *env, jclass cls, jlong req_ptr) -{ - char *local, *colon; - nxt_unit_request_t *r; - - r = nxt_jlong2ptr(req_ptr); + r = nxt_jlong2ptr(req_ptr); - local = nxt_unit_sptr_get(&r->local_addr); - colon = memchr(local, ':', r->local_addr_length); + local = nxt_unit_sptr_get(&r->local_addr); + colon = memchr(local, ':', r->local_addr_length); - if (colon == NULL) { - colon = local + r->local_addr_length; - } + if (colon == NULL) { + colon = local + r->local_addr_length; + } - return nxt_java_newString(env, local, colon - local); + return nxt_java_newString(env, local, colon - local); } +static jint JNICALL nxt_java_Request_getLocalPort(JNIEnv *env, jclass cls, + jlong req_ptr) { + jint res; + char *local, *colon, tmp; + nxt_unit_request_t *r; -static jint JNICALL -nxt_java_Request_getLocalPort(JNIEnv *env, jclass cls, jlong req_ptr) -{ - jint res; - char *local, *colon, tmp; - nxt_unit_request_t *r; + r = nxt_jlong2ptr(req_ptr); - r = nxt_jlong2ptr(req_ptr); + local = nxt_unit_sptr_get(&r->local_addr); + colon = memchr(local, ':', r->local_addr_length); - local = nxt_unit_sptr_get(&r->local_addr); - colon = memchr(local, ':', r->local_addr_length); + if (colon == NULL) { + return 80; + } - if (colon == NULL) { - return 80; - } - - tmp = local[r->local_addr_length]; + tmp = local[r->local_addr_length]; - local[r->local_addr_length] = '\0'; + local[r->local_addr_length] = '\0'; - res = strtol(colon + 1, NULL, 10); + res = strtol(colon + 1, NULL, 10); - local[r->local_addr_length] = tmp; + local[r->local_addr_length] = tmp; - return res; + return res; } +static jstring JNICALL nxt_java_Request_getProtocol(JNIEnv *env, jclass cls, + jlong req_ptr) { + nxt_unit_request_t *r; -static jstring JNICALL -nxt_java_Request_getProtocol(JNIEnv *env, jclass cls, jlong req_ptr) -{ - nxt_unit_request_t *r; - - r = nxt_jlong2ptr(req_ptr); + r = nxt_jlong2ptr(req_ptr); - return (*env)->NewStringUTF(env, nxt_unit_sptr_get(&r->version)); + return (*env)->NewStringUTF(env, nxt_unit_sptr_get(&r->version)); } +static jstring JNICALL nxt_java_Request_getRemoteAddr(JNIEnv *env, jclass cls, + jlong req_ptr) { + nxt_unit_request_t *r; -static jstring JNICALL -nxt_java_Request_getRemoteAddr(JNIEnv *env, jclass cls, jlong req_ptr) -{ - nxt_unit_request_t *r; - - r = nxt_jlong2ptr(req_ptr); + r = nxt_jlong2ptr(req_ptr); - return nxt_java_newString(env, nxt_unit_sptr_get(&r->remote), - r->remote_length); + return nxt_java_newString(env, nxt_unit_sptr_get(&r->remote), + r->remote_length); } +static jstring JNICALL nxt_java_Request_getRemoteHost(JNIEnv *env, jclass cls, + jlong req_ptr) { + char *remote, *colon; + nxt_unit_request_t *r; -static jstring JNICALL -nxt_java_Request_getRemoteHost(JNIEnv *env, jclass cls, jlong req_ptr) -{ - char *remote, *colon; - nxt_unit_request_t *r; - - r = nxt_jlong2ptr(req_ptr); + r = nxt_jlong2ptr(req_ptr); - remote = nxt_unit_sptr_get(&r->remote); - colon = memchr(remote, ':', r->remote_length); + remote = nxt_unit_sptr_get(&r->remote); + colon = memchr(remote, ':', r->remote_length); - if (colon == NULL) { - colon = remote + r->remote_length; - } + if (colon == NULL) { + colon = remote + r->remote_length; + } - return nxt_java_newString(env, remote, colon - remote); + return nxt_java_newString(env, remote, colon - remote); } +static jint JNICALL nxt_java_Request_getRemotePort(JNIEnv *env, jclass cls, + jlong req_ptr) { + jint res; + char *remote, *colon, tmp; + nxt_unit_request_t *r; -static jint JNICALL -nxt_java_Request_getRemotePort(JNIEnv *env, jclass cls, jlong req_ptr) -{ - jint res; - char *remote, *colon, tmp; - nxt_unit_request_t *r; - - r = nxt_jlong2ptr(req_ptr); + r = nxt_jlong2ptr(req_ptr); - remote = nxt_unit_sptr_get(&r->remote); - colon = memchr(remote, ':', r->remote_length); + remote = nxt_unit_sptr_get(&r->remote); + colon = memchr(remote, ':', r->remote_length); - if (colon == NULL) { - return 80; - } + if (colon == NULL) { + return 80; + } - tmp = remote[r->remote_length]; + tmp = remote[r->remote_length]; - remote[r->remote_length] = '\0'; + remote[r->remote_length] = '\0'; - res = strtol(colon + 1, NULL, 10); + res = strtol(colon + 1, NULL, 10); - remote[r->remote_length] = tmp; + remote[r->remote_length] = tmp; - return res; + return res; } +static jstring JNICALL nxt_java_Request_getScheme(JNIEnv *env, jclass cls, + jlong req_ptr) { + nxt_unit_request_t *r; -static jstring JNICALL -nxt_java_Request_getScheme(JNIEnv *env, jclass cls, jlong req_ptr) -{ - nxt_unit_request_t *r; - - r = nxt_jlong2ptr(req_ptr); + r = nxt_jlong2ptr(req_ptr); - return (*env)->NewStringUTF(env, r->tls ? "https" : "http"); + return (*env)->NewStringUTF(env, r->tls ? "https" : "http"); } +static jstring JNICALL nxt_java_Request_getServerName(JNIEnv *env, jclass cls, + jlong req_ptr) { + char *host, *colon; + nxt_unit_field_t *f; + nxt_unit_request_t *r; -static jstring JNICALL -nxt_java_Request_getServerName(JNIEnv *env, jclass cls, jlong req_ptr) -{ - char *host, *colon; - nxt_unit_field_t *f; - nxt_unit_request_t *r; - - r = nxt_jlong2ptr(req_ptr); - - f = nxt_java_findHeader(r->fields, r->fields + r->fields_count, - "Host", 4); - if (f != NULL) { - host = nxt_unit_sptr_get(&f->value); + r = nxt_jlong2ptr(req_ptr); - colon = memchr(host, ':', f->value_length); + f = nxt_java_findHeader(r->fields, r->fields + r->fields_count, "Host", 4); + if (f != NULL) { + host = nxt_unit_sptr_get(&f->value); - if (colon == NULL) { - colon = host + f->value_length; - } + colon = memchr(host, ':', f->value_length); - return nxt_java_newString(env, host, colon - host); + if (colon == NULL) { + colon = host + f->value_length; } - return nxt_java_Request_getLocalName(env, cls, req_ptr); -} + return nxt_java_newString(env, host, colon - host); + } + return nxt_java_Request_getLocalName(env, cls, req_ptr); +} -static jint JNICALL -nxt_java_Request_getServerPort(JNIEnv *env, jclass cls, jlong req_ptr) -{ - jint res; - char *host, *colon, tmp; - nxt_unit_field_t *f; - nxt_unit_request_t *r; +static jint JNICALL nxt_java_Request_getServerPort(JNIEnv *env, jclass cls, + jlong req_ptr) { + jint res; + char *host, *colon, tmp; + nxt_unit_field_t *f; + nxt_unit_request_t *r; - r = nxt_jlong2ptr(req_ptr); + r = nxt_jlong2ptr(req_ptr); - f = nxt_java_findHeader(r->fields, r->fields + r->fields_count, - "Host", 4); - if (f != NULL) { - host = nxt_unit_sptr_get(&f->value); + f = nxt_java_findHeader(r->fields, r->fields + r->fields_count, "Host", 4); + if (f != NULL) { + host = nxt_unit_sptr_get(&f->value); - colon = memchr(host, ':', f->value_length); + colon = memchr(host, ':', f->value_length); - if (colon == NULL) { - return 80; - } + if (colon == NULL) { + return 80; + } - tmp = host[f->value_length]; + tmp = host[f->value_length]; - host[f->value_length] = '\0'; + host[f->value_length] = '\0'; - res = strtol(colon + 1, NULL, 10); + res = strtol(colon + 1, NULL, 10); - host[f->value_length] = tmp; + host[f->value_length] = tmp; - return res; - } + return res; + } - return nxt_java_Request_getLocalPort(env, cls, req_ptr); + return nxt_java_Request_getLocalPort(env, cls, req_ptr); } +static jboolean JNICALL nxt_java_Request_isSecure(JNIEnv *env, jclass cls, + jlong req_ptr) { + nxt_unit_request_t *r; -static jboolean JNICALL -nxt_java_Request_isSecure(JNIEnv *env, jclass cls, jlong req_ptr) -{ - nxt_unit_request_t *r; - - r = nxt_jlong2ptr(req_ptr); + r = nxt_jlong2ptr(req_ptr); - return r->tls != 0; + return r->tls != 0; } +static void JNICALL nxt_java_Request_upgrade(JNIEnv *env, jclass cls, + jlong req_info_ptr) { + nxt_unit_request_info_t *req; -static void JNICALL -nxt_java_Request_upgrade(JNIEnv *env, jclass cls, jlong req_info_ptr) -{ - nxt_unit_request_info_t *req; - - req = nxt_jlong2ptr(req_info_ptr); + req = nxt_jlong2ptr(req_info_ptr); - if (!nxt_unit_response_is_init(req)) { - nxt_unit_response_init(req, 101, 0, 0); - } + if (!nxt_unit_response_is_init(req)) { + nxt_unit_response_init(req, 101, 0, 0); + } - (void) nxt_unit_response_upgrade(req); + (void)nxt_unit_response_upgrade(req); } +static jboolean JNICALL nxt_java_Request_isUpgrade(JNIEnv *env, jclass cls, + jlong req_info_ptr) { + nxt_unit_request_info_t *req; -static jboolean JNICALL -nxt_java_Request_isUpgrade(JNIEnv *env, jclass cls, jlong req_info_ptr) -{ - nxt_unit_request_info_t *req; - - req = nxt_jlong2ptr(req_info_ptr); + req = nxt_jlong2ptr(req_info_ptr); - return nxt_unit_request_is_websocket_handshake(req); + return nxt_unit_request_is_websocket_handshake(req); } +static void JNICALL nxt_java_Request_log(JNIEnv *env, jclass cls, + jlong req_info_ptr, jstring msg, + jint msg_len) { + const char *msg_str; + nxt_unit_request_info_t *req; -static void JNICALL -nxt_java_Request_log(JNIEnv *env, jclass cls, jlong req_info_ptr, jstring msg, - jint msg_len) -{ - const char *msg_str; - nxt_unit_request_info_t *req; - - req = nxt_jlong2ptr(req_info_ptr); + req = nxt_jlong2ptr(req_info_ptr); - msg_str = (*env)->GetStringUTFChars(env, msg, NULL); - if (msg_str == NULL) { - return; - } + msg_str = (*env)->GetStringUTFChars(env, msg, NULL); + if (msg_str == NULL) { + return; + } - nxt_unit_req_log(req, NXT_UNIT_LOG_INFO, "%.*s", msg_len, msg_str); + nxt_unit_req_log(req, NXT_UNIT_LOG_INFO, "%.*s", msg_len, msg_str); - (*env)->ReleaseStringUTFChars(env, msg, msg_str); + (*env)->ReleaseStringUTFChars(env, msg, msg_str); } - -static void JNICALL -nxt_java_Request_trace(JNIEnv *env, jclass cls, jlong req_info_ptr, jstring msg, - jint msg_len) -{ +static void JNICALL nxt_java_Request_trace(JNIEnv *env, jclass cls, + jlong req_info_ptr, jstring msg, + jint msg_len) { #if (NXT_DEBUG) - const char *msg_str; - nxt_unit_request_info_t *req; + const char *msg_str; + nxt_unit_request_info_t *req; - req = nxt_jlong2ptr(req_info_ptr); + req = nxt_jlong2ptr(req_info_ptr); - msg_str = (*env)->GetStringUTFChars(env, msg, NULL); - if (msg_str == NULL) { - return; - } + msg_str = (*env)->GetStringUTFChars(env, msg, NULL); + if (msg_str == NULL) { + return; + } - nxt_unit_req_debug(req, "%.*s", msg_len, msg_str); + nxt_unit_req_debug(req, "%.*s", msg_len, msg_str); - (*env)->ReleaseStringUTFChars(env, msg, msg_str); + (*env)->ReleaseStringUTFChars(env, msg, msg_str); #endif } +static jobject JNICALL nxt_java_Request_getResponse(JNIEnv *env, jclass cls, + jlong req_info_ptr) { + nxt_unit_request_info_t *req; + nxt_java_request_data_t *data; -static jobject JNICALL -nxt_java_Request_getResponse(JNIEnv *env, jclass cls, jlong req_info_ptr) -{ - nxt_unit_request_info_t *req; - nxt_java_request_data_t *data; - - req = nxt_jlong2ptr(req_info_ptr); - data = req->data; + req = nxt_jlong2ptr(req_info_ptr); + data = req->data; - return data->jresp; + return data->jresp; } +static void JNICALL nxt_java_Request_sendWsFrameBuf(JNIEnv *env, jclass cls, + jlong req_info_ptr, + jobject buf, jint pos, + jint len, jbyte opCode, + jboolean last) { + nxt_unit_request_info_t *req; -static void JNICALL -nxt_java_Request_sendWsFrameBuf(JNIEnv *env, jclass cls, - jlong req_info_ptr, jobject buf, jint pos, jint len, jbyte opCode, jboolean last) -{ - nxt_unit_request_info_t *req; - - req = nxt_jlong2ptr(req_info_ptr); - uint8_t *b = (*env)->GetDirectBufferAddress(env, buf); + req = nxt_jlong2ptr(req_info_ptr); + uint8_t *b = (*env)->GetDirectBufferAddress(env, buf); - if (b != NULL) { - nxt_unit_websocket_send(req, opCode, last, b + pos, len); + if (b != NULL) { + nxt_unit_websocket_send(req, opCode, last, b + pos, len); - } else { - nxt_unit_req_debug(req, "sendWsFrameBuf: b == NULL"); - } + } else { + nxt_unit_req_debug(req, "sendWsFrameBuf: b == NULL"); + } } +static void JNICALL nxt_java_Request_sendWsFrameArr(JNIEnv *env, jclass cls, + jlong req_info_ptr, + jarray arr, jint pos, + jint len, jbyte opCode, + jboolean last) { + nxt_unit_request_info_t *req; + + req = nxt_jlong2ptr(req_info_ptr); + uint8_t *b = (*env)->GetPrimitiveArrayCritical(env, arr, NULL); + + if (b != NULL) { + if (!nxt_unit_response_is_sent(req)) { + nxt_unit_response_send(req); + } -static void JNICALL -nxt_java_Request_sendWsFrameArr(JNIEnv *env, jclass cls, - jlong req_info_ptr, jarray arr, jint pos, jint len, jbyte opCode, jboolean last) -{ - nxt_unit_request_info_t *req; - - req = nxt_jlong2ptr(req_info_ptr); - uint8_t *b = (*env)->GetPrimitiveArrayCritical(env, arr, NULL); - - if (b != NULL) { - if (!nxt_unit_response_is_sent(req)) { - nxt_unit_response_send(req); - } - - nxt_unit_websocket_send(req, opCode, last, b + pos, len); + nxt_unit_websocket_send(req, opCode, last, b + pos, len); - (*env)->ReleasePrimitiveArrayCritical(env, arr, b, 0); + (*env)->ReleasePrimitiveArrayCritical(env, arr, b, 0); - } else { - nxt_unit_req_debug(req, "sendWsFrameArr: b == NULL"); - } + } else { + nxt_unit_req_debug(req, "sendWsFrameArr: b == NULL"); + } } +static void JNICALL nxt_java_Request_closeWs(JNIEnv *env, jclass cls, + jlong req_info_ptr) { + nxt_unit_request_info_t *req; + nxt_java_request_data_t *data; -static void JNICALL -nxt_java_Request_closeWs(JNIEnv *env, jclass cls, jlong req_info_ptr) -{ - nxt_unit_request_info_t *req; - nxt_java_request_data_t *data; - - req = nxt_jlong2ptr(req_info_ptr); + req = nxt_jlong2ptr(req_info_ptr); - data = req->data; + data = req->data; - (*env)->DeleteGlobalRef(env, data->jresp); - (*env)->DeleteGlobalRef(env, data->jreq); + (*env)->DeleteGlobalRef(env, data->jresp); + (*env)->DeleteGlobalRef(env, data->jreq); - nxt_unit_request_done(req, NXT_UNIT_OK); + nxt_unit_request_done(req, NXT_UNIT_OK); } - -void -nxt_java_Request_websocket(JNIEnv *env, jobject jreq, jobject jbuf, - uint8_t opcode, uint8_t fin) -{ - (*env)->CallVoidMethod(env, jreq, nxt_java_Request_processWsFrame, jbuf, opcode, fin); +void nxt_java_Request_websocket(JNIEnv *env, jobject jreq, jobject jbuf, + uint8_t opcode, uint8_t fin) { + (*env)->CallVoidMethod(env, jreq, nxt_java_Request_processWsFrame, jbuf, + opcode, fin); } - -void -nxt_java_Request_close(JNIEnv *env, jobject jreq) -{ - (*env)->CallVoidMethod(env, jreq, nxt_java_Request_closeWsSession); +void nxt_java_Request_close(JNIEnv *env, jobject jreq) { + (*env)->CallVoidMethod(env, jreq, nxt_java_Request_closeWsSession); } diff --git a/src/java/nxt_jni_Request.h b/src/java/nxt_jni_Request.h index 9187d8786..4b8264ec2 100644 --- a/src/java/nxt_jni_Request.h +++ b/src/java/nxt_jni_Request.h @@ -6,18 +6,17 @@ #ifndef _NXT_JAVA_REQUEST_H_INCLUDED_ #define _NXT_JAVA_REQUEST_H_INCLUDED_ - #include #include - int nxt_java_initRequest(JNIEnv *env, jobject cl); -jobject nxt_java_newRequest(JNIEnv *env, jobject ctx, nxt_unit_request_info_t *req); +jobject nxt_java_newRequest(JNIEnv *env, jobject ctx, + nxt_unit_request_info_t *req); void nxt_java_Request_websocket(JNIEnv *env, jobject jreq, jobject jbuf, - uint8_t opcode, uint8_t fin); + uint8_t opcode, uint8_t fin); void nxt_java_Request_close(JNIEnv *env, jobject jreq); -#endif /* _NXT_JAVA_REQUEST_H_INCLUDED_ */ +#endif /* _NXT_JAVA_REQUEST_H_INCLUDED_ */ diff --git a/src/java/nxt_jni_Response.c b/src/java/nxt_jni_Response.c index fa698ee89..ba431a7cb 100644 --- a/src/java/nxt_jni_Response.c +++ b/src/java/nxt_jni_Response.c @@ -17,1090 +17,992 @@ #include "nxt_jni_OutputStream.h" #include "nxt_jni_URLClassLoader.h" - -static jclass nxt_java_Response_class; -static jmethodID nxt_java_Response_ctor; - +static jclass nxt_java_Response_class; +static jmethodID nxt_java_Response_ctor; static void JNICALL nxt_java_Response_addHeader(JNIEnv *env, jclass cls, - jlong req_info_ptr, jarray name, jarray value); + jlong req_info_ptr, jarray name, + jarray value); -static nxt_unit_request_info_t *nxt_java_get_response_info( - jlong req_info_ptr, uint32_t extra_fields, uint32_t extra_data); +static nxt_unit_request_info_t * +nxt_java_get_response_info(jlong req_info_ptr, uint32_t extra_fields, + uint32_t extra_data); static void JNICALL nxt_java_Response_addIntHeader(JNIEnv *env, jclass cls, - jlong req_info_ptr, jarray name, jint value); + jlong req_info_ptr, + jarray name, jint value); static void nxt_java_add_int_header(nxt_unit_request_info_t *req, - const char *name, uint8_t name_len, int value); + const char *name, uint8_t name_len, + int value); static jboolean JNICALL nxt_java_Response_containsHeader(JNIEnv *env, - jclass cls, jlong req_info_ptr, jarray name); + jclass cls, + jlong req_info_ptr, + jarray name); static jstring JNICALL nxt_java_Response_getHeader(JNIEnv *env, jclass cls, - jlong req_info_ptr, jarray name); + jlong req_info_ptr, + jarray name); -static jobject JNICALL nxt_java_Response_getHeaderNames(JNIEnv *env, - jclass cls, jlong req_info_ptr); +static jobject JNICALL nxt_java_Response_getHeaderNames(JNIEnv *env, jclass cls, + jlong req_info_ptr); static jobject JNICALL nxt_java_Response_getHeaders(JNIEnv *env, jclass cls, - jlong req_info_ptr, jarray name); + jlong req_info_ptr, + jarray name); static jint JNICALL nxt_java_Response_getStatus(JNIEnv *env, jclass cls, - jlong req_info_ptr); + jlong req_info_ptr); static jobject JNICALL nxt_java_Response_getRequest(JNIEnv *env, jclass cls, - jlong req_info_ptr); + jlong req_info_ptr); static void JNICALL nxt_java_Response_commit(JNIEnv *env, jclass cls, - jlong req_info_ptr); + jlong req_info_ptr); static void JNICALL nxt_java_Response_sendRedirect(JNIEnv *env, jclass cls, - jlong req_info_ptr, jarray loc); + jlong req_info_ptr, + jarray loc); -static int nxt_java_response_set_header(jlong req_info_ptr, - const char *name, jint name_len, const char *value, jint value_len); +static int nxt_java_response_set_header(jlong req_info_ptr, const char *name, + jint name_len, const char *value, + jint value_len); static void JNICALL nxt_java_Response_setHeader(JNIEnv *env, jclass cls, - jlong req_info_ptr, jarray name, jarray value); + jlong req_info_ptr, jarray name, + jarray value); static void JNICALL nxt_java_Response_removeHeader(JNIEnv *env, jclass cls, - jlong req_info_ptr, jarray name); + jlong req_info_ptr, + jarray name); -static int nxt_java_response_remove_header(jlong req_info_ptr, - const char *name, jint name_len); +static int nxt_java_response_remove_header(jlong req_info_ptr, const char *name, + jint name_len); static void JNICALL nxt_java_Response_setIntHeader(JNIEnv *env, jclass cls, - jlong req_info_ptr, jarray name, jint value); + jlong req_info_ptr, + jarray name, jint value); static void JNICALL nxt_java_Response_setStatus(JNIEnv *env, jclass cls, - jlong req_info_ptr, jint sc); + jlong req_info_ptr, jint sc); -static jstring JNICALL nxt_java_Response_getContentType(JNIEnv *env, - jclass cls, jlong req_info_ptr); +static jstring JNICALL nxt_java_Response_getContentType(JNIEnv *env, jclass cls, + jlong req_info_ptr); static jboolean JNICALL nxt_java_Response_isCommitted(JNIEnv *env, jclass cls, - jlong req_info_ptr); + jlong req_info_ptr); static void JNICALL nxt_java_Response_reset(JNIEnv *env, jclass cls, - jlong req_info_ptr); + jlong req_info_ptr); static void JNICALL nxt_java_Response_resetBuffer(JNIEnv *env, jclass cls, - jlong req_info_ptr); + jlong req_info_ptr); static void JNICALL nxt_java_Response_setBufferSize(JNIEnv *env, jclass cls, - jlong req_info_ptr, jint size); + jlong req_info_ptr, + jint size); static jint JNICALL nxt_java_Response_getBufferSize(JNIEnv *env, jclass cls, - jlong req_info_ptr); + jlong req_info_ptr); static void JNICALL nxt_java_Response_setContentLength(JNIEnv *env, jclass cls, - jlong req_info_ptr, jlong len); + jlong req_info_ptr, + jlong len); static void JNICALL nxt_java_Response_setContentType(JNIEnv *env, jclass cls, - jlong req_info_ptr, jarray type); + jlong req_info_ptr, + jarray type); static void JNICALL nxt_java_Response_removeContentType(JNIEnv *env, jclass cls, - jlong req_info_ptr); + jlong req_info_ptr); static void JNICALL nxt_java_Response_log(JNIEnv *env, jclass cls, - jlong req_info_ptr, jarray msg); + jlong req_info_ptr, jarray msg); static void JNICALL nxt_java_Response_trace(JNIEnv *env, jclass cls, - jlong req_info_ptr, jarray msg); + jlong req_info_ptr, jarray msg); -int -nxt_java_initResponse(JNIEnv *env, jobject cl) -{ - int res; - jclass cls; +int nxt_java_initResponse(JNIEnv *env, jobject cl) { + int res; + jclass cls; - cls = nxt_java_loadClass(env, cl, "nginx.unit.Response"); - if (cls == NULL) { - return NXT_UNIT_ERROR; - } + cls = nxt_java_loadClass(env, cl, "nginx.unit.Response"); + if (cls == NULL) { + return NXT_UNIT_ERROR; + } - nxt_java_Response_class = (*env)->NewGlobalRef(env, cls); - (*env)->DeleteLocalRef(env, cls); - cls = nxt_java_Response_class; + nxt_java_Response_class = (*env)->NewGlobalRef(env, cls); + (*env)->DeleteLocalRef(env, cls); + cls = nxt_java_Response_class; - nxt_java_Response_ctor = (*env)->GetMethodID(env, cls, "", "(J)V"); - if (nxt_java_Response_ctor == NULL) { - (*env)->DeleteGlobalRef(env, cls); - return NXT_UNIT_ERROR; - } + nxt_java_Response_ctor = (*env)->GetMethodID(env, cls, "", "(J)V"); + if (nxt_java_Response_ctor == NULL) { + (*env)->DeleteGlobalRef(env, cls); + return NXT_UNIT_ERROR; + } - JNINativeMethod resp_methods[] = { - { (char *) "addHeader", - (char *) "(J[B[B)V", - nxt_java_Response_addHeader }, + JNINativeMethod resp_methods[] = { + {(char *)"addHeader", (char *)"(J[B[B)V", nxt_java_Response_addHeader}, - { (char *) "addIntHeader", - (char *) "(J[BI)V", - nxt_java_Response_addIntHeader }, + {(char *)"addIntHeader", (char *)"(J[BI)V", + nxt_java_Response_addIntHeader}, - { (char *) "containsHeader", - (char *) "(J[B)Z", - nxt_java_Response_containsHeader }, + {(char *)"containsHeader", (char *)"(J[B)Z", + nxt_java_Response_containsHeader}, - { (char *) "getHeader", - (char *) "(J[B)Ljava/lang/String;", - nxt_java_Response_getHeader }, + {(char *)"getHeader", (char *)"(J[B)Ljava/lang/String;", + nxt_java_Response_getHeader}, - { (char *) "getHeaderNames", - (char *) "(J)Ljava/util/Enumeration;", - nxt_java_Response_getHeaderNames }, + {(char *)"getHeaderNames", (char *)"(J)Ljava/util/Enumeration;", + nxt_java_Response_getHeaderNames}, - { (char *) "getHeaders", - (char *) "(J[B)Ljava/util/Enumeration;", - nxt_java_Response_getHeaders }, + {(char *)"getHeaders", (char *)"(J[B)Ljava/util/Enumeration;", + nxt_java_Response_getHeaders}, - { (char *) "getStatus", - (char *) "(J)I", - nxt_java_Response_getStatus }, + {(char *)"getStatus", (char *)"(J)I", nxt_java_Response_getStatus}, - { (char *) "getRequest", - (char *) "(J)Lnginx/unit/Request;", - nxt_java_Response_getRequest }, + {(char *)"getRequest", (char *)"(J)Lnginx/unit/Request;", + nxt_java_Response_getRequest}, - { (char *) "commit", - (char *) "(J)V", - nxt_java_Response_commit }, + {(char *)"commit", (char *)"(J)V", nxt_java_Response_commit}, - { (char *) "sendRedirect", - (char *) "(J[B)V", - nxt_java_Response_sendRedirect }, + {(char *)"sendRedirect", (char *)"(J[B)V", + nxt_java_Response_sendRedirect}, - { (char *) "setHeader", - (char *) "(J[B[B)V", - nxt_java_Response_setHeader }, + {(char *)"setHeader", (char *)"(J[B[B)V", nxt_java_Response_setHeader}, - { (char *) "removeHeader", - (char *) "(J[B)V", - nxt_java_Response_removeHeader }, + {(char *)"removeHeader", (char *)"(J[B)V", + nxt_java_Response_removeHeader}, - { (char *) "setIntHeader", - (char *) "(J[BI)V", - nxt_java_Response_setIntHeader }, + {(char *)"setIntHeader", (char *)"(J[BI)V", + nxt_java_Response_setIntHeader}, - { (char *) "setStatus", - (char *) "(JI)V", - nxt_java_Response_setStatus }, + {(char *)"setStatus", (char *)"(JI)V", nxt_java_Response_setStatus}, - { (char *) "getContentType", - (char *) "(J)Ljava/lang/String;", - nxt_java_Response_getContentType }, + {(char *)"getContentType", (char *)"(J)Ljava/lang/String;", + nxt_java_Response_getContentType}, - { (char *) "isCommitted", - (char *) "(J)Z", - nxt_java_Response_isCommitted }, + {(char *)"isCommitted", (char *)"(J)Z", nxt_java_Response_isCommitted}, - { (char *) "reset", - (char *) "(J)V", - nxt_java_Response_reset }, + {(char *)"reset", (char *)"(J)V", nxt_java_Response_reset}, - { (char *) "resetBuffer", - (char *) "(J)V", - nxt_java_Response_resetBuffer }, + {(char *)"resetBuffer", (char *)"(J)V", nxt_java_Response_resetBuffer}, - { (char *) "setBufferSize", - (char *) "(JI)V", - nxt_java_Response_setBufferSize }, + {(char *)"setBufferSize", (char *)"(JI)V", + nxt_java_Response_setBufferSize}, - { (char *) "getBufferSize", - (char *) "(J)I", - nxt_java_Response_getBufferSize }, + {(char *)"getBufferSize", (char *)"(J)I", + nxt_java_Response_getBufferSize}, - { (char *) "setContentLength", - (char *) "(JJ)V", - nxt_java_Response_setContentLength }, + {(char *)"setContentLength", (char *)"(JJ)V", + nxt_java_Response_setContentLength}, - { (char *) "setContentType", - (char *) "(J[B)V", - nxt_java_Response_setContentType }, + {(char *)"setContentType", (char *)"(J[B)V", + nxt_java_Response_setContentType}, - { (char *) "removeContentType", - (char *) "(J)V", - nxt_java_Response_removeContentType }, + {(char *)"removeContentType", (char *)"(J)V", + nxt_java_Response_removeContentType}, - { (char *) "log", - (char *) "(J[B)V", - nxt_java_Response_log }, + {(char *)"log", (char *)"(J[B)V", nxt_java_Response_log}, - { (char *) "trace", - (char *) "(J[B)V", - nxt_java_Response_trace }, + {(char *)"trace", (char *)"(J[B)V", nxt_java_Response_trace}, - }; + }; - res = (*env)->RegisterNatives(env, nxt_java_Response_class, - resp_methods, - sizeof(resp_methods) - / sizeof(resp_methods[0])); + res = (*env)->RegisterNatives(env, nxt_java_Response_class, resp_methods, + sizeof(resp_methods) / sizeof(resp_methods[0])); - nxt_unit_debug(NULL, "registered Response methods: %d", res); + nxt_unit_debug(NULL, "registered Response methods: %d", res); - if (res != 0) { - (*env)->DeleteGlobalRef(env, cls); - return NXT_UNIT_ERROR; - } + if (res != 0) { + (*env)->DeleteGlobalRef(env, cls); + return NXT_UNIT_ERROR; + } - return NXT_UNIT_OK; + return NXT_UNIT_OK; } - -jobject -nxt_java_newResponse(JNIEnv *env, nxt_unit_request_info_t *req) -{ - return (*env)->NewObject(env, nxt_java_Response_class, - nxt_java_Response_ctor, nxt_ptr2jlong(req)); +jobject nxt_java_newResponse(JNIEnv *env, nxt_unit_request_info_t *req) { + return (*env)->NewObject(env, nxt_java_Response_class, nxt_java_Response_ctor, + nxt_ptr2jlong(req)); } +static void JNICALL nxt_java_Response_addHeader(JNIEnv *env, jclass cls, + jlong req_info_ptr, jarray name, + jarray value) { + int rc; + char *name_str, *value_str; + jsize name_len, value_len; + nxt_unit_request_info_t *req; + + name_len = (*env)->GetArrayLength(env, name); + value_len = (*env)->GetArrayLength(env, value); + + req = nxt_java_get_response_info(req_info_ptr, 1, name_len + value_len + 2); + if (req == NULL) { + return; + } + + name_str = (*env)->GetPrimitiveArrayCritical(env, name, NULL); + if (name_str == NULL) { + nxt_unit_req_warn(req, "addHeader: failed to get name content"); + return; + } + + value_str = (*env)->GetPrimitiveArrayCritical(env, value, NULL); + if (value_str == NULL) { + (*env)->ReleasePrimitiveArrayCritical(env, name, name_str, 0); + nxt_unit_req_warn(req, "addHeader: failed to get value content"); -static void JNICALL -nxt_java_Response_addHeader(JNIEnv *env, jclass cls, jlong req_info_ptr, - jarray name, jarray value) -{ - int rc; - char *name_str, *value_str; - jsize name_len, value_len; - nxt_unit_request_info_t *req; - - name_len = (*env)->GetArrayLength(env, name); - value_len = (*env)->GetArrayLength(env, value); - - req = nxt_java_get_response_info(req_info_ptr, 1, name_len + value_len + 2); - if (req == NULL) { - return; - } - - name_str = (*env)->GetPrimitiveArrayCritical(env, name, NULL); - if (name_str == NULL) { - nxt_unit_req_warn(req, "addHeader: failed to get name content"); - return; - } - - value_str = (*env)->GetPrimitiveArrayCritical(env, value, NULL); - if (value_str == NULL) { - (*env)->ReleasePrimitiveArrayCritical(env, name, name_str, 0); - nxt_unit_req_warn(req, "addHeader: failed to get value content"); - - return; - } + return; + } - rc = nxt_unit_response_add_field(req, name_str, name_len, - value_str, value_len); - if (rc != NXT_UNIT_OK) { - // throw - } + rc = nxt_unit_response_add_field(req, name_str, name_len, value_str, + value_len); + if (rc != NXT_UNIT_OK) { + // throw + } - (*env)->ReleasePrimitiveArrayCritical(env, value, value_str, 0); - (*env)->ReleasePrimitiveArrayCritical(env, name, name_str, 0); + (*env)->ReleasePrimitiveArrayCritical(env, value, value_str, 0); + (*env)->ReleasePrimitiveArrayCritical(env, name, name_str, 0); } - static nxt_unit_request_info_t * nxt_java_get_response_info(jlong req_info_ptr, uint32_t extra_fields, - uint32_t extra_data) -{ - int rc; - char *p; - uint32_t max_size; - nxt_unit_buf_t *buf; - nxt_unit_request_info_t *req; - nxt_java_request_data_t *data; - - req = nxt_jlong2ptr(req_info_ptr); - - if (nxt_unit_response_is_sent(req)) { - return NULL; - } + uint32_t extra_data) { + int rc; + char *p; + uint32_t max_size; + nxt_unit_buf_t *buf; + nxt_unit_request_info_t *req; + nxt_java_request_data_t *data; - data = req->data; + req = nxt_jlong2ptr(req_info_ptr); - if (!nxt_unit_response_is_init(req)) { - max_size = nxt_unit_buf_max(); - max_size = max_size < data->header_size ? max_size : data->header_size; + if (nxt_unit_response_is_sent(req)) { + return NULL; + } - rc = nxt_unit_response_init(req, 200, 16, max_size); - if (rc != NXT_UNIT_OK) { - return NULL; - } - } + data = req->data; - buf = req->response_buf; + if (!nxt_unit_response_is_init(req)) { + max_size = nxt_unit_buf_max(); + max_size = max_size < data->header_size ? max_size : data->header_size; - if (extra_fields > req->response_max_fields - - req->response->fields_count - || extra_data > (uint32_t) (buf->end - buf->free)) - { - p = buf->start + sizeof(nxt_unit_response_t) - + req->response_max_fields * sizeof(nxt_unit_field_t); - - max_size = 2 * (buf->end - p); - if (max_size > nxt_unit_buf_max()) { - nxt_unit_req_warn(req, "required max_size is too big: %"PRIu32, - max_size); - return NULL; - } - - rc = nxt_unit_response_realloc(req, 2 * req->response_max_fields, - max_size); - if (rc != NXT_UNIT_OK) { - nxt_unit_req_warn(req, "reallocation failed: %"PRIu32", %"PRIu32, - 2 * req->response_max_fields, max_size); - return NULL; - } + rc = nxt_unit_response_init(req, 200, 16, max_size); + if (rc != NXT_UNIT_OK) { + return NULL; } + } - return req; -} - - -static void JNICALL -nxt_java_Response_addIntHeader(JNIEnv *env, jclass cls, jlong req_info_ptr, - jarray name, jint value) -{ - char *name_str; - jsize name_len; - nxt_unit_request_info_t *req; + buf = req->response_buf; - name_len = (*env)->GetArrayLength(env, name); + if (extra_fields > req->response_max_fields - req->response->fields_count || + extra_data > (uint32_t)(buf->end - buf->free)) { + p = buf->start + sizeof(nxt_unit_response_t) + + req->response_max_fields * sizeof(nxt_unit_field_t); - req = nxt_java_get_response_info(req_info_ptr, 1, name_len + 40); - if (req == NULL) { - return; + max_size = 2 * (buf->end - p); + if (max_size > nxt_unit_buf_max()) { + nxt_unit_req_warn(req, "required max_size is too big: %" PRIu32, + max_size); + return NULL; } - name_str = (*env)->GetPrimitiveArrayCritical(env, name, NULL); - if (name_str == NULL) { - nxt_unit_req_warn(req, "addIntHeader: failed to get name content"); - return; + rc = nxt_unit_response_realloc(req, 2 * req->response_max_fields, max_size); + if (rc != NXT_UNIT_OK) { + nxt_unit_req_warn(req, "reallocation failed: %" PRIu32 ", %" PRIu32, + 2 * req->response_max_fields, max_size); + return NULL; } + } - nxt_java_add_int_header(req, name_str, name_len, value); - - (*env)->ReleasePrimitiveArrayCritical(env, name, name_str, 0); + return req; } +static void JNICALL nxt_java_Response_addIntHeader(JNIEnv *env, jclass cls, + jlong req_info_ptr, + jarray name, jint value) { + char *name_str; + jsize name_len; + nxt_unit_request_info_t *req; -static void -nxt_java_add_int_header(nxt_unit_request_info_t *req, const char *name, - uint8_t name_len, int value) -{ - char *p; - nxt_unit_field_t *f; - nxt_unit_response_t *resp; + name_len = (*env)->GetArrayLength(env, name); - resp = req->response; + req = nxt_java_get_response_info(req_info_ptr, 1, name_len + 40); + if (req == NULL) { + return; + } - f = resp->fields + resp->fields_count; - p = req->response_buf->free; + name_str = (*env)->GetPrimitiveArrayCritical(env, name, NULL); + if (name_str == NULL) { + nxt_unit_req_warn(req, "addIntHeader: failed to get name content"); + return; + } - f->hash = nxt_unit_field_hash(name, name_len); - f->skip = 0; - f->name_length = name_len; + nxt_java_add_int_header(req, name_str, name_len, value); - nxt_unit_sptr_set(&f->name, p); - memcpy(p, name, name_len); - p += name_len; + (*env)->ReleasePrimitiveArrayCritical(env, name, name_str, 0); +} - nxt_unit_sptr_set(&f->value, p); - f->value_length = snprintf(p, 40, "%d", (int) value); - p += f->value_length + 1; +static void nxt_java_add_int_header(nxt_unit_request_info_t *req, + const char *name, uint8_t name_len, + int value) { + char *p; + nxt_unit_field_t *f; + nxt_unit_response_t *resp; - resp->fields_count++; - req->response_buf->free = p; + resp = req->response; -} + f = resp->fields + resp->fields_count; + p = req->response_buf->free; + f->hash = nxt_unit_field_hash(name, name_len); + f->skip = 0; + f->name_length = name_len; -static jboolean JNICALL -nxt_java_Response_containsHeader(JNIEnv *env, - jclass cls, jlong req_info_ptr, jarray name) -{ - jboolean res; - char *name_str; - jsize name_len; - nxt_unit_response_t *resp; - nxt_unit_request_info_t *req; + nxt_unit_sptr_set(&f->name, p); + memcpy(p, name, name_len); + p += name_len; - req = nxt_jlong2ptr(req_info_ptr); + nxt_unit_sptr_set(&f->value, p); + f->value_length = snprintf(p, 40, "%d", (int)value); + p += f->value_length + 1; - if (!nxt_unit_response_is_init(req)) { - nxt_unit_req_debug(req, "containsHeader: response is not initialized"); - return 0; - } + resp->fields_count++; + req->response_buf->free = p; +} - if (nxt_unit_response_is_sent(req)) { - nxt_unit_req_debug(req, "containsHeader: response already sent"); - return 0; - } +static jboolean JNICALL nxt_java_Response_containsHeader(JNIEnv *env, + jclass cls, + jlong req_info_ptr, + jarray name) { + jboolean res; + char *name_str; + jsize name_len; + nxt_unit_response_t *resp; + nxt_unit_request_info_t *req; + + req = nxt_jlong2ptr(req_info_ptr); + + if (!nxt_unit_response_is_init(req)) { + nxt_unit_req_debug(req, "containsHeader: response is not initialized"); + return 0; + } - name_len = (*env)->GetArrayLength(env, name); + if (nxt_unit_response_is_sent(req)) { + nxt_unit_req_debug(req, "containsHeader: response already sent"); + return 0; + } - name_str = (*env)->GetPrimitiveArrayCritical(env, name, NULL); - if (name_str == NULL) { - nxt_unit_req_warn(req, "containsHeader: failed to get name content"); - return 0; - } + name_len = (*env)->GetArrayLength(env, name); - resp = req->response; + name_str = (*env)->GetPrimitiveArrayCritical(env, name, NULL); + if (name_str == NULL) { + nxt_unit_req_warn(req, "containsHeader: failed to get name content"); + return 0; + } - res = nxt_java_findHeader(resp->fields, - resp->fields + resp->fields_count, - name_str, name_len) != NULL; + resp = req->response; - (*env)->ReleasePrimitiveArrayCritical(env, name, name_str, 0); + res = nxt_java_findHeader(resp->fields, resp->fields + resp->fields_count, + name_str, name_len) != NULL; - return res; -} + (*env)->ReleasePrimitiveArrayCritical(env, name, name_str, 0); + return res; +} -static jstring JNICALL -nxt_java_Response_getHeader(JNIEnv *env, jclass cls, jlong req_info_ptr, - jarray name) -{ - char *name_str; - jsize name_len; - nxt_unit_field_t *f; - nxt_unit_request_info_t *req; +static jstring JNICALL nxt_java_Response_getHeader(JNIEnv *env, jclass cls, + jlong req_info_ptr, + jarray name) { + char *name_str; + jsize name_len; + nxt_unit_field_t *f; + nxt_unit_request_info_t *req; - req = nxt_jlong2ptr(req_info_ptr); + req = nxt_jlong2ptr(req_info_ptr); - if (!nxt_unit_response_is_init(req)) { - nxt_unit_req_debug(req, "getHeader: response is not initialized"); - return NULL; - } + if (!nxt_unit_response_is_init(req)) { + nxt_unit_req_debug(req, "getHeader: response is not initialized"); + return NULL; + } - if (nxt_unit_response_is_sent(req)) { - nxt_unit_req_debug(req, "getHeader: response already sent"); - return NULL; - } + if (nxt_unit_response_is_sent(req)) { + nxt_unit_req_debug(req, "getHeader: response already sent"); + return NULL; + } - name_len = (*env)->GetArrayLength(env, name); + name_len = (*env)->GetArrayLength(env, name); - name_str = (*env)->GetPrimitiveArrayCritical(env, name, NULL); - if (name_str == NULL) { - nxt_unit_req_warn(req, "getHeader: failed to get name content"); - return NULL; - } + name_str = (*env)->GetPrimitiveArrayCritical(env, name, NULL); + if (name_str == NULL) { + nxt_unit_req_warn(req, "getHeader: failed to get name content"); + return NULL; + } - f = nxt_java_findHeader(req->response->fields, - req->response->fields + req->response->fields_count, - name_str, name_len); + f = nxt_java_findHeader(req->response->fields, + req->response->fields + req->response->fields_count, + name_str, name_len); - (*env)->ReleasePrimitiveArrayCritical(env, name, name_str, 0); + (*env)->ReleasePrimitiveArrayCritical(env, name, name_str, 0); - if (f == NULL) { - return NULL; - } + if (f == NULL) { + return NULL; + } - return nxt_java_newString(env, nxt_unit_sptr_get(&f->value), - f->value_length); + return nxt_java_newString(env, nxt_unit_sptr_get(&f->value), f->value_length); } +static jobject JNICALL nxt_java_Response_getHeaderNames(JNIEnv *env, jclass cls, + jlong req_info_ptr) { + nxt_unit_request_info_t *req; -static jobject JNICALL -nxt_java_Response_getHeaderNames(JNIEnv *env, jclass cls, jlong req_info_ptr) -{ - nxt_unit_request_info_t *req; - - req = nxt_jlong2ptr(req_info_ptr); + req = nxt_jlong2ptr(req_info_ptr); - if (!nxt_unit_response_is_init(req)) { - nxt_unit_req_debug(req, "getHeaderNames: response is not initialized"); - return NULL; - } + if (!nxt_unit_response_is_init(req)) { + nxt_unit_req_debug(req, "getHeaderNames: response is not initialized"); + return NULL; + } - if (nxt_unit_response_is_sent(req)) { - nxt_unit_req_debug(req, "getHeaderNames: response already sent"); - return NULL; - } + if (nxt_unit_response_is_sent(req)) { + nxt_unit_req_debug(req, "getHeaderNames: response already sent"); + return NULL; + } - return nxt_java_newHeaderNamesEnumeration(env, req->response->fields, - req->response->fields_count); + return nxt_java_newHeaderNamesEnumeration(env, req->response->fields, + req->response->fields_count); } +static jobject JNICALL nxt_java_Response_getHeaders(JNIEnv *env, jclass cls, + jlong req_info_ptr, + jarray name) { + char *name_str; + jsize name_len; + nxt_unit_field_t *f; + nxt_unit_response_t *resp; + nxt_unit_request_info_t *req; -static jobject JNICALL -nxt_java_Response_getHeaders(JNIEnv *env, jclass cls, - jlong req_info_ptr, jarray name) -{ - char *name_str; - jsize name_len; - nxt_unit_field_t *f; - nxt_unit_response_t *resp; - nxt_unit_request_info_t *req; - - req = nxt_jlong2ptr(req_info_ptr); + req = nxt_jlong2ptr(req_info_ptr); - if (!nxt_unit_response_is_init(req)) { - nxt_unit_req_debug(req, "getHeaders: response is not initialized"); - return NULL; - } + if (!nxt_unit_response_is_init(req)) { + nxt_unit_req_debug(req, "getHeaders: response is not initialized"); + return NULL; + } - if (nxt_unit_response_is_sent(req)) { - nxt_unit_req_debug(req, "getHeaders: response already sent"); - return NULL; - } + if (nxt_unit_response_is_sent(req)) { + nxt_unit_req_debug(req, "getHeaders: response already sent"); + return NULL; + } - resp = req->response; + resp = req->response; - name_len = (*env)->GetArrayLength(env, name); + name_len = (*env)->GetArrayLength(env, name); - name_str = (*env)->GetPrimitiveArrayCritical(env, name, NULL); - if (name_str == NULL) { - nxt_unit_req_warn(req, "getHeaders: failed to get name content"); - return NULL; - } + name_str = (*env)->GetPrimitiveArrayCritical(env, name, NULL); + if (name_str == NULL) { + nxt_unit_req_warn(req, "getHeaders: failed to get name content"); + return NULL; + } - f = nxt_java_findHeader(resp->fields, resp->fields + resp->fields_count, - name_str, name_len); + f = nxt_java_findHeader(resp->fields, resp->fields + resp->fields_count, + name_str, name_len); - (*env)->ReleasePrimitiveArrayCritical(env, name, name_str, 0); + (*env)->ReleasePrimitiveArrayCritical(env, name, name_str, 0); - if (f == NULL) { - f = resp->fields + resp->fields_count; - } + if (f == NULL) { + f = resp->fields + resp->fields_count; + } - return nxt_java_newHeadersEnumeration(env, resp->fields, resp->fields_count, - f - resp->fields); + return nxt_java_newHeadersEnumeration(env, resp->fields, resp->fields_count, + f - resp->fields); } +static jint JNICALL nxt_java_Response_getStatus(JNIEnv *env, jclass cls, + jlong req_info_ptr) { + nxt_unit_request_info_t *req; -static jint JNICALL -nxt_java_Response_getStatus(JNIEnv *env, jclass cls, jlong req_info_ptr) -{ - nxt_unit_request_info_t *req; - - req = nxt_jlong2ptr(req_info_ptr); + req = nxt_jlong2ptr(req_info_ptr); - if (!nxt_unit_response_is_init(req)) { - nxt_unit_req_debug(req, "getStatus: response is not initialized"); - return 200; - } + if (!nxt_unit_response_is_init(req)) { + nxt_unit_req_debug(req, "getStatus: response is not initialized"); + return 200; + } - if (nxt_unit_response_is_sent(req)) { - nxt_unit_req_debug(req, "getStatus: response already sent"); - return 200; - } + if (nxt_unit_response_is_sent(req)) { + nxt_unit_req_debug(req, "getStatus: response already sent"); + return 200; + } - return req->response->status; + return req->response->status; } +static jobject JNICALL nxt_java_Response_getRequest(JNIEnv *env, jclass cls, + jlong req_info_ptr) { + nxt_unit_request_info_t *req; + nxt_java_request_data_t *data; -static jobject JNICALL -nxt_java_Response_getRequest(JNIEnv *env, jclass cls, jlong req_info_ptr) -{ - nxt_unit_request_info_t *req; - nxt_java_request_data_t *data; - - req = nxt_jlong2ptr(req_info_ptr); - data = req->data; + req = nxt_jlong2ptr(req_info_ptr); + data = req->data; - return data->jreq; + return data->jreq; } +static void JNICALL nxt_java_Response_commit(JNIEnv *env, jclass cls, + jlong req_info_ptr) { + nxt_unit_request_info_t *req; -static void JNICALL -nxt_java_Response_commit(JNIEnv *env, jclass cls, jlong req_info_ptr) -{ - nxt_unit_request_info_t *req; - - req = nxt_jlong2ptr(req_info_ptr); + req = nxt_jlong2ptr(req_info_ptr); - nxt_java_OutputStream_flush_buf(env, req); + nxt_java_OutputStream_flush_buf(env, req); } +static void JNICALL nxt_java_Response_sendRedirect(JNIEnv *env, jclass cls, + jlong req_info_ptr, + jarray loc) { + int rc; + char *loc_str; + jsize loc_len; + nxt_unit_request_info_t *req; -static void JNICALL -nxt_java_Response_sendRedirect(JNIEnv *env, jclass cls, - jlong req_info_ptr, jarray loc) -{ - int rc; - char *loc_str; - jsize loc_len; - nxt_unit_request_info_t *req; + static const char location[] = "Location"; + static const uint32_t location_len = sizeof(location) - 1; - static const char location[] = "Location"; - static const uint32_t location_len = sizeof(location) - 1; + req = nxt_jlong2ptr(req_info_ptr); - req = nxt_jlong2ptr(req_info_ptr); + if (nxt_unit_response_is_sent(req)) { + nxt_java_throw_IllegalStateException(env, "Response already sent"); - if (nxt_unit_response_is_sent(req)) { - nxt_java_throw_IllegalStateException(env, "Response already sent"); + return; + } - return; - } + loc_len = (*env)->GetArrayLength(env, loc); - loc_len = (*env)->GetArrayLength(env, loc); + req = nxt_java_get_response_info(req_info_ptr, 1, location_len + loc_len + 2); + if (req == NULL) { + return; + } - req = nxt_java_get_response_info(req_info_ptr, 1, - location_len + loc_len + 2); - if (req == NULL) { - return; - } + loc_str = (*env)->GetPrimitiveArrayCritical(env, loc, NULL); + if (loc_str == NULL) { + nxt_unit_req_warn(req, "sendRedirect: failed to get loc content"); + return; + } - loc_str = (*env)->GetPrimitiveArrayCritical(env, loc, NULL); - if (loc_str == NULL) { - nxt_unit_req_warn(req, "sendRedirect: failed to get loc content"); - return; - } + req->response->status = 302; - req->response->status = 302; + rc = nxt_java_response_set_header(req_info_ptr, location, location_len, + loc_str, loc_len); + if (rc != NXT_UNIT_OK) { + // throw + } - rc = nxt_java_response_set_header(req_info_ptr, location, location_len, - loc_str, loc_len); - if (rc != NXT_UNIT_OK) { - // throw - } + (*env)->ReleasePrimitiveArrayCritical(env, loc, loc_str, 0); - (*env)->ReleasePrimitiveArrayCritical(env, loc, loc_str, 0); - - nxt_unit_response_send(req); + nxt_unit_response_send(req); } +static int nxt_java_response_set_header(jlong req_info_ptr, const char *name, + jint name_len, const char *value, + jint value_len) { + int add_field; + char *dst; + nxt_unit_field_t *f, *e; + nxt_unit_response_t *resp; + nxt_unit_request_info_t *req; -static int -nxt_java_response_set_header(jlong req_info_ptr, - const char *name, jint name_len, const char *value, jint value_len) -{ - int add_field; - char *dst; - nxt_unit_field_t *f, *e; - nxt_unit_response_t *resp; - nxt_unit_request_info_t *req; + req = nxt_java_get_response_info(req_info_ptr, 0, 0); + if (req == NULL) { + return NXT_UNIT_ERROR; + } - req = nxt_java_get_response_info(req_info_ptr, 0, 0); - if (req == NULL) { - return NXT_UNIT_ERROR; - } + resp = req->response; - resp = req->response; + f = resp->fields; + e = f + resp->fields_count; - f = resp->fields; - e = f + resp->fields_count; + add_field = 1; - add_field = 1; - - for ( ;; ) { - f = nxt_java_findHeader(f, e, name, name_len); - if (f == NULL) { - break; - } - - if (add_field && f->value_length >= (uint32_t) value_len) { - dst = nxt_unit_sptr_get(&f->value); - memcpy(dst, value, value_len); - dst[value_len] = '\0'; - f->value_length = value_len; - - add_field = 0; - f->skip = 0; - - } else { - f->skip = 1; - } - - ++f; - } - - if (!add_field) { - return NXT_UNIT_OK; - } - - req = nxt_java_get_response_info(req_info_ptr, 1, name_len + value_len + 2); - if (req == NULL) { - return NXT_UNIT_ERROR; + for (;;) { + f = nxt_java_findHeader(f, e, name, name_len); + if (f == NULL) { + break; } - return nxt_unit_response_add_field(req, name, name_len, value, value_len); -} + if (add_field && f->value_length >= (uint32_t)value_len) { + dst = nxt_unit_sptr_get(&f->value); + memcpy(dst, value, value_len); + dst[value_len] = '\0'; + f->value_length = value_len; + add_field = 0; + f->skip = 0; -static void JNICALL -nxt_java_Response_setHeader(JNIEnv *env, jclass cls, - jlong req_info_ptr, jarray name, jarray value) -{ - int rc; - char *name_str, *value_str; - jsize name_len, value_len; - nxt_unit_request_info_t *req; - - name_str = (*env)->GetPrimitiveArrayCritical(env, name, NULL); - if (name_str == NULL) { - req = nxt_jlong2ptr(req_info_ptr); - nxt_unit_req_warn(req, "setHeader: failed to get name content"); - return; + } else { + f->skip = 1; } - value_str = (*env)->GetPrimitiveArrayCritical(env, value, NULL); - if (value_str == NULL) { - (*env)->ReleasePrimitiveArrayCritical(env, name, name_str, 0); + ++f; + } - req = nxt_jlong2ptr(req_info_ptr); - nxt_unit_req_warn(req, "setHeader: failed to get value content"); + if (!add_field) { + return NXT_UNIT_OK; + } - return; - } + req = nxt_java_get_response_info(req_info_ptr, 1, name_len + value_len + 2); + if (req == NULL) { + return NXT_UNIT_ERROR; + } - name_len = (*env)->GetArrayLength(env, name); - value_len = (*env)->GetArrayLength(env, value); + return nxt_unit_response_add_field(req, name, name_len, value, value_len); +} - rc = nxt_java_response_set_header(req_info_ptr, name_str, name_len, - value_str, value_len); - if (rc != NXT_UNIT_OK) { - // throw - } +static void JNICALL nxt_java_Response_setHeader(JNIEnv *env, jclass cls, + jlong req_info_ptr, jarray name, + jarray value) { + int rc; + char *name_str, *value_str; + jsize name_len, value_len; + nxt_unit_request_info_t *req; + + name_str = (*env)->GetPrimitiveArrayCritical(env, name, NULL); + if (name_str == NULL) { + req = nxt_jlong2ptr(req_info_ptr); + nxt_unit_req_warn(req, "setHeader: failed to get name content"); + return; + } - (*env)->ReleasePrimitiveArrayCritical(env, value, value_str, 0); + value_str = (*env)->GetPrimitiveArrayCritical(env, value, NULL); + if (value_str == NULL) { (*env)->ReleasePrimitiveArrayCritical(env, name, name_str, 0); -} - -static void JNICALL -nxt_java_Response_removeHeader(JNIEnv *env, jclass cls, - jlong req_info_ptr, jarray name) -{ - int rc; - char *name_str; - jsize name_len; - nxt_unit_request_info_t *req; + req = nxt_jlong2ptr(req_info_ptr); + nxt_unit_req_warn(req, "setHeader: failed to get value content"); - name_len = (*env)->GetArrayLength(env, name); + return; + } - name_str = (*env)->GetPrimitiveArrayCritical(env, name, NULL); - if (name_str == NULL) { - req = nxt_jlong2ptr(req_info_ptr); - nxt_unit_req_warn(req, "setHeader: failed to get name content"); - return; - } + name_len = (*env)->GetArrayLength(env, name); + value_len = (*env)->GetArrayLength(env, value); - rc = nxt_java_response_remove_header(req_info_ptr, name_str, name_len); - if (rc != NXT_UNIT_OK) { - // throw - } + rc = nxt_java_response_set_header(req_info_ptr, name_str, name_len, value_str, + value_len); + if (rc != NXT_UNIT_OK) { + // throw + } - (*env)->ReleasePrimitiveArrayCritical(env, name, name_str, 0); + (*env)->ReleasePrimitiveArrayCritical(env, value, value_str, 0); + (*env)->ReleasePrimitiveArrayCritical(env, name, name_str, 0); } +static void JNICALL nxt_java_Response_removeHeader(JNIEnv *env, jclass cls, + jlong req_info_ptr, + jarray name) { + int rc; + char *name_str; + jsize name_len; + nxt_unit_request_info_t *req; -static int -nxt_java_response_remove_header(jlong req_info_ptr, - const char *name, jint name_len) -{ - nxt_unit_field_t *f, *e; - nxt_unit_response_t *resp; - nxt_unit_request_info_t *req; - - req = nxt_java_get_response_info(req_info_ptr, 0, 0); - if (req == NULL) { - return NXT_UNIT_ERROR; - } - - resp = req->response; - - f = resp->fields; - e = f + resp->fields_count; - - for ( ;; ) { - f = nxt_java_findHeader(f, e, name, name_len); - if (f == NULL) { - break; - } + name_len = (*env)->GetArrayLength(env, name); - f->skip = 1; + name_str = (*env)->GetPrimitiveArrayCritical(env, name, NULL); + if (name_str == NULL) { + req = nxt_jlong2ptr(req_info_ptr); + nxt_unit_req_warn(req, "setHeader: failed to get name content"); + return; + } - ++f; - } + rc = nxt_java_response_remove_header(req_info_ptr, name_str, name_len); + if (rc != NXT_UNIT_OK) { + // throw + } - return NXT_UNIT_OK; + (*env)->ReleasePrimitiveArrayCritical(env, name, name_str, 0); } +static int nxt_java_response_remove_header(jlong req_info_ptr, const char *name, + jint name_len) { + nxt_unit_field_t *f, *e; + nxt_unit_response_t *resp; + nxt_unit_request_info_t *req; -static void JNICALL -nxt_java_Response_setIntHeader(JNIEnv *env, jclass cls, - jlong req_info_ptr, jarray name, jint value) -{ - int value_len, rc; - char value_str[40]; - char *name_str; - jsize name_len; + req = nxt_java_get_response_info(req_info_ptr, 0, 0); + if (req == NULL) { + return NXT_UNIT_ERROR; + } - value_len = snprintf(value_str, sizeof(value_str), "%d", (int) value); + resp = req->response; - name_len = (*env)->GetArrayLength(env, name); + f = resp->fields; + e = f + resp->fields_count; - name_str = (*env)->GetPrimitiveArrayCritical(env, name, NULL); - if (name_str == NULL) { - nxt_unit_req_warn(nxt_jlong2ptr(req_info_ptr), - "setIntHeader: failed to get name content"); - return; + for (;;) { + f = nxt_java_findHeader(f, e, name, name_len); + if (f == NULL) { + break; } - rc = nxt_java_response_set_header(req_info_ptr, name_str, name_len, - value_str, value_len); - if (rc != NXT_UNIT_OK) { - // throw - } + f->skip = 1; - (*env)->ReleasePrimitiveArrayCritical(env, name, name_str, 0); + ++f; + } + + return NXT_UNIT_OK; } +static void JNICALL nxt_java_Response_setIntHeader(JNIEnv *env, jclass cls, + jlong req_info_ptr, + jarray name, jint value) { + int value_len, rc; + char value_str[40]; + char *name_str; + jsize name_len; + + value_len = snprintf(value_str, sizeof(value_str), "%d", (int)value); + + name_len = (*env)->GetArrayLength(env, name); + + name_str = (*env)->GetPrimitiveArrayCritical(env, name, NULL); + if (name_str == NULL) { + nxt_unit_req_warn(nxt_jlong2ptr(req_info_ptr), + "setIntHeader: failed to get name content"); + return; + } + + rc = nxt_java_response_set_header(req_info_ptr, name_str, name_len, value_str, + value_len); + if (rc != NXT_UNIT_OK) { + // throw + } + + (*env)->ReleasePrimitiveArrayCritical(env, name, name_str, 0); +} -static void JNICALL -nxt_java_Response_setStatus(JNIEnv *env, jclass cls, jlong req_info_ptr, - jint sc) -{ - nxt_unit_request_info_t *req; +static void JNICALL nxt_java_Response_setStatus(JNIEnv *env, jclass cls, + jlong req_info_ptr, jint sc) { + nxt_unit_request_info_t *req; - req = nxt_java_get_response_info(req_info_ptr, 0, 0); - if (req == NULL) { - return; - } + req = nxt_java_get_response_info(req_info_ptr, 0, 0); + if (req == NULL) { + return; + } - req->response->status = sc; + req->response->status = sc; } +static jstring JNICALL nxt_java_Response_getContentType(JNIEnv *env, jclass cls, + jlong req_info_ptr) { + nxt_unit_field_t *f; + nxt_unit_request_info_t *req; -static jstring JNICALL -nxt_java_Response_getContentType(JNIEnv *env, jclass cls, jlong req_info_ptr) -{ - nxt_unit_field_t *f; - nxt_unit_request_info_t *req; + req = nxt_jlong2ptr(req_info_ptr); - req = nxt_jlong2ptr(req_info_ptr); + if (!nxt_unit_response_is_init(req)) { + nxt_unit_req_debug(req, "getContentType: response is not initialized"); + return NULL; + } - if (!nxt_unit_response_is_init(req)) { - nxt_unit_req_debug(req, "getContentType: response is not initialized"); - return NULL; - } - - if (nxt_unit_response_is_sent(req)) { - nxt_unit_req_debug(req, "getContentType: response already sent"); - return NULL; - } + if (nxt_unit_response_is_sent(req)) { + nxt_unit_req_debug(req, "getContentType: response already sent"); + return NULL; + } - f = nxt_java_findHeader(req->response->fields, - req->response->fields + req->response->fields_count, - "Content-Type", sizeof("Content-Type") - 1); + f = nxt_java_findHeader(req->response->fields, + req->response->fields + req->response->fields_count, + "Content-Type", sizeof("Content-Type") - 1); - if (f == NULL) { - return NULL; - } + if (f == NULL) { + return NULL; + } - return nxt_java_newString(env, nxt_unit_sptr_get(&f->value), - f->value_length); + return nxt_java_newString(env, nxt_unit_sptr_get(&f->value), f->value_length); } +static jboolean JNICALL nxt_java_Response_isCommitted(JNIEnv *env, jclass cls, + jlong req_info_ptr) { + nxt_unit_request_info_t *req; -static jboolean JNICALL -nxt_java_Response_isCommitted(JNIEnv *env, jclass cls, jlong req_info_ptr) -{ - nxt_unit_request_info_t *req; - - req = nxt_jlong2ptr(req_info_ptr); + req = nxt_jlong2ptr(req_info_ptr); - if (nxt_unit_response_is_sent(req)) { - return 1; - } + if (nxt_unit_response_is_sent(req)) { + return 1; + } - return 0; + return 0; } +static void JNICALL nxt_java_Response_reset(JNIEnv *env, jclass cls, + jlong req_info_ptr) { + nxt_unit_buf_t *buf; + nxt_unit_request_info_t *req; + nxt_java_request_data_t *data; -static void JNICALL -nxt_java_Response_reset(JNIEnv *env, jclass cls, jlong req_info_ptr) -{ - nxt_unit_buf_t *buf; - nxt_unit_request_info_t *req; - nxt_java_request_data_t *data; - - req = nxt_jlong2ptr(req_info_ptr); + req = nxt_jlong2ptr(req_info_ptr); - if (nxt_unit_response_is_sent(req)) { - nxt_java_throw_IllegalStateException(env, "Response already sent"); + if (nxt_unit_response_is_sent(req)) { + nxt_java_throw_IllegalStateException(env, "Response already sent"); - return; - } + return; + } - data = req->data; + data = req->data; - if (data->buf != NULL && data->buf->free > data->buf->start) { - data->buf->free = data->buf->start; - } + if (data->buf != NULL && data->buf->free > data->buf->start) { + data->buf->free = data->buf->start; + } - if (nxt_unit_response_is_init(req)) { - req->response->status = 200; - req->response->fields_count = 0; + if (nxt_unit_response_is_init(req)) { + req->response->status = 200; + req->response->fields_count = 0; - buf = req->response_buf; + buf = req->response_buf; - buf->free = buf->start + sizeof(nxt_unit_response_t) - + req->response_max_fields * sizeof(nxt_unit_field_t); - } + buf->free = buf->start + sizeof(nxt_unit_response_t) + + req->response_max_fields * sizeof(nxt_unit_field_t); + } } +static void JNICALL nxt_java_Response_resetBuffer(JNIEnv *env, jclass cls, + jlong req_info_ptr) { + nxt_unit_request_info_t *req; + nxt_java_request_data_t *data; -static void JNICALL -nxt_java_Response_resetBuffer(JNIEnv *env, jclass cls, jlong req_info_ptr) -{ - nxt_unit_request_info_t *req; - nxt_java_request_data_t *data; - - req = nxt_jlong2ptr(req_info_ptr); - data = req->data; + req = nxt_jlong2ptr(req_info_ptr); + data = req->data; - if (data->buf != NULL && data->buf->free > data->buf->start) { - data->buf->free = data->buf->start; - } + if (data->buf != NULL && data->buf->free > data->buf->start) { + data->buf->free = data->buf->start; + } } +static void JNICALL nxt_java_Response_setBufferSize(JNIEnv *env, jclass cls, + jlong req_info_ptr, + jint size) { + nxt_unit_request_info_t *req; + nxt_java_request_data_t *data; -static void JNICALL -nxt_java_Response_setBufferSize(JNIEnv *env, jclass cls, jlong req_info_ptr, - jint size) -{ - nxt_unit_request_info_t *req; - nxt_java_request_data_t *data; - - req = nxt_jlong2ptr(req_info_ptr); - data = req->data; + req = nxt_jlong2ptr(req_info_ptr); + data = req->data; - if (data->buf_size == (uint32_t) size) { - return; - } + if (data->buf_size == (uint32_t)size) { + return; + } - if (data->buf != NULL && data->buf->free > data->buf->start) { - nxt_java_throw_IllegalStateException(env, "Buffer is not empty"); + if (data->buf != NULL && data->buf->free > data->buf->start) { + nxt_java_throw_IllegalStateException(env, "Buffer is not empty"); - return; - } + return; + } - data->buf_size = size; + data->buf_size = size; - if (data->buf_size > nxt_unit_buf_max()) { - data->buf_size = nxt_unit_buf_max(); - } + if (data->buf_size > nxt_unit_buf_max()) { + data->buf_size = nxt_unit_buf_max(); + } - if (data->buf != NULL - && (uint32_t) (data->buf->end - data->buf->start) < data->buf_size) - { - nxt_unit_buf_free(data->buf); + if (data->buf != NULL && + (uint32_t)(data->buf->end - data->buf->start) < data->buf_size) { + nxt_unit_buf_free(data->buf); - data->buf = NULL; - } + data->buf = NULL; + } } +static jint JNICALL nxt_java_Response_getBufferSize(JNIEnv *env, jclass cls, + jlong req_info_ptr) { + nxt_unit_request_info_t *req; + nxt_java_request_data_t *data; -static jint JNICALL -nxt_java_Response_getBufferSize(JNIEnv *env, jclass cls, jlong req_info_ptr) -{ - nxt_unit_request_info_t *req; - nxt_java_request_data_t *data; - - req = nxt_jlong2ptr(req_info_ptr); - data = req->data; + req = nxt_jlong2ptr(req_info_ptr); + data = req->data; - return data->buf_size; + return data->buf_size; } +static void JNICALL nxt_java_Response_setContentLength(JNIEnv *env, jclass cls, + jlong req_info_ptr, + jlong len) { + nxt_unit_request_info_t *req; -static void JNICALL -nxt_java_Response_setContentLength(JNIEnv *env, jclass cls, jlong req_info_ptr, - jlong len) -{ - nxt_unit_request_info_t *req; - - req = nxt_java_get_response_info(req_info_ptr, 0, 0); - if (req == NULL) { - return; - } + req = nxt_java_get_response_info(req_info_ptr, 0, 0); + if (req == NULL) { + return; + } - req->response->content_length = len; + req->response->content_length = len; } +static void JNICALL nxt_java_Response_setContentType(JNIEnv *env, jclass cls, + jlong req_info_ptr, + jarray type) { + int rc; + char *type_str; + jsize type_len; -static void JNICALL -nxt_java_Response_setContentType(JNIEnv *env, jclass cls, jlong req_info_ptr, - jarray type) -{ - int rc; - char *type_str; - jsize type_len; - - static const char content_type[] = "Content-Type"; - static const uint32_t content_type_len = sizeof(content_type) - 1; + static const char content_type[] = "Content-Type"; + static const uint32_t content_type_len = sizeof(content_type) - 1; - type_len = (*env)->GetArrayLength(env, type); + type_len = (*env)->GetArrayLength(env, type); - type_str = (*env)->GetPrimitiveArrayCritical(env, type, NULL); - if (type_str == NULL) { - return; - } + type_str = (*env)->GetPrimitiveArrayCritical(env, type, NULL); + if (type_str == NULL) { + return; + } - rc = nxt_java_response_set_header(req_info_ptr, - content_type, content_type_len, - type_str, type_len); - if (rc != NXT_UNIT_OK) { - // throw - } + rc = nxt_java_response_set_header(req_info_ptr, content_type, + content_type_len, type_str, type_len); + if (rc != NXT_UNIT_OK) { + // throw + } - (*env)->ReleasePrimitiveArrayCritical(env, type, type_str, 0); + (*env)->ReleasePrimitiveArrayCritical(env, type, type_str, 0); } - -static void JNICALL -nxt_java_Response_removeContentType(JNIEnv *env, jclass cls, jlong req_info_ptr) -{ - nxt_java_response_remove_header(req_info_ptr, "Content-Type", - sizeof("Content-Type") - 1); +static void JNICALL nxt_java_Response_removeContentType(JNIEnv *env, jclass cls, + jlong req_info_ptr) { + nxt_java_response_remove_header(req_info_ptr, "Content-Type", + sizeof("Content-Type") - 1); } +static void JNICALL nxt_java_Response_log(JNIEnv *env, jclass cls, + jlong req_info_ptr, jarray msg) { + char *msg_str; + jsize msg_len; + nxt_unit_request_info_t *req; -static void JNICALL -nxt_java_Response_log(JNIEnv *env, jclass cls, jlong req_info_ptr, jarray msg) -{ - char *msg_str; - jsize msg_len; - nxt_unit_request_info_t *req; - - req = nxt_jlong2ptr(req_info_ptr); - msg_len = (*env)->GetArrayLength(env, msg); + req = nxt_jlong2ptr(req_info_ptr); + msg_len = (*env)->GetArrayLength(env, msg); - msg_str = (*env)->GetPrimitiveArrayCritical(env, msg, NULL); - if (msg_str == NULL) { - nxt_unit_req_warn(req, "log: failed to get msg content"); - return; - } + msg_str = (*env)->GetPrimitiveArrayCritical(env, msg, NULL); + if (msg_str == NULL) { + nxt_unit_req_warn(req, "log: failed to get msg content"); + return; + } - nxt_unit_req_log(req, NXT_UNIT_LOG_INFO, "%.*s", msg_len, msg_str); + nxt_unit_req_log(req, NXT_UNIT_LOG_INFO, "%.*s", msg_len, msg_str); - (*env)->ReleasePrimitiveArrayCritical(env, msg, msg_str, 0); + (*env)->ReleasePrimitiveArrayCritical(env, msg, msg_str, 0); } - -static void JNICALL -nxt_java_Response_trace(JNIEnv *env, jclass cls, jlong req_info_ptr, jarray msg) -{ +static void JNICALL nxt_java_Response_trace(JNIEnv *env, jclass cls, + jlong req_info_ptr, jarray msg) { #if (NXT_DEBUG) - char *msg_str; - jsize msg_len; - nxt_unit_request_info_t *req; + char *msg_str; + jsize msg_len; + nxt_unit_request_info_t *req; - req = nxt_jlong2ptr(req_info_ptr); - msg_len = (*env)->GetArrayLength(env, msg); + req = nxt_jlong2ptr(req_info_ptr); + msg_len = (*env)->GetArrayLength(env, msg); - msg_str = (*env)->GetPrimitiveArrayCritical(env, msg, NULL); - if (msg_str == NULL) { - nxt_unit_req_warn(req, "trace: failed to get msg content"); - return; - } + msg_str = (*env)->GetPrimitiveArrayCritical(env, msg, NULL); + if (msg_str == NULL) { + nxt_unit_req_warn(req, "trace: failed to get msg content"); + return; + } - nxt_unit_req_debug(req, "%.*s", msg_len, msg_str); + nxt_unit_req_debug(req, "%.*s", msg_len, msg_str); - (*env)->ReleasePrimitiveArrayCritical(env, msg, msg_str, 0); + (*env)->ReleasePrimitiveArrayCritical(env, msg, msg_str, 0); #endif } - diff --git a/src/java/nxt_jni_Response.h b/src/java/nxt_jni_Response.h index d10dba58b..c271f441d 100644 --- a/src/java/nxt_jni_Response.h +++ b/src/java/nxt_jni_Response.h @@ -6,13 +6,11 @@ #ifndef _NXT_JAVA_RESPONSE_H_INCLUDED_ #define _NXT_JAVA_RESPONSE_H_INCLUDED_ - #include #include - int nxt_java_initResponse(JNIEnv *env, jobject cl); jobject nxt_java_newResponse(JNIEnv *env, nxt_unit_request_info_t *req); -#endif /* _NXT_JAVA_RESPONSE_H_INCLUDED_ */ +#endif /* _NXT_JAVA_RESPONSE_H_INCLUDED_ */ diff --git a/src/java/nxt_jni_Thread.c b/src/java/nxt_jni_Thread.c index 43dd90bdd..4aba6e778 100644 --- a/src/java/nxt_jni_Thread.c +++ b/src/java/nxt_jni_Thread.c @@ -8,87 +8,79 @@ #include "nxt_jni_Thread.h" +static jclass nxt_java_Thread_class; +static jmethodID nxt_java_Thread_currentThread; +static jmethodID nxt_java_Thread_getContextClassLoader; +static jmethodID nxt_java_Thread_setContextClassLoader; -static jclass nxt_java_Thread_class; -static jmethodID nxt_java_Thread_currentThread; -static jmethodID nxt_java_Thread_getContextClassLoader; -static jmethodID nxt_java_Thread_setContextClassLoader; - - -int -nxt_java_initThread(JNIEnv *env) -{ - jclass cls; - - cls = (*env)->FindClass(env, "java/lang/Thread"); - if (cls == NULL) { - nxt_unit_warn(NULL, "java.lang.Thread not found"); - return NXT_UNIT_ERROR; - } - - nxt_java_Thread_class = (*env)->NewGlobalRef(env, cls); - (*env)->DeleteLocalRef(env, cls); - cls = nxt_java_Thread_class; - - nxt_java_Thread_currentThread = (*env)->GetStaticMethodID(env, cls, - "currentThread", "()Ljava/lang/Thread;"); - if (nxt_java_Thread_currentThread == NULL) { - nxt_unit_warn(NULL, "java.lang.Thread.currentThread() not found"); - goto failed; - } - - nxt_java_Thread_getContextClassLoader = (*env)->GetMethodID(env, cls, - "getContextClassLoader", "()Ljava/lang/ClassLoader;"); - if (nxt_java_Thread_getContextClassLoader == NULL) { - nxt_unit_warn(NULL, "java.lang.Thread.getContextClassLoader() " - "not found"); - goto failed; - } - - nxt_java_Thread_setContextClassLoader = (*env)->GetMethodID(env, cls, - "setContextClassLoader", "(Ljava/lang/ClassLoader;)V"); - if (nxt_java_Thread_setContextClassLoader == NULL) { - nxt_unit_warn(NULL, "java.lang.Thread.setContextClassLoader() " - "not found"); - goto failed; - } - - return NXT_UNIT_OK; +int nxt_java_initThread(JNIEnv *env) { + jclass cls; + + cls = (*env)->FindClass(env, "java/lang/Thread"); + if (cls == NULL) { + nxt_unit_warn(NULL, "java.lang.Thread not found"); + return NXT_UNIT_ERROR; + } + + nxt_java_Thread_class = (*env)->NewGlobalRef(env, cls); + (*env)->DeleteLocalRef(env, cls); + cls = nxt_java_Thread_class; + + nxt_java_Thread_currentThread = (*env)->GetStaticMethodID( + env, cls, "currentThread", "()Ljava/lang/Thread;"); + if (nxt_java_Thread_currentThread == NULL) { + nxt_unit_warn(NULL, "java.lang.Thread.currentThread() not found"); + goto failed; + } + + nxt_java_Thread_getContextClassLoader = (*env)->GetMethodID( + env, cls, "getContextClassLoader", "()Ljava/lang/ClassLoader;"); + if (nxt_java_Thread_getContextClassLoader == NULL) { + nxt_unit_warn(NULL, "java.lang.Thread.getContextClassLoader() " + "not found"); + goto failed; + } + + nxt_java_Thread_setContextClassLoader = (*env)->GetMethodID( + env, cls, "setContextClassLoader", "(Ljava/lang/ClassLoader;)V"); + if (nxt_java_Thread_setContextClassLoader == NULL) { + nxt_unit_warn(NULL, "java.lang.Thread.setContextClassLoader() " + "not found"); + goto failed; + } + + return NXT_UNIT_OK; failed: - (*env)->DeleteGlobalRef(env, cls); - return NXT_UNIT_ERROR; + (*env)->DeleteGlobalRef(env, cls); + return NXT_UNIT_ERROR; } -void -nxt_java_setContextClassLoader(JNIEnv *env, jobject cl) -{ - jobject thread; +void nxt_java_setContextClassLoader(JNIEnv *env, jobject cl) { + jobject thread; - thread = (*env)->CallStaticObjectMethod(env, nxt_java_Thread_class, - nxt_java_Thread_currentThread); + thread = (*env)->CallStaticObjectMethod(env, nxt_java_Thread_class, + nxt_java_Thread_currentThread); - if (thread == NULL) { - return; - } + if (thread == NULL) { + return; + } - (*env)->CallVoidMethod(env, thread, nxt_java_Thread_setContextClassLoader, - cl); + (*env)->CallVoidMethod(env, thread, nxt_java_Thread_setContextClassLoader, + cl); } -jobject -nxt_java_getContextClassLoader(JNIEnv *env) -{ - jobject thread; +jobject nxt_java_getContextClassLoader(JNIEnv *env) { + jobject thread; - thread = (*env)->CallStaticObjectMethod(env, nxt_java_Thread_class, - nxt_java_Thread_currentThread); + thread = (*env)->CallStaticObjectMethod(env, nxt_java_Thread_class, + nxt_java_Thread_currentThread); - if (thread == NULL) { - return NULL; - } + if (thread == NULL) { + return NULL; + } - return (*env)->CallObjectMethod(env, thread, - nxt_java_Thread_getContextClassLoader); + return (*env)->CallObjectMethod(env, thread, + nxt_java_Thread_getContextClassLoader); } diff --git a/src/java/nxt_jni_Thread.h b/src/java/nxt_jni_Thread.h index 4d0b650eb..3b4365f26 100644 --- a/src/java/nxt_jni_Thread.h +++ b/src/java/nxt_jni_Thread.h @@ -6,15 +6,12 @@ #ifndef _NXT_JAVA_THREAD_H_INCLUDED_ #define _NXT_JAVA_THREAD_H_INCLUDED_ - #include - int nxt_java_initThread(JNIEnv *env); void nxt_java_setContextClassLoader(JNIEnv *env, jobject cl); jobject nxt_java_getContextClassLoader(JNIEnv *env); -#endif /* _NXT_JAVA_THREAD_H_INCLUDED_ */ - +#endif /* _NXT_JAVA_THREAD_H_INCLUDED_ */ diff --git a/src/java/nxt_jni_URLClassLoader.c b/src/java/nxt_jni_URLClassLoader.c index bf3ab0c38..5c7ed731d 100644 --- a/src/java/nxt_jni_URLClassLoader.c +++ b/src/java/nxt_jni_URLClassLoader.c @@ -8,180 +8,159 @@ #include "nxt_jni_URLClassLoader.h" +static jclass nxt_java_URLClassLoader_class; +static jmethodID nxt_java_URLClassLoader_ctor; +static jmethodID nxt_java_URLClassLoader_parent_ctor; +static jmethodID nxt_java_URLClassLoader_loadClass; +static jmethodID nxt_java_URLClassLoader_addURL; -static jclass nxt_java_URLClassLoader_class; -static jmethodID nxt_java_URLClassLoader_ctor; -static jmethodID nxt_java_URLClassLoader_parent_ctor; -static jmethodID nxt_java_URLClassLoader_loadClass; -static jmethodID nxt_java_URLClassLoader_addURL; +static jclass nxt_java_URL_class; +static jmethodID nxt_java_URL_ctor; -static jclass nxt_java_URL_class; -static jmethodID nxt_java_URL_ctor; +int nxt_java_initURLClassLoader(JNIEnv *env) { + jclass cls; + cls = (*env)->FindClass(env, "java/net/URLClassLoader"); + if (cls == NULL) { + nxt_unit_warn(NULL, "java.net.URLClassLoader not found"); + return NXT_UNIT_ERROR; + } + + nxt_java_URLClassLoader_class = (*env)->NewGlobalRef(env, cls); + (*env)->DeleteLocalRef(env, cls); + cls = nxt_java_URLClassLoader_class; + + nxt_java_URLClassLoader_ctor = + (*env)->GetMethodID(env, cls, "", "([Ljava/net/URL;)V"); + if (nxt_java_URLClassLoader_ctor == NULL) { + nxt_unit_warn(NULL, "java.net.URLClassLoader constructor not found"); + goto failed; + } + + nxt_java_URLClassLoader_parent_ctor = (*env)->GetMethodID( + env, cls, "", "([Ljava/net/URL;Ljava/lang/ClassLoader;)V"); + if (nxt_java_URLClassLoader_ctor == NULL) { + nxt_unit_warn(NULL, "java.net.URLClassLoader constructor not found"); + goto failed; + } + + nxt_java_URLClassLoader_loadClass = (*env)->GetMethodID( + env, cls, "loadClass", "(Ljava/lang/String;)Ljava/lang/Class;"); + if (nxt_java_URLClassLoader_loadClass == NULL) { + nxt_unit_warn(NULL, "java.net.URLClassLoader.loadClass not found"); + goto failed; + } + + nxt_java_URLClassLoader_addURL = + (*env)->GetMethodID(env, cls, "addURL", "(Ljava/net/URL;)V"); + if (nxt_java_URLClassLoader_addURL == NULL) { + nxt_unit_warn(NULL, "java.net.URLClassLoader.addURL not found"); + goto failed; + } + + cls = (*env)->FindClass(env, "java/net/URL"); + if (cls == NULL) { + nxt_unit_warn(NULL, "java.net.URL not found"); + return NXT_UNIT_ERROR; + } -int -nxt_java_initURLClassLoader(JNIEnv *env) -{ - jclass cls; - - cls = (*env)->FindClass(env, "java/net/URLClassLoader"); - if (cls == NULL) { - nxt_unit_warn(NULL, "java.net.URLClassLoader not found"); - return NXT_UNIT_ERROR; - } - - nxt_java_URLClassLoader_class = (*env)->NewGlobalRef(env, cls); - (*env)->DeleteLocalRef(env, cls); - cls = nxt_java_URLClassLoader_class; - - nxt_java_URLClassLoader_ctor = (*env)->GetMethodID(env, cls, - "", "([Ljava/net/URL;)V"); - if (nxt_java_URLClassLoader_ctor == NULL) { - nxt_unit_warn(NULL, "java.net.URLClassLoader constructor not found"); - goto failed; - } - - nxt_java_URLClassLoader_parent_ctor = (*env)->GetMethodID(env, cls, - "", "([Ljava/net/URL;Ljava/lang/ClassLoader;)V"); - if (nxt_java_URLClassLoader_ctor == NULL) { - nxt_unit_warn(NULL, "java.net.URLClassLoader constructor not found"); - goto failed; - } - - nxt_java_URLClassLoader_loadClass = (*env)->GetMethodID(env, cls, - "loadClass", "(Ljava/lang/String;)Ljava/lang/Class;"); - if (nxt_java_URLClassLoader_loadClass == NULL) { - nxt_unit_warn(NULL, "java.net.URLClassLoader.loadClass not found"); - goto failed; - } - - nxt_java_URLClassLoader_addURL = (*env)->GetMethodID(env, cls, - "addURL", "(Ljava/net/URL;)V"); - if (nxt_java_URLClassLoader_addURL == NULL) { - nxt_unit_warn(NULL, "java.net.URLClassLoader.addURL not found"); - goto failed; - } - - cls = (*env)->FindClass(env, "java/net/URL"); - if (cls == NULL) { - nxt_unit_warn(NULL, "java.net.URL not found"); - return NXT_UNIT_ERROR; - } - - nxt_java_URL_class = (*env)->NewGlobalRef(env, cls); - (*env)->DeleteLocalRef(env, cls); - cls = nxt_java_URL_class; + nxt_java_URL_class = (*env)->NewGlobalRef(env, cls); + (*env)->DeleteLocalRef(env, cls); + cls = nxt_java_URL_class; - nxt_java_URL_ctor = (*env)->GetMethodID(env, cls, - "", "(Ljava/lang/String;)V"); - if (nxt_java_URL_ctor == NULL) { - nxt_unit_warn(NULL, "java.net.URL constructor not found"); - goto failed; - } + nxt_java_URL_ctor = + (*env)->GetMethodID(env, cls, "", "(Ljava/lang/String;)V"); + if (nxt_java_URL_ctor == NULL) { + nxt_unit_warn(NULL, "java.net.URL constructor not found"); + goto failed; + } - return NXT_UNIT_OK; + return NXT_UNIT_OK; failed: - (*env)->DeleteGlobalRef(env, cls); - return NXT_UNIT_ERROR; + (*env)->DeleteGlobalRef(env, cls); + return NXT_UNIT_ERROR; } +jobject nxt_java_newURLClassLoader(JNIEnv *env, int url_count, char **urls) { + jobjectArray jurls; -jobject -nxt_java_newURLClassLoader(JNIEnv *env, int url_count, char **urls) -{ - jobjectArray jurls; + jurls = nxt_java_newURLs(env, url_count, urls); + if (jurls == NULL) { + return NULL; + } - jurls = nxt_java_newURLs(env, url_count, urls); - if (jurls == NULL) { - return NULL; - } - - return (*env)->NewObject(env, nxt_java_URLClassLoader_class, - nxt_java_URLClassLoader_ctor, jurls); + return (*env)->NewObject(env, nxt_java_URLClassLoader_class, + nxt_java_URLClassLoader_ctor, jurls); } +jobject nxt_java_newURLClassLoader_parent(JNIEnv *env, int url_count, + char **urls, jobject parent) { + jobjectArray jurls; -jobject -nxt_java_newURLClassLoader_parent(JNIEnv *env, int url_count, char **urls, - jobject parent) -{ - jobjectArray jurls; + jurls = nxt_java_newURLs(env, url_count, urls); + if (jurls == NULL) { + return NULL; + } - jurls = nxt_java_newURLs(env, url_count, urls); - if (jurls == NULL) { - return NULL; - } - - return (*env)->NewObject(env, nxt_java_URLClassLoader_class, - nxt_java_URLClassLoader_parent_ctor, jurls, - parent); + return (*env)->NewObject(env, nxt_java_URLClassLoader_class, + nxt_java_URLClassLoader_parent_ctor, jurls, parent); } +jobjectArray nxt_java_newURLs(JNIEnv *env, int url_count, char **urls) { + int i; + jstring surl; + jobject jurl; + jobjectArray jurls; -jobjectArray -nxt_java_newURLs(JNIEnv *env, int url_count, char **urls) -{ - int i; - jstring surl; - jobject jurl; - jobjectArray jurls; + jurls = (*env)->NewObjectArray(env, url_count, nxt_java_URL_class, NULL); + if (jurls == NULL) { + return NULL; + } - jurls = (*env)->NewObjectArray(env, url_count, nxt_java_URL_class, NULL); - if (jurls == NULL) { - return NULL; + for (i = 0; i < url_count; i++) { + surl = (*env)->NewStringUTF(env, urls[i]); + if (surl == NULL) { + return NULL; } - for (i = 0; i < url_count; i++) { - surl = (*env)->NewStringUTF(env, urls[i]); - if (surl == NULL) { - return NULL; - } - - jurl = (*env)->NewObject(env, nxt_java_URL_class, nxt_java_URL_ctor, - surl); - if (jurl == NULL) { - return NULL; - } - - (*env)->SetObjectArrayElement(env, jurls, i, jurl); + jurl = (*env)->NewObject(env, nxt_java_URL_class, nxt_java_URL_ctor, surl); + if (jurl == NULL) { + return NULL; } - return jurls; -} + (*env)->SetObjectArrayElement(env, jurls, i, jurl); + } + return jurls; +} -jclass -nxt_java_loadClass(JNIEnv *env, jobject cl, const char *name) -{ - jstring jname; +jclass nxt_java_loadClass(JNIEnv *env, jobject cl, const char *name) { + jstring jname; - jname = (*env)->NewStringUTF(env, name); - if (jname == NULL) { - return NULL; - } + jname = (*env)->NewStringUTF(env, name); + if (jname == NULL) { + return NULL; + } - return (*env)->CallObjectMethod(env, cl, nxt_java_URLClassLoader_loadClass, - jname); + return (*env)->CallObjectMethod(env, cl, nxt_java_URLClassLoader_loadClass, + jname); } +void nxt_java_addURL(JNIEnv *env, jobject cl, const char *url) { + jstring surl; + jobject jurl; -void -nxt_java_addURL(JNIEnv *env, jobject cl, const char *url) -{ - jstring surl; - jobject jurl; + surl = (*env)->NewStringUTF(env, url); + if (surl == NULL) { + return; + } - surl = (*env)->NewStringUTF(env, url); - if (surl == NULL) { - return; - } - - jurl = (*env)->NewObject(env, nxt_java_URL_class, nxt_java_URL_ctor, surl); - if (jurl == NULL) { - return; - } + jurl = (*env)->NewObject(env, nxt_java_URL_class, nxt_java_URL_ctor, surl); + if (jurl == NULL) { + return; + } - (*env)->CallVoidMethod(env, cl, nxt_java_URLClassLoader_addURL, jurl); + (*env)->CallVoidMethod(env, cl, nxt_java_URLClassLoader_addURL, jurl); } diff --git a/src/java/nxt_jni_URLClassLoader.h b/src/java/nxt_jni_URLClassLoader.h index 4cf2c0ec9..fd0511612 100644 --- a/src/java/nxt_jni_URLClassLoader.h +++ b/src/java/nxt_jni_URLClassLoader.h @@ -6,16 +6,14 @@ #ifndef _NXT_JAVA_URLCLASSLOADER_H_INCLUDED_ #define _NXT_JAVA_URLCLASSLOADER_H_INCLUDED_ - #include - int nxt_java_initURLClassLoader(JNIEnv *env); jobject nxt_java_newURLClassLoader(JNIEnv *env, int url_count, char **urls); jobject nxt_java_newURLClassLoader_parent(JNIEnv *env, int url_count, - char **urls, jobject parent); + char **urls, jobject parent); jobjectArray nxt_java_newURLs(JNIEnv *env, int url_count, char **urls); @@ -23,5 +21,4 @@ jclass nxt_java_loadClass(JNIEnv *env, jobject cl, const char *name); void nxt_java_addURL(JNIEnv *env, jobject cl, const char *url); -#endif /* _NXT_JAVA_URLCLASSLOADER_H_INCLUDED_ */ - +#endif /* _NXT_JAVA_URLCLASSLOADER_H_INCLUDED_ */ diff --git a/src/nodejs/unit-http/nxt_napi.h b/src/nodejs/unit-http/nxt_napi.h index d9721a406..4858e13f8 100644 --- a/src/nodejs/unit-http/nxt_napi.h +++ b/src/nodejs/unit-http/nxt_napi.h @@ -8,7 +8,6 @@ #include - #ifdef __cplusplus extern "C" { #endif @@ -23,817 +22,651 @@ extern "C" { #include #include - #ifdef __cplusplus } /* extern "C" */ #endif - struct nxt_napi { - struct exception { - exception(const char *s) : str(s) { } - - const char *str; - }; - - - nxt_napi(napi_env env) : env_(env) { } - - - inline napi_value - coerce_to_string(napi_value val) - { - napi_value res; - napi_status status; - - status = napi_coerce_to_string(env_, val, &res); - if (status != napi_ok) { - throw exception("Failed to coerce to string"); - } - - return res; - } + struct exception { + exception(const char *s) : str(s) {} + const char *str; + }; - inline napi_value - create_buffer(size_t size, void **data) - { - napi_value res; - napi_status status; + nxt_napi(napi_env env) : env_(env) {} - status = napi_create_buffer(env_, size, data, &res); - if (status != napi_ok) { - throw exception("Failed to create buffer"); - } + inline napi_value coerce_to_string(napi_value val) { + napi_value res; + napi_status status; - return res; + status = napi_coerce_to_string(env_, val, &res); + if (status != napi_ok) { + throw exception("Failed to coerce to string"); } + return res; + } - inline napi_value - create_function(const char *name, size_t len, napi_callback cb, void *data) - { - napi_value res; - napi_status status; - - status = napi_create_function(env_, name, len, cb, data, &res); - if (status != napi_ok) { - throw exception("Failed to create function"); - } - - return res; - } - + inline napi_value create_buffer(size_t size, void **data) { + napi_value res; + napi_status status; - inline napi_value - create_function(napi_callback cb) - { - return create_function(NULL, 0, cb, NULL); + status = napi_create_buffer(env_, size, data, &res); + if (status != napi_ok) { + throw exception("Failed to create buffer"); } + return res; + } - inline napi_value - create_object() - { - napi_value res; - napi_status status; + inline napi_value create_function(const char *name, size_t len, + napi_callback cb, void *data) { + napi_value res; + napi_status status; - status = napi_create_object(env_, &res); - if (status != napi_ok) { - throw exception("Failed to create object"); - } - - return res; + status = napi_create_function(env_, name, len, cb, data, &res); + if (status != napi_ok) { + throw exception("Failed to create function"); } + return res; + } - inline napi_ref - create_reference(napi_value val, int ref_count = 1) - { - napi_ref res; - napi_status status; + inline napi_value create_function(napi_callback cb) { + return create_function(NULL, 0, cb, NULL); + } - status = napi_create_reference(env_, val, ref_count, &res); - if (status != napi_ok) { - throw exception("Failed to create reference"); - } + inline napi_value create_object() { + napi_value res; + napi_status status; - return res; + status = napi_create_object(env_, &res); + if (status != napi_ok) { + throw exception("Failed to create object"); } + return res; + } - inline napi_value - create_string_latin1(const char *str, size_t len) - { - napi_value res; - napi_status status; - - status = napi_create_string_latin1(env_, str, len, &res); - if (status != napi_ok) { - throw exception("Failed to create latin1 string"); - } + inline napi_ref create_reference(napi_value val, int ref_count = 1) { + napi_ref res; + napi_status status; - return res; + status = napi_create_reference(env_, val, ref_count, &res); + if (status != napi_ok) { + throw exception("Failed to create reference"); } + return res; + } - inline napi_value - create_string_latin1(nxt_unit_sptr_t &str, size_t len) - { - const char *p; - - p = (const char *) nxt_unit_sptr_get(&str); + inline napi_value create_string_latin1(const char *str, size_t len) { + napi_value res; + napi_status status; - return create_string_latin1(p, len); + status = napi_create_string_latin1(env_, str, len, &res); + if (status != napi_ok) { + throw exception("Failed to create latin1 string"); } + return res; + } - inline napi_value - define_class(const char *name, napi_callback ctor, size_t prop_count, - const napi_property_descriptor* props) - { - napi_value res; - napi_status status; + inline napi_value create_string_latin1(nxt_unit_sptr_t &str, size_t len) { + const char *p; - status = napi_define_class(env_, name, NAPI_AUTO_LENGTH, ctor, nullptr, - prop_count, props, &res); - if (status != napi_ok) { - throw exception("Failed to define class"); - } + p = (const char *)nxt_unit_sptr_get(&str); - return res; - } + return create_string_latin1(p, len); + } + inline napi_value define_class(const char *name, napi_callback ctor, + size_t prop_count, + const napi_property_descriptor *props) { + napi_value res; + napi_status status; - inline void - delete_reference(napi_ref ref) - { - napi_delete_reference(env_, ref); + status = napi_define_class(env_, name, NAPI_AUTO_LENGTH, ctor, nullptr, + prop_count, props, &res); + if (status != napi_ok) { + throw exception("Failed to define class"); } + return res; + } - inline uint32_t - get_array_length(napi_value val) - { - uint32_t res; - napi_status status; + inline void delete_reference(napi_ref ref) { + napi_delete_reference(env_, ref); + } - status = napi_get_array_length(env_, val, &res); - if (status != napi_ok) { - throw exception("Failed to get array length"); - } + inline uint32_t get_array_length(napi_value val) { + uint32_t res; + napi_status status; - return res; + status = napi_get_array_length(env_, val, &res); + if (status != napi_ok) { + throw exception("Failed to get array length"); } + return res; + } - inline void * - get_buffer_info(napi_value val, size_t &size) - { - void *res; - napi_status status; - - status = napi_get_buffer_info(env_, val, &res, &size); - if (status != napi_ok) { - throw exception("Failed to get buffer info"); - } + inline void *get_buffer_info(napi_value val, size_t &size) { + void *res; + napi_status status; - return res; + status = napi_get_buffer_info(env_, val, &res, &size); + if (status != napi_ok) { + throw exception("Failed to get buffer info"); } + return res; + } - inline napi_value - get_cb_info(napi_callback_info info, size_t &argc, napi_value *argv) - { - napi_value res; - napi_status status; + inline napi_value get_cb_info(napi_callback_info info, size_t &argc, + napi_value *argv) { + napi_value res; + napi_status status; - status = napi_get_cb_info(env_, info, &argc, argv, &res, nullptr); - if (status != napi_ok) { - throw exception("Failed to get arguments from js"); - } - - return res; + status = napi_get_cb_info(env_, info, &argc, argv, &res, nullptr); + if (status != napi_ok) { + throw exception("Failed to get arguments from js"); } + return res; + } - inline napi_value - get_cb_info(napi_callback_info info) - { - napi_value res; - napi_status status; - - status = napi_get_cb_info(env_, info, nullptr, nullptr, &res, nullptr); - if (status != napi_ok) { - throw exception("Failed to get arguments from js"); - } + inline napi_value get_cb_info(napi_callback_info info) { + napi_value res; + napi_status status; - return res; + status = napi_get_cb_info(env_, info, nullptr, nullptr, &res, nullptr); + if (status != napi_ok) { + throw exception("Failed to get arguments from js"); } + return res; + } - inline napi_value - get_cb_info(napi_callback_info info, napi_value &arg) - { - size_t argc; - napi_value res; - - argc = 1; - res = get_cb_info(info, argc, &arg); + inline napi_value get_cb_info(napi_callback_info info, napi_value &arg) { + size_t argc; + napi_value res; - if (argc != 1) { - throw exception("Wrong args count. Expected 1"); - } + argc = 1; + res = get_cb_info(info, argc, &arg); - return res; + if (argc != 1) { + throw exception("Wrong args count. Expected 1"); } + return res; + } - inline napi_value - get_element(napi_value obj, uint32_t i) - { - napi_value res; - napi_status status; + inline napi_value get_element(napi_value obj, uint32_t i) { + napi_value res; + napi_status status; - status = napi_get_element(env_, obj, i, &res); - if (status != napi_ok) { - throw exception("Failed to get element"); - } - - return res; + status = napi_get_element(env_, obj, i, &res); + if (status != napi_ok) { + throw exception("Failed to get element"); } + return res; + } - inline napi_value - get_named_property(napi_value obj, const char *name) - { - napi_value res; - napi_status status; - - status = napi_get_named_property(env_, obj, name, &res); - if (status != napi_ok) { - throw exception("Failed to get named property"); - } + inline napi_value get_named_property(napi_value obj, const char *name) { + napi_value res; + napi_status status; - return res; + status = napi_get_named_property(env_, obj, name, &res); + if (status != napi_ok) { + throw exception("Failed to get named property"); } + return res; + } - inline napi_value - get_new_target(napi_callback_info info) - { - napi_value res; - napi_status status; + inline napi_value get_new_target(napi_callback_info info) { + napi_value res; + napi_status status; - status = napi_get_new_target(env_, info, &res); - if (status != napi_ok) { - throw exception("Failed to get new target"); - } - - return res; + status = napi_get_new_target(env_, info, &res); + if (status != napi_ok) { + throw exception("Failed to get new target"); } + return res; + } - inline napi_value - get_property(napi_value val, napi_value key) - { - napi_value res; - napi_status status; - - status = napi_get_property(env_, val, key, &res); - if (status != napi_ok) { - throw exception("Failed to get property"); - } + inline napi_value get_property(napi_value val, napi_value key) { + napi_value res; + napi_status status; - return res; + status = napi_get_property(env_, val, key, &res); + if (status != napi_ok) { + throw exception("Failed to get property"); } + return res; + } - inline napi_value - get_property_names(napi_value val) - { - napi_value res; - napi_status status; - - status = napi_get_property_names(env_, val, &res); - if (status != napi_ok) { - throw exception("Failed to get property names"); - } + inline napi_value get_property_names(napi_value val) { + napi_value res; + napi_status status; - return res; + status = napi_get_property_names(env_, val, &res); + if (status != napi_ok) { + throw exception("Failed to get property names"); } + return res; + } - inline napi_value - get_reference_value(napi_ref ref) - { - napi_value res; - napi_status status; + inline napi_value get_reference_value(napi_ref ref) { + napi_value res; + napi_status status; - status = napi_get_reference_value(env_, ref, &res); - if (status != napi_ok) { - throw exception("Failed to get reference value"); - } - - return res; + status = napi_get_reference_value(env_, ref, &res); + if (status != napi_ok) { + throw exception("Failed to get reference value"); } + return res; + } - inline nxt_unit_request_info_t * - get_request_info(napi_value obj) - { - return (nxt_unit_request_info_t *) unwrap(obj); - } + inline nxt_unit_request_info_t *get_request_info(napi_value obj) { + return (nxt_unit_request_info_t *)unwrap(obj); + } + inline uint32_t get_value_bool(napi_value obj) { + bool res; + napi_status status; - inline uint32_t - get_value_bool(napi_value obj) - { - bool res; - napi_status status; - - status = napi_get_value_bool(env_, obj, &res); - if (status != napi_ok) { - throw exception("Failed to get bool"); - } - - return res; + status = napi_get_value_bool(env_, obj, &res); + if (status != napi_ok) { + throw exception("Failed to get bool"); } + return res; + } - inline size_t - get_value_string_latin1(napi_value val, char *buf, size_t bufsize) - { - size_t res; - napi_status status; - - status = napi_get_value_string_latin1(env_, val, buf, bufsize, &res); - if (status != napi_ok) { - throw exception("Failed to get string latin1"); - } + inline size_t get_value_string_latin1(napi_value val, char *buf, + size_t bufsize) { + size_t res; + napi_status status; - return res; + status = napi_get_value_string_latin1(env_, val, buf, bufsize, &res); + if (status != napi_ok) { + throw exception("Failed to get string latin1"); } + return res; + } - inline uint32_t - get_value_uint32(napi_value obj) - { - uint32_t res; - napi_status status; + inline uint32_t get_value_uint32(napi_value obj) { + uint32_t res; + napi_status status; - status = napi_get_value_uint32(env_, obj, &res); - if (status != napi_ok) { - throw exception("Failed to get uint32_t"); - } - - return res; + status = napi_get_value_uint32(env_, obj, &res); + if (status != napi_ok) { + throw exception("Failed to get uint32_t"); } + return res; + } - inline size_t - get_value_string_utf8(napi_value val, char *buf, size_t bufsize) - { - size_t res; - napi_status status; - - status = napi_get_value_string_utf8(env_, val, buf, bufsize, &res); - if (status != napi_ok) { - throw exception("Failed to get string utf8"); - } + inline size_t get_value_string_utf8(napi_value val, char *buf, + size_t bufsize) { + size_t res; + napi_status status; - return res; + status = napi_get_value_string_utf8(env_, val, buf, bufsize, &res); + if (status != napi_ok) { + throw exception("Failed to get string utf8"); } + return res; + } - inline bool - is_array(napi_value val) - { - bool res; - napi_status status; + inline bool is_array(napi_value val) { + bool res; + napi_status status; - status = napi_is_array(env_, val, &res); - if (status != napi_ok) { - throw exception("Failed to confirm value is array"); - } - - return res; + status = napi_is_array(env_, val, &res); + if (status != napi_ok) { + throw exception("Failed to confirm value is array"); } + return res; + } - inline bool - is_buffer(napi_value val) - { - bool res; - napi_status status; - - status = napi_is_buffer(env_, val, &res); - if (status != napi_ok) { - throw exception("Failed to confirm value is buffer"); - } + inline bool is_buffer(napi_value val) { + bool res; + napi_status status; - return res; + status = napi_is_buffer(env_, val, &res); + if (status != napi_ok) { + throw exception("Failed to confirm value is buffer"); } + return res; + } - inline napi_value - make_callback(napi_async_context ctx, napi_value val, napi_value func, - int argc, const napi_value *argv) - { - napi_value res, ex; - napi_status status; + inline napi_value make_callback(napi_async_context ctx, napi_value val, + napi_value func, int argc, + const napi_value *argv) { + napi_value res, ex; + napi_status status; - status = napi_make_callback(env_, ctx, val, func, argc, argv, &res); - if (status != napi_ok) { - if (status != napi_pending_exception) { - throw exception("Failed to make callback"); - } + status = napi_make_callback(env_, ctx, val, func, argc, argv, &res); + if (status != napi_ok) { + if (status != napi_pending_exception) { + throw exception("Failed to make callback"); + } - status = napi_get_and_clear_last_exception(env_, &ex); - if (status != napi_ok) { - throw exception("Failed to get and clear last exception"); - } + status = napi_get_and_clear_last_exception(env_, &ex); + if (status != napi_ok) { + throw exception("Failed to get and clear last exception"); + } - /* Logging a description of the error and call stack. */ - status = napi_fatal_exception(env_, ex); - if (status != napi_ok) { - throw exception("Failed napi_fatal_exception()"); - } - } - - return res; + /* Logging a description of the error and call stack. */ + status = napi_fatal_exception(env_, ex); + if (status != napi_ok) { + throw exception("Failed napi_fatal_exception()"); + } } + return res; + } - inline napi_value - make_callback(napi_async_context ctx, napi_value val, napi_value func) - { - return make_callback(ctx, val, func, 0, NULL); - } + inline napi_value make_callback(napi_async_context ctx, napi_value val, + napi_value func) { + return make_callback(ctx, val, func, 0, NULL); + } + inline napi_value make_callback(napi_async_context ctx, napi_value val, + napi_value func, napi_value arg1) { + return make_callback(ctx, val, func, 1, &arg1); + } - inline napi_value - make_callback(napi_async_context ctx, napi_value val, napi_value func, - napi_value arg1) - { - return make_callback(ctx, val, func, 1, &arg1); - } - + inline napi_value make_callback(napi_async_context ctx, napi_value val, + napi_value func, napi_value arg1, + napi_value arg2) { + napi_value args[2] = {arg1, arg2}; - inline napi_value - make_callback(napi_async_context ctx, napi_value val, napi_value func, - napi_value arg1, napi_value arg2) - { - napi_value args[2] = { arg1, arg2 }; + return make_callback(ctx, val, func, 2, args); + } - return make_callback(ctx, val, func, 2, args); - } + inline napi_value make_callback(napi_async_context ctx, napi_value val, + napi_value func, napi_value arg1, + napi_value arg2, napi_value arg3) { + napi_value args[3] = {arg1, arg2, arg3}; + return make_callback(ctx, val, func, 3, args); + } - inline napi_value - make_callback(napi_async_context ctx, napi_value val, napi_value func, - napi_value arg1, napi_value arg2, napi_value arg3) - { - napi_value args[3] = { arg1, arg2, arg3 }; + inline napi_value new_instance(napi_value ctor) { + napi_value res; + napi_status status; - return make_callback(ctx, val, func, 3, args); + status = napi_new_instance(env_, ctor, 0, NULL, &res); + if (status != napi_ok) { + throw exception("Failed to create instance"); } + return res; + } - inline napi_value - new_instance(napi_value ctor) - { - napi_value res; - napi_status status; + inline napi_value new_instance(napi_value ctor, napi_value param) { + napi_value res; + napi_status status; - status = napi_new_instance(env_, ctor, 0, NULL, &res); - if (status != napi_ok) { - throw exception("Failed to create instance"); - } - - return res; + status = napi_new_instance(env_, ctor, 1, ¶m, &res); + if (status != napi_ok) { + throw exception("Failed to create instance"); } + return res; + } - inline napi_value - new_instance(napi_value ctor, napi_value param) - { - napi_value res; - napi_status status; - - status = napi_new_instance(env_, ctor, 1, ¶m, &res); - if (status != napi_ok) { - throw exception("Failed to create instance"); - } + inline napi_value new_instance(napi_value ctor, napi_value param1, + napi_value param2) { + napi_value res; + napi_status status; + napi_value param[2] = {param1, param2}; - return res; + status = napi_new_instance(env_, ctor, 2, param, &res); + if (status != napi_ok) { + throw exception("Failed to create instance"); } + return res; + } - inline napi_value - new_instance(napi_value ctor, napi_value param1, napi_value param2) - { - napi_value res; - napi_status status; - napi_value param[2] = { param1, param2 }; + inline void set_element(napi_value obj, uint32_t i, napi_value val) { + napi_status status; - status = napi_new_instance(env_, ctor, 2, param, &res); - if (status != napi_ok) { - throw exception("Failed to create instance"); - } - - return res; + status = napi_set_element(env_, obj, i, val); + if (status != napi_ok) { + throw exception("Failed to set element"); } + } + inline void set_named_property(napi_value obj, const char *name, + napi_value val) { + napi_status status; - inline void - set_element(napi_value obj, uint32_t i, napi_value val) - { - napi_status status; - - status = napi_set_element(env_, obj, i, val); - if (status != napi_ok) { - throw exception("Failed to set element"); - } + status = napi_set_named_property(env_, obj, name, val); + if (status != napi_ok) { + throw exception("Failed to set named property"); } + } + inline void set_named_property(napi_value obj, const char *name, + napi_callback cb) { + set_named_property(obj, name, create_function(cb)); + } - inline void - set_named_property(napi_value obj, const char *name, napi_value val) - { - napi_status status; + inline napi_value set_named_property(napi_value obj, const char *name, + nxt_unit_sptr_t &val, size_t len) { + napi_value str; - status = napi_set_named_property(env_, obj, name, val); - if (status != napi_ok) { - throw exception("Failed to set named property"); - } - } + str = create_string_latin1(val, len); + set_named_property(obj, name, str); - inline void - set_named_property(napi_value obj, const char *name, napi_callback cb) - { - set_named_property(obj, name, create_function(cb)); - } - - - inline napi_value - set_named_property(napi_value obj, const char *name, nxt_unit_sptr_t &val, - size_t len) - { - napi_value str; - - str = create_string_latin1(val, len); - - set_named_property(obj, name, str); - - return str; - } - - - template - inline void - set_named_property(napi_value obj, const char *name, T val) - { - set_named_property(obj, name, create(val)); - } - + return str; + } - inline napi_value - create(int32_t val) - { - napi_value ptr; - napi_status status; + template + inline void set_named_property(napi_value obj, const char *name, T val) { + set_named_property(obj, name, create(val)); + } - status = napi_create_int32(env_, val, &ptr); - if (status != napi_ok) { - throw exception("Failed to create int32"); - } + inline napi_value create(int32_t val) { + napi_value ptr; + napi_status status; - return ptr; + status = napi_create_int32(env_, val, &ptr); + if (status != napi_ok) { + throw exception("Failed to create int32"); } + return ptr; + } - inline napi_value - create(uint32_t val) - { - napi_value ptr; - napi_status status; + inline napi_value create(uint32_t val) { + napi_value ptr; + napi_status status; - status = napi_create_uint32(env_, val, &ptr); - if (status != napi_ok) { - throw exception("Failed to create uint32"); - } - - return ptr; + status = napi_create_uint32(env_, val, &ptr); + if (status != napi_ok) { + throw exception("Failed to create uint32"); } + return ptr; + } - inline napi_value - create(int64_t val) - { - napi_value ptr; - napi_status status; - - status = napi_create_int64(env_, val, &ptr); - if (status != napi_ok) { - throw exception("Failed to create int64"); - } - - return ptr; - } - + inline napi_value create(int64_t val) { + napi_value ptr; + napi_status status; - inline void - remove_wrap(napi_ref& ref) - { - if (ref != nullptr) { - remove_wrap(get_reference_value(ref)); - ref = nullptr; - } + status = napi_create_int64(env_, val, &ptr); + if (status != napi_ok) { + throw exception("Failed to create int64"); } + return ptr; + } - inline void * - remove_wrap(napi_value val) - { - void *res; - napi_status status; - - status = napi_remove_wrap(env_, val, &res); - if (status != napi_ok) { - throw exception("Failed to remove_wrap"); - } - - return res; + inline void remove_wrap(napi_ref &ref) { + if (ref != nullptr) { + remove_wrap(get_reference_value(ref)); + ref = nullptr; } + } + inline void *remove_wrap(napi_value val) { + void *res; + napi_status status; - inline void - throw_error(const char *str) - { - napi_throw_error(env_, NULL, str); + status = napi_remove_wrap(env_, val, &res); + if (status != napi_ok) { + throw exception("Failed to remove_wrap"); } + return res; + } - inline void - throw_error(const exception &e) - { - napi_throw_error(env_, NULL, e.str); - } + inline void throw_error(const char *str) { + napi_throw_error(env_, NULL, str); + } + inline void throw_error(const exception &e) { + napi_throw_error(env_, NULL, e.str); + } - inline napi_valuetype - type_of(napi_value val) - { - napi_status status; - napi_valuetype res; + inline napi_valuetype type_of(napi_value val) { + napi_status status; + napi_valuetype res; - status = napi_typeof(env_, val, &res); - if (status != napi_ok) { - throw exception("Failed to get typeof"); - } - - return res; + status = napi_typeof(env_, val, &res); + if (status != napi_ok) { + throw exception("Failed to get typeof"); } + return res; + } - inline void * - unwrap(napi_value val) - { - void *res; - napi_status status; - - status = napi_unwrap(env_, val, &res); - if (status != napi_ok) { - throw exception("Failed to unwrap"); - } + inline void *unwrap(napi_value val) { + void *res; + napi_status status; - return res; + status = napi_unwrap(env_, val, &res); + if (status != napi_ok) { + throw exception("Failed to unwrap"); } + return res; + } - inline napi_ref - wrap(napi_value val, void *obj, napi_finalize fin_cb, void *hint = nullptr) - { - napi_ref res; - napi_status status; + inline napi_ref wrap(napi_value val, void *obj, napi_finalize fin_cb, + void *hint = nullptr) { + napi_ref res; + napi_status status; - status = napi_wrap(env_, val, obj, fin_cb, hint, &res); - if (status != napi_ok) { - throw exception("Failed to wrap"); - } - - return res; + status = napi_wrap(env_, val, obj, fin_cb, hint, &res); + if (status != napi_ok) { + throw exception("Failed to wrap"); } + return res; + } - inline - operator napi_env() - { - return env_; - } + inline operator napi_env() { return env_; } - - napi_env env() - { - return env_; - } + napi_env env() { return env_; } private: - napi_env env_; + napi_env env_; }; - struct nxt_handle_scope : public nxt_napi { - nxt_handle_scope(napi_env env) : nxt_napi(env) - { - napi_status status; + nxt_handle_scope(napi_env env) : nxt_napi(env) { + napi_status status; - status = napi_open_handle_scope(env, &scope_); - if (status != napi_ok) { - throw exception("Failed to open handle scope"); - } + status = napi_open_handle_scope(env, &scope_); + if (status != napi_ok) { + throw exception("Failed to open handle scope"); } + } - ~nxt_handle_scope() - { - napi_status status; + ~nxt_handle_scope() { + napi_status status; - status = napi_close_handle_scope(env(), scope_); - if (status != napi_ok) { - throw_error("Failed to close handle scope"); - } + status = napi_close_handle_scope(env(), scope_); + if (status != napi_ok) { + throw_error("Failed to close handle scope"); } + } private: - napi_handle_scope scope_; + napi_handle_scope scope_; }; - struct nxt_async_context : public nxt_napi { - nxt_async_context(napi_env env, const char *name) : - nxt_napi(env) - { - napi_value name_val; - napi_status status; + nxt_async_context(napi_env env, const char *name) : nxt_napi(env) { + napi_value name_val; + napi_status status; - name_val = create_string_latin1(name, NAPI_AUTO_LENGTH); + name_val = create_string_latin1(name, NAPI_AUTO_LENGTH); - status = napi_async_init(env, NULL, name_val, &context_); - if (status != napi_ok) { - throw exception("Failed to init async object"); - } + status = napi_async_init(env, NULL, name_val, &context_); + if (status != napi_ok) { + throw exception("Failed to init async object"); } + } - operator napi_async_context() { - return context_; - } + operator napi_async_context() { return context_; } - ~nxt_async_context() - { - napi_status status; + ~nxt_async_context() { + napi_status status; - status = napi_async_destroy(env(), context_); - if (status != napi_ok) { - throw_error("Failed to destroy async object"); - } + status = napi_async_destroy(env(), context_); + if (status != napi_ok) { + throw_error("Failed to destroy async object"); } + } private: - napi_async_context context_; + napi_async_context context_; }; - struct nxt_callback_scope : public nxt_napi { - nxt_callback_scope(nxt_async_context& ctx) : - nxt_napi(ctx.env()) - { - napi_value resource; - napi_status status; + nxt_callback_scope(nxt_async_context &ctx) : nxt_napi(ctx.env()) { + napi_value resource; + napi_status status; - resource = create_object(); + resource = create_object(); - status = napi_open_callback_scope(env(), resource, ctx, &scope_); - if (status != napi_ok) { - throw exception("Failed to open callback scope"); - } + status = napi_open_callback_scope(env(), resource, ctx, &scope_); + if (status != napi_ok) { + throw exception("Failed to open callback scope"); } + } - ~nxt_callback_scope() - { - napi_status status; + ~nxt_callback_scope() { + napi_status status; - status = napi_close_callback_scope(env(), scope_); - if (status != napi_ok) { - throw_error("Failed to close callback scope"); - } + status = napi_close_callback_scope(env(), scope_); + if (status != napi_ok) { + throw_error("Failed to close callback scope"); } + } private: - napi_callback_scope scope_; + napi_callback_scope scope_; }; - #endif /* _NXT_NODEJS_NAPI_H_INCLUDED_ */ diff --git a/src/nodejs/unit-http/unit.h b/src/nodejs/unit-http/unit.h index 1aa93073a..fb3a17bdf 100644 --- a/src/nodejs/unit-http/unit.h +++ b/src/nodejs/unit-http/unit.h @@ -8,80 +8,80 @@ #include "nxt_napi.h" - class Unit : public nxt_napi { public: - static napi_value init(napi_env env, napi_value exports); + static napi_value init(napi_env env, napi_value exports); private: - Unit(napi_env env, napi_value jsthis); - ~Unit(); + Unit(napi_env env, napi_value jsthis); + ~Unit(); - static napi_value create(napi_env env, napi_callback_info info); - static void destroy(napi_env env, void *nativeObject, void *finalize_hint); - static void conn_destroy(napi_env env, void *nativeObject, void *finalize_hint); - static void sock_destroy(napi_env env, void *nativeObject, void *finalize_hint); - static void req_destroy(napi_env env, void *nativeObject, void *finalize_hint); - static void resp_destroy(napi_env env, void *nativeObject, void *finalize_hint); + static napi_value create(napi_env env, napi_callback_info info); + static void destroy(napi_env env, void *nativeObject, void *finalize_hint); + static void conn_destroy(napi_env env, void *nativeObject, + void *finalize_hint); + static void sock_destroy(napi_env env, void *nativeObject, + void *finalize_hint); + static void req_destroy(napi_env env, void *nativeObject, + void *finalize_hint); + static void resp_destroy(napi_env env, void *nativeObject, + void *finalize_hint); - static napi_value create_server(napi_env env, napi_callback_info info); - static napi_value listen(napi_env env, napi_callback_info info); - static napi_value _read(napi_env env, napi_callback_info info); + static napi_value create_server(napi_env env, napi_callback_info info); + static napi_value listen(napi_env env, napi_callback_info info); + static napi_value _read(napi_env env, napi_callback_info info); - static void request_handler_cb(nxt_unit_request_info_t *req); - void request_handler(nxt_unit_request_info_t *req); + static void request_handler_cb(nxt_unit_request_info_t *req); + void request_handler(nxt_unit_request_info_t *req); - static void websocket_handler_cb(nxt_unit_websocket_frame_t *ws); - void websocket_handler(nxt_unit_websocket_frame_t *ws); + static void websocket_handler_cb(nxt_unit_websocket_frame_t *ws); + void websocket_handler(nxt_unit_websocket_frame_t *ws); - static void close_handler_cb(nxt_unit_request_info_t *req); - void close_handler(nxt_unit_request_info_t *req); + static void close_handler_cb(nxt_unit_request_info_t *req); + void close_handler(nxt_unit_request_info_t *req); - static void shm_ack_handler_cb(nxt_unit_ctx_t *ctx); - void shm_ack_handler(nxt_unit_ctx_t *ctx); + static void shm_ack_handler_cb(nxt_unit_ctx_t *ctx); + void shm_ack_handler(nxt_unit_ctx_t *ctx); - static int add_port(nxt_unit_ctx_t *ctx, nxt_unit_port_t *port); - static void remove_port(nxt_unit_t *unit, nxt_unit_ctx_t *ctx, - nxt_unit_port_t *port); + static int add_port(nxt_unit_ctx_t *ctx, nxt_unit_port_t *port); + static void remove_port(nxt_unit_t *unit, nxt_unit_ctx_t *ctx, + nxt_unit_port_t *port); - static void quit_cb(nxt_unit_ctx_t *ctx); - void quit(nxt_unit_ctx_t *ctx); + static void quit_cb(nxt_unit_ctx_t *ctx); + void quit(nxt_unit_ctx_t *ctx); - napi_value get_server_object(); + napi_value get_server_object(); - napi_value create_socket(napi_value server_obj, - nxt_unit_request_info_t *req); + napi_value create_socket(napi_value server_obj, nxt_unit_request_info_t *req); - napi_value create_request(napi_value server_obj, napi_value socket, - nxt_unit_request_info_t *req); + napi_value create_request(napi_value server_obj, napi_value socket, + nxt_unit_request_info_t *req); - napi_value create_response(napi_value server_obj, napi_value request, - nxt_unit_request_info_t *req); + napi_value create_response(napi_value server_obj, napi_value request, + nxt_unit_request_info_t *req); - napi_value create_websocket_frame(napi_value server_obj, - nxt_unit_websocket_frame_t *ws); + napi_value create_websocket_frame(napi_value server_obj, + nxt_unit_websocket_frame_t *ws); - static napi_value request_read(napi_env env, napi_callback_info info); + static napi_value request_read(napi_env env, napi_callback_info info); - static napi_value response_send_headers(napi_env env, - napi_callback_info info); + static napi_value response_send_headers(napi_env env, + napi_callback_info info); - static napi_value response_write(napi_env env, napi_callback_info info); - static napi_value response_end(napi_env env, napi_callback_info info); - static napi_value websocket_send_frame(napi_env env, - napi_callback_info info); - static napi_value websocket_set_sock(napi_env env, napi_callback_info info); + static napi_value response_write(napi_env env, napi_callback_info info); + static napi_value response_end(napi_env env, napi_callback_info info); + static napi_value websocket_send_frame(napi_env env, napi_callback_info info); + static napi_value websocket_set_sock(napi_env env, napi_callback_info info); - void create_headers(nxt_unit_request_info_t *req, napi_value request); + void create_headers(nxt_unit_request_info_t *req, napi_value request); - void append_header(nxt_unit_field_t *f, napi_value headers, - napi_value raw_headers, uint32_t idx); + void append_header(nxt_unit_field_t *f, napi_value headers, + napi_value raw_headers, uint32_t idx); - static napi_ref constructor_; + static napi_ref constructor_; - napi_ref wrapper_; - nxt_unit_ctx_t *unit_ctx_; + napi_ref wrapper_; + nxt_unit_ctx_t *unit_ctx_; }; - #endif /* _NXT_NODEJS_UNIT_H_INCLUDED_ */ diff --git a/src/nxt_aix_send_file.c b/src/nxt_aix_send_file.c index 6462efd55..d79c8fab9 100644 --- a/src/nxt_aix_send_file.c +++ b/src/nxt_aix_send_file.c @@ -6,121 +6,117 @@ #include - /* send_file() has been introduced in AIX 4.3.2 */ ssize_t nxt_aix_event_conn_io_send_file(nxt_event_conn_t *c, nxt_buf_t *b, - size_t limit); - - -ssize_t -nxt_aix_event_conn_io_send_file(nxt_event_conn_t *c, nxt_buf_t *b, size_t limit) -{ - ssize_t n; - nxt_buf_t *fb; - nxt_err_t err; - nxt_off_t file_size, sent; - nxt_uint_t nhd, ntr; - struct iovec hd[NXT_IOBUF_MAX], tr; - struct sf_parms sfp; - nxt_sendbuf_coalesce_t sb; - - sb.buf = b; - sb.iobuf = hd; - sb.nmax = NXT_IOBUF_MAX; - sb.sync = 0; - sb.size = 0; - sb.limit = limit; - - nhd = nxt_sendbuf_mem_coalesce(c->socket.task, &sb); - - if (nhd == 0 && sb.sync) { - return 0; - } + size_t limit); - if (nhd > 1 || sb.buf == NULL || !nxt_buf_is_file(sb.buf)) { - return nxt_event_conn_io_writev(c, hd, nhd); - } +ssize_t nxt_aix_event_conn_io_send_file(nxt_event_conn_t *c, nxt_buf_t *b, + size_t limit) { + ssize_t n; + nxt_buf_t *fb; + nxt_err_t err; + nxt_off_t file_size, sent; + nxt_uint_t nhd, ntr; + struct iovec hd[NXT_IOBUF_MAX], tr; + struct sf_parms sfp; + nxt_sendbuf_coalesce_t sb; - fb = sb.buf; + sb.buf = b; + sb.iobuf = hd; + sb.nmax = NXT_IOBUF_MAX; + sb.sync = 0; + sb.size = 0; + sb.limit = limit; - file_size = nxt_sendbuf_file_coalesce(&sb); + nhd = nxt_sendbuf_mem_coalesce(c->socket.task, &sb); - if (file_size == 0) { - return nxt_event_conn_io_writev(c, hd, nhd); - } + if (nhd == 0 && sb.sync) { + return 0; + } - sb.iobuf = &tr; - sb.nmax = 1; + if (nhd > 1 || sb.buf == NULL || !nxt_buf_is_file(sb.buf)) { + return nxt_event_conn_io_writev(c, hd, nhd); + } - ntr = nxt_sendbuf_mem_coalesce(c->socket.task, &sb); + fb = sb.buf; - nxt_memzero(&sfp, sizeof(struct sf_parms)); + file_size = nxt_sendbuf_file_coalesce(&sb); - if (nhd != 0) { - sfp.header_data = hd[0].iov_base; - sfp.header_length = hd[0].iov_len; - } + if (file_size == 0) { + return nxt_event_conn_io_writev(c, hd, nhd); + } - sfp.file_descriptor = fb->file->fd; - sfp.file_offset = fb->file_pos; - sfp.file_bytes = file_size; + sb.iobuf = &tr; + sb.nmax = 1; - if (ntr != 0) { - sfp.trailer_data = tr.iov_base; - sfp.trailer_length = tr.iov_len; - } + ntr = nxt_sendbuf_mem_coalesce(c->socket.task, &sb); - nxt_debug(c->socket.task, "send_file(%d) fd:%FD @%O:%O hd:%ui tr:%ui", - c->socket.fd, fb->file->fd, fb->file_pos, file_size, nhd, ntr); + nxt_memzero(&sfp, sizeof(struct sf_parms)); - n = send_file(&c->socket.fd, &sfp, 0); + if (nhd != 0) { + sfp.header_data = hd[0].iov_base; + sfp.header_length = hd[0].iov_len; + } - err = (n == -1) ? nxt_errno : 0; - sent = sfp.bytes_sent; + sfp.file_descriptor = fb->file->fd; + sfp.file_offset = fb->file_pos; + sfp.file_bytes = file_size; - nxt_debug(c->socket.task, "send_file(%d): %d sent:%O", - c->socket.fd, n, sent); + if (ntr != 0) { + sfp.trailer_data = tr.iov_base; + sfp.trailer_length = tr.iov_len; + } - /* - * -1 an error has occurred, errno contains the error code; - * 0 the command has completed successfully; - * 1 the command was completed partially, some data has been - * transmitted but the command has to return for some reason, - * for example, the command was interrupted by signals. - */ - if (n == -1) { - switch (err) { + nxt_debug(c->socket.task, "send_file(%d) fd:%FD @%O:%O hd:%ui tr:%ui", + c->socket.fd, fb->file->fd, fb->file_pos, file_size, nhd, ntr); - case NXT_EAGAIN: - c->socket.write_ready = 0; - break; + n = send_file(&c->socket.fd, &sfp, 0); - case NXT_EINTR: - break; + err = (n == -1) ? nxt_errno : 0; + sent = sfp.bytes_sent; - default: - c->socket.error = err; - nxt_log(c->socket.task, nxt_socket_error_level(err), - "send_file(%d) failed %E \"%FN\" fd:%FD @%O:%O hd:%ui tr:%ui", - c->socket.fd, err, fb->file->name, fb->file->fd, fb->file_pos, - file_size, nhd, ntr); + nxt_debug(c->socket.task, "send_file(%d): %d sent:%O", c->socket.fd, n, sent); - return NXT_ERROR; - } + /* + * -1 an error has occurred, errno contains the error code; + * 0 the command has completed successfully; + * 1 the command was completed partially, some data has been + * transmitted but the command has to return for some reason, + * for example, the command was interrupted by signals. + */ + if (n == -1) { + switch (err) { - nxt_debug(c->socket.task, "sendfile() %E", err); + case NXT_EAGAIN: + c->socket.write_ready = 0; + break; - return sent; - } + case NXT_EINTR: + break; - if (n == 1) { - return sent; - } + default: + c->socket.error = err; + nxt_log(c->socket.task, nxt_socket_error_level(err), + "send_file(%d) failed %E \"%FN\" fd:%FD @%O:%O hd:%ui tr:%ui", + c->socket.fd, err, fb->file->name, fb->file->fd, fb->file_pos, + file_size, nhd, ntr); - if (sent < (nxt_off_t) sb.size) { - c->socket.write_ready = 0; + return NXT_ERROR; } + nxt_debug(c->socket.task, "sendfile() %E", err); + return sent; + } + + if (n == 1) { + return sent; + } + + if (sent < (nxt_off_t)sb.size) { + c->socket.write_ready = 0; + } + + return sent; } diff --git a/src/nxt_app_log.c b/src/nxt_app_log.c index ae57c2a2f..d610f1d1d 100644 --- a/src/nxt_app_log.c +++ b/src/nxt_app_log.c @@ -7,35 +7,34 @@ #include #include - -static nxt_time_string_t nxt_log_error_time_cache; +static nxt_time_string_t nxt_log_error_time_cache; static u_char *nxt_log_error_time(u_char *buf, nxt_realtime_t *now, - struct tm *tm, size_t size, const char *format); -static nxt_time_string_t nxt_log_debug_time_cache; + struct tm *tm, size_t size, + const char *format); +static nxt_time_string_t nxt_log_debug_time_cache; static u_char *nxt_log_debug_time(u_char *buf, nxt_realtime_t *now, - struct tm *tm, size_t size, const char *format); - + struct tm *tm, size_t size, + const char *format); -void nxt_cdecl -nxt_log_time_handler(nxt_uint_t level, nxt_log_t *log, const char *fmt, ...) -{ - u_char *p, *end; +void nxt_cdecl nxt_log_time_handler(nxt_uint_t level, nxt_log_t *log, + const char *fmt, ...) { + u_char *p, *end; #if 0 u_char *syslogmsg; #endif - va_list args; - nxt_thread_t *thr; - nxt_time_string_t *time_cache; - u_char msg[NXT_MAX_ERROR_STR]; + va_list args; + nxt_thread_t *thr; + nxt_time_string_t *time_cache; + u_char msg[NXT_MAX_ERROR_STR]; - thr = nxt_thread(); + thr = nxt_thread(); - end = msg + NXT_MAX_ERROR_STR; + end = msg + NXT_MAX_ERROR_STR; - time_cache = (log->level != NXT_LOG_DEBUG) ? &nxt_log_error_time_cache: - &nxt_log_debug_time_cache; + time_cache = (log->level != NXT_LOG_DEBUG) ? &nxt_log_error_time_cache + : &nxt_log_debug_time_cache; - p = nxt_thread_time_string(thr, time_cache, msg); + p = nxt_thread_time_string(thr, time_cache, msg); #if 0 syslogmsg = p; @@ -60,29 +59,29 @@ nxt_log_time_handler(nxt_uint_t level, nxt_log_t *log, const char *fmt, ...) p = nxt_sprintf(p, end, id, &nxt_log_levels[level], nxt_pid, nxt_thread_tid(thr), fid); #else - p = nxt_sprintf(p, end, "[%V] %PI#%PT ", &nxt_log_levels[level], nxt_pid, - nxt_thread_tid(thr)); + p = nxt_sprintf(p, end, "[%V] %PI#%PT ", &nxt_log_levels[level], nxt_pid, + nxt_thread_tid(thr)); #endif - if (log->ident != 0) { - p = nxt_sprintf(p, end, "*%D ", log->ident); - } + if (log->ident != 0) { + p = nxt_sprintf(p, end, "*%D ", log->ident); + } - va_start(args, fmt); - p = nxt_vsprintf(p, end, fmt, args); - va_end(args); + va_start(args, fmt); + p = nxt_vsprintf(p, end, fmt, args); + va_end(args); - if (level != NXT_LOG_DEBUG && log->ctx_handler != NULL) { - p = log->ctx_handler(log->ctx, p, end); - } + if (level != NXT_LOG_DEBUG && log->ctx_handler != NULL) { + p = log->ctx_handler(log->ctx, p, end); + } - if (p > end - nxt_length("\n")) { - p = end - nxt_length("\n"); - } + if (p > end - nxt_length("\n")) { + p = end - nxt_length("\n"); + } - *p++ = '\n'; + *p++ = '\n'; - (void) nxt_write_console(nxt_stderr, msg, p - msg); + (void)nxt_write_console(nxt_stderr, msg, p - msg); #if 0 if (level == NXT_LOG_ALERT) { @@ -97,29 +96,22 @@ nxt_log_time_handler(nxt_uint_t level, nxt_log_t *log, const char *fmt, ...) #endif } - -static nxt_time_string_t nxt_log_error_time_cache = { - (nxt_atomic_uint_t) -1, - nxt_log_error_time, - "%4d/%02d/%02d %02d:%02d:%02d ", - nxt_length("1970/09/28 12:00:00 "), - NXT_THREAD_TIME_LOCAL, - NXT_THREAD_TIME_SEC, +static nxt_time_string_t nxt_log_error_time_cache = { + (nxt_atomic_uint_t)-1, nxt_log_error_time, + "%4d/%02d/%02d %02d:%02d:%02d ", nxt_length("1970/09/28 12:00:00 "), + NXT_THREAD_TIME_LOCAL, NXT_THREAD_TIME_SEC, }; - -static u_char * -nxt_log_error_time(u_char *buf, nxt_realtime_t *now, struct tm *tm, size_t size, - const char *format) -{ - return nxt_sprintf(buf, buf + size, format, - tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday, - tm->tm_hour, tm->tm_min, tm->tm_sec); +static u_char *nxt_log_error_time(u_char *buf, nxt_realtime_t *now, + struct tm *tm, size_t size, + const char *format) { + return nxt_sprintf(buf, buf + size, format, tm->tm_year + 1900, + tm->tm_mon + 1, tm->tm_mday, tm->tm_hour, tm->tm_min, + tm->tm_sec); } - -static nxt_time_string_t nxt_log_debug_time_cache = { - (nxt_atomic_uint_t) -1, +static nxt_time_string_t nxt_log_debug_time_cache = { + (nxt_atomic_uint_t)-1, nxt_log_debug_time, "%4d/%02d/%02d %02d:%02d:%02d.%03d ", nxt_length("1970/09/28 12:00:00.000 "), @@ -127,13 +119,10 @@ static nxt_time_string_t nxt_log_debug_time_cache = { NXT_THREAD_TIME_MSEC, }; - -static u_char * -nxt_log_debug_time(u_char *buf, nxt_realtime_t *now, struct tm *tm, size_t size, - const char *format) -{ - return nxt_sprintf(buf, buf + size, format, - tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday, - tm->tm_hour, tm->tm_min, tm->tm_sec, - now->nsec / 1000000); +static u_char *nxt_log_debug_time(u_char *buf, nxt_realtime_t *now, + struct tm *tm, size_t size, + const char *format) { + return nxt_sprintf(buf, buf + size, format, tm->tm_year + 1900, + tm->tm_mon + 1, tm->tm_mday, tm->tm_hour, tm->tm_min, + tm->tm_sec, now->nsec / 1000000); } diff --git a/src/nxt_app_nncq.h b/src/nxt_app_nncq.h index f9b8ce0c8..1eb617ff7 100644 --- a/src/nxt_app_nncq.h +++ b/src/nxt_app_nncq.h @@ -6,160 +6,131 @@ #ifndef _NXT_APP_NNCQ_H_INCLUDED_ #define _NXT_APP_NNCQ_H_INCLUDED_ - /* Appilcation Numeric Naive Circular Queue */ -#define NXT_APP_NNCQ_SIZE 131072 +#define NXT_APP_NNCQ_SIZE 131072 typedef uint32_t nxt_app_nncq_atomic_t; typedef uint16_t nxt_app_nncq_cycle_t; typedef struct { - nxt_app_nncq_atomic_t head; - nxt_app_nncq_atomic_t entries[NXT_APP_NNCQ_SIZE]; - nxt_app_nncq_atomic_t tail; + nxt_app_nncq_atomic_t head; + nxt_app_nncq_atomic_t entries[NXT_APP_NNCQ_SIZE]; + nxt_app_nncq_atomic_t tail; } nxt_app_nncq_t; - static inline nxt_app_nncq_atomic_t -nxt_app_nncq_head(nxt_app_nncq_t const volatile *q) -{ - return q->head; +nxt_app_nncq_head(nxt_app_nncq_t const volatile *q) { + return q->head; } - static inline nxt_app_nncq_atomic_t -nxt_app_nncq_tail(nxt_app_nncq_t const volatile *q) -{ - return q->tail; +nxt_app_nncq_tail(nxt_app_nncq_t const volatile *q) { + return q->tail; } - -static inline void -nxt_app_nncq_tail_cmp_inc(nxt_app_nncq_t volatile *q, nxt_app_nncq_atomic_t t) -{ - nxt_atomic_cmp_set(&q->tail, t, t + 1); +static inline void nxt_app_nncq_tail_cmp_inc(nxt_app_nncq_t volatile *q, + nxt_app_nncq_atomic_t t) { + nxt_atomic_cmp_set(&q->tail, t, t + 1); } - static inline nxt_app_nncq_atomic_t -nxt_app_nncq_index(nxt_app_nncq_t const volatile *q, nxt_app_nncq_atomic_t i) -{ - return i % NXT_APP_NNCQ_SIZE; +nxt_app_nncq_index(nxt_app_nncq_t const volatile *q, nxt_app_nncq_atomic_t i) { + return i % NXT_APP_NNCQ_SIZE; } - static inline nxt_app_nncq_atomic_t -nxt_app_nncq_map(nxt_app_nncq_t const volatile *q, nxt_app_nncq_atomic_t i) -{ - return i % NXT_APP_NNCQ_SIZE; +nxt_app_nncq_map(nxt_app_nncq_t const volatile *q, nxt_app_nncq_atomic_t i) { + return i % NXT_APP_NNCQ_SIZE; } - static inline nxt_app_nncq_cycle_t -nxt_app_nncq_cycle(nxt_app_nncq_t const volatile *q, nxt_app_nncq_atomic_t i) -{ - return i / NXT_APP_NNCQ_SIZE; +nxt_app_nncq_cycle(nxt_app_nncq_t const volatile *q, nxt_app_nncq_atomic_t i) { + return i / NXT_APP_NNCQ_SIZE; } - static inline nxt_app_nncq_cycle_t nxt_app_nncq_next_cycle(nxt_app_nncq_t const volatile *q, - nxt_app_nncq_cycle_t i) -{ - return i + 1; + nxt_app_nncq_cycle_t i) { + return i + 1; } - static inline nxt_app_nncq_atomic_t nxt_app_nncq_new_entry(nxt_app_nncq_t const volatile *q, - nxt_app_nncq_cycle_t cycle, - nxt_app_nncq_atomic_t i) -{ - return cycle * NXT_APP_NNCQ_SIZE + (i % NXT_APP_NNCQ_SIZE); + nxt_app_nncq_cycle_t cycle, nxt_app_nncq_atomic_t i) { + return cycle * NXT_APP_NNCQ_SIZE + (i % NXT_APP_NNCQ_SIZE); } - static inline nxt_app_nncq_atomic_t -nxt_app_nncq_empty(nxt_app_nncq_t const volatile *q) -{ - return NXT_APP_NNCQ_SIZE; +nxt_app_nncq_empty(nxt_app_nncq_t const volatile *q) { + return NXT_APP_NNCQ_SIZE; } - -static void -nxt_app_nncq_init(nxt_app_nncq_t volatile *q) -{ - q->head = NXT_APP_NNCQ_SIZE; - nxt_memzero((void *) q->entries, - NXT_APP_NNCQ_SIZE * sizeof(nxt_app_nncq_atomic_t)); - q->tail = NXT_APP_NNCQ_SIZE; +static void nxt_app_nncq_init(nxt_app_nncq_t volatile *q) { + q->head = NXT_APP_NNCQ_SIZE; + nxt_memzero((void *)q->entries, + NXT_APP_NNCQ_SIZE * sizeof(nxt_app_nncq_atomic_t)); + q->tail = NXT_APP_NNCQ_SIZE; } +static void nxt_app_nncq_enqueue(nxt_app_nncq_t volatile *q, + nxt_app_nncq_atomic_t val) { + nxt_app_nncq_cycle_t e_cycle, t_cycle; + nxt_app_nncq_atomic_t n, t, e, j; -static void -nxt_app_nncq_enqueue(nxt_app_nncq_t volatile *q, nxt_app_nncq_atomic_t val) -{ - nxt_app_nncq_cycle_t e_cycle, t_cycle; - nxt_app_nncq_atomic_t n, t, e, j; + for (;;) { + t = nxt_app_nncq_tail(q); + j = nxt_app_nncq_map(q, t); + e = q->entries[j]; - for ( ;; ) { - t = nxt_app_nncq_tail(q); - j = nxt_app_nncq_map(q, t); - e = q->entries[j]; + e_cycle = nxt_app_nncq_cycle(q, e); + t_cycle = nxt_app_nncq_cycle(q, t); - e_cycle = nxt_app_nncq_cycle(q, e); - t_cycle = nxt_app_nncq_cycle(q, t); - - if (e_cycle == t_cycle) { - nxt_app_nncq_tail_cmp_inc(q, t); - continue; - } + if (e_cycle == t_cycle) { + nxt_app_nncq_tail_cmp_inc(q, t); + continue; + } - if (nxt_app_nncq_next_cycle(q, e_cycle) != t_cycle) { - continue; - } + if (nxt_app_nncq_next_cycle(q, e_cycle) != t_cycle) { + continue; + } - n = nxt_app_nncq_new_entry(q, t_cycle, val); + n = nxt_app_nncq_new_entry(q, t_cycle, val); - if (nxt_atomic_cmp_set(&q->entries[j], e, n)) { - break; - } + if (nxt_atomic_cmp_set(&q->entries[j], e, n)) { + break; } + } - nxt_app_nncq_tail_cmp_inc(q, t); + nxt_app_nncq_tail_cmp_inc(q, t); } +static nxt_app_nncq_atomic_t nxt_app_nncq_dequeue(nxt_app_nncq_t volatile *q) { + nxt_app_nncq_cycle_t e_cycle, h_cycle; + nxt_app_nncq_atomic_t h, j, e; -static nxt_app_nncq_atomic_t -nxt_app_nncq_dequeue(nxt_app_nncq_t volatile *q) -{ - nxt_app_nncq_cycle_t e_cycle, h_cycle; - nxt_app_nncq_atomic_t h, j, e; - - for ( ;; ) { - h = nxt_app_nncq_head(q); - j = nxt_app_nncq_map(q, h); - e = q->entries[j]; + for (;;) { + h = nxt_app_nncq_head(q); + j = nxt_app_nncq_map(q, h); + e = q->entries[j]; - e_cycle = nxt_app_nncq_cycle(q, e); - h_cycle = nxt_app_nncq_cycle(q, h); + e_cycle = nxt_app_nncq_cycle(q, e); + h_cycle = nxt_app_nncq_cycle(q, h); - if (e_cycle != h_cycle) { - if (nxt_app_nncq_next_cycle(q, e_cycle) == h_cycle) { - return nxt_app_nncq_empty(q); - } + if (e_cycle != h_cycle) { + if (nxt_app_nncq_next_cycle(q, e_cycle) == h_cycle) { + return nxt_app_nncq_empty(q); + } - continue; - } + continue; + } - if (nxt_atomic_cmp_set(&q->head, h, h + 1)) { - break; - } + if (nxt_atomic_cmp_set(&q->head, h, h + 1)) { + break; } + } - return nxt_app_nncq_index(q, e); + return nxt_app_nncq_index(q, e); } - #endif /* _NXT_APP_NNCQ_H_INCLUDED_ */ diff --git a/src/nxt_app_queue.h b/src/nxt_app_queue.h index a1cc2f11d..56d1879a3 100644 --- a/src/nxt_app_queue.h +++ b/src/nxt_app_queue.h @@ -6,120 +6,105 @@ #ifndef _NXT_APP_QUEUE_H_INCLUDED_ #define _NXT_APP_QUEUE_H_INCLUDED_ - #include - /* Using Numeric Naive Circular Queue as a backend. */ -#define NXT_APP_QUEUE_SIZE NXT_APP_NNCQ_SIZE -#define NXT_APP_QUEUE_MSG_SIZE 31 +#define NXT_APP_QUEUE_SIZE NXT_APP_NNCQ_SIZE +#define NXT_APP_QUEUE_MSG_SIZE 31 typedef struct { - uint8_t size; - uint8_t data[NXT_APP_QUEUE_MSG_SIZE]; - uint32_t tracking; + uint8_t size; + uint8_t data[NXT_APP_QUEUE_MSG_SIZE]; + uint32_t tracking; } nxt_app_queue_item_t; - typedef struct { - nxt_app_nncq_atomic_t notified; - nxt_app_nncq_t free_items; - nxt_app_nncq_t queue; - nxt_app_queue_item_t items[NXT_APP_QUEUE_SIZE]; + nxt_app_nncq_atomic_t notified; + nxt_app_nncq_t free_items; + nxt_app_nncq_t queue; + nxt_app_queue_item_t items[NXT_APP_QUEUE_SIZE]; } nxt_app_queue_t; +nxt_inline void nxt_app_queue_init(nxt_app_queue_t volatile *q) { + nxt_app_nncq_atomic_t i; -nxt_inline void -nxt_app_queue_init(nxt_app_queue_t volatile *q) -{ - nxt_app_nncq_atomic_t i; - - nxt_app_nncq_init(&q->free_items); - nxt_app_nncq_init(&q->queue); + nxt_app_nncq_init(&q->free_items); + nxt_app_nncq_init(&q->queue); - for (i = 0; i < NXT_APP_QUEUE_SIZE; i++) { - nxt_app_nncq_enqueue(&q->free_items, i); - } + for (i = 0; i < NXT_APP_QUEUE_SIZE; i++) { + nxt_app_nncq_enqueue(&q->free_items, i); + } - q->notified = 0; + q->notified = 0; } +nxt_inline nxt_int_t nxt_app_queue_send(nxt_app_queue_t volatile *q, + const void *p, uint8_t size, + uint32_t tracking, int *notify, + uint32_t *cookie) { + int n; + nxt_app_queue_item_t *qi; + nxt_app_nncq_atomic_t i; -nxt_inline nxt_int_t -nxt_app_queue_send(nxt_app_queue_t volatile *q, const void *p, - uint8_t size, uint32_t tracking, int *notify, uint32_t *cookie) -{ - int n; - nxt_app_queue_item_t *qi; - nxt_app_nncq_atomic_t i; + i = nxt_app_nncq_dequeue(&q->free_items); + if (i == nxt_app_nncq_empty(&q->free_items)) { + return NXT_AGAIN; + } - i = nxt_app_nncq_dequeue(&q->free_items); - if (i == nxt_app_nncq_empty(&q->free_items)) { - return NXT_AGAIN; - } + qi = (nxt_app_queue_item_t *)&q->items[i]; - qi = (nxt_app_queue_item_t *) &q->items[i]; + qi->size = size; + nxt_memcpy(qi->data, p, size); + qi->tracking = tracking; + *cookie = i; - qi->size = size; - nxt_memcpy(qi->data, p, size); - qi->tracking = tracking; - *cookie = i; + nxt_app_nncq_enqueue(&q->queue, i); - nxt_app_nncq_enqueue(&q->queue, i); + n = nxt_atomic_cmp_set(&q->notified, 0, 1); - n = nxt_atomic_cmp_set(&q->notified, 0, 1); + if (notify != NULL) { + *notify = n; + } - if (notify != NULL) { - *notify = n; - } - - return NXT_OK; + return NXT_OK; } - nxt_inline void -nxt_app_queue_notification_received(nxt_app_queue_t volatile *q) -{ - q->notified = 0; +nxt_app_queue_notification_received(nxt_app_queue_t volatile *q) { + q->notified = 0; } +nxt_inline nxt_bool_t nxt_app_queue_cancel(nxt_app_queue_t volatile *q, + uint32_t cookie, uint32_t tracking) { + nxt_app_queue_item_t *qi; -nxt_inline nxt_bool_t -nxt_app_queue_cancel(nxt_app_queue_t volatile *q, uint32_t cookie, - uint32_t tracking) -{ - nxt_app_queue_item_t *qi; - - qi = (nxt_app_queue_item_t *) &q->items[cookie]; + qi = (nxt_app_queue_item_t *)&q->items[cookie]; - return nxt_atomic_cmp_set(&qi->tracking, tracking, 0); + return nxt_atomic_cmp_set(&qi->tracking, tracking, 0); } +nxt_inline ssize_t nxt_app_queue_recv(nxt_app_queue_t volatile *q, void *p, + uint32_t *cookie) { + ssize_t res; + nxt_app_queue_item_t *qi; + nxt_app_nncq_atomic_t i; -nxt_inline ssize_t -nxt_app_queue_recv(nxt_app_queue_t volatile *q, void *p, uint32_t *cookie) -{ - ssize_t res; - nxt_app_queue_item_t *qi; - nxt_app_nncq_atomic_t i; + i = nxt_app_nncq_dequeue(&q->queue); + if (i == nxt_app_nncq_empty(&q->queue)) { + *cookie = 0; + return -1; + } - i = nxt_app_nncq_dequeue(&q->queue); - if (i == nxt_app_nncq_empty(&q->queue)) { - *cookie = 0; - return -1; - } + qi = (nxt_app_queue_item_t *)&q->items[i]; - qi = (nxt_app_queue_item_t *) &q->items[i]; + res = qi->size; + nxt_memcpy(p, qi->data, qi->size); + *cookie = i; - res = qi->size; - nxt_memcpy(p, qi->data, qi->size); - *cookie = i; + nxt_app_nncq_enqueue(&q->free_items, i); - nxt_app_nncq_enqueue(&q->free_items, i); - - return res; + return res; } - #endif /* _NXT_APP_QUEUE_H_INCLUDED_ */ diff --git a/src/nxt_application.c b/src/nxt_application.c index 629aa11c4..441e2ca60 100644 --- a/src/nxt_application.c +++ b/src/nxt_application.c @@ -22,43 +22,40 @@ #include #endif - #ifdef WCOREDUMP #define NXT_WCOREDUMP(s) WCOREDUMP(s) #else #define NXT_WCOREDUMP(s) 0 #endif - typedef struct { - nxt_app_type_t type; - nxt_str_t name; - nxt_str_t version; - nxt_str_t file; - nxt_array_t *mounts; + nxt_app_type_t type; + nxt_str_t name; + nxt_str_t version; + nxt_str_t file; + nxt_array_t *mounts; } nxt_module_t; - static nxt_int_t nxt_discovery_start(nxt_task_t *task, - nxt_process_data_t *data); + nxt_process_data_t *data); static nxt_buf_t *nxt_discovery_modules(nxt_task_t *task, const char *path); static nxt_int_t nxt_discovery_module(nxt_task_t *task, nxt_mp_t *mp, - nxt_array_t *modules, const char *name); + nxt_array_t *modules, const char *name); static void nxt_discovery_completion_handler(nxt_task_t *task, void *obj, - void *data); + void *data); static void nxt_discovery_quit(nxt_task_t *task, nxt_port_recv_msg_t *msg, - void *data); + void *data); static nxt_app_module_t *nxt_app_module_load(nxt_task_t *task, - const char *name); + const char *name); static nxt_int_t nxt_proto_setup(nxt_task_t *task, nxt_process_t *process); static nxt_int_t nxt_proto_start(nxt_task_t *task, nxt_process_data_t *data); static nxt_int_t nxt_app_setup(nxt_task_t *task, nxt_process_t *process); static nxt_int_t nxt_app_set_environment(nxt_conf_value_t *environment); static void nxt_proto_start_process_handler(nxt_task_t *task, - nxt_port_recv_msg_t *msg); + nxt_port_recv_msg_t *msg); static void nxt_proto_quit_handler(nxt_task_t *task, nxt_port_recv_msg_t *msg); static void nxt_proto_process_created_handler(nxt_task_t *task, - nxt_port_recv_msg_t *msg); + nxt_port_recv_msg_t *msg); static void nxt_proto_quit_children(nxt_task_t *task); static nxt_process_t *nxt_proto_process_find(nxt_task_t *task, nxt_pid_t pid); static void nxt_proto_process_add(nxt_task_t *task, nxt_process_t *process); @@ -68,1229 +65,1134 @@ static void nxt_proto_signal_handler(nxt_task_t *task, void *obj, void *data); static void nxt_proto_sigterm_handler(nxt_task_t *task, void *obj, void *data); static void nxt_proto_sigchld_handler(nxt_task_t *task, void *obj, void *data); +nxt_str_t nxt_server = nxt_string(NXT_SERVER); -nxt_str_t nxt_server = nxt_string(NXT_SERVER); - - -static uint32_t compat[] = { - NXT_VERNUM, NXT_DEBUG, +static uint32_t compat[] = { + NXT_VERNUM, + NXT_DEBUG, }; - -static nxt_lvlhsh_t nxt_proto_processes; -static nxt_queue_t nxt_proto_children; -static nxt_bool_t nxt_proto_exiting; - -static nxt_app_module_t *nxt_app; -static nxt_common_app_conf_t *nxt_app_conf; - - -static const nxt_port_handlers_t nxt_discovery_process_port_handlers = { - .quit = nxt_signal_quit_handler, - .new_port = nxt_port_new_port_handler, - .change_file = nxt_port_change_log_file_handler, - .mmap = nxt_port_mmap_handler, - .data = nxt_port_data_handler, - .remove_pid = nxt_port_remove_pid_handler, - .rpc_ready = nxt_port_rpc_handler, - .rpc_error = nxt_port_rpc_handler, +static nxt_lvlhsh_t nxt_proto_processes; +static nxt_queue_t nxt_proto_children; +static nxt_bool_t nxt_proto_exiting; + +static nxt_app_module_t *nxt_app; +static nxt_common_app_conf_t *nxt_app_conf; + +static const nxt_port_handlers_t nxt_discovery_process_port_handlers = { + .quit = nxt_signal_quit_handler, + .new_port = nxt_port_new_port_handler, + .change_file = nxt_port_change_log_file_handler, + .mmap = nxt_port_mmap_handler, + .data = nxt_port_data_handler, + .remove_pid = nxt_port_remove_pid_handler, + .rpc_ready = nxt_port_rpc_handler, + .rpc_error = nxt_port_rpc_handler, }; - -const nxt_sig_event_t nxt_prototype_signals[] = { - nxt_event_signal(SIGHUP, nxt_proto_signal_handler), - nxt_event_signal(SIGINT, nxt_proto_sigterm_handler), +const nxt_sig_event_t nxt_prototype_signals[] = { + nxt_event_signal(SIGHUP, nxt_proto_signal_handler), + nxt_event_signal(SIGINT, nxt_proto_sigterm_handler), nxt_event_signal(SIGQUIT, nxt_proto_sigterm_handler), nxt_event_signal(SIGTERM, nxt_proto_sigterm_handler), nxt_event_signal(SIGCHLD, nxt_proto_sigchld_handler), nxt_event_signal_end, }; - -static const nxt_port_handlers_t nxt_proto_process_port_handlers = { - .quit = nxt_proto_quit_handler, - .change_file = nxt_port_change_log_file_handler, - .new_port = nxt_port_new_port_handler, +static const nxt_port_handlers_t nxt_proto_process_port_handlers = { + .quit = nxt_proto_quit_handler, + .change_file = nxt_port_change_log_file_handler, + .new_port = nxt_port_new_port_handler, .process_created = nxt_proto_process_created_handler, - .process_ready = nxt_port_process_ready_handler, - .remove_pid = nxt_port_remove_pid_handler, - .start_process = nxt_proto_start_process_handler, - .rpc_ready = nxt_port_rpc_handler, - .rpc_error = nxt_port_rpc_handler, + .process_ready = nxt_port_process_ready_handler, + .remove_pid = nxt_port_remove_pid_handler, + .start_process = nxt_proto_start_process_handler, + .rpc_ready = nxt_port_rpc_handler, + .rpc_error = nxt_port_rpc_handler, }; - -static const nxt_port_handlers_t nxt_app_process_port_handlers = { - .quit = nxt_signal_quit_handler, - .rpc_ready = nxt_port_rpc_handler, - .rpc_error = nxt_port_rpc_handler, +static const nxt_port_handlers_t nxt_app_process_port_handlers = { + .quit = nxt_signal_quit_handler, + .rpc_ready = nxt_port_rpc_handler, + .rpc_error = nxt_port_rpc_handler, }; - -const nxt_process_init_t nxt_discovery_process = { - .name = "discovery", - .type = NXT_PROCESS_DISCOVERY, - .prefork = NULL, - .restart = 0, - .setup = nxt_process_core_setup, - .start = nxt_discovery_start, - .port_handlers = &nxt_discovery_process_port_handlers, - .signals = nxt_process_signals, +const nxt_process_init_t nxt_discovery_process = { + .name = "discovery", + .type = NXT_PROCESS_DISCOVERY, + .prefork = NULL, + .restart = 0, + .setup = nxt_process_core_setup, + .start = nxt_discovery_start, + .port_handlers = &nxt_discovery_process_port_handlers, + .signals = nxt_process_signals, }; - -const nxt_process_init_t nxt_proto_process = { - .type = NXT_PROCESS_PROTOTYPE, - .prefork = nxt_isolation_main_prefork, - .restart = 0, - .setup = nxt_proto_setup, - .start = nxt_proto_start, - .port_handlers = &nxt_proto_process_port_handlers, - .signals = nxt_prototype_signals, +const nxt_process_init_t nxt_proto_process = { + .type = NXT_PROCESS_PROTOTYPE, + .prefork = nxt_isolation_main_prefork, + .restart = 0, + .setup = nxt_proto_setup, + .start = nxt_proto_start, + .port_handlers = &nxt_proto_process_port_handlers, + .signals = nxt_prototype_signals, }; - -const nxt_process_init_t nxt_app_process = { - .type = NXT_PROCESS_APP, - .setup = nxt_app_setup, - .start = NULL, - .prefork = NULL, - .restart = 0, - .port_handlers = &nxt_app_process_port_handlers, - .signals = nxt_process_signals, +const nxt_process_init_t nxt_app_process = { + .type = NXT_PROCESS_APP, + .setup = nxt_app_setup, + .start = NULL, + .prefork = NULL, + .restart = 0, + .port_handlers = &nxt_app_process_port_handlers, + .signals = nxt_process_signals, }; +static nxt_int_t nxt_discovery_start(nxt_task_t *task, + nxt_process_data_t *data) { + uint32_t stream; + nxt_buf_t *b; + nxt_int_t ret; + nxt_port_t *main_port, *discovery_port; + nxt_runtime_t *rt; -static nxt_int_t -nxt_discovery_start(nxt_task_t *task, nxt_process_data_t *data) -{ - uint32_t stream; - nxt_buf_t *b; - nxt_int_t ret; - nxt_port_t *main_port, *discovery_port; - nxt_runtime_t *rt; + nxt_log(task, NXT_LOG_INFO, "discovery started"); - nxt_log(task, NXT_LOG_INFO, "discovery started"); + rt = task->thread->runtime; - rt = task->thread->runtime; + b = nxt_discovery_modules(task, rt->modules); + if (nxt_slow_path(b == NULL)) { + return NXT_ERROR; + } - b = nxt_discovery_modules(task, rt->modules); - if (nxt_slow_path(b == NULL)) { - return NXT_ERROR; - } + main_port = rt->port_by_type[NXT_PROCESS_MAIN]; + discovery_port = rt->port_by_type[NXT_PROCESS_DISCOVERY]; - main_port = rt->port_by_type[NXT_PROCESS_MAIN]; - discovery_port = rt->port_by_type[NXT_PROCESS_DISCOVERY]; + stream = + nxt_port_rpc_register_handler(task, discovery_port, nxt_discovery_quit, + nxt_discovery_quit, main_port->pid, NULL); - stream = nxt_port_rpc_register_handler(task, discovery_port, - nxt_discovery_quit, - nxt_discovery_quit, - main_port->pid, NULL); + if (nxt_slow_path(stream == 0)) { + return NXT_ERROR; + } - if (nxt_slow_path(stream == 0)) { - return NXT_ERROR; - } + ret = nxt_port_socket_write(task, main_port, NXT_PORT_MSG_MODULES, -1, stream, + discovery_port->id, b); - ret = nxt_port_socket_write(task, main_port, NXT_PORT_MSG_MODULES, -1, - stream, discovery_port->id, b); + if (nxt_slow_path(ret != NXT_OK)) { + nxt_port_rpc_cancel(task, discovery_port, stream); + return NXT_ERROR; + } - if (nxt_slow_path(ret != NXT_OK)) { - nxt_port_rpc_cancel(task, discovery_port, stream); - return NXT_ERROR; - } - - return NXT_OK; + return NXT_OK; } +static nxt_buf_t *nxt_discovery_modules(nxt_task_t *task, const char *path) { + char *name; + u_char *p, *end; + size_t size; + glob_t glb; + nxt_mp_t *mp; + nxt_buf_t *b; + nxt_int_t ret; + nxt_uint_t i, n, j; + nxt_array_t *modules, *mounts; + nxt_module_t *module; + nxt_fs_mount_t *mnt; + + b = NULL; + + mp = nxt_mp_create(1024, 128, 256, 32); + if (mp == NULL) { + return b; + } -static nxt_buf_t * -nxt_discovery_modules(nxt_task_t *task, const char *path) -{ - char *name; - u_char *p, *end; - size_t size; - glob_t glb; - nxt_mp_t *mp; - nxt_buf_t *b; - nxt_int_t ret; - nxt_uint_t i, n, j; - nxt_array_t *modules, *mounts; - nxt_module_t *module; - nxt_fs_mount_t *mnt; - - b = NULL; - - mp = nxt_mp_create(1024, 128, 256, 32); - if (mp == NULL) { - return b; - } - - ret = glob(path, 0, NULL, &glb); + ret = glob(path, 0, NULL, &glb); - n = glb.gl_pathc; + n = glb.gl_pathc; - if (ret != 0) { - nxt_log(task, NXT_LOG_NOTICE, - "no modules matching: \"%s\" found", path); - n = 0; - } + if (ret != 0) { + nxt_log(task, NXT_LOG_NOTICE, "no modules matching: \"%s\" found", path); + n = 0; + } - modules = nxt_array_create(mp, n, sizeof(nxt_module_t)); - if (modules == NULL) { - goto fail; - } + modules = nxt_array_create(mp, n, sizeof(nxt_module_t)); + if (modules == NULL) { + goto fail; + } - for (i = 0; i < n; i++) { - name = glb.gl_pathv[i]; + for (i = 0; i < n; i++) { + name = glb.gl_pathv[i]; - ret = nxt_discovery_module(task, mp, modules, name); - if (ret != NXT_OK) { - goto fail; - } + ret = nxt_discovery_module(task, mp, modules, name); + if (ret != NXT_OK) { + goto fail; } + } - size = nxt_length("[]"); - module = modules->elts; - n = modules->nelts; + size = nxt_length("[]"); + module = modules->elts; + n = modules->nelts; - for (i = 0; i < n; i++) { - nxt_debug(task, "module: %d %V %V", - module[i].type, &module[i].version, &module[i].file); + for (i = 0; i < n; i++) { + nxt_debug(task, "module: %d %V %V", module[i].type, &module[i].version, + &module[i].file); - size += nxt_length("{\"type\": ,"); - size += nxt_length(" \"name\": \"\","); - size += nxt_length(" \"version\": \"\","); - size += nxt_length(" \"file\": \"\","); - size += nxt_length(" \"mounts\": []},"); + size += nxt_length("{\"type\": ,"); + size += nxt_length(" \"name\": \"\","); + size += nxt_length(" \"version\": \"\","); + size += nxt_length(" \"file\": \"\","); + size += nxt_length(" \"mounts\": []},"); - size += NXT_INT_T_LEN - + module[i].version.length - + module[i].name.length - + module[i].file.length; + size += NXT_INT_T_LEN + module[i].version.length + module[i].name.length + + module[i].file.length; - mounts = module[i].mounts; + mounts = module[i].mounts; - size += mounts->nelts * nxt_length("{\"src\": \"\", \"dst\": \"\", " - "\"type\": , \"name\": \"\", " - "\"flags\": , \"data\": \"\"},"); + size += mounts->nelts * nxt_length("{\"src\": \"\", \"dst\": \"\", " + "\"type\": , \"name\": \"\", " + "\"flags\": , \"data\": \"\"},"); - mnt = mounts->elts; + mnt = mounts->elts; - for (j = 0; j < mounts->nelts; j++) { - size += nxt_strlen(mnt[j].src) + nxt_strlen(mnt[j].dst) - + nxt_strlen(mnt[j].name) + (2 * NXT_INT_T_LEN) - + (mnt[j].data == NULL ? 0 : nxt_strlen(mnt[j].data)); - } + for (j = 0; j < mounts->nelts; j++) { + size += nxt_strlen(mnt[j].src) + nxt_strlen(mnt[j].dst) + + nxt_strlen(mnt[j].name) + (2 * NXT_INT_T_LEN) + + (mnt[j].data == NULL ? 0 : nxt_strlen(mnt[j].data)); } - - b = nxt_buf_mem_alloc(mp, size, 0); - if (b == NULL) { - goto fail; - } - - b->completion_handler = nxt_discovery_completion_handler; - - p = b->mem.free; - end = b->mem.end; - *p++ = '['; - - for (i = 0; i < n; i++) { - mounts = module[i].mounts; - - p = nxt_sprintf(p, end, "{\"type\": %d, \"name\": \"%V\", " - "\"version\": \"%V\", \"file\": \"%V\", \"mounts\": [", - module[i].type, &module[i].name, &module[i].version, - &module[i].file); - - mnt = mounts->elts; - for (j = 0; j < mounts->nelts; j++) { - p = nxt_sprintf(p, end, - "{\"src\": \"%s\", \"dst\": \"%s\", " - "\"name\": \"%s\", \"type\": %d, \"flags\": %d, " - "\"data\": \"%s\"},", - mnt[j].src, mnt[j].dst, mnt[j].name, mnt[j].type, - mnt[j].flags, - mnt[j].data == NULL ? (u_char *) "" : mnt[j].data); - } - - *p++ = ']'; - *p++ = '}'; - *p++ = ','; + } + + b = nxt_buf_mem_alloc(mp, size, 0); + if (b == NULL) { + goto fail; + } + + b->completion_handler = nxt_discovery_completion_handler; + + p = b->mem.free; + end = b->mem.end; + *p++ = '['; + + for (i = 0; i < n; i++) { + mounts = module[i].mounts; + + p = nxt_sprintf(p, end, + "{\"type\": %d, \"name\": \"%V\", " + "\"version\": \"%V\", \"file\": \"%V\", \"mounts\": [", + module[i].type, &module[i].name, &module[i].version, + &module[i].file); + + mnt = mounts->elts; + for (j = 0; j < mounts->nelts; j++) { + p = nxt_sprintf(p, end, + "{\"src\": \"%s\", \"dst\": \"%s\", " + "\"name\": \"%s\", \"type\": %d, \"flags\": %d, " + "\"data\": \"%s\"},", + mnt[j].src, mnt[j].dst, mnt[j].name, mnt[j].type, + mnt[j].flags, + mnt[j].data == NULL ? (u_char *)"" : mnt[j].data); } *p++ = ']'; + *p++ = '}'; + *p++ = ','; + } - if (nxt_slow_path(p > end)) { - nxt_alert(task, "discovery write past the buffer"); - goto fail; - } + *p++ = ']'; + + if (nxt_slow_path(p > end)) { + nxt_alert(task, "discovery write past the buffer"); + goto fail; + } - b->mem.free = p; + b->mem.free = p; fail: - globfree(&glb); + globfree(&glb); - return b; + return b; } +static nxt_int_t nxt_discovery_module(nxt_task_t *task, nxt_mp_t *mp, + nxt_array_t *modules, const char *name) { + void *dl; + nxt_str_t version; + nxt_int_t ret; + nxt_uint_t i, j, n; + nxt_array_t *mounts; + nxt_module_t *module; + nxt_app_type_t type; + nxt_fs_mount_t *to; + nxt_app_module_t *app; + const nxt_fs_mount_t *from; + + /* + * Only memory allocation failure should return NXT_ERROR. + * Any module processing errors are ignored. + */ + ret = NXT_ERROR; + + dl = dlopen(name, RTLD_GLOBAL | RTLD_NOW); + + if (dl == NULL) { + nxt_alert(task, "dlopen(\"%s\"), failed: \"%s\"", name, dlerror()); + return NXT_OK; + } -static nxt_int_t -nxt_discovery_module(nxt_task_t *task, nxt_mp_t *mp, nxt_array_t *modules, - const char *name) -{ - void *dl; - nxt_str_t version; - nxt_int_t ret; - nxt_uint_t i, j, n; - nxt_array_t *mounts; - nxt_module_t *module; - nxt_app_type_t type; - nxt_fs_mount_t *to; - nxt_app_module_t *app; - const nxt_fs_mount_t *from; + app = dlsym(dl, "nxt_app_module"); - /* - * Only memory allocation failure should return NXT_ERROR. - * Any module processing errors are ignored. - */ - ret = NXT_ERROR; + if (app != NULL) { + nxt_log(task, NXT_LOG_NOTICE, "module: %V %s \"%s\"", &app->type, + app->version, name); - dl = dlopen(name, RTLD_GLOBAL | RTLD_NOW); + if (app->compat_length != sizeof(compat) || + memcmp(app->compat, compat, sizeof(compat)) != 0) { + nxt_log(task, NXT_LOG_NOTICE, "incompatible module %s", name); - if (dl == NULL) { - nxt_alert(task, "dlopen(\"%s\"), failed: \"%s\"", name, dlerror()); - return NXT_OK; + goto done; } - app = dlsym(dl, "nxt_app_module"); - - if (app != NULL) { - nxt_log(task, NXT_LOG_NOTICE, "module: %V %s \"%s\"", - &app->type, app->version, name); - - if (app->compat_length != sizeof(compat) - || memcmp(app->compat, compat, sizeof(compat)) != 0) - { - nxt_log(task, NXT_LOG_NOTICE, "incompatible module %s", name); - - goto done; - } - - type = nxt_app_parse_type(app->type.start, app->type.length); - - if (type == NXT_APP_UNKNOWN) { - nxt_log(task, NXT_LOG_NOTICE, "unknown module type %V", &app->type); + type = nxt_app_parse_type(app->type.start, app->type.length); - goto done; - } + if (type == NXT_APP_UNKNOWN) { + nxt_log(task, NXT_LOG_NOTICE, "unknown module type %V", &app->type); - module = modules->elts; - n = modules->nelts; + goto done; + } - version.start = (u_char *) app->version; - version.length = nxt_strlen(app->version); + module = modules->elts; + n = modules->nelts; - for (i = 0; i < n; i++) { - if (type == module[i].type - && nxt_strstr_eq(&module[i].version, &version)) - { - nxt_log(task, NXT_LOG_NOTICE, - "ignoring %s module with the same " - "application language version %V %V as in %V", - name, &app->type, &version, &module[i].file); + version.start = (u_char *)app->version; + version.length = nxt_strlen(app->version); - goto done; - } - } + for (i = 0; i < n; i++) { + if (type == module[i].type && + nxt_strstr_eq(&module[i].version, &version)) { + nxt_log(task, NXT_LOG_NOTICE, + "ignoring %s module with the same " + "application language version %V %V as in %V", + name, &app->type, &version, &module[i].file); - module = nxt_array_add(modules); - if (module == NULL) { - goto fail; - } + goto done; + } + } - module->type = type; + module = nxt_array_add(modules); + if (module == NULL) { + goto fail; + } - nxt_str_dup(mp, &module->version, &version); - if (module->version.start == NULL) { - goto fail; - } + module->type = type; - nxt_str_dup(mp, &module->name, &app->type); - if (module->name.start == NULL) { - goto fail; - } + nxt_str_dup(mp, &module->version, &version); + if (module->version.start == NULL) { + goto fail; + } - module->file.length = nxt_strlen(name); + nxt_str_dup(mp, &module->name, &app->type); + if (module->name.start == NULL) { + goto fail; + } - module->file.start = nxt_mp_alloc(mp, module->file.length); - if (module->file.start == NULL) { - goto fail; - } + module->file.length = nxt_strlen(name); - nxt_memcpy(module->file.start, name, module->file.length); + module->file.start = nxt_mp_alloc(mp, module->file.length); + if (module->file.start == NULL) { + goto fail; + } - module->mounts = nxt_array_create(mp, app->nmounts, - sizeof(nxt_fs_mount_t)); + nxt_memcpy(module->file.start, name, module->file.length); - if (nxt_slow_path(module->mounts == NULL)) { - goto fail; - } + module->mounts = nxt_array_create(mp, app->nmounts, sizeof(nxt_fs_mount_t)); - mounts = module->mounts; + if (nxt_slow_path(module->mounts == NULL)) { + goto fail; + } - for (j = 0; j < app->nmounts; j++) { - from = &app->mounts[j]; - to = nxt_array_zero_add(mounts); - if (nxt_slow_path(to == NULL)) { - goto fail; - } + mounts = module->mounts; - to->src = nxt_cstr_dup(mp, to->src, from->src); - if (nxt_slow_path(to->src == NULL)) { - goto fail; - } + for (j = 0; j < app->nmounts; j++) { + from = &app->mounts[j]; + to = nxt_array_zero_add(mounts); + if (nxt_slow_path(to == NULL)) { + goto fail; + } - to->dst = nxt_cstr_dup(mp, to->dst, from->dst); - if (nxt_slow_path(to->dst == NULL)) { - goto fail; - } + to->src = nxt_cstr_dup(mp, to->src, from->src); + if (nxt_slow_path(to->src == NULL)) { + goto fail; + } - to->name = nxt_cstr_dup(mp, to->name, from->name); - if (nxt_slow_path(to->name == NULL)) { - goto fail; - } + to->dst = nxt_cstr_dup(mp, to->dst, from->dst); + if (nxt_slow_path(to->dst == NULL)) { + goto fail; + } - to->type = from->type; + to->name = nxt_cstr_dup(mp, to->name, from->name); + if (nxt_slow_path(to->name == NULL)) { + goto fail; + } - if (from->data != NULL) { - to->data = nxt_cstr_dup(mp, to->data, from->data); - if (nxt_slow_path(to->data == NULL)) { - goto fail; - } - } + to->type = from->type; - to->flags = from->flags; + if (from->data != NULL) { + to->data = nxt_cstr_dup(mp, to->data, from->data); + if (nxt_slow_path(to->data == NULL)) { + goto fail; } + } - } else { - nxt_alert(task, "dlsym(\"%s\"), failed: \"%s\"", name, dlerror()); + to->flags = from->flags; } + } else { + nxt_alert(task, "dlsym(\"%s\"), failed: \"%s\"", name, dlerror()); + } + done: - ret = NXT_OK; + ret = NXT_OK; fail: - if (dlclose(dl) != 0) { - nxt_alert(task, "dlclose(\"%s\"), failed: \"%s\"", name, dlerror()); - } + if (dlclose(dl) != 0) { + nxt_alert(task, "dlclose(\"%s\"), failed: \"%s\"", name, dlerror()); + } - return ret; + return ret; } +static void nxt_discovery_completion_handler(nxt_task_t *task, void *obj, + void *data) { + nxt_mp_t *mp; + nxt_buf_t *b; -static void -nxt_discovery_completion_handler(nxt_task_t *task, void *obj, void *data) -{ - nxt_mp_t *mp; - nxt_buf_t *b; - - b = obj; - mp = b->data; + b = obj; + mp = b->data; - nxt_mp_destroy(mp); + nxt_mp_destroy(mp); } - -static void -nxt_discovery_quit(nxt_task_t *task, nxt_port_recv_msg_t *msg, void *data) -{ - nxt_signal_quit_handler(task, msg); +static void nxt_discovery_quit(nxt_task_t *task, nxt_port_recv_msg_t *msg, + void *data) { + nxt_signal_quit_handler(task, msg); } +static nxt_int_t nxt_proto_setup(nxt_task_t *task, nxt_process_t *process) { + nxt_int_t ret; + nxt_app_lang_module_t *lang; + nxt_common_app_conf_t *app_conf; -static nxt_int_t -nxt_proto_setup(nxt_task_t *task, nxt_process_t *process) -{ - nxt_int_t ret; - nxt_app_lang_module_t *lang; - nxt_common_app_conf_t *app_conf; - - app_conf = process->data.app; + app_conf = process->data.app; - nxt_queue_init(&nxt_proto_children); + nxt_queue_init(&nxt_proto_children); - nxt_app_conf = app_conf; + nxt_app_conf = app_conf; - lang = nxt_app_lang_module(task->thread->runtime, &app_conf->type); - if (nxt_slow_path(lang == NULL)) { - nxt_alert(task, "unknown application type: \"%V\"", &app_conf->type); - return NXT_ERROR; - } + lang = nxt_app_lang_module(task->thread->runtime, &app_conf->type); + if (nxt_slow_path(lang == NULL)) { + nxt_alert(task, "unknown application type: \"%V\"", &app_conf->type); + return NXT_ERROR; + } - nxt_app = lang->module; + nxt_app = lang->module; - if (nxt_app == NULL) { - nxt_debug(task, "application language module: %s \"%s\"", - lang->version, lang->file); + if (nxt_app == NULL) { + nxt_debug(task, "application language module: %s \"%s\"", lang->version, + lang->file); - nxt_app = nxt_app_module_load(task, lang->file); - if (nxt_slow_path(nxt_app == NULL)) { - return NXT_ERROR; - } + nxt_app = nxt_app_module_load(task, lang->file); + if (nxt_slow_path(nxt_app == NULL)) { + return NXT_ERROR; } + } - if (nxt_slow_path(nxt_app_set_environment(app_conf->environment) - != NXT_OK)) - { - nxt_alert(task, "failed to set environment"); - return NXT_ERROR; - } + if (nxt_slow_path(nxt_app_set_environment(app_conf->environment) != NXT_OK)) { + nxt_alert(task, "failed to set environment"); + return NXT_ERROR; + } - if (nxt_app->setup != NULL) { - ret = nxt_app->setup(task, process, app_conf); - if (nxt_slow_path(ret != NXT_OK)) { - return ret; - } + if (nxt_app->setup != NULL) { + ret = nxt_app->setup(task, process, app_conf); + if (nxt_slow_path(ret != NXT_OK)) { + return ret; } + } #if (NXT_HAVE_ISOLATION_ROOTFS) - if (process->isolation.rootfs != NULL) { - if (process->isolation.mounts != NULL) { - ret = nxt_isolation_prepare_rootfs(task, process); - if (nxt_slow_path(ret != NXT_OK)) { - return ret; - } - } + if (process->isolation.rootfs != NULL) { + if (process->isolation.mounts != NULL) { + ret = nxt_isolation_prepare_rootfs(task, process); + if (nxt_slow_path(ret != NXT_OK)) { + return ret; + } + } - ret = nxt_isolation_change_root(task, process); - if (nxt_slow_path(ret != NXT_OK)) { - return NXT_ERROR; - } + ret = nxt_isolation_change_root(task, process); + if (nxt_slow_path(ret != NXT_OK)) { + return NXT_ERROR; } + } #endif - if (app_conf->working_directory != NULL - && app_conf->working_directory[0] != 0) - { - ret = chdir(app_conf->working_directory); + if (app_conf->working_directory != NULL && + app_conf->working_directory[0] != 0) { + ret = chdir(app_conf->working_directory); - if (nxt_slow_path(ret != 0)) { - nxt_log(task, NXT_LOG_WARN, "chdir(%s) failed %E", - app_conf->working_directory, nxt_errno); + if (nxt_slow_path(ret != 0)) { + nxt_log(task, NXT_LOG_WARN, "chdir(%s) failed %E", + app_conf->working_directory, nxt_errno); - return NXT_ERROR; - } + return NXT_ERROR; } + } - process->state = NXT_PROCESS_STATE_CREATED; + process->state = NXT_PROCESS_STATE_CREATED; - return NXT_OK; + return NXT_OK; } +static nxt_int_t nxt_proto_start(nxt_task_t *task, nxt_process_data_t *data) { + nxt_debug(task, "prototype waiting for clone messages"); -static nxt_int_t -nxt_proto_start(nxt_task_t *task, nxt_process_data_t *data) -{ - nxt_debug(task, "prototype waiting for clone messages"); - - return NXT_OK; + return NXT_OK; } +static void nxt_proto_start_process_handler(nxt_task_t *task, + nxt_port_recv_msg_t *msg) { + u_char *p; + nxt_int_t ret; + nxt_port_t *port; + nxt_runtime_t *rt; + nxt_process_t *process; + nxt_process_init_t *init; -static void -nxt_proto_start_process_handler(nxt_task_t *task, nxt_port_recv_msg_t *msg) -{ - u_char *p; - nxt_int_t ret; - nxt_port_t *port; - nxt_runtime_t *rt; - nxt_process_t *process; - nxt_process_init_t *init; + rt = task->thread->runtime; - rt = task->thread->runtime; + process = nxt_process_new(rt); + if (nxt_slow_path(process == NULL)) { + goto failed; + } - process = nxt_process_new(rt); - if (nxt_slow_path(process == NULL)) { - goto failed; - } + process->mem_pool = nxt_mp_create(1024, 128, 256, 32); + if (nxt_slow_path(process->mem_pool == NULL)) { + nxt_process_use(task, process, -1); + goto failed; + } - process->mem_pool = nxt_mp_create(1024, 128, 256, 32); - if (nxt_slow_path(process->mem_pool == NULL)) { - nxt_process_use(task, process, -1); - goto failed; - } + process->parent_port = rt->port_by_type[NXT_PROCESS_PROTOTYPE]; - process->parent_port = rt->port_by_type[NXT_PROCESS_PROTOTYPE]; + init = nxt_process_init(process); + *init = nxt_app_process; - init = nxt_process_init(process); - *init = nxt_app_process; + process->name = + nxt_mp_alloc(process->mem_pool, + nxt_app_conf->name.length + sizeof("\"\" application") + 1); - process->name = nxt_mp_alloc(process->mem_pool, nxt_app_conf->name.length - + sizeof("\"\" application") + 1); + if (nxt_slow_path(process->name == NULL)) { + nxt_process_use(task, process, -1); - if (nxt_slow_path(process->name == NULL)) { - nxt_process_use(task, process, -1); + goto failed; + } - goto failed; - } - - init->start = nxt_app->start; + init->start = nxt_app->start; - init->name = (const char *) nxt_app_conf->name.start; + init->name = (const char *)nxt_app_conf->name.start; - p = (u_char *) process->name; - *p++ = '"'; - p = nxt_cpymem(p, nxt_app_conf->name.start, nxt_app_conf->name.length); - p = nxt_cpymem(p, "\" application", 13); - *p = '\0'; + p = (u_char *)process->name; + *p++ = '"'; + p = nxt_cpymem(p, nxt_app_conf->name.start, nxt_app_conf->name.length); + p = nxt_cpymem(p, "\" application", 13); + *p = '\0'; - process->user_cred = &rt->user_cred; + process->user_cred = &rt->user_cred; - process->data.app = nxt_app_conf; - process->stream = msg->port_msg.stream; + process->data.app = nxt_app_conf; + process->stream = msg->port_msg.stream; - init->siblings = &nxt_proto_children; + init->siblings = &nxt_proto_children; - ret = nxt_process_start(task, process); - if (nxt_slow_path(ret == NXT_ERROR)) { - nxt_process_use(task, process, -1); + ret = nxt_process_start(task, process); + if (nxt_slow_path(ret == NXT_ERROR)) { + nxt_process_use(task, process, -1); - goto failed; - } + goto failed; + } - nxt_proto_process_add(task, process); + nxt_proto_process_add(task, process); - return; + return; failed: - port = nxt_runtime_port_find(rt, msg->port_msg.pid, - msg->port_msg.reply_port); + port = nxt_runtime_port_find(rt, msg->port_msg.pid, msg->port_msg.reply_port); - if (nxt_fast_path(port != NULL)) { - nxt_port_socket_write(task, port, NXT_PORT_MSG_RPC_ERROR, - -1, msg->port_msg.stream, 0, NULL); - } + if (nxt_fast_path(port != NULL)) { + nxt_port_socket_write(task, port, NXT_PORT_MSG_RPC_ERROR, -1, + msg->port_msg.stream, 0, NULL); + } } +static void nxt_proto_quit_handler(nxt_task_t *task, nxt_port_recv_msg_t *msg) { + nxt_debug(task, "prototype quit handler"); -static void -nxt_proto_quit_handler(nxt_task_t *task, nxt_port_recv_msg_t *msg) -{ - nxt_debug(task, "prototype quit handler"); + nxt_proto_quit_children(task); - nxt_proto_quit_children(task); + nxt_proto_exiting = 1; - nxt_proto_exiting = 1; - - if (nxt_queue_is_empty(&nxt_proto_children)) { - nxt_process_quit(task, 0); - } + if (nxt_queue_is_empty(&nxt_proto_children)) { + nxt_process_quit(task, 0); + } } +static void nxt_proto_quit_children(nxt_task_t *task) { + nxt_port_t *port; + nxt_process_t *process; -static void -nxt_proto_quit_children(nxt_task_t *task) -{ - nxt_port_t *port; - nxt_process_t *process; + nxt_queue_each(process, &nxt_proto_children, nxt_process_t, link) { + port = nxt_process_port_first(process); - nxt_queue_each(process, &nxt_proto_children, nxt_process_t, link) { - port = nxt_process_port_first(process); - - (void) nxt_port_socket_write(task, port, NXT_PORT_MSG_QUIT, - -1, 0, 0, NULL); - } - nxt_queue_loop; + (void)nxt_port_socket_write(task, port, NXT_PORT_MSG_QUIT, -1, 0, 0, NULL); + } + nxt_queue_loop; } +static void nxt_proto_process_created_handler(nxt_task_t *task, + nxt_port_recv_msg_t *msg) { + nxt_pid_t isolated_pid, pid; + nxt_process_t *process; -static void -nxt_proto_process_created_handler(nxt_task_t *task, nxt_port_recv_msg_t *msg) -{ - nxt_pid_t isolated_pid, pid; - nxt_process_t *process; - - isolated_pid = nxt_recv_msg_cmsg_pid(msg); + isolated_pid = nxt_recv_msg_cmsg_pid(msg); - process = nxt_proto_process_find(task, isolated_pid); - if (nxt_slow_path(process == NULL)) { - return; - } + process = nxt_proto_process_find(task, isolated_pid); + if (nxt_slow_path(process == NULL)) { + return; + } - process->state = NXT_PROCESS_STATE_CREATED; + process->state = NXT_PROCESS_STATE_CREATED; - pid = msg->port_msg.pid; + pid = msg->port_msg.pid; - if (process->pid != pid) { - nxt_debug(task, "app process %PI (aka %PI) is created", isolated_pid, - pid); + if (process->pid != pid) { + nxt_debug(task, "app process %PI (aka %PI) is created", isolated_pid, pid); - process->pid = pid; + process->pid = pid; - } else { - nxt_debug(task, "app process %PI is created", isolated_pid); - } + } else { + nxt_debug(task, "app process %PI is created", isolated_pid); + } - if (!process->registered) { - nxt_assert(!nxt_queue_is_empty(&process->ports)); + if (!process->registered) { + nxt_assert(!nxt_queue_is_empty(&process->ports)); - nxt_runtime_process_add(task, process); + nxt_runtime_process_add(task, process); - nxt_port_use(task, nxt_process_port_first(process), -1); - } + nxt_port_use(task, nxt_process_port_first(process), -1); + } } - -static void -nxt_proto_signal_handler(nxt_task_t *task, void *obj, void *data) -{ - nxt_trace(task, "signal signo:%d (%s) received, ignored", - (int) (uintptr_t) obj, data); +static void nxt_proto_signal_handler(nxt_task_t *task, void *obj, void *data) { + nxt_trace(task, "signal signo:%d (%s) received, ignored", (int)(uintptr_t)obj, + data); } +static void nxt_proto_sigterm_handler(nxt_task_t *task, void *obj, void *data) { + nxt_trace(task, "signal signo:%d (%s) received", (int)(uintptr_t)obj, data); -static void -nxt_proto_sigterm_handler(nxt_task_t *task, void *obj, void *data) -{ - nxt_trace(task, "signal signo:%d (%s) received", - (int) (uintptr_t) obj, data); - - nxt_proto_quit_children(task); + nxt_proto_quit_children(task); - nxt_proto_exiting = 1; + nxt_proto_exiting = 1; - if (nxt_queue_is_empty(&nxt_proto_children)) { - nxt_process_quit(task, 0); - } + if (nxt_queue_is_empty(&nxt_proto_children)) { + nxt_process_quit(task, 0); + } } +static void nxt_proto_sigchld_handler(nxt_task_t *task, void *obj, void *data) { + int status; + nxt_err_t err; + nxt_pid_t pid; + nxt_port_t *port; + nxt_process_t *process; + nxt_runtime_t *rt; -static void -nxt_proto_sigchld_handler(nxt_task_t *task, void *obj, void *data) -{ - int status; - nxt_err_t err; - nxt_pid_t pid; - nxt_port_t *port; - nxt_process_t *process; - nxt_runtime_t *rt; + rt = task->thread->runtime; - rt = task->thread->runtime; + nxt_debug(task, "proto sigchld handler signo:%d (%s)", (int)(uintptr_t)obj, + data); - nxt_debug(task, "proto sigchld handler signo:%d (%s)", - (int) (uintptr_t) obj, data); + for (;;) { + pid = waitpid(-1, &status, WNOHANG); - for ( ;; ) { - pid = waitpid(-1, &status, WNOHANG); + if (pid == -1) { + + switch (err = nxt_errno) { + + case NXT_ECHILD: + return; - if (pid == -1) { + case NXT_EINTR: + continue; - switch (err = nxt_errno) { + default: + nxt_alert(task, "waitpid() failed: %E", err); + return; + } + } - case NXT_ECHILD: - return; + nxt_debug(task, "waitpid(): %PI", pid); - case NXT_EINTR: - continue; + if (pid == 0) { + return; + } - default: - nxt_alert(task, "waitpid() failed: %E", err); - return; - } - } + process = nxt_proto_process_remove(task, pid); - nxt_debug(task, "waitpid(): %PI", pid); + if (WTERMSIG(status)) { + if (rt->is_pid_isolated) { + nxt_alert(task, + "app process %PI (isolated %PI) " + "exited on signal %d%s", + process != NULL ? process->pid : 0, pid, WTERMSIG(status), + NXT_WCOREDUMP(status) ? " (core dumped)" : ""); - if (pid == 0) { - return; - } + } else { + nxt_alert(task, "app process %PI exited on signal %d%s", pid, + WTERMSIG(status), + NXT_WCOREDUMP(status) ? " (core dumped)" : ""); + } - process = nxt_proto_process_remove(task, pid); - - if (WTERMSIG(status)) { - if (rt->is_pid_isolated) { - nxt_alert(task, "app process %PI (isolated %PI) " - "exited on signal %d%s", - process != NULL ? process->pid : 0, - pid, WTERMSIG(status), - NXT_WCOREDUMP(status) ? " (core dumped)" : ""); - - } else { - nxt_alert(task, "app process %PI exited on signal %d%s", - pid, WTERMSIG(status), - NXT_WCOREDUMP(status) ? " (core dumped)" : ""); - } - - } else { - if (rt->is_pid_isolated) { - nxt_trace(task, "app process %PI (isolated %PI) " - "exited with code %d", - process != NULL ? process->pid : 0, - pid, WEXITSTATUS(status)); - - } else { - nxt_trace(task, "app process %PI exited with code %d", - pid, WEXITSTATUS(status)); - } - } + } else { + if (rt->is_pid_isolated) { + nxt_trace(task, + "app process %PI (isolated %PI) " + "exited with code %d", + process != NULL ? process->pid : 0, pid, WEXITSTATUS(status)); + + } else { + nxt_trace(task, "app process %PI exited with code %d", pid, + WEXITSTATUS(status)); + } + } - if (process == NULL) { - continue; - } + if (process == NULL) { + continue; + } - if (process->registered) { - port = NULL; + if (process->registered) { + port = NULL; - } else { - nxt_assert(!nxt_queue_is_empty(&process->ports)); + } else { + nxt_assert(!nxt_queue_is_empty(&process->ports)); - port = nxt_process_port_first(process); - } + port = nxt_process_port_first(process); + } - if (process->state != NXT_PROCESS_STATE_CREATING) { - nxt_port_remove_notify_others(task, process); - } + if (process->state != NXT_PROCESS_STATE_CREATING) { + nxt_port_remove_notify_others(task, process); + } - nxt_process_close_ports(task, process); + nxt_process_close_ports(task, process); - if (port != NULL) { - nxt_port_use(task, port, -1); - } + if (port != NULL) { + nxt_port_use(task, port, -1); + } - if (nxt_proto_exiting && nxt_queue_is_empty(&nxt_proto_children)) { - nxt_process_quit(task, 0); - return; - } + if (nxt_proto_exiting && nxt_queue_is_empty(&nxt_proto_children)) { + nxt_process_quit(task, 0); + return; } + } } +static nxt_app_module_t *nxt_app_module_load(nxt_task_t *task, + const char *name) { + char *err; + void *dl; + nxt_app_module_t *app; -static nxt_app_module_t * -nxt_app_module_load(nxt_task_t *task, const char *name) -{ - char *err; - void *dl; - nxt_app_module_t *app; - - dl = dlopen(name, RTLD_GLOBAL | RTLD_LAZY); + dl = dlopen(name, RTLD_GLOBAL | RTLD_LAZY); - if (nxt_slow_path(dl == NULL)) { - err = dlerror(); - nxt_alert(task, "dlopen(\"%s\") failed: \"%s\"", - name, err != NULL ? err : "(null)"); - return NULL; - } + if (nxt_slow_path(dl == NULL)) { + err = dlerror(); + nxt_alert(task, "dlopen(\"%s\") failed: \"%s\"", name, + err != NULL ? err : "(null)"); + return NULL; + } - app = dlsym(dl, "nxt_app_module"); + app = dlsym(dl, "nxt_app_module"); - if (nxt_slow_path(app == NULL)) { - err = dlerror(); - nxt_alert(task, "dlsym(\"%s\", \"nxt_app_module\") failed: \"%s\"", - name, err != NULL ? err : "(null)"); + if (nxt_slow_path(app == NULL)) { + err = dlerror(); + nxt_alert(task, "dlsym(\"%s\", \"nxt_app_module\") failed: \"%s\"", name, + err != NULL ? err : "(null)"); - if (dlclose(dl) != 0) { - err = dlerror(); - nxt_alert(task, "dlclose(\"%s\") failed: \"%s\"", - name, err != NULL ? err : "(null)"); - } + if (dlclose(dl) != 0) { + err = dlerror(); + nxt_alert(task, "dlclose(\"%s\") failed: \"%s\"", name, + err != NULL ? err : "(null)"); } + } - return app; + return app; } +static nxt_int_t nxt_app_set_environment(nxt_conf_value_t *environment) { + char *env, *p; + uint32_t next; + nxt_str_t name, value; + nxt_conf_value_t *value_obj; -static nxt_int_t -nxt_app_set_environment(nxt_conf_value_t *environment) -{ - char *env, *p; - uint32_t next; - nxt_str_t name, value; - nxt_conf_value_t *value_obj; + if (environment != NULL) { + next = 0; - if (environment != NULL) { - next = 0; - - for ( ;; ) { - value_obj = nxt_conf_next_object_member(environment, &name, &next); - if (value_obj == NULL) { - break; - } + for (;;) { + value_obj = nxt_conf_next_object_member(environment, &name, &next); + if (value_obj == NULL) { + break; + } - nxt_conf_get_string(value_obj, &value); + nxt_conf_get_string(value_obj, &value); - env = nxt_malloc(name.length + value.length + 2); - if (nxt_slow_path(env == NULL)) { - return NXT_ERROR; - } + env = nxt_malloc(name.length + value.length + 2); + if (nxt_slow_path(env == NULL)) { + return NXT_ERROR; + } - p = nxt_cpymem(env, name.start, name.length); - *p++ = '='; - p = nxt_cpymem(p, value.start, value.length); - *p = '\0'; + p = nxt_cpymem(env, name.start, name.length); + *p++ = '='; + p = nxt_cpymem(p, value.start, value.length); + *p = '\0'; - if (nxt_slow_path(putenv(env) != 0)) { - return NXT_ERROR; - } - } + if (nxt_slow_path(putenv(env) != 0)) { + return NXT_ERROR; + } } + } - return NXT_OK; + return NXT_OK; } +nxt_int_t nxt_app_set_logs(void) { + nxt_int_t ret; + nxt_file_t file; + nxt_task_t *task; + nxt_thread_t *thr; + nxt_process_t *process; + nxt_runtime_t *rt; + nxt_common_app_conf_t *app_conf; -nxt_int_t -nxt_app_set_logs(void) -{ - nxt_int_t ret; - nxt_file_t file; - nxt_task_t *task; - nxt_thread_t *thr; - nxt_process_t *process; - nxt_runtime_t *rt; - nxt_common_app_conf_t *app_conf; - - thr = nxt_thread(); + thr = nxt_thread(); - task = thr->task; + task = thr->task; - rt = task->thread->runtime; - if (!rt->daemon) { - return NXT_OK; + rt = task->thread->runtime; + if (!rt->daemon) { + return NXT_OK; + } + + process = rt->port_by_type[NXT_PROCESS_PROTOTYPE]->process; + app_conf = process->data.app; + + if (app_conf->stdout_log != NULL) { + nxt_memzero(&file, sizeof(nxt_file_t)); + file.log_level = 1; + file.name = (u_char *)app_conf->stdout_log; + ret = nxt_file_open(task, &file, O_WRONLY | O_APPEND, O_CREAT, 0666); + if (ret == NXT_ERROR) { + return NXT_ERROR; } - process = rt->port_by_type[NXT_PROCESS_PROTOTYPE]->process; - app_conf = process->data.app; - - if (app_conf->stdout_log != NULL) { - nxt_memzero(&file, sizeof(nxt_file_t)); - file.log_level = 1; - file.name = (u_char *) app_conf->stdout_log; - ret = nxt_file_open(task, &file, O_WRONLY | O_APPEND, O_CREAT, 0666); - if (ret == NXT_ERROR) { - return NXT_ERROR; - } - - nxt_file_stdout(&file); - nxt_file_close(task, &file); + nxt_file_stdout(&file); + nxt_file_close(task, &file); + } + + if (app_conf->stderr_log != NULL) { + nxt_memzero(&file, sizeof(nxt_file_t)); + file.log_level = 1; + file.name = (u_char *)app_conf->stderr_log; + ret = nxt_file_open(task, &file, O_WRONLY | O_APPEND, O_CREAT, 0666); + if (ret == NXT_ERROR) { + return NXT_ERROR; } - if (app_conf->stderr_log != NULL) { - nxt_memzero(&file, sizeof(nxt_file_t)); - file.log_level = 1; - file.name = (u_char *) app_conf->stderr_log; - ret = nxt_file_open(task, &file, O_WRONLY | O_APPEND, O_CREAT, 0666); - if (ret == NXT_ERROR) { - return NXT_ERROR; - } - - nxt_file_stderr(&file); - nxt_file_close(task, &file); - } + nxt_file_stderr(&file); + nxt_file_close(task, &file); + } - return NXT_OK; + return NXT_OK; } +static u_char *nxt_cstr_dup(nxt_mp_t *mp, u_char *dst, u_char *src) { + u_char *p; + size_t len; -static u_char * -nxt_cstr_dup(nxt_mp_t *mp, u_char *dst, u_char *src) -{ - u_char *p; - size_t len; - - len = nxt_strlen(src); + len = nxt_strlen(src); - if (dst == NULL) { - dst = nxt_mp_alloc(mp, len + 1); - if (nxt_slow_path(dst == NULL)) { - return NULL; - } + if (dst == NULL) { + dst = nxt_mp_alloc(mp, len + 1); + if (nxt_slow_path(dst == NULL)) { + return NULL; } + } - p = nxt_cpymem(dst, src, len); - *p = '\0'; + p = nxt_cpymem(dst, src, len); + *p = '\0'; - return dst; + return dst; } +static nxt_int_t nxt_app_setup(nxt_task_t *task, nxt_process_t *process) { + nxt_process_init_t *init; -static nxt_int_t -nxt_app_setup(nxt_task_t *task, nxt_process_t *process) -{ - nxt_process_init_t *init; + process->state = NXT_PROCESS_STATE_CREATED; - process->state = NXT_PROCESS_STATE_CREATED; + init = nxt_process_init(process); - init = nxt_process_init(process); - - return init->start(task, &process->data); + return init->start(task, &process->data); } +nxt_app_lang_module_t *nxt_app_lang_module(nxt_runtime_t *rt, nxt_str_t *name) { + u_char *p, *end, *version; + size_t version_length; + nxt_uint_t i, n; + nxt_app_type_t type; + nxt_app_lang_module_t *lang; -nxt_app_lang_module_t * -nxt_app_lang_module(nxt_runtime_t *rt, nxt_str_t *name) -{ - u_char *p, *end, *version; - size_t version_length; - nxt_uint_t i, n; - nxt_app_type_t type; - nxt_app_lang_module_t *lang; - - end = name->start + name->length; - version = end; + end = name->start + name->length; + version = end; - for (p = name->start; p < end; p++) { - if (*p == ' ') { - version = p + 1; - break; - } + for (p = name->start; p < end; p++) { + if (*p == ' ') { + version = p + 1; + break; + } - if (*p >= '0' && *p <= '9') { - version = p; - break; - } + if (*p >= '0' && *p <= '9') { + version = p; + break; } + } - type = nxt_app_parse_type(name->start, p - name->start); + type = nxt_app_parse_type(name->start, p - name->start); - if (type == NXT_APP_UNKNOWN) { - return NULL; - } + if (type == NXT_APP_UNKNOWN) { + return NULL; + } - version_length = end - version; + version_length = end - version; - lang = rt->languages->elts; - n = rt->languages->nelts; + lang = rt->languages->elts; + n = rt->languages->nelts; - for (i = 0; i < n; i++) { + for (i = 0; i < n; i++) { - /* - * Versions are sorted in descending order - * so first match chooses the highest version. - */ + /* + * Versions are sorted in descending order + * so first match chooses the highest version. + */ - if (lang[i].type == type - && nxt_strvers_match(lang[i].version, version, version_length)) - { - return &lang[i]; - } + if (lang[i].type == type && + nxt_strvers_match(lang[i].version, version, version_length)) { + return &lang[i]; } + } - return NULL; + return NULL; } +nxt_app_type_t nxt_app_parse_type(u_char *p, size_t length) { + nxt_str_t str; -nxt_app_type_t -nxt_app_parse_type(u_char *p, size_t length) -{ - nxt_str_t str; + str.length = length; + str.start = p; - str.length = length; - str.start = p; + if (nxt_str_eq(&str, "external", 8) || nxt_str_eq(&str, "go", 2)) { + return NXT_APP_EXTERNAL; - if (nxt_str_eq(&str, "external", 8) || nxt_str_eq(&str, "go", 2)) { - return NXT_APP_EXTERNAL; + } else if (nxt_str_eq(&str, "python", 6)) { + return NXT_APP_PYTHON; - } else if (nxt_str_eq(&str, "python", 6)) { - return NXT_APP_PYTHON; + } else if (nxt_str_eq(&str, "php", 3)) { + return NXT_APP_PHP; - } else if (nxt_str_eq(&str, "php", 3)) { - return NXT_APP_PHP; + } else if (nxt_str_eq(&str, "perl", 4)) { + return NXT_APP_PERL; - } else if (nxt_str_eq(&str, "perl", 4)) { - return NXT_APP_PERL; + } else if (nxt_str_eq(&str, "ruby", 4)) { + return NXT_APP_RUBY; - } else if (nxt_str_eq(&str, "ruby", 4)) { - return NXT_APP_RUBY; + } else if (nxt_str_eq(&str, "java", 4)) { + return NXT_APP_JAVA; - } else if (nxt_str_eq(&str, "java", 4)) { - return NXT_APP_JAVA; + } else if (nxt_str_eq(&str, "wasm-wasi-component", 19)) { + return NXT_APP_WASM_WC; - } else if (nxt_str_eq(&str, "wasm-wasi-component", 19)) { - return NXT_APP_WASM_WC; + } else if (nxt_str_eq(&str, "wasm", 4)) { + return NXT_APP_WASM; + } - } else if (nxt_str_eq(&str, "wasm", 4)) { - return NXT_APP_WASM; - } - - return NXT_APP_UNKNOWN; + return NXT_APP_UNKNOWN; } +nxt_int_t nxt_unit_default_init(nxt_task_t *task, nxt_unit_init_t *init, + nxt_common_app_conf_t *conf) { + nxt_port_t *my_port, *proto_port, *router_port; + nxt_runtime_t *rt; -nxt_int_t -nxt_unit_default_init(nxt_task_t *task, nxt_unit_init_t *init, - nxt_common_app_conf_t *conf) -{ - nxt_port_t *my_port, *proto_port, *router_port; - nxt_runtime_t *rt; + nxt_memzero(init, sizeof(nxt_unit_init_t)); - nxt_memzero(init, sizeof(nxt_unit_init_t)); + rt = task->thread->runtime; - rt = task->thread->runtime; + proto_port = rt->port_by_type[NXT_PROCESS_PROTOTYPE]; + if (nxt_slow_path(proto_port == NULL)) { + return NXT_ERROR; + } - proto_port = rt->port_by_type[NXT_PROCESS_PROTOTYPE]; - if (nxt_slow_path(proto_port == NULL)) { - return NXT_ERROR; - } + router_port = rt->port_by_type[NXT_PROCESS_ROUTER]; + if (nxt_slow_path(router_port == NULL)) { + return NXT_ERROR; + } - router_port = rt->port_by_type[NXT_PROCESS_ROUTER]; - if (nxt_slow_path(router_port == NULL)) { - return NXT_ERROR; - } + my_port = nxt_runtime_port_find(rt, nxt_pid, 0); + if (nxt_slow_path(my_port == NULL)) { + return NXT_ERROR; + } - my_port = nxt_runtime_port_find(rt, nxt_pid, 0); - if (nxt_slow_path(my_port == NULL)) { - return NXT_ERROR; - } - - init->ready_port.id.pid = proto_port->pid; - init->ready_port.id.id = proto_port->id; - init->ready_port.in_fd = -1; - init->ready_port.out_fd = proto_port->pair[1]; + init->ready_port.id.pid = proto_port->pid; + init->ready_port.id.id = proto_port->id; + init->ready_port.in_fd = -1; + init->ready_port.out_fd = proto_port->pair[1]; - init->ready_stream = my_port->process->stream; + init->ready_stream = my_port->process->stream; - init->router_port.id.pid = router_port->pid; - init->router_port.id.id = router_port->id; - init->router_port.in_fd = -1; - init->router_port.out_fd = router_port->pair[1]; + init->router_port.id.pid = router_port->pid; + init->router_port.id.id = router_port->id; + init->router_port.in_fd = -1; + init->router_port.out_fd = router_port->pair[1]; - init->read_port.id.pid = my_port->pid; - init->read_port.id.id = my_port->id; - init->read_port.in_fd = my_port->pair[0]; - init->read_port.out_fd = my_port->pair[1]; + init->read_port.id.pid = my_port->pid; + init->read_port.id.id = my_port->id; + init->read_port.in_fd = my_port->pair[0]; + init->read_port.out_fd = my_port->pair[1]; - init->shared_port_fd = conf->shared_port_fd; - init->shared_queue_fd = conf->shared_queue_fd; + init->shared_port_fd = conf->shared_port_fd; + init->shared_queue_fd = conf->shared_queue_fd; - init->log_fd = 2; + init->log_fd = 2; - init->shm_limit = conf->shm_limit; - init->request_limit = conf->request_limit; + init->shm_limit = conf->shm_limit; + init->request_limit = conf->request_limit; - return NXT_OK; + return NXT_OK; } +static nxt_int_t nxt_proto_lvlhsh_isolated_pid_test(nxt_lvlhsh_query_t *lhq, + void *data) { + nxt_pid_t *qpid; + nxt_process_t *process; -static nxt_int_t -nxt_proto_lvlhsh_isolated_pid_test(nxt_lvlhsh_query_t *lhq, void *data) -{ - nxt_pid_t *qpid; - nxt_process_t *process; + process = data; + qpid = (nxt_pid_t *)lhq->key.start; - process = data; - qpid = (nxt_pid_t *) lhq->key.start; - - if (*qpid == process->isolated_pid) { - return NXT_OK; - } + if (*qpid == process->isolated_pid) { + return NXT_OK; + } - return NXT_DECLINED; + return NXT_DECLINED; } - -static const nxt_lvlhsh_proto_t lvlhsh_processes_proto nxt_aligned(64) = { +static const nxt_lvlhsh_proto_t lvlhsh_processes_proto nxt_aligned(64) = { NXT_LVLHSH_DEFAULT, nxt_proto_lvlhsh_isolated_pid_test, nxt_lvlhsh_alloc, nxt_lvlhsh_free, }; - -nxt_inline void -nxt_proto_process_lhq_pid(nxt_lvlhsh_query_t *lhq, nxt_pid_t *pid) -{ - lhq->key_hash = nxt_murmur_hash2(pid, sizeof(nxt_pid_t)); - lhq->key.length = sizeof(nxt_pid_t); - lhq->key.start = (u_char *) pid; - lhq->proto = &lvlhsh_processes_proto; +nxt_inline void nxt_proto_process_lhq_pid(nxt_lvlhsh_query_t *lhq, + nxt_pid_t *pid) { + lhq->key_hash = nxt_murmur_hash2(pid, sizeof(nxt_pid_t)); + lhq->key.length = sizeof(nxt_pid_t); + lhq->key.start = (u_char *)pid; + lhq->proto = &lvlhsh_processes_proto; } +static void nxt_proto_process_add(nxt_task_t *task, nxt_process_t *process) { + nxt_runtime_t *rt; + nxt_lvlhsh_query_t lhq; -static void -nxt_proto_process_add(nxt_task_t *task, nxt_process_t *process) -{ - nxt_runtime_t *rt; - nxt_lvlhsh_query_t lhq; + rt = task->thread->runtime; - rt = task->thread->runtime; + nxt_proto_process_lhq_pid(&lhq, &process->isolated_pid); - nxt_proto_process_lhq_pid(&lhq, &process->isolated_pid); + lhq.replace = 0; + lhq.value = process; + lhq.pool = rt->mem_pool; - lhq.replace = 0; - lhq.value = process; - lhq.pool = rt->mem_pool; + switch (nxt_lvlhsh_insert(&nxt_proto_processes, &lhq)) { - switch (nxt_lvlhsh_insert(&nxt_proto_processes, &lhq)) { + case NXT_OK: + nxt_debug(task, "process (isolated %PI) added", process->isolated_pid); - case NXT_OK: - nxt_debug(task, "process (isolated %PI) added", process->isolated_pid); - - nxt_queue_insert_tail(&nxt_proto_children, &process->link); - break; + nxt_queue_insert_tail(&nxt_proto_children, &process->link); + break; - default: - nxt_alert(task, "process (isolated %PI) failed to add", - process->isolated_pid); - break; - } + default: + nxt_alert(task, "process (isolated %PI) failed to add", + process->isolated_pid); + break; + } } +static nxt_process_t *nxt_proto_process_remove(nxt_task_t *task, + nxt_pid_t pid) { + nxt_runtime_t *rt; + nxt_process_t *process; + nxt_lvlhsh_query_t lhq; -static nxt_process_t * -nxt_proto_process_remove(nxt_task_t *task, nxt_pid_t pid) -{ - nxt_runtime_t *rt; - nxt_process_t *process; - nxt_lvlhsh_query_t lhq; + nxt_proto_process_lhq_pid(&lhq, &pid); - nxt_proto_process_lhq_pid(&lhq, &pid); + rt = task->thread->runtime; - rt = task->thread->runtime; + lhq.pool = rt->mem_pool; - lhq.pool = rt->mem_pool; + switch (nxt_lvlhsh_delete(&nxt_proto_processes, &lhq)) { - switch (nxt_lvlhsh_delete(&nxt_proto_processes, &lhq)) { + case NXT_OK: + nxt_debug(task, "process (isolated %PI) removed", pid); - case NXT_OK: - nxt_debug(task, "process (isolated %PI) removed", pid); + process = lhq.value; - process = lhq.value; + nxt_queue_remove(&process->link); + process->link.next = NULL; - nxt_queue_remove(&process->link); - process->link.next = NULL; + break; - break; + default: + nxt_debug(task, "process (isolated %PI) remove failed", pid); + process = NULL; + break; + } - default: - nxt_debug(task, "process (isolated %PI) remove failed", pid); - process = NULL; - break; - } - - return process; + return process; } +static nxt_process_t *nxt_proto_process_find(nxt_task_t *task, nxt_pid_t pid) { + nxt_process_t *process; + nxt_lvlhsh_query_t lhq; -static nxt_process_t * -nxt_proto_process_find(nxt_task_t *task, nxt_pid_t pid) -{ - nxt_process_t *process; - nxt_lvlhsh_query_t lhq; + nxt_proto_process_lhq_pid(&lhq, &pid); - nxt_proto_process_lhq_pid(&lhq, &pid); + if (nxt_lvlhsh_find(&nxt_proto_processes, &lhq) == NXT_OK) { + process = lhq.value; - if (nxt_lvlhsh_find(&nxt_proto_processes, &lhq) == NXT_OK) { - process = lhq.value; + } else { + nxt_debug(task, "process (isolated %PI) not found", pid); - } else { - nxt_debug(task, "process (isolated %PI) not found", pid); - - process = NULL; - } + process = NULL; + } - return process; + return process; } diff --git a/src/nxt_application.h b/src/nxt_application.h index a3b4230a0..d1d81747e 100644 --- a/src/nxt_application.h +++ b/src/nxt_application.h @@ -8,170 +8,157 @@ #ifndef _NXT_APPLICATION_H_INCLUDED_ #define _NXT_APPLICATION_H_INCLUDED_ - #include #include - typedef enum { - NXT_APP_EXTERNAL, - NXT_APP_PYTHON, - NXT_APP_PHP, - NXT_APP_PERL, - NXT_APP_RUBY, - NXT_APP_JAVA, - NXT_APP_WASM, - NXT_APP_WASM_WC, - - NXT_APP_UNKNOWN, + NXT_APP_EXTERNAL, + NXT_APP_PYTHON, + NXT_APP_PHP, + NXT_APP_PERL, + NXT_APP_RUBY, + NXT_APP_JAVA, + NXT_APP_WASM, + NXT_APP_WASM_WC, + + NXT_APP_UNKNOWN, } nxt_app_type_t; - -typedef struct nxt_app_module_s nxt_app_module_t; +typedef struct nxt_app_module_s nxt_app_module_t; typedef nxt_int_t (*nxt_application_setup_t)(nxt_task_t *task, - nxt_process_t *process, nxt_common_app_conf_t *conf); - + nxt_process_t *process, + nxt_common_app_conf_t *conf); typedef struct { - nxt_app_type_t type; - char *name; - u_char *version; - char *file; - nxt_app_module_t *module; - nxt_array_t *mounts; /* of nxt_fs_mount_t */ + nxt_app_type_t type; + char *name; + u_char *version; + char *file; + nxt_app_module_t *module; + nxt_array_t *mounts; /* of nxt_fs_mount_t */ } nxt_app_lang_module_t; - typedef struct { - char *executable; - nxt_conf_value_t *arguments; + char *executable; + nxt_conf_value_t *arguments; } nxt_external_app_conf_t; - typedef struct { - char *home; - nxt_conf_value_t *path; - nxt_str_t protocol; - uint32_t threads; - uint32_t thread_stack_size; - nxt_conf_value_t *targets; + char *home; + nxt_conf_value_t *path; + nxt_str_t protocol; + uint32_t threads; + uint32_t thread_stack_size; + nxt_conf_value_t *targets; } nxt_python_app_conf_t; - typedef struct { - nxt_conf_value_t *targets; - nxt_conf_value_t *options; + nxt_conf_value_t *targets; + nxt_conf_value_t *options; } nxt_php_app_conf_t; - typedef struct { - char *script; - uint32_t threads; - uint32_t thread_stack_size; + char *script; + uint32_t threads; + uint32_t thread_stack_size; } nxt_perl_app_conf_t; - typedef struct { - nxt_str_t script; - uint32_t threads; - nxt_str_t hooks; + nxt_str_t script; + uint32_t threads; + nxt_str_t hooks; } nxt_ruby_app_conf_t; - typedef struct { - nxt_conf_value_t *classpath; - char *webapp; - nxt_conf_value_t *options; - char *unit_jars; - uint32_t threads; - uint32_t thread_stack_size; + nxt_conf_value_t *classpath; + char *webapp; + nxt_conf_value_t *options; + char *unit_jars; + uint32_t threads; + uint32_t thread_stack_size; } nxt_java_app_conf_t; - typedef struct { - const char *module; + const char *module; - const char *request_handler; - const char *malloc_handler; - const char *free_handler; + const char *request_handler; + const char *malloc_handler; + const char *free_handler; - const char *module_init_handler; - const char *module_end_handler; - const char *request_init_handler; - const char *request_end_handler; - const char *response_end_handler; + const char *module_init_handler; + const char *module_end_handler; + const char *request_init_handler; + const char *request_end_handler; + const char *response_end_handler; - nxt_conf_value_t *access; + nxt_conf_value_t *access; } nxt_wasm_app_conf_t; - typedef struct { - const char *component; + const char *component; - nxt_conf_value_t *access; + nxt_conf_value_t *access; } nxt_wasm_wc_app_conf_t; - struct nxt_common_app_conf_s { - nxt_str_t name; - nxt_str_t type; - nxt_str_t user; - nxt_str_t group; - - char *stdout_log; - char *stderr_log; - - char *working_directory; - nxt_conf_value_t *environment; - - nxt_conf_value_t *isolation; - nxt_conf_value_t *limits; - - size_t shm_limit; - uint32_t request_limit; - - nxt_fd_t shared_port_fd; - nxt_fd_t shared_queue_fd; - - union { - nxt_external_app_conf_t external; - nxt_python_app_conf_t python; - nxt_php_app_conf_t php; - nxt_perl_app_conf_t perl; - nxt_ruby_app_conf_t ruby; - nxt_java_app_conf_t java; - nxt_wasm_app_conf_t wasm; - nxt_wasm_wc_app_conf_t wasm_wc; - } u; - - nxt_conf_value_t *self; + nxt_str_t name; + nxt_str_t type; + nxt_str_t user; + nxt_str_t group; + + char *stdout_log; + char *stderr_log; + + char *working_directory; + nxt_conf_value_t *environment; + + nxt_conf_value_t *isolation; + nxt_conf_value_t *limits; + + size_t shm_limit; + uint32_t request_limit; + + nxt_fd_t shared_port_fd; + nxt_fd_t shared_queue_fd; + + union { + nxt_external_app_conf_t external; + nxt_python_app_conf_t python; + nxt_php_app_conf_t php; + nxt_perl_app_conf_t perl; + nxt_ruby_app_conf_t ruby; + nxt_java_app_conf_t java; + nxt_wasm_app_conf_t wasm; + nxt_wasm_wc_app_conf_t wasm_wc; + } u; + + nxt_conf_value_t *self; }; - struct nxt_app_module_s { - size_t compat_length; - uint32_t *compat; + size_t compat_length; + uint32_t *compat; - nxt_str_t type; - const char *version; + nxt_str_t type; + const char *version; - const nxt_fs_mount_t *mounts; - nxt_uint_t nmounts; + const nxt_fs_mount_t *mounts; + nxt_uint_t nmounts; - nxt_application_setup_t setup; - nxt_process_start_t start; + nxt_application_setup_t setup; + nxt_process_start_t start; }; - nxt_app_lang_module_t *nxt_app_lang_module(nxt_runtime_t *rt, nxt_str_t *name); nxt_app_type_t nxt_app_parse_type(u_char *p, size_t length); -NXT_EXPORT extern nxt_str_t nxt_server; -extern nxt_app_module_t nxt_external_module; +NXT_EXPORT extern nxt_str_t nxt_server; +extern nxt_app_module_t nxt_external_module; NXT_EXPORT nxt_int_t nxt_unit_default_init(nxt_task_t *task, - nxt_unit_init_t *init, nxt_common_app_conf_t *conf); + nxt_unit_init_t *init, + nxt_common_app_conf_t *conf); NXT_EXPORT nxt_int_t nxt_app_set_logs(void); diff --git a/src/nxt_array.c b/src/nxt_array.c index 1e13c22a8..afbc78a7e 100644 --- a/src/nxt_array.c +++ b/src/nxt_array.c @@ -6,145 +6,127 @@ #include +nxt_array_t *nxt_array_create(nxt_mp_t *mp, nxt_uint_t n, size_t size) { + nxt_array_t *array; -nxt_array_t * -nxt_array_create(nxt_mp_t *mp, nxt_uint_t n, size_t size) -{ - nxt_array_t *array; + array = nxt_mp_alloc(mp, sizeof(nxt_array_t) + n * size); - array = nxt_mp_alloc(mp, sizeof(nxt_array_t) + n * size); + if (nxt_slow_path(array == NULL)) { + return NULL; + } - if (nxt_slow_path(array == NULL)) { - return NULL; - } - - array->elts = nxt_pointer_to(array, sizeof(nxt_array_t)); - array->nelts = 0; - array->size = size; - array->nalloc = n; - array->mem_pool = mp; + array->elts = nxt_pointer_to(array, sizeof(nxt_array_t)); + array->nelts = 0; + array->size = size; + array->nalloc = n; + array->mem_pool = mp; - return array; + return array; } +void nxt_array_destroy(nxt_array_t *array) { + if (array->elts != nxt_pointer_to(array, sizeof(nxt_array_t))) { + nxt_mp_free(array->mem_pool, array->elts); + } -void -nxt_array_destroy(nxt_array_t *array) -{ - if (array->elts != nxt_pointer_to(array, sizeof(nxt_array_t))) { - nxt_mp_free(array->mem_pool, array->elts); - } - - nxt_mp_free(array->mem_pool, array); + nxt_mp_free(array->mem_pool, array); } +void *nxt_array_add(nxt_array_t *array) { + void *p; + uint32_t nalloc, new_alloc; -void * -nxt_array_add(nxt_array_t *array) -{ - void *p; - uint32_t nalloc, new_alloc; - - nalloc = array->nalloc; - - if (array->nelts == nalloc) { + nalloc = array->nalloc; - if (nalloc < 16) { - /* Allocate new array twice larger than current. */ - new_alloc = (nalloc == 0) ? 4 : nalloc * 2; + if (array->nelts == nalloc) { - } else { - /* Allocate new array 1.5 times larger than current. */ - new_alloc = nalloc + nalloc / 2; - } + if (nalloc < 16) { + /* Allocate new array twice larger than current. */ + new_alloc = (nalloc == 0) ? 4 : nalloc * 2; - p = nxt_mp_alloc(array->mem_pool, array->size * new_alloc); + } else { + /* Allocate new array 1.5 times larger than current. */ + new_alloc = nalloc + nalloc / 2; + } - if (nxt_slow_path(p == NULL)) { - return NULL; - } + p = nxt_mp_alloc(array->mem_pool, array->size * new_alloc); - nxt_memcpy(p, array->elts, array->size * nalloc); + if (nxt_slow_path(p == NULL)) { + return NULL; + } - if (array->elts != nxt_pointer_to(array, sizeof(nxt_array_t))) { - nxt_mp_free(array->mem_pool, array->elts); - } + nxt_memcpy(p, array->elts, array->size * nalloc); - array->elts = p; - array->nalloc = new_alloc; + if (array->elts != nxt_pointer_to(array, sizeof(nxt_array_t))) { + nxt_mp_free(array->mem_pool, array->elts); } - p = nxt_pointer_to(array->elts, array->size * array->nelts); - array->nelts++; + array->elts = p; + array->nalloc = new_alloc; + } - return p; -} + p = nxt_pointer_to(array->elts, array->size * array->nelts); + array->nelts++; + return p; +} -void * -nxt_array_zero_add(nxt_array_t *array) -{ - void *p; +void *nxt_array_zero_add(nxt_array_t *array) { + void *p; - p = nxt_array_add(array); + p = nxt_array_add(array); - if (nxt_fast_path(p != NULL)) { - nxt_memzero(p, array->size); - } + if (nxt_fast_path(p != NULL)) { + nxt_memzero(p, array->size); + } - return p; + return p; } +void nxt_array_remove(nxt_array_t *array, void *elt) { + void *last; -void -nxt_array_remove(nxt_array_t *array, void *elt) -{ - void *last; + last = nxt_array_last(array); - last = nxt_array_last(array); + if (elt != last) { + nxt_memcpy(elt, last, array->size); + } - if (elt != last) { - nxt_memcpy(elt, last, array->size); - } - - array->nelts--; + array->nelts--; } +nxt_array_t *nxt_array_copy(nxt_mp_t *mp, nxt_array_t *dst, nxt_array_t *src) { + void *data; + uint32_t i, size; -nxt_array_t * -nxt_array_copy(nxt_mp_t *mp, nxt_array_t *dst, nxt_array_t *src) -{ - void *data; - uint32_t i, size; - - size = src->size; + size = src->size; - if (dst == NULL) { - dst = nxt_array_create(mp, src->nelts, size); - if (nxt_slow_path(dst == NULL)) { - return NULL; - } + if (dst == NULL) { + dst = nxt_array_create(mp, src->nelts, size); + if (nxt_slow_path(dst == NULL)) { + return NULL; } + } - nxt_assert(size == dst->size); + nxt_assert(size == dst->size); - if (dst->nalloc >= src->nelts) { - nxt_memcpy(dst->elts, src->elts, src->nelts * size); + if (dst->nalloc >= src->nelts) { + nxt_memcpy(dst->elts, src->elts, src->nelts * size); - } else { - nxt_memcpy(dst->elts, src->elts, dst->nelts * size); + } else { + nxt_memcpy(dst->elts, src->elts, dst->nelts * size); - for (i = dst->nelts; i < src->nelts; i++) { - data = nxt_array_add(dst); - if (nxt_slow_path(data == NULL)) { - return NULL; - } + for (i = dst->nelts; i < src->nelts; i++) { + data = nxt_array_add(dst); + if (nxt_slow_path(data == NULL)) { + return NULL; + } - nxt_memcpy(data, src->elts + (i * size), size); - } + nxt_memcpy(data, src->elts + (i * size), size); } + } - dst->nelts = src->nelts; + dst->nelts = src->nelts; - return dst; + return dst; } diff --git a/src/nxt_array.h b/src/nxt_array.h index f06ff14c8..ed28dde3e 100644 --- a/src/nxt_array.h +++ b/src/nxt_array.h @@ -7,52 +7,40 @@ #ifndef _NXT_ARRAY_H_INCLUDED_ #define _NXT_ARRAY_H_INCLUDED_ - typedef struct { - void *elts; - /* nelts has uint32_t type because it is used most often. */ - uint32_t nelts; - uint16_t size; - uint16_t nalloc; - nxt_mp_t *mem_pool; + void *elts; + /* nelts has uint32_t type because it is used most often. */ + uint32_t nelts; + uint16_t size; + uint16_t nalloc; + nxt_mp_t *mem_pool; } nxt_array_t; - -nxt_inline void -nxt_array_init(nxt_array_t *array, nxt_mp_t *mp, size_t size) -{ - array->elts = nxt_pointer_to(array, sizeof(nxt_array_t)); - array->size = size; - array->mem_pool = mp; +nxt_inline void nxt_array_init(nxt_array_t *array, nxt_mp_t *mp, size_t size) { + array->elts = nxt_pointer_to(array, sizeof(nxt_array_t)); + array->size = size; + array->mem_pool = mp; } NXT_EXPORT nxt_array_t *nxt_array_create(nxt_mp_t *mp, nxt_uint_t n, - size_t size); + size_t size); NXT_EXPORT void nxt_array_destroy(nxt_array_t *array); NXT_EXPORT void *nxt_array_add(nxt_array_t *array); NXT_EXPORT void *nxt_array_zero_add(nxt_array_t *array); NXT_EXPORT void nxt_array_remove(nxt_array_t *array, void *elt); NXT_EXPORT nxt_array_t *nxt_array_copy(nxt_mp_t *mp, nxt_array_t *dst, - nxt_array_t *src); - -#define nxt_array_last(array) \ - nxt_pointer_to((array)->elts, (array)->size * ((array)->nelts - 1)) + nxt_array_t *src); +#define nxt_array_last(array) \ + nxt_pointer_to((array)->elts, (array)->size *((array)->nelts - 1)) -#define nxt_array_reset(array) \ - (array)->nelts = 0; +#define nxt_array_reset(array) (array)->nelts = 0; +#define nxt_array_is_empty(array) ((array)->nelts == 0) -#define nxt_array_is_empty(array) \ - ((array)->nelts == 0) - - -nxt_inline void * -nxt_array_remove_last(nxt_array_t *array) -{ - array->nelts--; - return nxt_pointer_to(array->elts, array->size * array->nelts); +nxt_inline void *nxt_array_remove_last(nxt_array_t *array) { + array->nelts--; + return nxt_pointer_to(array->elts, array->size * array->nelts); } - #endif /* _NXT_ARRAY_H_INCLUDED_ */ diff --git a/src/nxt_atomic.h b/src/nxt_atomic.h index 376375c58..9f987dc4d 100644 --- a/src/nxt_atomic.h +++ b/src/nxt_atomic.h @@ -7,7 +7,6 @@ #ifndef _NXT_ATOMIC_H_INCLUDED_ #define _NXT_ATOMIC_H_INCLUDED_ - /* * nxt_atomic_try_lock() must set an acquire barrier on lock. * nxt_atomic_xchg() must set an acquire barrier. @@ -16,9 +15,9 @@ #if (NXT_HAVE_GCC_ATOMIC) /* GCC 4.1 builtin atomic operations */ -typedef intptr_t nxt_atomic_int_t; -typedef uintptr_t nxt_atomic_uint_t; -typedef volatile nxt_atomic_uint_t nxt_atomic_t; +typedef intptr_t nxt_atomic_int_t; +typedef uintptr_t nxt_atomic_uint_t; +typedef volatile nxt_atomic_uint_t nxt_atomic_t; /* * __sync_bool_compare_and_swap() is a full barrier. @@ -26,47 +25,31 @@ typedef volatile nxt_atomic_uint_t nxt_atomic_t; * __sync_lock_release() is a release barrier. */ -#define nxt_atomic_cmp_set(lock, cmp, set) \ - __sync_bool_compare_and_swap(lock, cmp, set) - - -#define nxt_atomic_xchg(lock, set) \ - __sync_lock_test_and_set(lock, set) - - -#define nxt_atomic_fetch_add(value, add) \ - __sync_fetch_and_add(value, add) - +#define nxt_atomic_cmp_set(lock, cmp, set) \ + __sync_bool_compare_and_swap(lock, cmp, set) -#define nxt_atomic_try_lock(lock) \ - nxt_atomic_cmp_set(lock, 0, 1) +#define nxt_atomic_xchg(lock, set) __sync_lock_test_and_set(lock, set) +#define nxt_atomic_fetch_add(value, add) __sync_fetch_and_add(value, add) -#define nxt_atomic_release(lock) \ - __sync_lock_release(lock) +#define nxt_atomic_try_lock(lock) nxt_atomic_cmp_set(lock, 0, 1) +#define nxt_atomic_release(lock) __sync_lock_release(lock) -#define nxt_atomic_or_fetch(ptr, val) \ - __sync_or_and_fetch(ptr, val) - - -#define nxt_atomic_and_fetch(ptr, val) \ - __sync_and_and_fetch(ptr, val) +#define nxt_atomic_or_fetch(ptr, val) __sync_or_and_fetch(ptr, val) +#define nxt_atomic_and_fetch(ptr, val) __sync_and_and_fetch(ptr, val) #if (__i386__ || __i386 || __amd64__ || __amd64) -#define nxt_cpu_pause() \ - __asm__ ("pause") +#define nxt_cpu_pause() __asm__("pause") #elif (__aarch64__ || __arm64__) -#define nxt_cpu_pause() \ - __asm__ ("isb") +#define nxt_cpu_pause() __asm__("isb") #else #define nxt_cpu_pause() #endif - /* elif (NXT_HAVE_MACOSX_ATOMIC) */ /* @@ -85,8 +68,6 @@ typedef volatile nxt_atomic_uint_t nxt_atomic_t; * and Clang in modern MacOSX systems. */ - #endif /* NXT_HAVE_GCC_ATOMIC */ - #endif /* _NXT_ATOMIC_H_INCLUDED_ */ diff --git a/src/nxt_buf.c b/src/nxt_buf.c index cbde069ed..3544042d8 100644 --- a/src/nxt_buf.c +++ b/src/nxt_buf.c @@ -6,324 +6,280 @@ #include - static void nxt_buf_completion(nxt_task_t *task, void *obj, void *data); static void nxt_buf_ts_completion(nxt_task_t *task, void *obj, void *data); - typedef struct { - nxt_work_t work; - nxt_event_engine_t *engine; + nxt_work_t work; + nxt_event_engine_t *engine; } nxt_buf_ts_t; - -void -nxt_buf_mem_init(nxt_buf_t *b, void *start, size_t size) -{ - b->mem.start = start; - b->mem.pos = start; - b->mem.free = start; - b->mem.end = nxt_pointer_to(start, size); +void nxt_buf_mem_init(nxt_buf_t *b, void *start, size_t size) { + b->mem.start = start; + b->mem.pos = start; + b->mem.free = start; + b->mem.end = nxt_pointer_to(start, size); } +nxt_buf_t *nxt_buf_mem_alloc(nxt_mp_t *mp, size_t size, nxt_uint_t flags) { + nxt_buf_t *b; -nxt_buf_t * -nxt_buf_mem_alloc(nxt_mp_t *mp, size_t size, nxt_uint_t flags) -{ - nxt_buf_t *b; + b = nxt_mp_alloc(mp, NXT_BUF_MEM_SIZE + size); + if (nxt_slow_path(b == NULL)) { + return NULL; + } - b = nxt_mp_alloc(mp, NXT_BUF_MEM_SIZE + size); - if (nxt_slow_path(b == NULL)) { - return NULL; - } + nxt_memzero(b, NXT_BUF_MEM_SIZE); - nxt_memzero(b, NXT_BUF_MEM_SIZE); + b->data = mp; + b->completion_handler = nxt_buf_completion; - b->data = mp; - b->completion_handler = nxt_buf_completion; + if (size != 0) { + b->mem.start = nxt_pointer_to(b, NXT_BUF_MEM_SIZE); + b->mem.pos = b->mem.start; + b->mem.free = b->mem.start; + b->mem.end = b->mem.start + size; + } - if (size != 0) { - b->mem.start = nxt_pointer_to(b, NXT_BUF_MEM_SIZE); - b->mem.pos = b->mem.start; - b->mem.free = b->mem.start; - b->mem.end = b->mem.start + size; - } - - return b; + return b; } +nxt_buf_t *nxt_buf_mem_ts_alloc(nxt_task_t *task, nxt_mp_t *mp, size_t size) { + nxt_buf_t *b; + nxt_buf_ts_t *ts; -nxt_buf_t * -nxt_buf_mem_ts_alloc(nxt_task_t *task, nxt_mp_t *mp, size_t size) -{ - nxt_buf_t *b; - nxt_buf_ts_t *ts; + b = nxt_mp_alloc(mp, NXT_BUF_MEM_SIZE + sizeof(nxt_buf_ts_t) + size); + if (nxt_slow_path(b == NULL)) { + return NULL; + } - b = nxt_mp_alloc(mp, NXT_BUF_MEM_SIZE + sizeof(nxt_buf_ts_t) + size); - if (nxt_slow_path(b == NULL)) { - return NULL; - } + nxt_mp_retain(mp); - nxt_mp_retain(mp); + nxt_memzero(b, NXT_BUF_MEM_SIZE + sizeof(nxt_buf_ts_t)); - nxt_memzero(b, NXT_BUF_MEM_SIZE + sizeof(nxt_buf_ts_t)); + b->data = mp; + b->completion_handler = nxt_buf_ts_completion; + b->is_ts = 1; - b->data = mp; - b->completion_handler = nxt_buf_ts_completion; - b->is_ts = 1; - - if (size != 0) { - b->mem.start = nxt_pointer_to(b, NXT_BUF_MEM_SIZE - + sizeof(nxt_buf_ts_t)); - b->mem.pos = b->mem.start; - b->mem.free = b->mem.start; - b->mem.end = b->mem.start + size; - } + if (size != 0) { + b->mem.start = nxt_pointer_to(b, NXT_BUF_MEM_SIZE + sizeof(nxt_buf_ts_t)); + b->mem.pos = b->mem.start; + b->mem.free = b->mem.start; + b->mem.end = b->mem.start + size; + } - ts = nxt_pointer_to(b, NXT_BUF_MEM_SIZE); - ts->engine = task->thread->engine; + ts = nxt_pointer_to(b, NXT_BUF_MEM_SIZE); + ts->engine = task->thread->engine; - ts->work.handler = nxt_buf_ts_completion; - ts->work.task = task; - ts->work.obj = b; - ts->work.data = b->parent; + ts->work.handler = nxt_buf_ts_completion; + ts->work.task = task; + ts->work.obj = b; + ts->work.data = b->parent; - return b; + return b; } +nxt_buf_t *nxt_buf_file_alloc(nxt_mp_t *mp, size_t size, nxt_uint_t flags) { + nxt_buf_t *b; -nxt_buf_t * -nxt_buf_file_alloc(nxt_mp_t *mp, size_t size, nxt_uint_t flags) -{ - nxt_buf_t *b; + b = nxt_mp_alloc(mp, NXT_BUF_FILE_SIZE + size); + if (nxt_slow_path(b == NULL)) { + return NULL; + } - b = nxt_mp_alloc(mp, NXT_BUF_FILE_SIZE + size); - if (nxt_slow_path(b == NULL)) { - return NULL; - } - - nxt_memzero(b, NXT_BUF_FILE_SIZE); + nxt_memzero(b, NXT_BUF_FILE_SIZE); - b->data = mp; - b->completion_handler = nxt_buf_completion; - nxt_buf_set_file(b); + b->data = mp; + b->completion_handler = nxt_buf_completion; + nxt_buf_set_file(b); - if (size != 0) { - b->mem.start = nxt_pointer_to(b, NXT_BUF_FILE_SIZE); - b->mem.pos = b->mem.start; - b->mem.free = b->mem.start; - b->mem.end = b->mem.start + size; - } + if (size != 0) { + b->mem.start = nxt_pointer_to(b, NXT_BUF_FILE_SIZE); + b->mem.pos = b->mem.start; + b->mem.free = b->mem.start; + b->mem.end = b->mem.start + size; + } - return b; + return b; } +nxt_buf_t *nxt_buf_mmap_alloc(nxt_mp_t *mp, size_t size) { + nxt_buf_t *b; -nxt_buf_t * -nxt_buf_mmap_alloc(nxt_mp_t *mp, size_t size) -{ - nxt_buf_t *b; + b = nxt_mp_zalloc(mp, NXT_BUF_MMAP_SIZE); - b = nxt_mp_zalloc(mp, NXT_BUF_MMAP_SIZE); - - if (nxt_fast_path(b != NULL)) { - b->data = mp; - b->completion_handler = nxt_buf_completion; + if (nxt_fast_path(b != NULL)) { + b->data = mp; + b->completion_handler = nxt_buf_completion; - nxt_buf_set_file(b); - nxt_buf_set_mmap(b); - nxt_buf_mem_set_size(&b->mem, size); - } + nxt_buf_set_file(b); + nxt_buf_set_mmap(b); + nxt_buf_mem_set_size(&b->mem, size); + } - return b; + return b; } +nxt_buf_t *nxt_buf_sync_alloc(nxt_mp_t *mp, nxt_uint_t flags) { + nxt_buf_t *b; -nxt_buf_t * -nxt_buf_sync_alloc(nxt_mp_t *mp, nxt_uint_t flags) -{ - nxt_buf_t *b; + b = nxt_mp_zalloc(mp, NXT_BUF_MEM_SIZE); - b = nxt_mp_zalloc(mp, NXT_BUF_MEM_SIZE); - - if (nxt_fast_path(b != NULL)) { - b->data = mp; - b->completion_handler = nxt_buf_completion; + if (nxt_fast_path(b != NULL)) { + b->data = mp; + b->completion_handler = nxt_buf_completion; - nxt_buf_set_sync(b); - b->is_nobuf = ((flags & NXT_BUF_SYNC_NOBUF) != 0); - b->is_flush = ((flags & NXT_BUF_SYNC_FLUSH) != 0); - b->is_last = ((flags & NXT_BUF_SYNC_LAST) != 0); - } + nxt_buf_set_sync(b); + b->is_nobuf = ((flags & NXT_BUF_SYNC_NOBUF) != 0); + b->is_flush = ((flags & NXT_BUF_SYNC_FLUSH) != 0); + b->is_last = ((flags & NXT_BUF_SYNC_LAST) != 0); + } - return b; + return b; } +void nxt_buf_chain_add(nxt_buf_t **head, nxt_buf_t *in) { + nxt_buf_t *b, **prev; -void -nxt_buf_chain_add(nxt_buf_t **head, nxt_buf_t *in) -{ - nxt_buf_t *b, **prev; - - prev = head; + prev = head; - for (b = *head; b != NULL; b = b->next) { - prev = &b->next; - } + for (b = *head; b != NULL; b = b->next) { + prev = &b->next; + } - *prev = in; + *prev = in; } +size_t nxt_buf_chain_length(nxt_buf_t *b) { + size_t length; -size_t -nxt_buf_chain_length(nxt_buf_t *b) -{ - size_t length; + length = 0; - length = 0; - - while (b != NULL) { - if (!nxt_buf_is_sync(b)) { - length += b->mem.free - b->mem.pos; - } - - b = b->next; + while (b != NULL) { + if (!nxt_buf_is_sync(b)) { + length += b->mem.free - b->mem.pos; } - return length; -} + b = b->next; + } + return length; +} -static void -nxt_buf_completion(nxt_task_t *task, void *obj, void *data) -{ - nxt_mp_t *mp; - nxt_buf_t *b, *next, *parent; +static void nxt_buf_completion(nxt_task_t *task, void *obj, void *data) { + nxt_mp_t *mp; + nxt_buf_t *b, *next, *parent; - b = obj; + b = obj; - nxt_debug(task, "buf completion: %p %p", b, b->mem.start); + nxt_debug(task, "buf completion: %p %p", b, b->mem.start); - nxt_assert(data == b->parent); + nxt_assert(data == b->parent); - do { - next = b->next; - parent = b->parent; - mp = b->data; + do { + next = b->next; + parent = b->parent; + mp = b->data; - nxt_mp_free(mp, b); + nxt_mp_free(mp, b); - nxt_buf_parent_completion(task, parent); + nxt_buf_parent_completion(task, parent); - b = next; - } while (b != NULL); + b = next; + } while (b != NULL); } +void nxt_buf_parent_completion(nxt_task_t *task, nxt_buf_t *parent) { + if (parent != NULL) { + nxt_debug(task, "parent retain:%uD", parent->retain); -void -nxt_buf_parent_completion(nxt_task_t *task, nxt_buf_t *parent) -{ - if (parent != NULL) { - nxt_debug(task, "parent retain:%uD", parent->retain); - - parent->retain--; + parent->retain--; - if (parent->retain == 0) { - parent->mem.pos = parent->mem.free; + if (parent->retain == 0) { + parent->mem.pos = parent->mem.free; - parent->completion_handler(task, parent, parent->parent); - } + parent->completion_handler(task, parent, parent->parent); } + } } +nxt_int_t nxt_buf_ts_handle(nxt_task_t *task, void *obj, void *data) { + nxt_buf_t *b; + nxt_buf_ts_t *ts; -nxt_int_t -nxt_buf_ts_handle(nxt_task_t *task, void *obj, void *data) -{ - nxt_buf_t *b; - nxt_buf_ts_t *ts; + b = obj; - b = obj; + nxt_assert(b->is_ts != 0); - nxt_assert(b->is_ts != 0); + ts = nxt_pointer_to(b, NXT_BUF_MEM_SIZE); - ts = nxt_pointer_to(b, NXT_BUF_MEM_SIZE); + if (ts->engine != task->thread->engine) { - if (ts->engine != task->thread->engine) { + nxt_debug(task, "buf ts: %p current engine is %p, expected %p", b, + task->thread->engine, ts->engine); - nxt_debug(task, "buf ts: %p current engine is %p, expected %p", - b, task->thread->engine, ts->engine); + ts->work.handler = b->completion_handler; + ts->work.obj = obj; + ts->work.data = data; - ts->work.handler = b->completion_handler; - ts->work.obj = obj; - ts->work.data = data; + nxt_event_engine_post(ts->engine, &ts->work); - nxt_event_engine_post(ts->engine, &ts->work); + return 1; + } - return 1; - } - - return 0; + return 0; } +static void nxt_buf_ts_completion(nxt_task_t *task, void *obj, void *data) { + nxt_mp_t *mp; + nxt_buf_t *b, *next, *parent; -static void -nxt_buf_ts_completion(nxt_task_t *task, void *obj, void *data) -{ - nxt_mp_t *mp; - nxt_buf_t *b, *next, *parent; + b = obj; - b = obj; + if (nxt_buf_ts_handle(task, obj, data)) { + return; + } - if (nxt_buf_ts_handle(task, obj, data)) { - return; - } + nxt_debug(task, "buf ts completion: %p %p", b, b->mem.start); - nxt_debug(task, "buf ts completion: %p %p", b, b->mem.start); + nxt_assert(data == b->parent); - nxt_assert(data == b->parent); + do { + next = b->next; + parent = b->parent; + mp = b->data; - do { - next = b->next; - parent = b->parent; - mp = b->data; + nxt_mp_free(mp, b); + nxt_mp_release(mp); - nxt_mp_free(mp, b); - nxt_mp_release(mp); + nxt_buf_parent_completion(task, parent); - nxt_buf_parent_completion(task, parent); - - b = next; - } while (b != NULL); + b = next; + } while (b != NULL); } +nxt_buf_t *nxt_buf_make_plain(nxt_mp_t *mp, nxt_buf_t *src, size_t size) { + nxt_buf_t *b, *i; -nxt_buf_t * -nxt_buf_make_plain(nxt_mp_t *mp, nxt_buf_t *src, size_t size) -{ - nxt_buf_t *b, *i; - - if (nxt_slow_path(size == 0)) { - for (i = src; i != NULL; i = i->next) { - size += nxt_buf_used_size(i); - } + if (nxt_slow_path(size == 0)) { + for (i = src; i != NULL; i = i->next) { + size += nxt_buf_used_size(i); } + } - b = nxt_buf_mem_alloc(mp, size, 0); + b = nxt_buf_mem_alloc(mp, size, 0); - if (nxt_slow_path(b == NULL)) { - return NULL; - } + if (nxt_slow_path(b == NULL)) { + return NULL; + } - for (i = src; i != NULL; i = i->next) { - if (nxt_slow_path(nxt_buf_mem_free_size(&b->mem) - < nxt_buf_used_size(i))) - { - break; - } - - b->mem.free = nxt_cpymem(b->mem.free, i->mem.pos, nxt_buf_used_size(i)); + for (i = src; i != NULL; i = i->next) { + if (nxt_slow_path(nxt_buf_mem_free_size(&b->mem) < nxt_buf_used_size(i))) { + break; } - return b; + b->mem.free = nxt_cpymem(b->mem.free, i->mem.pos, nxt_buf_used_size(i)); + } + + return b; } diff --git a/src/nxt_buf.h b/src/nxt_buf.h index a561ef4e1..b0b81620d 100644 --- a/src/nxt_buf.h +++ b/src/nxt_buf.h @@ -7,7 +7,6 @@ #ifndef _NXT_BUF_H_INCLUDED_ #define _NXT_BUF_H_INCLUDED_ - /* * There are four types of buffers. They are different sizes, so they * should be allocated by appropriate nxt_buf_XXX_alloc() function. @@ -57,167 +56,125 @@ */ typedef struct { - u_char *pos; - u_char *free; - u_char *start; - u_char *end; + u_char *pos; + u_char *free; + u_char *start; + u_char *end; } nxt_buf_mem_t; - struct nxt_buf_s { - void *data; - nxt_work_handler_t completion_handler; - void *parent; - - /* - * The next link, flags, and nxt_buf_mem_t should - * reside together to improve cache locality. - */ - nxt_buf_t *next; - - uint32_t retain; - - uint8_t cache_hint; - - uint8_t is_file:1; - uint8_t is_mmap:1; - uint8_t is_port_mmap:1; - uint8_t is_sync:1; - uint8_t is_nobuf:1; - uint8_t is_flush:1; - uint8_t is_last:1; - uint8_t is_port_mmap_sent:1; - uint8_t is_ts:1; - - nxt_buf_mem_t mem; - - /* The file and mmap parts are not allocated by nxt_buf_mem_alloc(). */ - nxt_file_t *file; - nxt_off_t file_pos; - nxt_off_t file_end; - - /* The mmap part is not allocated by nxt_buf_file_alloc(). */ - nxt_mem_map_file_ctx_t (mmap) + void *data; + nxt_work_handler_t completion_handler; + void *parent; + + /* + * The next link, flags, and nxt_buf_mem_t should + * reside together to improve cache locality. + */ + nxt_buf_t *next; + + uint32_t retain; + + uint8_t cache_hint; + + uint8_t is_file : 1; + uint8_t is_mmap : 1; + uint8_t is_port_mmap : 1; + uint8_t is_sync : 1; + uint8_t is_nobuf : 1; + uint8_t is_flush : 1; + uint8_t is_last : 1; + uint8_t is_port_mmap_sent : 1; + uint8_t is_ts : 1; + + nxt_buf_mem_t mem; + + /* The file and mmap parts are not allocated by nxt_buf_mem_alloc(). */ + nxt_file_t *file; + nxt_off_t file_pos; + nxt_off_t file_end; + + /* The mmap part is not allocated by nxt_buf_file_alloc(). */ + nxt_mem_map_file_ctx_t(mmap) }; +#define NXT_BUF_SYNC_SIZE offsetof(nxt_buf_t, mem.free) +#define NXT_BUF_MEM_SIZE offsetof(nxt_buf_t, file) +#define NXT_BUF_FILE_SIZE sizeof(nxt_buf_t) +#define NXT_BUF_MMAP_SIZE NXT_BUF_FILE_SIZE +#define NXT_BUF_PORT_MMAP_SIZE NXT_BUF_MEM_SIZE -#define NXT_BUF_SYNC_SIZE offsetof(nxt_buf_t, mem.free) -#define NXT_BUF_MEM_SIZE offsetof(nxt_buf_t, file) -#define NXT_BUF_FILE_SIZE sizeof(nxt_buf_t) -#define NXT_BUF_MMAP_SIZE NXT_BUF_FILE_SIZE -#define NXT_BUF_PORT_MMAP_SIZE NXT_BUF_MEM_SIZE - - -#define NXT_BUF_SYNC_NOBUF 1 -#define NXT_BUF_SYNC_FLUSH 2 -#define NXT_BUF_SYNC_LAST 4 - - -#define nxt_buf_is_mem(b) \ - ((b)->mem.pos != NULL) - - -#define nxt_buf_is_file(b) \ - ((b)->is_file) - -#define nxt_buf_set_file(b) \ - (b)->is_file = 1 - -#define nxt_buf_clear_file(b) \ - (b)->is_file = 0 - +#define NXT_BUF_SYNC_NOBUF 1 +#define NXT_BUF_SYNC_FLUSH 2 +#define NXT_BUF_SYNC_LAST 4 -#define nxt_buf_is_mmap(b) \ - ((b)->is_mmap) +#define nxt_buf_is_mem(b) ((b)->mem.pos != NULL) -#define nxt_buf_set_mmap(b) \ - (b)->is_mmap = 1 +#define nxt_buf_is_file(b) ((b)->is_file) -#define nxt_buf_clear_mmap(b) \ - (b)->is_mmap = 0 +#define nxt_buf_set_file(b) (b)->is_file = 1 +#define nxt_buf_clear_file(b) (b)->is_file = 0 -#define nxt_buf_is_port_mmap(b) \ - ((b)->is_port_mmap) +#define nxt_buf_is_mmap(b) ((b)->is_mmap) -#define nxt_buf_set_port_mmap(b) \ - (b)->is_port_mmap = 1 +#define nxt_buf_set_mmap(b) (b)->is_mmap = 1 -#define nxt_buf_clear_port_mmap(b) \ - (b)->is_port_mmap = 0 +#define nxt_buf_clear_mmap(b) (b)->is_mmap = 0 +#define nxt_buf_is_port_mmap(b) ((b)->is_port_mmap) -#define nxt_buf_is_sync(b) \ - ((b)->is_sync) +#define nxt_buf_set_port_mmap(b) (b)->is_port_mmap = 1 -#define nxt_buf_set_sync(b) \ - (b)->is_sync = 1 +#define nxt_buf_clear_port_mmap(b) (b)->is_port_mmap = 0 -#define nxt_buf_clear_sync(b) \ - (b)->is_sync = 0 +#define nxt_buf_is_sync(b) ((b)->is_sync) +#define nxt_buf_set_sync(b) (b)->is_sync = 1 -#define nxt_buf_is_nobuf(b) \ - ((b)->is_nobuf) +#define nxt_buf_clear_sync(b) (b)->is_sync = 0 -#define nxt_buf_set_nobuf(b) \ - (b)->is_nobuf = 1 +#define nxt_buf_is_nobuf(b) ((b)->is_nobuf) -#define nxt_buf_clear_nobuf(b) \ - (b)->is_nobuf = 0 +#define nxt_buf_set_nobuf(b) (b)->is_nobuf = 1 +#define nxt_buf_clear_nobuf(b) (b)->is_nobuf = 0 -#define nxt_buf_is_flush(b) \ - ((b)->is_flush) +#define nxt_buf_is_flush(b) ((b)->is_flush) -#define nxt_buf_set_flush(b) \ - (b)->is_flush = 1 +#define nxt_buf_set_flush(b) (b)->is_flush = 1 -#define nxt_buf_clear_flush(b) \ - (b)->is_flush = 0 +#define nxt_buf_clear_flush(b) (b)->is_flush = 0 +#define nxt_buf_is_last(b) ((b)->is_last) -#define nxt_buf_is_last(b) \ - ((b)->is_last) +#define nxt_buf_set_last(b) (b)->is_last = 1 -#define nxt_buf_set_last(b) \ - (b)->is_last = 1 +#define nxt_buf_clear_last(b) (b)->is_last = 0 -#define nxt_buf_clear_last(b) \ - (b)->is_last = 0 +#define nxt_buf_mem_set_size(bm, size) \ + do { \ + (bm)->start = 0; \ + (bm)->end = (void *)size; \ + } while (0) +#define nxt_buf_mem_size(bm) ((bm)->end - (bm)->start) -#define nxt_buf_mem_set_size(bm, size) \ - do { \ - (bm)->start = 0; \ - (bm)->end = (void *) size; \ - } while (0) +#define nxt_buf_mem_used_size(bm) ((bm)->free - (bm)->pos) +#define nxt_buf_mem_free_size(bm) ((bm)->end - (bm)->free) -#define nxt_buf_mem_size(bm) \ - ((bm)->end - (bm)->start) - - -#define nxt_buf_mem_used_size(bm) \ - ((bm)->free - (bm)->pos) - - -#define nxt_buf_mem_free_size(bm) \ - ((bm)->end - (bm)->free) - - -#define nxt_buf_used_size(b) \ - (nxt_buf_is_file(b) ? (b)->file_end - (b)->file_pos: \ - nxt_buf_mem_used_size(&(b)->mem)) - +#define nxt_buf_used_size(b) \ + (nxt_buf_is_file(b) ? (b)->file_end - (b)->file_pos \ + : nxt_buf_mem_used_size(&(b)->mem)) NXT_EXPORT void nxt_buf_mem_init(nxt_buf_t *b, void *start, size_t size); NXT_EXPORT nxt_buf_t *nxt_buf_mem_alloc(nxt_mp_t *mp, size_t size, - nxt_uint_t flags); + nxt_uint_t flags); NXT_EXPORT nxt_buf_t *nxt_buf_mem_ts_alloc(nxt_task_t *task, nxt_mp_t *mp, - size_t size); + size_t size); NXT_EXPORT nxt_buf_t *nxt_buf_file_alloc(nxt_mp_t *mp, size_t size, - nxt_uint_t flags); + nxt_uint_t flags); NXT_EXPORT nxt_buf_t *nxt_buf_mmap_alloc(nxt_mp_t *mp, size_t size); NXT_EXPORT nxt_buf_t *nxt_buf_sync_alloc(nxt_mp_t *mp, nxt_uint_t flags); @@ -225,45 +182,35 @@ NXT_EXPORT nxt_int_t nxt_buf_ts_handle(nxt_task_t *task, void *obj, void *data); NXT_EXPORT void nxt_buf_parent_completion(nxt_task_t *task, nxt_buf_t *parent); NXT_EXPORT nxt_buf_t *nxt_buf_make_plain(nxt_mp_t *mp, nxt_buf_t *src, - size_t size); + size_t size); -nxt_inline nxt_buf_t * -nxt_buf_chk_make_plain(nxt_mp_t *mp, nxt_buf_t *src, size_t size) -{ - if (nxt_slow_path(src != NULL && src->next != NULL)) { - return nxt_buf_make_plain(mp, src, size); - } +nxt_inline nxt_buf_t *nxt_buf_chk_make_plain(nxt_mp_t *mp, nxt_buf_t *src, + size_t size) { + if (nxt_slow_path(src != NULL && src->next != NULL)) { + return nxt_buf_make_plain(mp, src, size); + } - return src; + return src; } -#define nxt_buf_free(mp, b) \ - nxt_mp_free((mp), (b)) - +#define nxt_buf_free(mp, b) nxt_mp_free((mp), (b)) NXT_EXPORT void nxt_buf_chain_add(nxt_buf_t **head, nxt_buf_t *in); NXT_EXPORT size_t nxt_buf_chain_length(nxt_buf_t *b); -nxt_inline nxt_buf_t * -nxt_buf_cpy(nxt_buf_t *b, const void *src, size_t length) -{ - nxt_memcpy(b->mem.free, src, length); - b->mem.free += length; +nxt_inline nxt_buf_t *nxt_buf_cpy(nxt_buf_t *b, const void *src, + size_t length) { + nxt_memcpy(b->mem.free, src, length); + b->mem.free += length; - return b; + return b; } -nxt_inline nxt_buf_t * -nxt_buf_cpystr(nxt_buf_t *b, const nxt_str_t *str) -{ - return nxt_buf_cpy(b, str->start, str->length); -} - - -nxt_inline void -nxt_buf_dummy_completion(nxt_task_t *task, void *obj, void *data) -{ +nxt_inline nxt_buf_t *nxt_buf_cpystr(nxt_buf_t *b, const nxt_str_t *str) { + return nxt_buf_cpy(b, str->start, str->length); } +nxt_inline void nxt_buf_dummy_completion(nxt_task_t *task, void *obj, + void *data) {} #endif /* _NXT_BUF_H_INCLIDED_ */ diff --git a/src/nxt_buf_pool.c b/src/nxt_buf_pool.c index f2be88a79..b966b0111 100644 --- a/src/nxt_buf_pool.c +++ b/src/nxt_buf_pool.c @@ -6,180 +6,165 @@ #include +nxt_int_t nxt_buf_pool_mem_alloc(nxt_buf_pool_t *bp, size_t size) { + nxt_buf_t *b; -nxt_int_t -nxt_buf_pool_mem_alloc(nxt_buf_pool_t *bp, size_t size) -{ - nxt_buf_t *b; + b = bp->current; - b = bp->current; + if (b != NULL && b->mem.free < b->mem.end) { + return NXT_OK; + } - if (b != NULL && b->mem.free < b->mem.end) { - return NXT_OK; - } + b = bp->free; - b = bp->free; + if (b != NULL) { + bp->current = b; + bp->free = b->next; + b->next = NULL; + return NXT_OK; + } - if (b != NULL) { - bp->current = b; - bp->free = b->next; - b->next = NULL; - return NXT_OK; - } + if (bp->num >= bp->max) { + return NXT_AGAIN; + } - if (bp->num >= bp->max) { - return NXT_AGAIN; - } + if (size == 0 || size >= bp->size + bp->size / 4) { + size = bp->size; + } - if (size == 0 || size >= bp->size + bp->size / 4) { - size = bp->size; - } + b = nxt_buf_mem_alloc(bp->mem_pool, size, bp->flags); - b = nxt_buf_mem_alloc(bp->mem_pool, size, bp->flags); + if (nxt_fast_path(b != NULL)) { + bp->current = b; + bp->num++; + return NXT_OK; + } - if (nxt_fast_path(b != NULL)) { - bp->current = b; - bp->num++; - return NXT_OK; - } - - return NXT_ERROR; + return NXT_ERROR; } +nxt_int_t nxt_buf_pool_file_alloc(nxt_buf_pool_t *bp, size_t size) { + nxt_buf_t *b; -nxt_int_t -nxt_buf_pool_file_alloc(nxt_buf_pool_t *bp, size_t size) -{ - nxt_buf_t *b; + b = bp->current; - b = bp->current; + if (b != NULL && b->mem.free < b->mem.end) { + return NXT_OK; + } - if (b != NULL && b->mem.free < b->mem.end) { - return NXT_OK; - } + b = bp->free; - b = bp->free; + if (b != NULL) { + bp->current = b; + bp->free = b->next; + b->next = NULL; + return NXT_OK; + } - if (b != NULL) { - bp->current = b; - bp->free = b->next; - b->next = NULL; - return NXT_OK; - } - - if (bp->num >= bp->max) { - return NXT_AGAIN; - } + if (bp->num >= bp->max) { + return NXT_AGAIN; + } - if (size == 0 || size >= bp->size + bp->size / 4) { - size = bp->size; - } + if (size == 0 || size >= bp->size + bp->size / 4) { + size = bp->size; + } - b = nxt_buf_file_alloc(bp->mem_pool, size, bp->flags); + b = nxt_buf_file_alloc(bp->mem_pool, size, bp->flags); - if (nxt_fast_path(b != NULL)) { - bp->current = b; - bp->num++; - return NXT_OK; - } + if (nxt_fast_path(b != NULL)) { + bp->current = b; + bp->num++; + return NXT_OK; + } - return NXT_ERROR; + return NXT_ERROR; } +nxt_int_t nxt_buf_pool_mmap_alloc(nxt_buf_pool_t *bp, size_t size) { + nxt_buf_t *b; -nxt_int_t -nxt_buf_pool_mmap_alloc(nxt_buf_pool_t *bp, size_t size) -{ - nxt_buf_t *b; - - b = bp->current; + b = bp->current; - if (b != NULL) { - return NXT_OK; - } + if (b != NULL) { + return NXT_OK; + } - b = bp->free; + b = bp->free; - if (b != NULL) { - bp->current = b; - bp->free = b->next; - b->next = NULL; - return NXT_OK; - } + if (b != NULL) { + bp->current = b; + bp->free = b->next; + b->next = NULL; + return NXT_OK; + } - if (bp->num >= bp->max) { - return NXT_AGAIN; - } + if (bp->num >= bp->max) { + return NXT_AGAIN; + } - if (size == 0 || size >= bp->size + bp->size / 4) { - size = bp->size; - } + if (size == 0 || size >= bp->size + bp->size / 4) { + size = bp->size; + } - b = nxt_buf_mmap_alloc(bp->mem_pool, size); + b = nxt_buf_mmap_alloc(bp->mem_pool, size); - if (nxt_fast_path(b != NULL)) { - bp->mmap = 1; - bp->current = b; - bp->num++; - return NXT_OK; - } + if (nxt_fast_path(b != NULL)) { + bp->mmap = 1; + bp->current = b; + bp->num++; + return NXT_OK; + } - return NXT_ERROR; + return NXT_ERROR; } +void nxt_buf_pool_free(nxt_buf_pool_t *bp, nxt_buf_t *b) { + size_t size; -void -nxt_buf_pool_free(nxt_buf_pool_t *bp, nxt_buf_t *b) -{ - size_t size; - - nxt_thread_log_debug("buf pool free: %p %p", b, b->mem.start); + nxt_thread_log_debug("buf pool free: %p %p", b, b->mem.start); - size = nxt_buf_mem_size(&b->mem); + size = nxt_buf_mem_size(&b->mem); - if (bp->mmap) { - nxt_mem_unmap(b->mem.start, &b->mmap, size); - } + if (bp->mmap) { + nxt_mem_unmap(b->mem.start, &b->mmap, size); + } - if (bp->destroy) { + if (bp->destroy) { - if (b == bp->current) { - bp->current = NULL; - } + if (b == bp->current) { + bp->current = NULL; + } - nxt_buf_free(bp->mem_pool, b); + nxt_buf_free(bp->mem_pool, b); - return; - } + return; + } - if (bp->mmap) { - b->mem.pos = NULL; - b->mem.free = NULL; - nxt_buf_mem_set_size(&b->mem, size); + if (bp->mmap) { + b->mem.pos = NULL; + b->mem.free = NULL; + nxt_buf_mem_set_size(&b->mem, size); - } else { - b->mem.pos = b->mem.start; - b->mem.free = b->mem.start; - } + } else { + b->mem.pos = b->mem.start; + b->mem.free = b->mem.start; + } - if (b != bp->current) { - b->next = bp->free; - bp->free = b; - } + if (b != bp->current) { + b->next = bp->free; + bp->free = b; + } } +void nxt_buf_pool_destroy(nxt_buf_pool_t *bp) { + nxt_buf_t *b, *n; -void -nxt_buf_pool_destroy(nxt_buf_pool_t *bp) -{ - nxt_buf_t *b, *n; - - bp->destroy = 1; + bp->destroy = 1; - for (b = bp->free; b != NULL; b = n) { - n = b->next; - nxt_buf_free(bp->mem_pool, b); - } + for (b = bp->free; b != NULL; b = n) { + n = b->next; + nxt_buf_free(bp->mem_pool, b); + } - bp->free = b; /* NULL */ + bp->free = b; /* NULL */ } diff --git a/src/nxt_buf_pool.h b/src/nxt_buf_pool.h index 3d22d7fa0..5bb9c0f0e 100644 --- a/src/nxt_buf_pool.h +++ b/src/nxt_buf_pool.h @@ -7,7 +7,6 @@ #ifndef _NXT_BUF_POOL_H_INCLUDED_ #define _NXT_BUF_POOL_H_INCLUDED_ - /* * nxt_buf_pool_t is intended to allocate up to the "max" number * memory, memory/file, or mmap/file buffers. A size of the buffers @@ -18,58 +17,47 @@ */ typedef struct { - nxt_buf_t *current; - nxt_buf_t *free; - nxt_mp_t *mem_pool; + nxt_buf_t *current; + nxt_buf_t *free; + nxt_mp_t *mem_pool; - uint16_t num; - uint16_t max; + uint16_t num; + uint16_t max; - uint32_t size; + uint32_t size; - uint8_t flags; /* 2 bits */ - uint8_t destroy; /* 1 bit */ - uint8_t mmap; /* 1 bit */ + uint8_t flags; /* 2 bits */ + uint8_t destroy; /* 1 bit */ + uint8_t mmap; /* 1 bit */ } nxt_buf_pool_t; - NXT_EXPORT nxt_int_t nxt_buf_pool_mem_alloc(nxt_buf_pool_t *bp, size_t size); NXT_EXPORT nxt_int_t nxt_buf_pool_file_alloc(nxt_buf_pool_t *bp, size_t size); NXT_EXPORT nxt_int_t nxt_buf_pool_mmap_alloc(nxt_buf_pool_t *bp, size_t size); NXT_EXPORT void nxt_buf_pool_free(nxt_buf_pool_t *bp, nxt_buf_t *b); NXT_EXPORT void nxt_buf_pool_destroy(nxt_buf_pool_t *bp); - /* There is ready free buffer. */ -#define nxt_buf_pool_ready(bp) \ - ((bp)->free != NULL \ - || ((bp)->current != NULL \ - && (bp)->current->mem.free < (bp)->current->mem.end)) - +#define nxt_buf_pool_ready(bp) \ + ((bp)->free != NULL || ((bp)->current != NULL && \ + (bp)->current->mem.free < (bp)->current->mem.end)) /* A free buffer is allowed to be allocated. */ -#define nxt_buf_pool_obtainable(bp) \ - ((bp)->num < (bp)->max) - +#define nxt_buf_pool_obtainable(bp) ((bp)->num < (bp)->max) /* There is ready free buffer or it is allowed to be allocated. */ -#define nxt_buf_pool_available(bp) \ - (nxt_buf_pool_obtainable(bp) || nxt_buf_pool_ready(bp)) - +#define nxt_buf_pool_available(bp) \ + (nxt_buf_pool_obtainable(bp) || nxt_buf_pool_ready(bp)) /* Reserve allocation of "n" free buffers as they were allocated. */ -#define nxt_buf_pool_reserve(bp, n) \ - (bp)->num += (n) - +#define nxt_buf_pool_reserve(bp, n) (bp)->num += (n) /* Release a reservation. */ -#define nxt_buf_pool_release(bp, n) \ - (bp)->num -= (n) - +#define nxt_buf_pool_release(bp, n) (bp)->num -= (n) #endif /* _NXT_BUF_POOL_H_INCLUDED_ */ diff --git a/src/nxt_capability.c b/src/nxt_capability.c index 9f36ab997..b99f19a92 100644 --- a/src/nxt_capability.c +++ b/src/nxt_capability.c @@ -10,110 +10,96 @@ #include #include - #if (_LINUX_CAPABILITY_VERSION_3) -#define NXT_CAPABILITY_VERSION _LINUX_CAPABILITY_VERSION_3 +#define NXT_CAPABILITY_VERSION _LINUX_CAPABILITY_VERSION_3 #elif (_LINUX_CAPABILITY_VERSION_2) -#define NXT_CAPABILITY_VERSION _LINUX_CAPABILITY_VERSION_2 +#define NXT_CAPABILITY_VERSION _LINUX_CAPABILITY_VERSION_2 #else -#define NXT_CAPABILITY_VERSION _LINUX_CAPABILITY_VERSION +#define NXT_CAPABILITY_VERSION _LINUX_CAPABILITY_VERSION #endif - -#define nxt_capget(hdrp, datap) \ - syscall(SYS_capget, hdrp, datap) -#define nxt_capset(hdrp, datap) \ - syscall(SYS_capset, hdrp, datap) +#define nxt_capget(hdrp, datap) syscall(SYS_capget, hdrp, datap) +#define nxt_capset(hdrp, datap) syscall(SYS_capset, hdrp, datap) #endif /* NXT_HAVE_LINUX_CAPABILITY */ - static nxt_int_t nxt_capability_specific_set(nxt_task_t *task, - nxt_capabilities_t *cap); - + nxt_capabilities_t *cap); -nxt_int_t -nxt_capability_set(nxt_task_t *task, nxt_capabilities_t *cap) -{ - nxt_assert(cap->setid == 0); +nxt_int_t nxt_capability_set(nxt_task_t *task, nxt_capabilities_t *cap) { + nxt_assert(cap->setid == 0); - if (geteuid() == 0) { - cap->setid = 1; - cap->chroot = 1; - return NXT_OK; - } + if (geteuid() == 0) { + cap->setid = 1; + cap->chroot = 1; + return NXT_OK; + } - return nxt_capability_specific_set(task, cap); + return nxt_capability_specific_set(task, cap); } - #if (NXT_HAVE_LINUX_CAPABILITY) -static uint32_t -nxt_capability_linux_get_version(void) -{ - struct __user_cap_header_struct hdr; +static uint32_t nxt_capability_linux_get_version(void) { + struct __user_cap_header_struct hdr; - hdr.version = NXT_CAPABILITY_VERSION; - hdr.pid = nxt_pid; + hdr.version = NXT_CAPABILITY_VERSION; + hdr.pid = nxt_pid; - nxt_capget(&hdr, NULL); - return hdr.version; + nxt_capget(&hdr, NULL); + return hdr.version; } +static nxt_int_t nxt_capability_specific_set(nxt_task_t *task, + nxt_capabilities_t *cap) { + struct __user_cap_data_struct *val, data[2]; + struct __user_cap_header_struct hdr; + + /* + * Linux capability v1 fills an u32 struct. + * Linux capability v2 and v3 fills an u64 struct. + * We allocate data[2] for compatibility, we waste 4 bytes on v1. + * + * This is safe as we only need to check CAP_SETUID and CAP_SETGID + * that resides in the first 32-bit chunk. + */ + + val = &data[0]; + + /* + * Ask the kernel the preferred capability version + * instead of using _LINUX_CAPABILITY_VERSION from header. + * This is safer when distributing a pre-compiled Unit binary. + */ + hdr.version = nxt_capability_linux_get_version(); + hdr.pid = nxt_pid; + + if (nxt_slow_path(nxt_capget(&hdr, val) == -1)) { + nxt_alert(task, "failed to get process capabilities: %E", nxt_errno); + return NXT_ERROR; + } + + if ((val->effective & (1 << CAP_SYS_CHROOT)) != 0) { + cap->chroot = 1; + } + + if ((val->effective & (1 << CAP_SETUID)) == 0) { + return NXT_OK; + } -static nxt_int_t -nxt_capability_specific_set(nxt_task_t *task, nxt_capabilities_t *cap) -{ - struct __user_cap_data_struct *val, data[2]; - struct __user_cap_header_struct hdr; - - /* - * Linux capability v1 fills an u32 struct. - * Linux capability v2 and v3 fills an u64 struct. - * We allocate data[2] for compatibility, we waste 4 bytes on v1. - * - * This is safe as we only need to check CAP_SETUID and CAP_SETGID - * that resides in the first 32-bit chunk. - */ - - val = &data[0]; - - /* - * Ask the kernel the preferred capability version - * instead of using _LINUX_CAPABILITY_VERSION from header. - * This is safer when distributing a pre-compiled Unit binary. - */ - hdr.version = nxt_capability_linux_get_version(); - hdr.pid = nxt_pid; - - if (nxt_slow_path(nxt_capget(&hdr, val) == -1)) { - nxt_alert(task, "failed to get process capabilities: %E", nxt_errno); - return NXT_ERROR; - } - - if ((val->effective & (1 << CAP_SYS_CHROOT)) != 0) { - cap->chroot = 1; - } - - if ((val->effective & (1 << CAP_SETUID)) == 0) { - return NXT_OK; - } - - if ((val->effective & (1 << CAP_SETGID)) == 0) { - return NXT_OK; - } - - cap->setid = 1; + if ((val->effective & (1 << CAP_SETGID)) == 0) { return NXT_OK; + } + + cap->setid = 1; + return NXT_OK; } #else -static nxt_int_t -nxt_capability_specific_set(nxt_task_t *task, nxt_capabilities_t *cap) -{ - return NXT_OK; +static nxt_int_t nxt_capability_specific_set(nxt_task_t *task, + nxt_capabilities_t *cap) { + return NXT_OK; } #endif diff --git a/src/nxt_capability.h b/src/nxt_capability.h index 1575d4094..b16d1343a 100644 --- a/src/nxt_capability.h +++ b/src/nxt_capability.h @@ -7,12 +7,11 @@ #define _NXT_CAPABILITY_INCLUDED_ typedef struct { - uint8_t setid; /* 1 bit */ - uint8_t chroot; /* 1 bit */ + uint8_t setid; /* 1 bit */ + uint8_t chroot; /* 1 bit */ } nxt_capabilities_t; - NXT_EXPORT nxt_int_t nxt_capability_set(nxt_task_t *task, - nxt_capabilities_t *cap); + nxt_capabilities_t *cap); #endif /* _NXT_CAPABILITY_INCLUDED_ */ diff --git a/src/nxt_cert.c b/src/nxt_cert.c index 4a1f14961..ad1c75d63 100644 --- a/src/nxt_cert.c +++ b/src/nxt_cert.c @@ -18,934 +18,862 @@ #include #include - struct nxt_cert_s { - EVP_PKEY *key; - nxt_uint_t count; - X509 *chain[]; + EVP_PKEY *key; + nxt_uint_t count; + X509 *chain[]; }; - typedef struct { - nxt_str_t name; - nxt_conf_value_t *value; - nxt_mp_t *mp; + nxt_str_t name; + nxt_conf_value_t *value; + nxt_mp_t *mp; } nxt_cert_info_t; - typedef struct { - nxt_str_t name; - nxt_fd_t fd; + nxt_str_t name; + nxt_fd_t fd; } nxt_cert_item_t; - static nxt_cert_t *nxt_cert_fd(nxt_task_t *task, nxt_fd_t fd); static nxt_cert_t *nxt_cert_bio(nxt_task_t *task, BIO *bio); static int nxt_nxt_cert_pem_suffix(char *pem_str, const char *suffix); static nxt_conf_value_t *nxt_cert_details(nxt_mp_t *mp, nxt_cert_t *cert); static nxt_conf_value_t *nxt_cert_name_details(nxt_mp_t *mp, X509 *x509, - nxt_bool_t issuer); -static nxt_conf_value_t *nxt_cert_alt_names_details(nxt_mp_t *mp, - STACK_OF(GENERAL_NAME) *alt_names); + nxt_bool_t issuer); +static nxt_conf_value_t * +nxt_cert_alt_names_details(nxt_mp_t *mp, STACK_OF(GENERAL_NAME) * alt_names); static void nxt_cert_buf_completion(nxt_task_t *task, void *obj, void *data); +static nxt_lvlhsh_t nxt_cert_info; -static nxt_lvlhsh_t nxt_cert_info; - +nxt_cert_t *nxt_cert_mem(nxt_task_t *task, nxt_buf_mem_t *mbuf) { + BIO *bio; + nxt_cert_t *cert; -nxt_cert_t * -nxt_cert_mem(nxt_task_t *task, nxt_buf_mem_t *mbuf) -{ - BIO *bio; - nxt_cert_t *cert; + bio = BIO_new_mem_buf(mbuf->pos, nxt_buf_mem_used_size(mbuf)); + if (nxt_slow_path(bio == NULL)) { + nxt_openssl_log_error(task, NXT_LOG_ALERT, "BIO_new_mem_buf() failed"); + return NULL; + } - bio = BIO_new_mem_buf(mbuf->pos, nxt_buf_mem_used_size(mbuf)); - if (nxt_slow_path(bio == NULL)) { - nxt_openssl_log_error(task, NXT_LOG_ALERT, "BIO_new_mem_buf() failed"); - return NULL; - } + cert = nxt_cert_bio(task, bio); - cert = nxt_cert_bio(task, bio); + BIO_free(bio); - BIO_free(bio); - - return cert; + return cert; } +static nxt_cert_t *nxt_cert_fd(nxt_task_t *task, nxt_fd_t fd) { + BIO *bio; + nxt_cert_t *cert; -static nxt_cert_t * -nxt_cert_fd(nxt_task_t *task, nxt_fd_t fd) -{ - BIO *bio; - nxt_cert_t *cert; - - bio = BIO_new_fd(fd, 0); - if (nxt_slow_path(bio == NULL)) { - nxt_openssl_log_error(task, NXT_LOG_ALERT, "BIO_new_fd() failed"); - return NULL; - } + bio = BIO_new_fd(fd, 0); + if (nxt_slow_path(bio == NULL)) { + nxt_openssl_log_error(task, NXT_LOG_ALERT, "BIO_new_fd() failed"); + return NULL; + } - cert = nxt_cert_bio(task, bio); + cert = nxt_cert_bio(task, bio); - BIO_free(bio); + BIO_free(bio); - return cert; + return cert; } +static nxt_cert_t *nxt_cert_bio(nxt_task_t *task, BIO *bio) { + int ret, suffix, key_id; + long length, reason; + char *type, *header; + X509 *x509; + EVP_PKEY *key; + nxt_uint_t nalloc; + nxt_cert_t *cert, *new_cert; + u_char *data; + const u_char *data_copy; + PKCS8_PRIV_KEY_INFO *p8inf; + const EVP_PKEY_ASN1_METHOD *ameth; + + nalloc = 4; + + cert = nxt_zalloc(sizeof(nxt_cert_t) + nalloc * sizeof(X509 *)); + if (cert == NULL) { + return NULL; + } -static nxt_cert_t * -nxt_cert_bio(nxt_task_t *task, BIO *bio) -{ - int ret, suffix, key_id; - long length, reason; - char *type, *header; - X509 *x509; - EVP_PKEY *key; - nxt_uint_t nalloc; - nxt_cert_t *cert, *new_cert; - u_char *data; - const u_char *data_copy; - PKCS8_PRIV_KEY_INFO *p8inf; - const EVP_PKEY_ASN1_METHOD *ameth; - - nalloc = 4; - - cert = nxt_zalloc(sizeof(nxt_cert_t) + nalloc * sizeof(X509 *)); - if (cert == NULL) { - return NULL; - } - - for ( ;; ) { - ret = PEM_read_bio(bio, &type, &header, &data, &length); - - if (ret == 0) { - reason = ERR_GET_REASON(ERR_peek_last_error()); - if (reason != PEM_R_NO_START_LINE) { - nxt_openssl_log_error(task, NXT_LOG_ALERT, - "PEM_read_bio() failed"); - goto fail; - } - - ERR_clear_error(); - break; - } - - nxt_debug(task, "PEM type: \"%s\"", type); + for (;;) { + ret = PEM_read_bio(bio, &type, &header, &data, &length); - key = NULL; - x509 = NULL; -/* - EVP_CIPHER_INFO cipher; + if (ret == 0) { + reason = ERR_GET_REASON(ERR_peek_last_error()); + if (reason != PEM_R_NO_START_LINE) { + nxt_openssl_log_error(task, NXT_LOG_ALERT, "PEM_read_bio() failed"); + goto fail; + } - if (PEM_get_EVP_CIPHER_INFO(header, &cipher) != 0) { - nxt_alert(task, "encrypted PEM isn't supported"); - goto done; - } -*/ - if (nxt_strcmp(type, PEM_STRING_PKCS8) == 0) { - nxt_alert(task, "PEM PKCS8 isn't supported"); - goto done; - } + ERR_clear_error(); + break; + } - if (nxt_strcmp(type, PEM_STRING_PKCS8INF) == 0) { - data_copy = data; + nxt_debug(task, "PEM type: \"%s\"", type); - p8inf = d2i_PKCS8_PRIV_KEY_INFO(NULL, &data_copy, length); + key = NULL; + x509 = NULL; + /* + EVP_CIPHER_INFO cipher; - if (p8inf == NULL) { - nxt_openssl_log_error(task, NXT_LOG_ALERT, - "d2i_PKCS8_PRIV_KEY_INFO() failed"); + if (PEM_get_EVP_CIPHER_INFO(header, &cipher) != 0) { + nxt_alert(task, "encrypted PEM isn't supported"); goto done; } + */ + if (nxt_strcmp(type, PEM_STRING_PKCS8) == 0) { + nxt_alert(task, "PEM PKCS8 isn't supported"); + goto done; + } - key = EVP_PKCS82PKEY(p8inf); + if (nxt_strcmp(type, PEM_STRING_PKCS8INF) == 0) { + data_copy = data; - PKCS8_PRIV_KEY_INFO_free(p8inf); - goto done; - } + p8inf = d2i_PKCS8_PRIV_KEY_INFO(NULL, &data_copy, length); - suffix = nxt_nxt_cert_pem_suffix(type, PEM_STRING_PKCS8INF); + if (p8inf == NULL) { + nxt_openssl_log_error(task, NXT_LOG_ALERT, + "d2i_PKCS8_PRIV_KEY_INFO() failed"); + goto done; + } - if (suffix != 0) { + key = EVP_PKCS82PKEY(p8inf); - ameth = EVP_PKEY_asn1_find_str(NULL, type, suffix); - if (ameth == NULL) { - nxt_openssl_log_error(task, NXT_LOG_ALERT, - "EVP_PKEY_asn1_find_str() failed"); - goto done; - } + PKCS8_PRIV_KEY_INFO_free(p8inf); + goto done; + } - EVP_PKEY_asn1_get0_info(&key_id, NULL, NULL, NULL, NULL, ameth); + suffix = nxt_nxt_cert_pem_suffix(type, PEM_STRING_PKCS8INF); - data_copy = data; + if (suffix != 0) { - key = d2i_PrivateKey(key_id, NULL, &data_copy, length); - goto done; - } + ameth = EVP_PKEY_asn1_find_str(NULL, type, suffix); + if (ameth == NULL) { + nxt_openssl_log_error(task, NXT_LOG_ALERT, + "EVP_PKEY_asn1_find_str() failed"); + goto done; + } - if (nxt_strcmp(type, PEM_STRING_X509) == 0 - || nxt_strcmp(type, PEM_STRING_X509_OLD) == 0) - { - data_copy = data; + EVP_PKEY_asn1_get0_info(&key_id, NULL, NULL, NULL, NULL, ameth); - x509 = d2i_X509(NULL, &data_copy, length); - if (x509 == NULL) { - nxt_openssl_log_error(task, NXT_LOG_ALERT, - "d2i_X509() failed"); - } + data_copy = data; - goto done; - } + key = d2i_PrivateKey(key_id, NULL, &data_copy, length); + goto done; + } - if (nxt_strcmp(type, PEM_STRING_X509_TRUSTED) == 0) { - data_copy = data; + if (nxt_strcmp(type, PEM_STRING_X509) == 0 || + nxt_strcmp(type, PEM_STRING_X509_OLD) == 0) { + data_copy = data; - x509 = d2i_X509_AUX(NULL, &data_copy, length); - if (x509 == NULL) { - nxt_openssl_log_error(task, NXT_LOG_ALERT, - "d2i_X509_AUX() failed"); - } + x509 = d2i_X509(NULL, &data_copy, length); + if (x509 == NULL) { + nxt_openssl_log_error(task, NXT_LOG_ALERT, "d2i_X509() failed"); + } - goto done; - } + goto done; + } - nxt_alert(task, "unsupported PEM type: \"%s\"", type); + if (nxt_strcmp(type, PEM_STRING_X509_TRUSTED) == 0) { + data_copy = data; - done: + x509 = d2i_X509_AUX(NULL, &data_copy, length); + if (x509 == NULL) { + nxt_openssl_log_error(task, NXT_LOG_ALERT, "d2i_X509_AUX() failed"); + } - OPENSSL_free(data); - OPENSSL_free(header); - OPENSSL_free(type); + goto done; + } - if (key != NULL) { - if (cert->key != NULL) { - EVP_PKEY_free(key); - nxt_alert(task, "multiple private keys in PEM"); - goto fail; - } + nxt_alert(task, "unsupported PEM type: \"%s\"", type); - cert->key = key; - continue; - } + done: - if (x509 != NULL) { + OPENSSL_free(data); + OPENSSL_free(header); + OPENSSL_free(type); - if (cert->count == nalloc) { - nalloc += 4; + if (key != NULL) { + if (cert->key != NULL) { + EVP_PKEY_free(key); + nxt_alert(task, "multiple private keys in PEM"); + goto fail; + } - new_cert = nxt_realloc(cert, sizeof(nxt_cert_t) - + nalloc * sizeof(X509 *)); - if (new_cert == NULL) { - X509_free(x509); - goto fail; - } + cert->key = key; + continue; + } - cert = new_cert; - } + if (x509 != NULL) { - cert->chain[cert->count++] = x509; - continue; + if (cert->count == nalloc) { + nalloc += 4; + + new_cert = + nxt_realloc(cert, sizeof(nxt_cert_t) + nalloc * sizeof(X509 *)); + if (new_cert == NULL) { + X509_free(x509); + goto fail; } - goto fail; - } + cert = new_cert; + } - if (cert->key == NULL) { - nxt_alert(task, "no key found"); - goto fail; + cert->chain[cert->count++] = x509; + continue; } - if (cert->count == 0) { - nxt_alert(task, "no certificates found"); - goto fail; - } + goto fail; + } + + if (cert->key == NULL) { + nxt_alert(task, "no key found"); + goto fail; + } + + if (cert->count == 0) { + nxt_alert(task, "no certificates found"); + goto fail; + } - return cert; + return cert; fail: - nxt_cert_destroy(cert); + nxt_cert_destroy(cert); - return NULL; + return NULL; } +static int nxt_nxt_cert_pem_suffix(char *pem_str, const char *suffix) { + char *p; + nxt_uint_t pem_len, suffix_len; -static int -nxt_nxt_cert_pem_suffix(char *pem_str, const char *suffix) -{ - char *p; - nxt_uint_t pem_len, suffix_len; + pem_len = strlen(pem_str); + suffix_len = strlen(suffix); - pem_len = strlen(pem_str); - suffix_len = strlen(suffix); + if (suffix_len + 1 >= pem_len) { + return 0; + } - if (suffix_len + 1 >= pem_len) { - return 0; - } + p = pem_str + pem_len - suffix_len; - p = pem_str + pem_len - suffix_len; + if (nxt_strcmp(p, suffix) != 0) { + return 0; + } - if (nxt_strcmp(p, suffix) != 0) { - return 0; - } + p--; - p--; - - if (*p != ' ') { - return 0; - } + if (*p != ' ') { + return 0; + } - return p - pem_str; + return p - pem_str; } +void nxt_cert_destroy(nxt_cert_t *cert) { + nxt_uint_t i; -void -nxt_cert_destroy(nxt_cert_t *cert) -{ - nxt_uint_t i; + EVP_PKEY_free(cert->key); - EVP_PKEY_free(cert->key); + for (i = 0; i != cert->count; i++) { + X509_free(cert->chain[i]); + } - for (i = 0; i != cert->count; i++) { - X509_free(cert->chain[i]); - } - - nxt_free(cert); + nxt_free(cert); } +static nxt_int_t nxt_cert_info_hash_test(nxt_lvlhsh_query_t *lhq, void *data) { + nxt_cert_info_t *info; + info = data; -static nxt_int_t -nxt_cert_info_hash_test(nxt_lvlhsh_query_t *lhq, void *data) -{ - nxt_cert_info_t *info; - - info = data; - - if (nxt_strcasestr_eq(&lhq->key, &info->name)) { - return NXT_OK; - } + if (nxt_strcasestr_eq(&lhq->key, &info->name)) { + return NXT_OK; + } - return NXT_DECLINED; + return NXT_DECLINED; } - -static const nxt_lvlhsh_proto_t nxt_cert_info_hash_proto - nxt_aligned(64) = -{ +static const nxt_lvlhsh_proto_t nxt_cert_info_hash_proto nxt_aligned(64) = { NXT_LVLHSH_DEFAULT, nxt_cert_info_hash_test, nxt_lvlhsh_alloc, nxt_lvlhsh_free, }; +void nxt_cert_info_init(nxt_task_t *task, nxt_array_t *certs) { + uint32_t i; + nxt_cert_t *cert; + nxt_cert_item_t *items; -void -nxt_cert_info_init(nxt_task_t *task, nxt_array_t *certs) -{ - uint32_t i; - nxt_cert_t *cert; - nxt_cert_item_t *items; - - for (items = certs->elts, i = 0; i < certs->nelts; i++) { - cert = nxt_cert_fd(task, items[i].fd); - - if (nxt_slow_path(cert == NULL)) { - continue; - } - - (void) nxt_cert_info_save(&items[i].name, cert); + for (items = certs->elts, i = 0; i < certs->nelts; i++) { + cert = nxt_cert_fd(task, items[i].fd); - nxt_cert_destroy(cert); + if (nxt_slow_path(cert == NULL)) { + continue; } -} + (void)nxt_cert_info_save(&items[i].name, cert); -nxt_int_t -nxt_cert_info_save(nxt_str_t *name, nxt_cert_t *cert) -{ - nxt_mp_t *mp; - nxt_int_t ret; - nxt_cert_info_t *info; - nxt_conf_value_t *value; - nxt_lvlhsh_query_t lhq; - - mp = nxt_mp_create(1024, 128, 256, 32); - if (nxt_slow_path(mp == NULL)) { - return NXT_ERROR; - } + nxt_cert_destroy(cert); + } +} - info = nxt_mp_get(mp, sizeof(nxt_cert_info_t)); - if (nxt_slow_path(info == NULL)) { - goto fail; - } +nxt_int_t nxt_cert_info_save(nxt_str_t *name, nxt_cert_t *cert) { + nxt_mp_t *mp; + nxt_int_t ret; + nxt_cert_info_t *info; + nxt_conf_value_t *value; + nxt_lvlhsh_query_t lhq; - name = nxt_str_dup(mp, &info->name, name); - if (nxt_slow_path(name == NULL)) { - goto fail; - } + mp = nxt_mp_create(1024, 128, 256, 32); + if (nxt_slow_path(mp == NULL)) { + return NXT_ERROR; + } + + info = nxt_mp_get(mp, sizeof(nxt_cert_info_t)); + if (nxt_slow_path(info == NULL)) { + goto fail; + } + + name = nxt_str_dup(mp, &info->name, name); + if (nxt_slow_path(name == NULL)) { + goto fail; + } + + value = nxt_cert_details(mp, cert); + if (nxt_slow_path(value == NULL)) { + goto fail; + } + + info->mp = mp; + info->value = value; + + lhq.key_hash = nxt_djb_hash(name->start, name->length); + lhq.replace = 1; + lhq.key = *name; + lhq.value = info; + lhq.proto = &nxt_cert_info_hash_proto; + + ret = nxt_lvlhsh_insert(&nxt_cert_info, &lhq); + if (nxt_slow_path(ret != NXT_OK)) { + goto fail; + } + + if (lhq.value != info) { + info = lhq.value; + nxt_mp_destroy(info->mp); + } - value = nxt_cert_details(mp, cert); - if (nxt_slow_path(value == NULL)) { - goto fail; - } + return NXT_OK; - info->mp = mp; - info->value = value; +fail: - lhq.key_hash = nxt_djb_hash(name->start, name->length); - lhq.replace = 1; - lhq.key = *name; - lhq.value = info; - lhq.proto = &nxt_cert_info_hash_proto; + nxt_mp_destroy(mp); + return NXT_ERROR; +} - ret = nxt_lvlhsh_insert(&nxt_cert_info, &lhq); - if (nxt_slow_path(ret != NXT_OK)) { - goto fail; - } +nxt_conf_value_t *nxt_cert_info_get(nxt_str_t *name) { + nxt_int_t ret; + nxt_cert_info_t *info; + nxt_lvlhsh_query_t lhq; - if (lhq.value != info) { - info = lhq.value; - nxt_mp_destroy(info->mp); - } + lhq.key_hash = nxt_djb_hash(name->start, name->length); + lhq.key = *name; + lhq.proto = &nxt_cert_info_hash_proto; - return NXT_OK; + ret = nxt_lvlhsh_find(&nxt_cert_info, &lhq); + if (ret != NXT_OK) { + return NULL; + } -fail: + info = lhq.value; - nxt_mp_destroy(mp); - return NXT_ERROR; + return info->value; } +nxt_conf_value_t *nxt_cert_info_get_all(nxt_mp_t *mp) { + uint32_t i; + nxt_cert_info_t *info; + nxt_conf_value_t *all; + nxt_lvlhsh_each_t lhe; -nxt_conf_value_t * -nxt_cert_info_get(nxt_str_t *name) -{ - nxt_int_t ret; - nxt_cert_info_t *info; - nxt_lvlhsh_query_t lhq; + nxt_lvlhsh_each_init(&lhe, &nxt_cert_info_hash_proto); + + i = 0; - lhq.key_hash = nxt_djb_hash(name->start, name->length); - lhq.key = *name; - lhq.proto = &nxt_cert_info_hash_proto; + for (;;) { + info = nxt_lvlhsh_each(&nxt_cert_info, &lhe); - ret = nxt_lvlhsh_find(&nxt_cert_info, &lhq); - if (ret != NXT_OK) { - return NULL; + if (info == NULL) { + break; } - info = lhq.value; + i++; + } - return info->value; -} + all = nxt_conf_create_object(mp, i); + if (nxt_slow_path(all == NULL)) { + return NULL; + } + nxt_lvlhsh_each_init(&lhe, &nxt_cert_info_hash_proto); -nxt_conf_value_t * -nxt_cert_info_get_all(nxt_mp_t *mp) -{ - uint32_t i; - nxt_cert_info_t *info; - nxt_conf_value_t *all; - nxt_lvlhsh_each_t lhe; + i = 0; - nxt_lvlhsh_each_init(&lhe, &nxt_cert_info_hash_proto); + for (;;) { + info = nxt_lvlhsh_each(&nxt_cert_info, &lhe); - i = 0; + if (info == NULL) { + break; + } - for ( ;; ) { - info = nxt_lvlhsh_each(&nxt_cert_info, &lhe); + nxt_conf_set_member(all, &info->name, info->value, i); - if (info == NULL) { - break; - } + i++; + } - i++; - } + return all; +} - all = nxt_conf_create_object(mp, i); - if (nxt_slow_path(all == NULL)) { - return NULL; - } +static nxt_conf_value_t *nxt_cert_details(nxt_mp_t *mp, nxt_cert_t *cert) { + BIO *bio; + X509 *x509; + u_char *end; + EVP_PKEY *key; + ASN1_TIME *asn1_time; + nxt_str_t str; + nxt_int_t ret; + nxt_uint_t i; + nxt_conf_value_t *object, *chain, *element, *value; + u_char buf[256]; + + static nxt_str_t key_str = nxt_string("key"); + static nxt_str_t chain_str = nxt_string("chain"); + static nxt_str_t since_str = nxt_string("since"); + static nxt_str_t until_str = nxt_string("until"); + static nxt_str_t issuer_str = nxt_string("issuer"); + static nxt_str_t subject_str = nxt_string("subject"); + static nxt_str_t validity_str = nxt_string("validity"); + + object = nxt_conf_create_object(mp, 2); + if (nxt_slow_path(object == NULL)) { + return NULL; + } - nxt_lvlhsh_each_init(&lhe, &nxt_cert_info_hash_proto); + if (cert->key != NULL) { + key = cert->key; - i = 0; + switch (EVP_PKEY_base_id(key)) { + case EVP_PKEY_RSA: + end = nxt_sprintf(buf, buf + sizeof(buf), "RSA (%d bits)", + EVP_PKEY_bits(key)); - for ( ;; ) { - info = nxt_lvlhsh_each(&nxt_cert_info, &lhe); + str.length = end - buf; + str.start = buf; + break; - if (info == NULL) { - break; - } + case EVP_PKEY_DH: + end = nxt_sprintf(buf, buf + sizeof(buf), "DH (%d bits)", + EVP_PKEY_bits(key)); - nxt_conf_set_member(all, &info->name, info->value, i); + str.length = end - buf; + str.start = buf; + break; - i++; - } + case EVP_PKEY_EC: + nxt_str_set(&str, "ECDH"); + break; - return all; -} + default: + nxt_str_set(&str, "unknown"); + } + ret = nxt_conf_set_member_string_dup(object, mp, &key_str, &str, 0); -static nxt_conf_value_t * -nxt_cert_details(nxt_mp_t *mp, nxt_cert_t *cert) -{ - BIO *bio; - X509 *x509; - u_char *end; - EVP_PKEY *key; - ASN1_TIME *asn1_time; - nxt_str_t str; - nxt_int_t ret; - nxt_uint_t i; - nxt_conf_value_t *object, *chain, *element, *value; - u_char buf[256]; - - static nxt_str_t key_str = nxt_string("key"); - static nxt_str_t chain_str = nxt_string("chain"); - static nxt_str_t since_str = nxt_string("since"); - static nxt_str_t until_str = nxt_string("until"); - static nxt_str_t issuer_str = nxt_string("issuer"); - static nxt_str_t subject_str = nxt_string("subject"); - static nxt_str_t validity_str = nxt_string("validity"); - - object = nxt_conf_create_object(mp, 2); - if (nxt_slow_path(object == NULL)) { - return NULL; + if (nxt_slow_path(ret != NXT_OK)) { + return NULL; } - if (cert->key != NULL) { - key = cert->key; - - switch (EVP_PKEY_base_id(key)) { - case EVP_PKEY_RSA: - end = nxt_sprintf(buf, buf + sizeof(buf), "RSA (%d bits)", - EVP_PKEY_bits(key)); + } else { + nxt_conf_set_member_null(object, &key_str, 0); + } - str.length = end - buf; - str.start = buf; - break; + chain = nxt_conf_create_array(mp, cert->count); + if (nxt_slow_path(chain == NULL)) { + return NULL; + } - case EVP_PKEY_DH: - end = nxt_sprintf(buf, buf + sizeof(buf), "DH (%d bits)", - EVP_PKEY_bits(key)); + for (i = 0; i < cert->count; i++) { + element = nxt_conf_create_object(mp, 3); + if (nxt_slow_path(element == NULL)) { + return NULL; + } - str.length = end - buf; - str.start = buf; - break; + x509 = cert->chain[i]; - case EVP_PKEY_EC: - nxt_str_set(&str, "ECDH"); - break; + value = nxt_cert_name_details(mp, x509, 0); + if (value == NULL) { + return NULL; + } - default: - nxt_str_set(&str, "unknown"); - } + nxt_conf_set_member(element, &subject_str, value, 0); - ret = nxt_conf_set_member_string_dup(object, mp, &key_str, &str, 0); + value = nxt_cert_name_details(mp, x509, 1); + if (value == NULL) { + return NULL; + } - if (nxt_slow_path(ret != NXT_OK)) { - return NULL; - } + nxt_conf_set_member(element, &issuer_str, value, 1); - } else { - nxt_conf_set_member_null(object, &key_str, 0); + value = nxt_conf_create_object(mp, 2); + if (nxt_slow_path(value == NULL)) { + return NULL; } - chain = nxt_conf_create_array(mp, cert->count); - if (nxt_slow_path(chain == NULL)) { - return NULL; + bio = BIO_new(BIO_s_mem()); + if (nxt_slow_path(bio == NULL)) { + return NULL; } - for (i = 0; i < cert->count; i++) { - element = nxt_conf_create_object(mp, 3); - if (nxt_slow_path(element == NULL)) { - return NULL; - } + asn1_time = X509_get_notBefore(x509); - x509 = cert->chain[i]; + ret = ASN1_TIME_print(bio, asn1_time); - value = nxt_cert_name_details(mp, x509, 0); - if (value == NULL) { - return NULL; - } + if (nxt_fast_path(ret == 1)) { + str.length = BIO_get_mem_data(bio, &str.start); + ret = nxt_conf_set_member_string_dup(value, mp, &since_str, &str, 0); + } else { + ret = NXT_ERROR; + } - nxt_conf_set_member(element, &subject_str, value, 0); + BIO_free(bio); - value = nxt_cert_name_details(mp, x509, 1); - if (value == NULL) { - return NULL; - } + if (nxt_slow_path(ret != NXT_OK)) { + return NULL; + } - nxt_conf_set_member(element, &issuer_str, value, 1); + bio = BIO_new(BIO_s_mem()); + if (nxt_slow_path(bio == NULL)) { + return NULL; + } - value = nxt_conf_create_object(mp, 2); - if (nxt_slow_path(value == NULL)) { - return NULL; - } + asn1_time = X509_get_notAfter(x509); - bio = BIO_new(BIO_s_mem()); - if (nxt_slow_path(bio == NULL)) { - return NULL; - } + ret = ASN1_TIME_print(bio, asn1_time); - asn1_time = X509_get_notBefore(x509); + if (nxt_fast_path(ret == 1)) { + str.length = BIO_get_mem_data(bio, &str.start); + ret = nxt_conf_set_member_string_dup(value, mp, &until_str, &str, 1); + } else { + ret = NXT_ERROR; + } - ret = ASN1_TIME_print(bio, asn1_time); + BIO_free(bio); - if (nxt_fast_path(ret == 1)) { - str.length = BIO_get_mem_data(bio, &str.start); - ret = nxt_conf_set_member_string_dup(value, mp, &since_str, &str, - 0); - } else { - ret = NXT_ERROR; - } + if (nxt_slow_path(ret != NXT_OK)) { + return NULL; + } - BIO_free(bio); + nxt_conf_set_member(element, &validity_str, value, 2); - if (nxt_slow_path(ret != NXT_OK)) { - return NULL; - } + nxt_conf_set_element(chain, i, element); + } - bio = BIO_new(BIO_s_mem()); - if (nxt_slow_path(bio == NULL)) { - return NULL; - } + nxt_conf_set_member(object, &chain_str, chain, 1); - asn1_time = X509_get_notAfter(x509); + return object; +} - ret = ASN1_TIME_print(bio, asn1_time); +typedef struct { + int nid; + nxt_str_t name; +} nxt_cert_nid_t; - if (nxt_fast_path(ret == 1)) { - str.length = BIO_get_mem_data(bio, &str.start); - ret = nxt_conf_set_member_string_dup(value, mp, &until_str, &str, - 1); - } else { - ret = NXT_ERROR; - } +static nxt_conf_value_t *nxt_cert_name_details(nxt_mp_t *mp, X509 *x509, + nxt_bool_t issuer) { + int len; + X509_NAME *x509_name; + nxt_str_t str; + nxt_int_t ret; + nxt_uint_t i, n, count; + nxt_conf_value_t *object, *names; + STACK_OF(GENERAL_NAME) * alt_names; + u_char buf[256]; - BIO_free(bio); + static nxt_cert_nid_t nids[] = { + {NID_commonName, nxt_string("common_name")}, + {NID_countryName, nxt_string("country")}, + {NID_stateOrProvinceName, nxt_string("state_or_province")}, + {NID_localityName, nxt_string("locality")}, + {NID_organizationName, nxt_string("organization")}, + {NID_organizationalUnitName, nxt_string("department")}, + }; - if (nxt_slow_path(ret != NXT_OK)) { - return NULL; - } + static nxt_str_t alt_names_str = nxt_string("alt_names"); - nxt_conf_set_member(element, &validity_str, value, 2); + count = 0; - nxt_conf_set_element(chain, i, element); - } + x509_name = issuer ? X509_get_issuer_name(x509) : X509_get_subject_name(x509); - nxt_conf_set_member(object, &chain_str, chain, 1); + for (n = 0; n != nxt_nitems(nids); n++) { - return object; -} + if (X509_NAME_get_index_by_NID(x509_name, nids[n].nid, -1) < 0) { + continue; + } + count++; + } -typedef struct { - int nid; - nxt_str_t name; -} nxt_cert_nid_t; + alt_names = X509_get_ext_d2i( + x509, issuer ? NID_issuer_alt_name : NID_subject_alt_name, NULL, NULL); + if (alt_names != NULL) { + names = nxt_cert_alt_names_details(mp, alt_names); -static nxt_conf_value_t * -nxt_cert_name_details(nxt_mp_t *mp, X509 *x509, nxt_bool_t issuer) -{ - int len; - X509_NAME *x509_name; - nxt_str_t str; - nxt_int_t ret; - nxt_uint_t i, n, count; - nxt_conf_value_t *object, *names; - STACK_OF(GENERAL_NAME) *alt_names; - u_char buf[256]; - - static nxt_cert_nid_t nids[] = { - { NID_commonName, nxt_string("common_name") }, - { NID_countryName, nxt_string("country") }, - { NID_stateOrProvinceName, nxt_string("state_or_province") }, - { NID_localityName, nxt_string("locality") }, - { NID_organizationName, nxt_string("organization") }, - { NID_organizationalUnitName, nxt_string("department") }, - }; - - static nxt_str_t alt_names_str = nxt_string("alt_names"); - - count = 0; - - x509_name = issuer ? X509_get_issuer_name(x509) - : X509_get_subject_name(x509); - - for (n = 0; n != nxt_nitems(nids); n++) { - - if (X509_NAME_get_index_by_NID(x509_name, nids[n].nid, -1) < 0) { - continue; - } + sk_GENERAL_NAME_pop_free(alt_names, GENERAL_NAME_free); - count++; + if (nxt_slow_path(names == NULL)) { + return NULL; } - alt_names = X509_get_ext_d2i(x509, issuer ? NID_issuer_alt_name - : NID_subject_alt_name, - NULL, NULL); + count++; - if (alt_names != NULL) { - names = nxt_cert_alt_names_details(mp, alt_names); + } else { + names = NULL; + } - sk_GENERAL_NAME_pop_free(alt_names, GENERAL_NAME_free); + object = nxt_conf_create_object(mp, count); + if (nxt_slow_path(object == NULL)) { + return NULL; + } - if (nxt_slow_path(names == NULL)) { - return NULL; - } + for (n = 0, i = 0; n != nxt_nitems(nids) && i != count; n++) { - count++; + len = X509_NAME_get_text_by_NID(x509_name, nids[n].nid, (char *)buf, + sizeof(buf)); - } else { - names = NULL; + if (n == 1 && names != NULL) { + nxt_conf_set_member(object, &alt_names_str, names, i++); } - object = nxt_conf_create_object(mp, count); - if (nxt_slow_path(object == NULL)) { - return NULL; + if (len < 0) { + continue; } - for (n = 0, i = 0; n != nxt_nitems(nids) && i != count; n++) { - - len = X509_NAME_get_text_by_NID(x509_name, nids[n].nid, - (char *) buf, sizeof(buf)); - - if (n == 1 && names != NULL) { - nxt_conf_set_member(object, &alt_names_str, names, i++); - } - - if (len < 0) { - continue; - } - - str.length = len; - str.start = buf; + str.length = len; + str.start = buf; - ret = nxt_conf_set_member_string_dup(object, mp, &nids[n].name, - &str, i++); - if (nxt_slow_path(ret != NXT_OK)) { - return NULL; - } + ret = nxt_conf_set_member_string_dup(object, mp, &nids[n].name, &str, i++); + if (nxt_slow_path(ret != NXT_OK)) { + return NULL; } + } - return object; + return object; } - static nxt_conf_value_t * -nxt_cert_alt_names_details(nxt_mp_t *mp, STACK_OF(GENERAL_NAME) *alt_names) -{ - nxt_str_t str; - nxt_int_t ret; - nxt_uint_t i, n, count; - GENERAL_NAME *name; - nxt_conf_value_t *array; - - count = sk_GENERAL_NAME_num(alt_names); - n = 0; +nxt_cert_alt_names_details(nxt_mp_t *mp, STACK_OF(GENERAL_NAME) * alt_names) { + nxt_str_t str; + nxt_int_t ret; + nxt_uint_t i, n, count; + GENERAL_NAME *name; + nxt_conf_value_t *array; - for (i = 0; i != count; i++) { - name = sk_GENERAL_NAME_value(alt_names, i); + count = sk_GENERAL_NAME_num(alt_names); + n = 0; - if (name->type != GEN_DNS) { - continue; - } + for (i = 0; i != count; i++) { + name = sk_GENERAL_NAME_value(alt_names, i); - n++; + if (name->type != GEN_DNS) { + continue; } - array = nxt_conf_create_array(mp, n); - if (nxt_slow_path(array == NULL)) { - return NULL; - } + n++; + } - for (n = 0, i = 0; n != count; n++) { - name = sk_GENERAL_NAME_value(alt_names, n); + array = nxt_conf_create_array(mp, n); + if (nxt_slow_path(array == NULL)) { + return NULL; + } - if (name->type != GEN_DNS) { - continue; - } + for (n = 0, i = 0; n != count; n++) { + name = sk_GENERAL_NAME_value(alt_names, n); + + if (name->type != GEN_DNS) { + continue; + } - str.length = ASN1_STRING_length(name->d.dNSName); + str.length = ASN1_STRING_length(name->d.dNSName); #if OPENSSL_VERSION_NUMBER > 0x10100000L - str.start = (u_char *) ASN1_STRING_get0_data(name->d.dNSName); + str.start = (u_char *)ASN1_STRING_get0_data(name->d.dNSName); #else - str.start = ASN1_STRING_data(name->d.dNSName); + str.start = ASN1_STRING_data(name->d.dNSName); #endif - ret = nxt_conf_set_element_string_dup(array, mp, i++, &str); - if (nxt_slow_path(ret != NXT_OK)) { - return NULL; - } + ret = nxt_conf_set_element_string_dup(array, mp, i++, &str); + if (nxt_slow_path(ret != NXT_OK)) { + return NULL; } + } - return array; + return array; } +nxt_int_t nxt_cert_info_delete(nxt_str_t *name) { + nxt_int_t ret; + nxt_cert_info_t *info; + nxt_lvlhsh_query_t lhq; -nxt_int_t -nxt_cert_info_delete(nxt_str_t *name) -{ - nxt_int_t ret; - nxt_cert_info_t *info; - nxt_lvlhsh_query_t lhq; - - lhq.key_hash = nxt_djb_hash(name->start, name->length); - lhq.key = *name; - lhq.proto = &nxt_cert_info_hash_proto; + lhq.key_hash = nxt_djb_hash(name->start, name->length); + lhq.key = *name; + lhq.proto = &nxt_cert_info_hash_proto; - ret = nxt_lvlhsh_delete(&nxt_cert_info, &lhq); + ret = nxt_lvlhsh_delete(&nxt_cert_info, &lhq); - if (ret == NXT_OK) { - info = lhq.value; - nxt_mp_destroy(info->mp); - } + if (ret == NXT_OK) { + info = lhq.value; + nxt_mp_destroy(info->mp); + } - return ret; + return ret; } +nxt_array_t *nxt_cert_store_load(nxt_task_t *task, nxt_mp_t *mp) { + DIR *dir; + size_t size, alloc; + u_char *buf, *p; + nxt_str_t name; + nxt_int_t ret; + nxt_file_t file; + nxt_array_t *certs; + nxt_runtime_t *rt; + struct dirent *de; + nxt_cert_item_t *item; + + rt = task->thread->runtime; + + if (nxt_slow_path(rt->certs.start == NULL)) { + nxt_alert(task, "no certificates storage directory"); + return NULL; + } + certs = nxt_array_create(mp, 16, sizeof(nxt_cert_item_t)); + if (nxt_slow_path(certs == NULL)) { + return NULL; + } -nxt_array_t * -nxt_cert_store_load(nxt_task_t *task, nxt_mp_t *mp) -{ - DIR *dir; - size_t size, alloc; - u_char *buf, *p; - nxt_str_t name; - nxt_int_t ret; - nxt_file_t file; - nxt_array_t *certs; - nxt_runtime_t *rt; - struct dirent *de; - nxt_cert_item_t *item; + buf = NULL; + alloc = 0; - rt = task->thread->runtime; + dir = opendir((char *)rt->certs.start); + if (nxt_slow_path(dir == NULL)) { + nxt_alert(task, "opendir(\"%s\") failed %E", rt->certs.start, nxt_errno); + goto fail; + } - if (nxt_slow_path(rt->certs.start == NULL)) { - nxt_alert(task, "no certificates storage directory"); - return NULL; + for (;;) { + de = readdir(dir); + if (de == NULL) { + break; } - certs = nxt_array_create(mp, 16, sizeof(nxt_cert_item_t)); - if (nxt_slow_path(certs == NULL)) { - return NULL; - } + nxt_debug(task, "readdir(\"%s\"): \"%s\"", rt->certs.start, de->d_name); - buf = NULL; - alloc = 0; + name.length = nxt_strlen(de->d_name); + name.start = (u_char *)de->d_name; - dir = opendir((char *) rt->certs.start); - if (nxt_slow_path(dir == NULL)) { - nxt_alert(task, "opendir(\"%s\") failed %E", - rt->certs.start, nxt_errno); - goto fail; + if (nxt_str_eq(&name, ".", 1) || nxt_str_eq(&name, "..", 2)) { + continue; } - for ( ;; ) { - de = readdir(dir); - if (de == NULL) { - break; - } - - nxt_debug(task, "readdir(\"%s\"): \"%s\"", rt->certs.start, de->d_name); - - name.length = nxt_strlen(de->d_name); - name.start = (u_char *) de->d_name; - - if (nxt_str_eq(&name, ".", 1) || nxt_str_eq(&name, "..", 2)) { - continue; - } - - item = nxt_array_add(certs); - if (nxt_slow_path(item == NULL)) { - goto fail; - } - - item->fd = -1; + item = nxt_array_add(certs); + if (nxt_slow_path(item == NULL)) { + goto fail; + } - size = rt->certs.length + name.length + 1; + item->fd = -1; - if (size > alloc) { - size += 32; + size = rt->certs.length + name.length + 1; - p = nxt_realloc(buf, size); - if (p == NULL) { - goto fail; - } + if (size > alloc) { + size += 32; - alloc = size; - buf = p; - } + p = nxt_realloc(buf, size); + if (p == NULL) { + goto fail; + } - p = nxt_cpymem(buf, rt->certs.start, rt->certs.length); - p = nxt_cpymem(p, name.start, name.length + 1); + alloc = size; + buf = p; + } - nxt_memzero(&file, sizeof(nxt_file_t)); + p = nxt_cpymem(buf, rt->certs.start, rt->certs.length); + p = nxt_cpymem(p, name.start, name.length + 1); - file.name = buf; + nxt_memzero(&file, sizeof(nxt_file_t)); - ret = nxt_file_open(task, &file, NXT_FILE_RDONLY, NXT_FILE_OPEN, - NXT_FILE_OWNER_ACCESS); + file.name = buf; + ret = nxt_file_open(task, &file, NXT_FILE_RDONLY, NXT_FILE_OPEN, + NXT_FILE_OWNER_ACCESS); - if (nxt_slow_path(ret != NXT_OK)) { - nxt_array_remove_last(certs); - continue; - } + if (nxt_slow_path(ret != NXT_OK)) { + nxt_array_remove_last(certs); + continue; + } - item->fd = file.fd; + item->fd = file.fd; - if (nxt_slow_path(nxt_str_dup(mp, &item->name, &name) == NULL)) { - goto fail; - } + if (nxt_slow_path(nxt_str_dup(mp, &item->name, &name) == NULL)) { + goto fail; } + } - if (buf != NULL) { - nxt_free(buf); - } + if (buf != NULL) { + nxt_free(buf); + } - (void) closedir(dir); + (void)closedir(dir); - return certs; + return certs; fail: - if (buf != NULL) { - nxt_free(buf); - } + if (buf != NULL) { + nxt_free(buf); + } - if (dir != NULL) { - (void) closedir(dir); - } + if (dir != NULL) { + (void)closedir(dir); + } - nxt_cert_store_release(certs); + nxt_cert_store_release(certs); - return NULL; + return NULL; } +void nxt_cert_store_release(nxt_array_t *certs) { + uint32_t i; + nxt_cert_item_t *items; -void -nxt_cert_store_release(nxt_array_t *certs) -{ - uint32_t i; - nxt_cert_item_t *items; - - for (items = certs->elts, i = 0; - i < certs->nelts; - i++) - { - nxt_fd_close(items[i].fd); - } + for (items = certs->elts, i = 0; i < certs->nelts; i++) { + nxt_fd_close(items[i].fd); + } - nxt_array_destroy(certs); + nxt_array_destroy(certs); } - #if 0 void @@ -1057,198 +985,181 @@ nxt_cert_store_discovery_handler(nxt_task_t *task, nxt_port_recv_msg_t *msg) #endif +void nxt_cert_store_get(nxt_task_t *task, nxt_str_t *name, nxt_mp_t *mp, + nxt_port_rpc_handler_t handler, void *ctx) { + uint32_t stream; + nxt_int_t ret; + nxt_buf_t *b; + nxt_port_t *main_port, *recv_port; + nxt_runtime_t *rt; -void -nxt_cert_store_get(nxt_task_t *task, nxt_str_t *name, nxt_mp_t *mp, - nxt_port_rpc_handler_t handler, void *ctx) -{ - uint32_t stream; - nxt_int_t ret; - nxt_buf_t *b; - nxt_port_t *main_port, *recv_port; - nxt_runtime_t *rt; - - b = nxt_buf_mem_alloc(mp, name->length + 1, 0); - if (nxt_slow_path(b == NULL)) { - goto fail; - } + b = nxt_buf_mem_alloc(mp, name->length + 1, 0); + if (nxt_slow_path(b == NULL)) { + goto fail; + } - nxt_mp_retain(mp); - b->completion_handler = nxt_cert_buf_completion; + nxt_mp_retain(mp); + b->completion_handler = nxt_cert_buf_completion; - nxt_buf_cpystr(b, name); - *b->mem.free++ = '\0'; + nxt_buf_cpystr(b, name); + *b->mem.free++ = '\0'; - rt = task->thread->runtime; - main_port = rt->port_by_type[NXT_PROCESS_MAIN]; - recv_port = rt->port_by_type[rt->type]; + rt = task->thread->runtime; + main_port = rt->port_by_type[NXT_PROCESS_MAIN]; + recv_port = rt->port_by_type[rt->type]; - stream = nxt_port_rpc_register_handler(task, recv_port, handler, handler, - -1, ctx); - if (nxt_slow_path(stream == 0)) { - goto fail; - } + stream = + nxt_port_rpc_register_handler(task, recv_port, handler, handler, -1, ctx); + if (nxt_slow_path(stream == 0)) { + goto fail; + } - ret = nxt_port_socket_write(task, main_port, NXT_PORT_MSG_CERT_GET, -1, - stream, recv_port->id, b); + ret = nxt_port_socket_write(task, main_port, NXT_PORT_MSG_CERT_GET, -1, + stream, recv_port->id, b); - if (nxt_slow_path(ret != NXT_OK)) { - nxt_port_rpc_cancel(task, recv_port, stream); - goto fail; - } + if (nxt_slow_path(ret != NXT_OK)) { + nxt_port_rpc_cancel(task, recv_port, stream); + goto fail; + } - return; + return; fail: - handler(task, NULL, ctx); + handler(task, NULL, ctx); } +static void nxt_cert_buf_completion(nxt_task_t *task, void *obj, void *data) { + nxt_mp_t *mp; + nxt_buf_t *b; -static void -nxt_cert_buf_completion(nxt_task_t *task, void *obj, void *data) -{ - nxt_mp_t *mp; - nxt_buf_t *b; + b = obj; + mp = b->data; + nxt_assert(b->next == NULL); - b = obj; - mp = b->data; - nxt_assert(b->next == NULL); - - nxt_mp_free(mp, b); - nxt_mp_release(mp); + nxt_mp_free(mp, b); + nxt_mp_release(mp); } +void nxt_cert_store_get_handler(nxt_task_t *task, nxt_port_recv_msg_t *msg) { + u_char *p; + nxt_int_t ret; + nxt_str_t name; + nxt_file_t file; + nxt_port_t *port; + nxt_runtime_t *rt; + nxt_port_msg_type_t type; + + port = nxt_runtime_port_find(task->thread->runtime, msg->port_msg.pid, + msg->port_msg.reply_port); + + if (nxt_slow_path(port == NULL)) { + nxt_alert(task, "process port not found (pid %PI, reply_port %d)", + msg->port_msg.pid, msg->port_msg.reply_port); + return; + } -void -nxt_cert_store_get_handler(nxt_task_t *task, nxt_port_recv_msg_t *msg) -{ - u_char *p; - nxt_int_t ret; - nxt_str_t name; - nxt_file_t file; - nxt_port_t *port; - nxt_runtime_t *rt; - nxt_port_msg_type_t type; - - port = nxt_runtime_port_find(task->thread->runtime, msg->port_msg.pid, - msg->port_msg.reply_port); - - if (nxt_slow_path(port == NULL)) { - nxt_alert(task, "process port not found (pid %PI, reply_port %d)", - msg->port_msg.pid, msg->port_msg.reply_port); - return; - } - - if (nxt_slow_path(port->type != NXT_PROCESS_CONTROLLER - && port->type != NXT_PROCESS_ROUTER)) - { - nxt_alert(task, "process %PI cannot store certificates", - msg->port_msg.pid); - return; - } + if (nxt_slow_path(port->type != NXT_PROCESS_CONTROLLER && + port->type != NXT_PROCESS_ROUTER)) { + nxt_alert(task, "process %PI cannot store certificates", msg->port_msg.pid); + return; + } - nxt_memzero(&file, sizeof(nxt_file_t)); + nxt_memzero(&file, sizeof(nxt_file_t)); - file.fd = -1; - type = NXT_PORT_MSG_RPC_ERROR; + file.fd = -1; + type = NXT_PORT_MSG_RPC_ERROR; - rt = task->thread->runtime; + rt = task->thread->runtime; - if (nxt_slow_path(rt->certs.start == NULL)) { - nxt_alert(task, "no certificates storage directory"); - goto error; - } + if (nxt_slow_path(rt->certs.start == NULL)) { + nxt_alert(task, "no certificates storage directory"); + goto error; + } - name.start = msg->buf->mem.pos; - name.length = nxt_strlen(name.start); + name.start = msg->buf->mem.pos; + name.length = nxt_strlen(name.start); - file.name = nxt_malloc(rt->certs.length + name.length + 1); + file.name = nxt_malloc(rt->certs.length + name.length + 1); - if (nxt_slow_path(file.name == NULL)) { - goto error; - } + if (nxt_slow_path(file.name == NULL)) { + goto error; + } - p = nxt_cpymem(file.name, rt->certs.start, rt->certs.length); - p = nxt_cpymem(p, name.start, name.length + 1); + p = nxt_cpymem(file.name, rt->certs.start, rt->certs.length); + p = nxt_cpymem(p, name.start, name.length + 1); - ret = nxt_file_open(task, &file, NXT_FILE_RDWR, NXT_FILE_CREATE_OR_OPEN, - NXT_FILE_OWNER_ACCESS); + ret = nxt_file_open(task, &file, NXT_FILE_RDWR, NXT_FILE_CREATE_OR_OPEN, + NXT_FILE_OWNER_ACCESS); - nxt_free(file.name); + nxt_free(file.name); - if (nxt_fast_path(ret == NXT_OK)) { - type = NXT_PORT_MSG_RPC_READY_LAST | NXT_PORT_MSG_CLOSE_FD; - } + if (nxt_fast_path(ret == NXT_OK)) { + type = NXT_PORT_MSG_RPC_READY_LAST | NXT_PORT_MSG_CLOSE_FD; + } error: - (void) nxt_port_socket_write(task, port, type, file.fd, - msg->port_msg.stream, 0, NULL); + (void)nxt_port_socket_write(task, port, type, file.fd, msg->port_msg.stream, + 0, NULL); } +void nxt_cert_store_delete(nxt_task_t *task, nxt_str_t *name, nxt_mp_t *mp) { + nxt_buf_t *b; + nxt_port_t *main_port; + nxt_runtime_t *rt; -void -nxt_cert_store_delete(nxt_task_t *task, nxt_str_t *name, nxt_mp_t *mp) -{ - nxt_buf_t *b; - nxt_port_t *main_port; - nxt_runtime_t *rt; - - b = nxt_buf_mem_alloc(mp, name->length + 1, 0); + b = nxt_buf_mem_alloc(mp, name->length + 1, 0); - if (nxt_fast_path(b != NULL)) { - nxt_buf_cpystr(b, name); - *b->mem.free++ = '\0'; + if (nxt_fast_path(b != NULL)) { + nxt_buf_cpystr(b, name); + *b->mem.free++ = '\0'; - rt = task->thread->runtime; - main_port = rt->port_by_type[NXT_PROCESS_MAIN]; + rt = task->thread->runtime; + main_port = rt->port_by_type[NXT_PROCESS_MAIN]; - (void) nxt_port_socket_write(task, main_port, NXT_PORT_MSG_CERT_DELETE, - -1, 0, 0, b); - } + (void)nxt_port_socket_write(task, main_port, NXT_PORT_MSG_CERT_DELETE, -1, + 0, 0, b); + } } +void nxt_cert_store_delete_handler(nxt_task_t *task, nxt_port_recv_msg_t *msg) { + u_char *p; + nxt_str_t name; + nxt_port_t *ctl_port; + nxt_runtime_t *rt; + nxt_file_name_t *path; -void -nxt_cert_store_delete_handler(nxt_task_t *task, nxt_port_recv_msg_t *msg) -{ - u_char *p; - nxt_str_t name; - nxt_port_t *ctl_port; - nxt_runtime_t *rt; - nxt_file_name_t *path; - - rt = task->thread->runtime; - ctl_port = rt->port_by_type[NXT_PROCESS_CONTROLLER]; + rt = task->thread->runtime; + ctl_port = rt->port_by_type[NXT_PROCESS_CONTROLLER]; - if (nxt_slow_path(ctl_port == NULL)) { - nxt_alert(task, "controller port not found"); - return; - } + if (nxt_slow_path(ctl_port == NULL)) { + nxt_alert(task, "controller port not found"); + return; + } - if (nxt_slow_path(nxt_recv_msg_cmsg_pid(msg) != ctl_port->pid)) { - nxt_alert(task, "process %PI cannot delete certificates", - nxt_recv_msg_cmsg_pid(msg)); - return; - } + if (nxt_slow_path(nxt_recv_msg_cmsg_pid(msg) != ctl_port->pid)) { + nxt_alert(task, "process %PI cannot delete certificates", + nxt_recv_msg_cmsg_pid(msg)); + return; + } - if (nxt_slow_path(rt->certs.start == NULL)) { - nxt_alert(task, "no certificates storage directory"); - return; - } + if (nxt_slow_path(rt->certs.start == NULL)) { + nxt_alert(task, "no certificates storage directory"); + return; + } - name.start = msg->buf->mem.pos; - name.length = nxt_strlen(name.start); + name.start = msg->buf->mem.pos; + name.length = nxt_strlen(name.start); - path = nxt_malloc(rt->certs.length + name.length + 1); + path = nxt_malloc(rt->certs.length + name.length + 1); - if (nxt_fast_path(path != NULL)) { - p = nxt_cpymem(path, rt->certs.start, rt->certs.length); - p = nxt_cpymem(p, name.start, name.length + 1); + if (nxt_fast_path(path != NULL)) { + p = nxt_cpymem(path, rt->certs.start, rt->certs.length); + p = nxt_cpymem(p, name.start, name.length + 1); - (void) nxt_file_delete(path); + (void)nxt_file_delete(path); - nxt_free(path); - } + nxt_free(path); + } } diff --git a/src/nxt_cert.h b/src/nxt_cert.h index dbaddcf93..760f89be3 100644 --- a/src/nxt_cert.h +++ b/src/nxt_cert.h @@ -7,8 +7,7 @@ #ifndef _NXT_CERT_INCLUDED_ #define _NXT_CERT_INCLUDED_ - -typedef struct nxt_cert_s nxt_cert_t; +typedef struct nxt_cert_s nxt_cert_t; nxt_cert_t *nxt_cert_mem(nxt_task_t *task, nxt_buf_mem_t *mbuf); void nxt_cert_destroy(nxt_cert_t *cert); @@ -23,7 +22,7 @@ nxt_array_t *nxt_cert_store_load(nxt_task_t *task, nxt_mp_t *mem_pool); void nxt_cert_store_release(nxt_array_t *certs); void nxt_cert_store_get(nxt_task_t *task, nxt_str_t *name, nxt_mp_t *mp, - nxt_port_rpc_handler_t handler, void *ctx); + nxt_port_rpc_handler_t handler, void *ctx); void nxt_cert_store_delete(nxt_task_t *task, nxt_str_t *name, nxt_mp_t *mp); void nxt_cert_store_get_handler(nxt_task_t *task, nxt_port_recv_msg_t *msg); diff --git a/src/nxt_cgroup.c b/src/nxt_cgroup.c index 79e240f1e..2bd9f74be 100644 --- a/src/nxt_cgroup.c +++ b/src/nxt_cgroup.c @@ -7,168 +7,154 @@ #include - static int nxt_mk_cgpath_relative(nxt_task_t *task, const char *dir, - char *cgpath); -static nxt_int_t nxt_mk_cgpath(nxt_task_t *task, const char *dir, - char *cgpath); - - -nxt_int_t -nxt_cgroup_proc_add(nxt_task_t *task, nxt_process_t *process) -{ - int len; - char cgprocs[NXT_MAX_PATH_LEN]; - FILE *fp; - nxt_int_t ret; - - if (task->thread->runtime->type != NXT_PROCESS_MAIN - || nxt_process_type(process) != NXT_PROCESS_PROTOTYPE - || process->isolation.cgroup.path == NULL) - { - return NXT_OK; - } + char *cgpath); +static nxt_int_t nxt_mk_cgpath(nxt_task_t *task, const char *dir, char *cgpath); + +nxt_int_t nxt_cgroup_proc_add(nxt_task_t *task, nxt_process_t *process) { + int len; + char cgprocs[NXT_MAX_PATH_LEN]; + FILE *fp; + nxt_int_t ret; + + if (task->thread->runtime->type != NXT_PROCESS_MAIN || + nxt_process_type(process) != NXT_PROCESS_PROTOTYPE || + process->isolation.cgroup.path == NULL) { + return NXT_OK; + } - ret = nxt_mk_cgpath(task, process->isolation.cgroup.path, cgprocs); - if (nxt_slow_path(ret == NXT_ERROR)) { - return NXT_ERROR; - } + ret = nxt_mk_cgpath(task, process->isolation.cgroup.path, cgprocs); + if (nxt_slow_path(ret == NXT_ERROR)) { + return NXT_ERROR; + } - ret = nxt_fs_mkdir_p((const u_char *) cgprocs, 0777); - if (nxt_slow_path(ret == NXT_ERROR)) { - return NXT_ERROR; - } + ret = nxt_fs_mkdir_p((const u_char *)cgprocs, 0777); + if (nxt_slow_path(ret == NXT_ERROR)) { + return NXT_ERROR; + } - len = strlen(cgprocs); + len = strlen(cgprocs); - len = snprintf(cgprocs + len, NXT_MAX_PATH_LEN - len, "/cgroup.procs"); - if (nxt_slow_path(len >= NXT_MAX_PATH_LEN - len)) { - nxt_errno = ENAMETOOLONG; - return NXT_ERROR; - } + len = snprintf(cgprocs + len, NXT_MAX_PATH_LEN - len, "/cgroup.procs"); + if (nxt_slow_path(len >= NXT_MAX_PATH_LEN - len)) { + nxt_errno = ENAMETOOLONG; + return NXT_ERROR; + } - fp = nxt_file_fopen(task, cgprocs, "we"); - if (nxt_slow_path(fp == NULL)) { - return NXT_ERROR; - } + fp = nxt_file_fopen(task, cgprocs, "we"); + if (nxt_slow_path(fp == NULL)) { + return NXT_ERROR; + } - setvbuf(fp, NULL, _IONBF, 0); - len = fprintf(fp, "%d\n", process->pid); - nxt_file_fclose(task, fp); + setvbuf(fp, NULL, _IONBF, 0); + len = fprintf(fp, "%d\n", process->pid); + nxt_file_fclose(task, fp); - if (nxt_slow_path(len < 0)) { - return NXT_ERROR; - } + if (nxt_slow_path(len < 0)) { + return NXT_ERROR; + } - return NXT_OK; + return NXT_OK; } - -void -nxt_cgroup_cleanup(nxt_task_t *task, const nxt_process_t *process) -{ - char *ptr; - char cgroot[NXT_MAX_PATH_LEN], cgpath[NXT_MAX_PATH_LEN]; - nxt_int_t ret; - - ret = nxt_mk_cgpath(task, "", cgroot); - if (nxt_slow_path(ret == NXT_ERROR)) { - return; - } - - ret = nxt_mk_cgpath(task, process->isolation.cgroup.path, cgpath); - if (nxt_slow_path(ret == NXT_ERROR)) { - return; - } - - while (*cgpath != '\0' && strcmp(cgroot, cgpath) != 0) { - rmdir(cgpath); - ptr = strrchr(cgpath, '/'); - *ptr = '\0'; - } +void nxt_cgroup_cleanup(nxt_task_t *task, const nxt_process_t *process) { + char *ptr; + char cgroot[NXT_MAX_PATH_LEN], cgpath[NXT_MAX_PATH_LEN]; + nxt_int_t ret; + + ret = nxt_mk_cgpath(task, "", cgroot); + if (nxt_slow_path(ret == NXT_ERROR)) { + return; + } + + ret = nxt_mk_cgpath(task, process->isolation.cgroup.path, cgpath); + if (nxt_slow_path(ret == NXT_ERROR)) { + return; + } + + while (*cgpath != '\0' && strcmp(cgroot, cgpath) != 0) { + rmdir(cgpath); + ptr = strrchr(cgpath, '/'); + *ptr = '\0'; + } } - -static int -nxt_mk_cgpath_relative(nxt_task_t *task, const char *dir, char *cgpath) -{ - int i, len; - char *buf, *ptr; - FILE *fp; - size_t size; - ssize_t nread; - nxt_bool_t found; - - fp = nxt_file_fopen(task, "/proc/self/cgroup", "re"); - if (nxt_slow_path(fp == NULL)) { - return -1; - } - - len = -1; - buf = NULL; - found = 0; - while ((nread = getline(&buf, &size, fp)) != -1) { - if (strncmp(buf, "0::", 3) == 0) { - found = 1; - break; - } - } - - nxt_file_fclose(task, fp); - - if (!found) { - nxt_errno = ENODATA; - goto out_free_buf; - } - - buf[nread - 1] = '\0'; /* lose the trailing '\n' */ - ptr = buf; - for (i = 0; i < 2; i++) { - ptr = strchr(ptr, ':'); - if (ptr == NULL) { - nxt_errno = ENODATA; - goto out_free_buf; - } - - ptr++; - } - - len = snprintf(cgpath, NXT_MAX_PATH_LEN, NXT_CGROUP_ROOT "%s/%s", - ptr, dir); +static int nxt_mk_cgpath_relative(nxt_task_t *task, const char *dir, + char *cgpath) { + int i, len; + char *buf, *ptr; + FILE *fp; + size_t size; + ssize_t nread; + nxt_bool_t found; + + fp = nxt_file_fopen(task, "/proc/self/cgroup", "re"); + if (nxt_slow_path(fp == NULL)) { + return -1; + } + + len = -1; + buf = NULL; + found = 0; + while ((nread = getline(&buf, &size, fp)) != -1) { + if (strncmp(buf, "0::", 3) == 0) { + found = 1; + break; + } + } + + nxt_file_fclose(task, fp); + + if (!found) { + nxt_errno = ENODATA; + goto out_free_buf; + } + + buf[nread - 1] = '\0'; /* lose the trailing '\n' */ + ptr = buf; + for (i = 0; i < 2; i++) { + ptr = strchr(ptr, ':'); + if (ptr == NULL) { + nxt_errno = ENODATA; + goto out_free_buf; + } + + ptr++; + } + + len = snprintf(cgpath, NXT_MAX_PATH_LEN, NXT_CGROUP_ROOT "%s/%s", ptr, dir); out_free_buf: - nxt_free(buf); + nxt_free(buf); - return len; + return len; } - -static nxt_int_t -nxt_mk_cgpath(nxt_task_t *task, const char *dir, char *cgpath) -{ - int len; - - /* - * If the path from the config is relative, we need to make - * the cgroup path include the main unit processes cgroup. I.e - * - * NXT_CGROUP_ROOT/
/ - */ - if (dir[0] != '/') { - len = nxt_mk_cgpath_relative(task, dir, cgpath); - } else { - len = snprintf(cgpath, NXT_MAX_PATH_LEN, NXT_CGROUP_ROOT "%s", dir); - } - - if (len == -1) { - return NXT_ERROR; - } - - if (len >= NXT_MAX_PATH_LEN) { - nxt_errno = ENAMETOOLONG; - return NXT_ERROR; - } - - return NXT_OK; +static nxt_int_t nxt_mk_cgpath(nxt_task_t *task, const char *dir, + char *cgpath) { + int len; + + /* + * If the path from the config is relative, we need to make + * the cgroup path include the main unit processes cgroup. I.e + * + * NXT_CGROUP_ROOT/
/ + */ + if (dir[0] != '/') { + len = nxt_mk_cgpath_relative(task, dir, cgpath); + } else { + len = snprintf(cgpath, NXT_MAX_PATH_LEN, NXT_CGROUP_ROOT "%s", dir); + } + + if (len == -1) { + return NXT_ERROR; + } + + if (len >= NXT_MAX_PATH_LEN) { + nxt_errno = ENAMETOOLONG; + return NXT_ERROR; + } + + return NXT_OK; } diff --git a/src/nxt_cgroup.h b/src/nxt_cgroup.h index 0b9055d29..3bd1ffbbb 100644 --- a/src/nxt_cgroup.h +++ b/src/nxt_cgroup.h @@ -6,9 +6,7 @@ #ifndef _NXT_CGROUP_H_INCLUDED_ #define _NXT_CGROUP_H_INCLUDED_ - nxt_int_t nxt_cgroup_proc_add(nxt_task_t *task, nxt_process_t *process); void nxt_cgroup_cleanup(nxt_task_t *task, const nxt_process_t *process); - #endif /* _NXT_CGROUP_H_INCLUDED_ */ diff --git a/src/nxt_clang.h b/src/nxt_clang.h index 94638346e..925ad77b3 100644 --- a/src/nxt_clang.h +++ b/src/nxt_clang.h @@ -7,17 +7,14 @@ #ifndef _NXT_CLANG_H_INCLUDED_ #define _NXT_CLANG_H_INCLUDED_ - -#define nxt_inline static inline __attribute__((always_inline)) -#define nxt_noinline __attribute__((noinline)) +#define nxt_inline static inline __attribute__((always_inline)) +#define nxt_noinline __attribute__((noinline)) #define nxt_cdecl - #if (NXT_CLANG) /* Any __asm__ directive disables loop vectorization in GCC and Clang. */ -#define nxt_pragma_loop_disable_vectorization \ - __asm__("") +#define nxt_pragma_loop_disable_vectorization __asm__("") #else @@ -25,37 +22,27 @@ #endif - #if (NXT_HAVE_BUILTIN_EXPECT) -#define nxt_expect(c, x) \ - __builtin_expect((long) (x), (c)) - -#define nxt_fast_path(x) \ - nxt_expect(1, x) +#define nxt_expect(c, x) __builtin_expect((long)(x), (c)) -#define nxt_slow_path(x) \ - nxt_expect(0, x) +#define nxt_fast_path(x) nxt_expect(1, x) +#define nxt_slow_path(x) nxt_expect(0, x) #else -#define nxt_expect(c, x) \ - (x) +#define nxt_expect(c, x) (x) -#define nxt_fast_path(x) \ - (x) +#define nxt_fast_path(x) (x) -#define nxt_slow_path(x) \ - (x) +#define nxt_slow_path(x) (x) #endif - #if (NXT_HAVE_BUILTIN_UNREACHABLE) -#define nxt_unreachable() \ - __builtin_unreachable() +#define nxt_unreachable() __builtin_unreachable() #else @@ -63,11 +50,9 @@ #endif - #if (NXT_HAVE_BUILTIN_PREFETCH) -#define nxt_prefetch(a) \ - __builtin_prefetch(a) +#define nxt_prefetch(a) __builtin_prefetch(a) #else @@ -75,10 +60,9 @@ #endif - #if (NXT_HAVE_GCC_ATTRIBUTE_VISIBILITY) -#define NXT_EXPORT __attribute__((visibility("default"))) +#define NXT_EXPORT __attribute__((visibility("default"))) #else @@ -86,10 +70,9 @@ #endif - #if (NXT_HAVE_GCC_ATTRIBUTE_MALLOC) -#define NXT_MALLOC_LIKE __attribute__((__malloc__)) +#define NXT_MALLOC_LIKE __attribute__((__malloc__)) #else @@ -97,10 +80,9 @@ #endif - #if (NXT_HAVE_GCC_ATTRIBUTE_ALIGNED) -#define nxt_aligned(x) __attribute__((aligned(x))) +#define nxt_aligned(x) __attribute__((aligned(x))) #else @@ -108,10 +90,9 @@ #endif - #if (NXT_HAVE_GCC_ATTRIBUTE_PACKED) -#define nxt_packed __attribute__((__packed__)) +#define nxt_packed __attribute__((__packed__)) #else @@ -119,10 +100,9 @@ #endif - #if (NXT_HAVE_GCC_ATTRIBUTE_UNUSED) -#define NXT_MAYBE_UNUSED __attribute__((__unused__)) +#define NXT_MAYBE_UNUSED __attribute__((__unused__)) #else @@ -130,129 +110,96 @@ #endif - #if (NXT_HAVE_BUILTIN_POPCOUNT) -#define nxt_popcount __builtin_popcount +#define nxt_popcount __builtin_popcount #else -nxt_inline int -nxt_popcount(unsigned int x) -{ - int count; +nxt_inline int nxt_popcount(unsigned int x) { + int count; - for (count = 0; x != 0; count++) { - x &= x - 1; - } + for (count = 0; x != 0; count++) { + x &= x - 1; + } - return count; + return count; } #endif - #ifndef NXT_ALIGNMENT #if (NXT_SOLARIS) -#define NXT_ALIGNMENT _POINTER_ALIGNMENT /* x86_64: 8, i386: 4 */ - /* sparcv9: 8, sparcv8: 4 */ +#define NXT_ALIGNMENT _POINTER_ALIGNMENT /* x86_64: 8, i386: 4 */ + /* sparcv9: 8, sparcv8: 4 */ #elif (__i386__ || __i386) -#define NXT_ALIGNMENT 4 +#define NXT_ALIGNMENT 4 #elif (__arm__) -#define NXT_ALIGNMENT 8 /* 32-bit ARM may use 64-bit load/store */ +#define NXT_ALIGNMENT 8 /* 32-bit ARM may use 64-bit load/store */ #elif (__ia64__) -#define NXT_ALIGNMENT 8 /* long long */ +#define NXT_ALIGNMENT 8 /* long long */ #else -#define NXT_ALIGNMENT NXT_PTR_SIZE +#define NXT_ALIGNMENT NXT_PTR_SIZE #endif #endif - #ifndef NXT_MAX_ALIGNMENT #if (NXT_SOLARIS) -#define NXT_MAX_ALIGNMENT _MAX_ALIGNMENT /* x86_64: 16, i386: 4 */ - /* sparcv9: 16, sparcv8: 8 */ +#define NXT_MAX_ALIGNMENT _MAX_ALIGNMENT /* x86_64: 16, i386: 4 */ + /* sparcv9: 16, sparcv8: 8 */ #elif (__i386__ || __i386) -#define NXT_MAX_ALIGNMENT 4 +#define NXT_MAX_ALIGNMENT 4 #elif (__arm__) -#define NXT_MAX_ALIGNMENT 16 +#define NXT_MAX_ALIGNMENT 16 #elif (__ia64__) -#define NXT_MAX_ALIGNMENT 16 +#define NXT_MAX_ALIGNMENT 16 #else -#define NXT_MAX_ALIGNMENT 16 +#define NXT_MAX_ALIGNMENT 16 #endif #endif +#define nxt_alloca(size) alloca(size) -#define nxt_alloca(size) \ - alloca(size) +#define nxt_container_of(p, type, field) \ + (type *)((u_char *)(p) - offsetof(type, field)) +#define nxt_pointer_to(p, offset) ((void *)((char *)(p) + (offset))) -#define nxt_container_of(p, type, field) \ - (type *) ((u_char *) (p) - offsetof(type, field)) - - -#define nxt_pointer_to(p, offset) \ - ((void *) ((char *) (p) + (offset))) - - -#define nxt_value_at(type, p, offset) \ - *(type *) ((u_char *) p + offset) - - -#define nxt_nitems(x) \ - (sizeof(x) / sizeof((x)[0])) +#define nxt_value_at(type, p, offset) *(type *)((u_char *)p + offset) +#define nxt_nitems(x) (sizeof(x) / sizeof((x)[0])) /* GCC and Clang use __builtin_abs() instead of libc abs(). */ -#define nxt_abs(val) \ - abs(val) - - -#define nxt_max(val1, val2) \ - ((val1 < val2) ? (val2) : (val1)) - - -#define nxt_min(val1, val2) \ - ((val1 > val2) ? (val2) : (val1)) - - -#define nxt_bswap32(val) \ - ( ((val) >> 24) \ - | (((val) & 0x00FF0000) >> 8) \ - | (((val) & 0x0000FF00) << 8) \ - | ((val) << 24)) - - -#define nxt_is_power_of_two(value) \ - ((((value) - 1) & (value)) == 0) +#define nxt_abs(val) abs(val) +#define nxt_max(val1, val2) ((val1 < val2) ? (val2) : (val1)) -#define nxt_align_size(d, a) \ - (((d) + ((size_t) (a) - 1)) & ~((size_t) (a) - 1)) +#define nxt_min(val1, val2) ((val1 > val2) ? (val2) : (val1)) +#define nxt_bswap32(val) \ + (((val) >> 24) | (((val) & 0x00FF0000) >> 8) | (((val) & 0x0000FF00) << 8) | \ + ((val) << 24)) -#define nxt_align_ptr(p, a) \ - (u_char *) (((uintptr_t) (p) + ((uintptr_t) (a) - 1)) \ - & ~((uintptr_t) (a) - 1)) +#define nxt_is_power_of_two(value) ((((value) - 1) & (value)) == 0) -#define nxt_trunc_ptr(p, a) \ - (u_char *) ((uintptr_t) (p) & ~((uintptr_t) (a) - 1)) +#define nxt_align_size(d, a) (((d) + ((size_t)(a) - 1)) & ~((size_t)(a) - 1)) +#define nxt_align_ptr(p, a) \ + (u_char *)(((uintptr_t)(p) + ((uintptr_t)(a) - 1)) & ~((uintptr_t)(a) - 1)) -#define nxt_length(s) \ - (sizeof(s) - 1) +#define nxt_trunc_ptr(p, a) (u_char *)((uintptr_t)(p) & ~((uintptr_t)(a) - 1)) +#define nxt_length(s) (sizeof(s) - 1) #endif /* _NXT_CLANG_H_INCLUDED_ */ diff --git a/src/nxt_clone.c b/src/nxt_clone.c index e78a7822a..b1823cd30 100644 --- a/src/nxt_clone.c +++ b/src/nxt_clone.c @@ -8,427 +8,417 @@ #include #include - #if (NXT_HAVE_CLONE_NEWUSER) nxt_int_t nxt_clone_credential_setgroups(nxt_task_t *task, pid_t child_pid, - const char *str); -nxt_int_t nxt_clone_credential_map_set(nxt_task_t *task, const char* mapfile, - pid_t pid, nxt_int_t default_container, nxt_int_t default_host, - nxt_clone_credential_map_t *map); + const char *str); +nxt_int_t nxt_clone_credential_map_set(nxt_task_t *task, const char *mapfile, + pid_t pid, nxt_int_t default_container, + nxt_int_t default_host, + nxt_clone_credential_map_t *map); nxt_int_t nxt_clone_credential_map_write(nxt_task_t *task, const char *mapfile, - pid_t pid, u_char *mapinfo); - - -nxt_int_t -nxt_clone_credential_setgroups(nxt_task_t *task, pid_t child_pid, - const char *str) -{ - int fd, n; - u_char *p, *end; - u_char path[PATH_MAX]; - - end = path + PATH_MAX; - p = nxt_sprintf(path, end, "/proc/%d/setgroups", child_pid); - *p = '\0'; - - if (nxt_slow_path(p == end)) { - nxt_alert(task, "error write past the buffer: %s", path); - return NXT_ERROR; - } + pid_t pid, u_char *mapinfo); - fd = open((char *)path, O_RDWR); +nxt_int_t nxt_clone_credential_setgroups(nxt_task_t *task, pid_t child_pid, + const char *str) { + int fd, n; + u_char *p, *end; + u_char path[PATH_MAX]; - if (fd == -1) { - /* - * If the /proc/pid/setgroups doesn't exists, we are - * safe to set uid/gid maps. But if the error is anything - * other than ENOENT, then we should abort and let user know. - */ + end = path + PATH_MAX; + p = nxt_sprintf(path, end, "/proc/%d/setgroups", child_pid); + *p = '\0'; - if (errno != ENOENT) { - nxt_alert(task, "open(%s): %E", path, nxt_errno); - return NXT_ERROR; - } + if (nxt_slow_path(p == end)) { + nxt_alert(task, "error write past the buffer: %s", path); + return NXT_ERROR; + } - return NXT_OK; - } + fd = open((char *)path, O_RDWR); - n = write(fd, str, strlen(str)); - close(fd); + if (fd == -1) { + /* + * If the /proc/pid/setgroups doesn't exists, we are + * safe to set uid/gid maps. But if the error is anything + * other than ENOENT, then we should abort and let user know. + */ - if (nxt_slow_path(n == -1)) { - nxt_alert(task, "write(%s): %E", path, nxt_errno); - return NXT_ERROR; + if (errno != ENOENT) { + nxt_alert(task, "open(%s): %E", path, nxt_errno); + return NXT_ERROR; } return NXT_OK; -} + } + n = write(fd, str, strlen(str)); + close(fd); -nxt_int_t -nxt_clone_credential_map_write(nxt_task_t *task, const char *mapfile, - pid_t pid, u_char *mapinfo) -{ - int len, mapfd; - u_char *p, *end; - ssize_t n; - u_char buf[256]; + if (nxt_slow_path(n == -1)) { + nxt_alert(task, "write(%s): %E", path, nxt_errno); + return NXT_ERROR; + } - end = buf + sizeof(buf); + return NXT_OK; +} - p = nxt_sprintf(buf, end, "/proc/%d/%s", pid, mapfile); - if (nxt_slow_path(p == end)) { - nxt_alert(task, "writing past the buffer"); - return NXT_ERROR; - } +nxt_int_t nxt_clone_credential_map_write(nxt_task_t *task, const char *mapfile, + pid_t pid, u_char *mapinfo) { + int len, mapfd; + u_char *p, *end; + ssize_t n; + u_char buf[256]; - *p = '\0'; + end = buf + sizeof(buf); - mapfd = open((char*)buf, O_RDWR); - if (nxt_slow_path(mapfd == -1)) { - nxt_alert(task, "failed to open proc map (%s) %E", buf, nxt_errno); - return NXT_ERROR; - } + p = nxt_sprintf(buf, end, "/proc/%d/%s", pid, mapfile); + if (nxt_slow_path(p == end)) { + nxt_alert(task, "writing past the buffer"); + return NXT_ERROR; + } - len = nxt_strlen(mapinfo); + *p = '\0'; - n = write(mapfd, (char *)mapinfo, len); - if (nxt_slow_path(n != len)) { + mapfd = open((char *)buf, O_RDWR); + if (nxt_slow_path(mapfd == -1)) { + nxt_alert(task, "failed to open proc map (%s) %E", buf, nxt_errno); + return NXT_ERROR; + } - if (n == -1 && nxt_errno == EINVAL) { - nxt_alert(task, "failed to write %s: Check kernel maximum " \ - "allowed lines %E", buf, nxt_errno); + len = nxt_strlen(mapinfo); - } else { - nxt_alert(task, "failed to write proc map (%s) %E", buf, - nxt_errno); - } + n = write(mapfd, (char *)mapinfo, len); + if (nxt_slow_path(n != len)) { - close(mapfd); + if (n == -1 && nxt_errno == EINVAL) { + nxt_alert(task, + "failed to write %s: Check kernel maximum " + "allowed lines %E", + buf, nxt_errno); - return NXT_ERROR; + } else { + nxt_alert(task, "failed to write proc map (%s) %E", buf, nxt_errno); } close(mapfd); - return NXT_OK; -} - + return NXT_ERROR; + } -nxt_int_t -nxt_clone_credential_map_set(nxt_task_t *task, const char* mapfile, pid_t pid, - nxt_int_t default_container, nxt_int_t default_host, - nxt_clone_credential_map_t *map) -{ - u_char *p, *end, *mapinfo; - nxt_int_t ret, len; - nxt_uint_t i; + close(mapfd); - /* - * uid_map one-entry size: - * alloc space for 3 numbers (32bit) plus 2 spaces and \n. - */ - len = sizeof(u_char) * (10 + 10 + 10 + 2 + 1); + return NXT_OK; +} - if (map->size > 0) { - len = len * map->size + 1; +nxt_int_t nxt_clone_credential_map_set(nxt_task_t *task, const char *mapfile, + pid_t pid, nxt_int_t default_container, + nxt_int_t default_host, + nxt_clone_credential_map_t *map) { + u_char *p, *end, *mapinfo; + nxt_int_t ret, len; + nxt_uint_t i; + + /* + * uid_map one-entry size: + * alloc space for 3 numbers (32bit) plus 2 spaces and \n. + */ + len = sizeof(u_char) * (10 + 10 + 10 + 2 + 1); + + if (map->size > 0) { + len = len * map->size + 1; + + mapinfo = nxt_malloc(len); + if (nxt_slow_path(mapinfo == NULL)) { + return NXT_ERROR; + } - mapinfo = nxt_malloc(len); - if (nxt_slow_path(mapinfo == NULL)) { - return NXT_ERROR; - } + p = mapinfo; + end = mapinfo + len; - p = mapinfo; - end = mapinfo + len; + for (i = 0; i < map->size; i++) { + p = nxt_sprintf(p, end, "%L %L %L", map->map[i].container, + map->map[i].host, map->map[i].size); - for (i = 0; i < map->size; i++) { - p = nxt_sprintf(p, end, "%L %L %L", map->map[i].container, - map->map[i].host, map->map[i].size); + if (nxt_slow_path(p == end)) { + nxt_alert(task, "write past the mapinfo buffer"); + nxt_free(mapinfo); + return NXT_ERROR; + } - if (nxt_slow_path(p == end)) { - nxt_alert(task, "write past the mapinfo buffer"); - nxt_free(mapinfo); - return NXT_ERROR; - } + if (i + 1 < map->size) { + *p++ = '\n'; - if (i + 1 < map->size) { - *p++ = '\n'; + } else { + *p = '\0'; + } + } - } else { - *p = '\0'; - } - } + } else { + mapinfo = nxt_malloc(len); + if (nxt_slow_path(mapinfo == NULL)) { + return NXT_ERROR; + } - } else { - mapinfo = nxt_malloc(len); - if (nxt_slow_path(mapinfo == NULL)) { - return NXT_ERROR; - } - - end = mapinfo + len; - p = nxt_sprintf(mapinfo, end, "%d %d 1", - default_container, default_host); - *p = '\0'; + end = mapinfo + len; + p = nxt_sprintf(mapinfo, end, "%d %d 1", default_container, default_host); + *p = '\0'; - if (nxt_slow_path(p == end)) { - nxt_alert(task, "write past mapinfo buffer"); - nxt_free(mapinfo); - return NXT_ERROR; - } + if (nxt_slow_path(p == end)) { + nxt_alert(task, "write past mapinfo buffer"); + nxt_free(mapinfo); + return NXT_ERROR; } + } - ret = nxt_clone_credential_map_write(task, mapfile, pid, mapinfo); + ret = nxt_clone_credential_map_write(task, mapfile, pid, mapinfo); - nxt_free(mapinfo); + nxt_free(mapinfo); - return ret; + return ret; } +nxt_int_t nxt_clone_credential_map(nxt_task_t *task, pid_t pid, + nxt_credential_t *app_creds, + nxt_clone_t *clone) { + nxt_int_t ret; + nxt_int_t default_host_uid; + nxt_int_t default_host_gid; + const char *rule; + nxt_runtime_t *rt; -nxt_int_t -nxt_clone_credential_map(nxt_task_t *task, pid_t pid, - nxt_credential_t *app_creds, nxt_clone_t *clone) -{ - nxt_int_t ret; - nxt_int_t default_host_uid; - nxt_int_t default_host_gid; - const char *rule; - nxt_runtime_t *rt; - - rt = task->thread->runtime; + rt = task->thread->runtime; - if (rt->capabilities.setid) { - rule = "allow"; + if (rt->capabilities.setid) { + rule = "allow"; - /* - * By default we don't map a privileged user - */ - default_host_uid = app_creds->uid; - default_host_gid = app_creds->base_gid; - } else { - rule = "deny"; + /* + * By default we don't map a privileged user + */ + default_host_uid = app_creds->uid; + default_host_gid = app_creds->base_gid; + } else { + rule = "deny"; - default_host_uid = nxt_euid; - default_host_gid = nxt_egid; - } + default_host_uid = nxt_euid; + default_host_gid = nxt_egid; + } - ret = nxt_clone_credential_map_set(task, "uid_map", pid, app_creds->uid, - default_host_uid, - &clone->uidmap); + ret = nxt_clone_credential_map_set(task, "uid_map", pid, app_creds->uid, + default_host_uid, &clone->uidmap); - if (nxt_slow_path(ret != NXT_OK)) { - return NXT_ERROR; - } + if (nxt_slow_path(ret != NXT_OK)) { + return NXT_ERROR; + } - ret = nxt_clone_credential_setgroups(task, pid, rule); - if (nxt_slow_path(ret != NXT_OK)) { - nxt_alert(task, "failed to write /proc/%d/setgroups", pid); - return NXT_ERROR; - } + ret = nxt_clone_credential_setgroups(task, pid, rule); + if (nxt_slow_path(ret != NXT_OK)) { + nxt_alert(task, "failed to write /proc/%d/setgroups", pid); + return NXT_ERROR; + } - ret = nxt_clone_credential_map_set(task, "gid_map", pid, app_creds->base_gid, - default_host_gid, - &clone->gidmap); + ret = nxt_clone_credential_map_set(task, "gid_map", pid, app_creds->base_gid, + default_host_gid, &clone->gidmap); - if (nxt_slow_path(ret != NXT_OK)) { - return NXT_ERROR; - } + if (nxt_slow_path(ret != NXT_OK)) { + return NXT_ERROR; + } - return NXT_OK; + return NXT_OK; } +nxt_int_t nxt_clone_vldt_credential_uidmap(nxt_task_t *task, + nxt_clone_credential_map_t *map, + nxt_credential_t *creds) { + nxt_int_t id; + nxt_uint_t i; + nxt_runtime_t *rt; + nxt_clone_map_entry_t m; -nxt_int_t -nxt_clone_vldt_credential_uidmap(nxt_task_t *task, - nxt_clone_credential_map_t *map, nxt_credential_t *creds) -{ - nxt_int_t id; - nxt_uint_t i; - nxt_runtime_t *rt; - nxt_clone_map_entry_t m; - - if (map->size == 0) { - return NXT_OK; - } - - rt = task->thread->runtime; + if (map->size == 0) { + return NXT_OK; + } - if (!rt->capabilities.setid) { - if (nxt_slow_path(map->size > 1)) { - nxt_log(task, NXT_LOG_NOTICE, "\"uidmap\" field has %d entries " - "but unprivileged unit has a maximum of 1 map.", - map->size); + rt = task->thread->runtime; - return NXT_ERROR; - } + if (!rt->capabilities.setid) { + if (nxt_slow_path(map->size > 1)) { + nxt_log(task, NXT_LOG_NOTICE, + "\"uidmap\" field has %d entries " + "but unprivileged unit has a maximum of 1 map.", + map->size); - id = map->map[0].host; + return NXT_ERROR; + } - if (nxt_slow_path((nxt_uid_t) id != nxt_euid)) { - nxt_log(task, NXT_LOG_NOTICE, "\"uidmap\" field has an entry for " - "host uid %d but unprivileged unit can only map itself " - "(uid %d) into child namespaces.", id, nxt_euid); + id = map->map[0].host; - return NXT_ERROR; - } + if (nxt_slow_path((nxt_uid_t)id != nxt_euid)) { + nxt_log(task, NXT_LOG_NOTICE, + "\"uidmap\" field has an entry for " + "host uid %d but unprivileged unit can only map itself " + "(uid %d) into child namespaces.", + id, nxt_euid); - return NXT_OK; + return NXT_ERROR; } - for (i = 0; i < map->size; i++) { - m = map->map[i]; + return NXT_OK; + } + + for (i = 0; i < map->size; i++) { + m = map->map[i]; - if (creds->uid >= (nxt_uid_t) m.container - && creds->uid < (nxt_uid_t) (m.container + m.size)) - { - return NXT_OK; - } + if (creds->uid >= (nxt_uid_t)m.container && + creds->uid < (nxt_uid_t)(m.container + m.size)) { + return NXT_OK; } + } - nxt_log(task, NXT_LOG_NOTICE, "\"uidmap\" field has no \"container\" " - "entry for user \"%s\" (uid %d)", creds->user, creds->uid); + nxt_log(task, NXT_LOG_NOTICE, + "\"uidmap\" field has no \"container\" " + "entry for user \"%s\" (uid %d)", + creds->user, creds->uid); - return NXT_ERROR; + return NXT_ERROR; } +nxt_int_t nxt_clone_vldt_credential_gidmap(nxt_task_t *task, + nxt_clone_credential_map_t *map, + nxt_credential_t *creds) { + nxt_uint_t base_ok, gid_ok, gids_ok; + nxt_uint_t i, j; + nxt_runtime_t *rt; + nxt_clone_map_entry_t m; + + rt = task->thread->runtime; + + if (!rt->capabilities.setid) { + if (creds->ngroups > 0 && + !(creds->ngroups == 1 && creds->gids[0] == creds->base_gid)) { + nxt_log(task, NXT_LOG_NOTICE, + "unprivileged unit disallow supplementary groups for " + "new namespace (user \"%s\" has %d group%s).", + creds->user, creds->ngroups, creds->ngroups > 1 ? "s" : ""); + + return NXT_ERROR; + } -nxt_int_t -nxt_clone_vldt_credential_gidmap(nxt_task_t *task, - nxt_clone_credential_map_t *map, nxt_credential_t *creds) -{ - nxt_uint_t base_ok, gid_ok, gids_ok; - nxt_uint_t i, j; - nxt_runtime_t *rt; - nxt_clone_map_entry_t m; - - rt = task->thread->runtime; - - if (!rt->capabilities.setid) { - if (creds->ngroups > 0 - && !(creds->ngroups == 1 && creds->gids[0] == creds->base_gid)) { - nxt_log(task, NXT_LOG_NOTICE, - "unprivileged unit disallow supplementary groups for " - "new namespace (user \"%s\" has %d group%s).", - creds->user, creds->ngroups, - creds->ngroups > 1 ? "s" : ""); + if (map->size == 0) { + return NXT_OK; + } - return NXT_ERROR; - } + if (nxt_slow_path(map->size > 1)) { + nxt_log(task, NXT_LOG_NOTICE, + "\"gidmap\" field has %d entries " + "but unprivileged unit has a maximum of 1 map.", + map->size); - if (map->size == 0) { - return NXT_OK; - } + return NXT_ERROR; + } - if (nxt_slow_path(map->size > 1)) { - nxt_log(task, NXT_LOG_NOTICE, "\"gidmap\" field has %d entries " - "but unprivileged unit has a maximum of 1 map.", - map->size); + m = map->map[0]; - return NXT_ERROR; - } + if (nxt_slow_path((nxt_gid_t)m.host != nxt_egid)) { + nxt_log(task, NXT_LOG_ERR, + "\"gidmap\" field has an entry for " + "host gid %L but unprivileged unit can only map itself " + "(gid %d) into child namespaces.", + m.host, nxt_egid); - m = map->map[0]; + return NXT_ERROR; + } - if (nxt_slow_path((nxt_gid_t) m.host != nxt_egid)) { - nxt_log(task, NXT_LOG_ERR, "\"gidmap\" field has an entry for " - "host gid %L but unprivileged unit can only map itself " - "(gid %d) into child namespaces.", m.host, nxt_egid); + if (nxt_slow_path(m.size > 1)) { + nxt_log(task, NXT_LOG_ERR, + "\"gidmap\" field has an entry with " + "\"size\": %L, but for unprivileged unit it must be 1.", + m.size); - return NXT_ERROR; - } + return NXT_ERROR; + } - if (nxt_slow_path(m.size > 1)) { - nxt_log(task, NXT_LOG_ERR, "\"gidmap\" field has an entry with " - "\"size\": %L, but for unprivileged unit it must be 1.", - m.size); + if (nxt_slow_path((nxt_gid_t)m.container != creds->base_gid)) { + nxt_log(task, NXT_LOG_ERR, + "\"gidmap\" field has no \"container\" entry for gid %d.", + creds->base_gid); - return NXT_ERROR; - } + return NXT_ERROR; + } - if (nxt_slow_path((nxt_gid_t) m.container != creds->base_gid)) { - nxt_log(task, NXT_LOG_ERR, - "\"gidmap\" field has no \"container\" entry for gid %d.", - creds->base_gid); + return NXT_OK; + } - return NXT_ERROR; - } + if (map->size == 0) { + if (creds->ngroups > 0 && + !(creds->ngroups == 1 && creds->gids[0] == creds->base_gid)) { + nxt_log(task, NXT_LOG_ERR, + "\"gidmap\" field has no entries " + "but user \"%s\" has %d suplementary group%s.", + creds->user, creds->ngroups, creds->ngroups > 1 ? "s" : ""); - return NXT_OK; + return NXT_ERROR; } - if (map->size == 0) { - if (creds->ngroups > 0 - && !(creds->ngroups == 1 && creds->gids[0] == creds->base_gid)) - { - nxt_log(task, NXT_LOG_ERR, "\"gidmap\" field has no entries " - "but user \"%s\" has %d suplementary group%s.", - creds->user, creds->ngroups, - creds->ngroups > 1 ? "s" : ""); - - return NXT_ERROR; - } - - return NXT_OK; - } - - base_ok = 0; - gids_ok = 0; + return NXT_OK; + } - for (i = 0; i < creds->ngroups; i++) { - gid_ok = 0; + base_ok = 0; + gids_ok = 0; - for (j = 0; j < map->size; j++) { - m = map->map[j]; + for (i = 0; i < creds->ngroups; i++) { + gid_ok = 0; - if (!base_ok && creds->base_gid >= (nxt_gid_t) m.container - && creds->base_gid < (nxt_gid_t) (m.container + m.size)) - { - base_ok = 1; - } + for (j = 0; j < map->size; j++) { + m = map->map[j]; - if (creds->gids[i] >= (nxt_gid_t) m.container - && creds->gids[i] < (nxt_gid_t) (m.container + m.size)) - { - gid_ok = 1; - break; - } - } + if (!base_ok && creds->base_gid >= (nxt_gid_t)m.container && + creds->base_gid < (nxt_gid_t)(m.container + m.size)) { + base_ok = 1; + } - if (nxt_fast_path(gid_ok)) { - gids_ok++; - } + if (creds->gids[i] >= (nxt_gid_t)m.container && + creds->gids[i] < (nxt_gid_t)(m.container + m.size)) { + gid_ok = 1; + break; + } } - if (!base_ok) { - for (i = 0; i < map->size; i++) { - m = map->map[i]; - - if (creds->base_gid >= (nxt_gid_t) m.container - && creds->base_gid < (nxt_gid_t) (m.container + m.size)) - { - base_ok = 1; - break; - } - } + if (nxt_fast_path(gid_ok)) { + gids_ok++; } + } - if (nxt_slow_path(!base_ok)) { - nxt_log(task, NXT_LOG_ERR, "\"gidmap\" field has no \"container\" " - "entry for gid %d.", creds->base_gid); + if (!base_ok) { + for (i = 0; i < map->size; i++) { + m = map->map[i]; - return NXT_ERROR; + if (creds->base_gid >= (nxt_gid_t)m.container && + creds->base_gid < (nxt_gid_t)(m.container + m.size)) { + base_ok = 1; + break; + } } + } - if (nxt_slow_path(gids_ok < creds->ngroups)) { - nxt_log(task, NXT_LOG_ERR, "\"gidmap\" field has missing " - "suplementary gid mappings (found %d out of %d).", gids_ok, - creds->ngroups); + if (nxt_slow_path(!base_ok)) { + nxt_log(task, NXT_LOG_ERR, + "\"gidmap\" field has no \"container\" " + "entry for gid %d.", + creds->base_gid); - return NXT_ERROR; - } + return NXT_ERROR; + } - return NXT_OK; + if (nxt_slow_path(gids_ok < creds->ngroups)) { + nxt_log(task, NXT_LOG_ERR, + "\"gidmap\" field has missing " + "suplementary gid mappings (found %d out of %d).", + gids_ok, creds->ngroups); + + return NXT_ERROR; + } + + return NXT_OK; } #endif diff --git a/src/nxt_clone.h b/src/nxt_clone.h index bf28322ff..c683b9f75 100644 --- a/src/nxt_clone.h +++ b/src/nxt_clone.h @@ -6,49 +6,46 @@ #ifndef _NXT_CLONE_H_INCLUDED_ #define _NXT_CLONE_H_INCLUDED_ - #if (NXT_HAVE_CLONE_NEWUSER) -typedef int64_t nxt_cred_t; +typedef int64_t nxt_cred_t; typedef struct { - nxt_cred_t container; - nxt_cred_t host; - nxt_cred_t size; + nxt_cred_t container; + nxt_cred_t host; + nxt_cred_t size; } nxt_clone_map_entry_t; typedef struct { - nxt_uint_t size; - nxt_clone_map_entry_t *map; + nxt_uint_t size; + nxt_clone_map_entry_t *map; } nxt_clone_credential_map_t; #endif typedef struct { - nxt_int_t flags; + nxt_int_t flags; #if (NXT_HAVE_CLONE_NEWUSER) - nxt_clone_credential_map_t uidmap; - nxt_clone_credential_map_t gidmap; + nxt_clone_credential_map_t uidmap; + nxt_clone_credential_map_t gidmap; #endif } nxt_clone_t; - -#define nxt_is_clone_flag_set(flags, test) \ - ((flags & CLONE_##test) == CLONE_##test) - +#define nxt_is_clone_flag_set(flags, test) \ + ((flags & CLONE_##test) == CLONE_##test) #if (NXT_HAVE_CLONE_NEWUSER) NXT_EXPORT nxt_int_t nxt_clone_credential_map(nxt_task_t *task, pid_t pid, - nxt_credential_t *creds, nxt_clone_t *clone); -NXT_EXPORT nxt_int_t nxt_clone_vldt_credential_uidmap(nxt_task_t *task, - nxt_clone_credential_map_t *map, nxt_credential_t *creds); -NXT_EXPORT nxt_int_t nxt_clone_vldt_credential_gidmap(nxt_task_t *task, - nxt_clone_credential_map_t *map, nxt_credential_t *creds); + nxt_credential_t *creds, + nxt_clone_t *clone); +NXT_EXPORT nxt_int_t nxt_clone_vldt_credential_uidmap( + nxt_task_t *task, nxt_clone_credential_map_t *map, nxt_credential_t *creds); +NXT_EXPORT nxt_int_t nxt_clone_vldt_credential_gidmap( + nxt_task_t *task, nxt_clone_credential_map_t *map, nxt_credential_t *creds); #endif - #endif /* _NXT_CLONE_H_INCLUDED_ */ diff --git a/src/nxt_conf.c b/src/nxt_conf.c index bb229c331..ebf56da73 100644 --- a/src/nxt_conf.c +++ b/src/nxt_conf.c @@ -12,2651 +12,2479 @@ #include #include +#define NXT_CONF_MAX_SHORT_STRING 14 +#define NXT_CONF_MAX_NUMBER_LEN 14 +#define NXT_CONF_MAX_STRING NXT_INT32_T_MAX -#define NXT_CONF_MAX_SHORT_STRING 14 -#define NXT_CONF_MAX_NUMBER_LEN 14 -#define NXT_CONF_MAX_STRING NXT_INT32_T_MAX - -#define NXT_CONF_MAX_TOKEN_LEN 256 - +#define NXT_CONF_MAX_TOKEN_LEN 256 typedef enum { - NXT_CONF_VALUE_NULL = 0, - NXT_CONF_VALUE_BOOLEAN, - NXT_CONF_VALUE_INTEGER, - NXT_CONF_VALUE_NUMBER, - NXT_CONF_VALUE_SHORT_STRING, - NXT_CONF_VALUE_STRING, - NXT_CONF_VALUE_ARRAY, - NXT_CONF_VALUE_OBJECT, + NXT_CONF_VALUE_NULL = 0, + NXT_CONF_VALUE_BOOLEAN, + NXT_CONF_VALUE_INTEGER, + NXT_CONF_VALUE_NUMBER, + NXT_CONF_VALUE_SHORT_STRING, + NXT_CONF_VALUE_STRING, + NXT_CONF_VALUE_ARRAY, + NXT_CONF_VALUE_OBJECT, } nxt_conf_value_type_t; - typedef enum { - NXT_CONF_OP_PASS = 0, - NXT_CONF_OP_CREATE, - NXT_CONF_OP_REPLACE, - NXT_CONF_OP_DELETE, + NXT_CONF_OP_PASS = 0, + NXT_CONF_OP_CREATE, + NXT_CONF_OP_REPLACE, + NXT_CONF_OP_DELETE, } nxt_conf_op_action_t; - -typedef struct nxt_conf_array_s nxt_conf_array_t; -typedef struct nxt_conf_object_s nxt_conf_object_t; - +typedef struct nxt_conf_array_s nxt_conf_array_t; +typedef struct nxt_conf_object_s nxt_conf_object_t; struct nxt_conf_value_s { - union { - uint8_t boolean; /* 1 bit. */ - u_char number[NXT_CONF_MAX_NUMBER_LEN + 1]; + union { + uint8_t boolean; /* 1 bit. */ + u_char number[NXT_CONF_MAX_NUMBER_LEN + 1]; - struct { - u_char start[NXT_CONF_MAX_SHORT_STRING]; - uint8_t length; - } str; + struct { + u_char start[NXT_CONF_MAX_SHORT_STRING]; + uint8_t length; + } str; - struct { - u_char *start; - uint32_t length; - } nxt_packed string; + struct { + u_char *start; + uint32_t length; + } nxt_packed string; - nxt_conf_array_t *array; - nxt_conf_object_t *object; - } nxt_packed u; + nxt_conf_array_t *array; + nxt_conf_object_t *object; + } nxt_packed u; - uint8_t type; /* 3 bits. */ + uint8_t type; /* 3 bits. */ } nxt_aligned(8); - struct nxt_conf_array_s { - nxt_uint_t count; - nxt_conf_value_t elements[]; + nxt_uint_t count; + nxt_conf_value_t elements[]; }; - typedef struct { - nxt_conf_value_t name; - nxt_conf_value_t value; + nxt_conf_value_t name; + nxt_conf_value_t value; } nxt_conf_object_member_t; - struct nxt_conf_object_s { - nxt_uint_t count; - nxt_conf_object_member_t members[]; + nxt_uint_t count; + nxt_conf_object_member_t members[]; }; - struct nxt_conf_op_s { - uint32_t index; - uint32_t action; /* nxt_conf_op_action_t */ - void *ctx; + uint32_t index; + uint32_t action; /* nxt_conf_op_action_t */ + void *ctx; }; - typedef struct { - u_char *start; - u_char *end; - nxt_bool_t last; - u_char buf[NXT_CONF_MAX_TOKEN_LEN]; + u_char *start; + u_char *end; + nxt_bool_t last; + u_char buf[NXT_CONF_MAX_TOKEN_LEN]; } nxt_conf_path_parse_t; - static nxt_int_t nxt_conf_path_next_token(nxt_conf_path_parse_t *parse, - nxt_str_t *token); + nxt_str_t *token); static u_char *nxt_conf_json_skip_space(u_char *start, const u_char *end); static u_char *nxt_conf_json_parse_value(nxt_mp_t *mp, nxt_conf_value_t *value, - u_char *start, u_char *end, nxt_conf_json_error_t *error); + u_char *start, u_char *end, + nxt_conf_json_error_t *error); static u_char *nxt_conf_json_parse_object(nxt_mp_t *mp, nxt_conf_value_t *value, - u_char *start, u_char *end, nxt_conf_json_error_t *error); -static nxt_int_t nxt_conf_object_hash_add(nxt_mp_t *mp, - nxt_lvlhsh_t *lvlhsh, nxt_conf_object_member_t *member); -static nxt_int_t nxt_conf_object_hash_test(nxt_lvlhsh_query_t *lhq, - void *data); + u_char *start, u_char *end, + nxt_conf_json_error_t *error); +static nxt_int_t nxt_conf_object_hash_add(nxt_mp_t *mp, nxt_lvlhsh_t *lvlhsh, + nxt_conf_object_member_t *member); +static nxt_int_t nxt_conf_object_hash_test(nxt_lvlhsh_query_t *lhq, void *data); static void *nxt_conf_object_hash_alloc(void *data, size_t size); static void nxt_conf_object_hash_free(void *data, void *p); static u_char *nxt_conf_json_parse_array(nxt_mp_t *mp, nxt_conf_value_t *value, - u_char *start, u_char *end, nxt_conf_json_error_t *error); + u_char *start, u_char *end, + nxt_conf_json_error_t *error); static u_char *nxt_conf_json_parse_string(nxt_mp_t *mp, nxt_conf_value_t *value, - u_char *start, u_char *end, nxt_conf_json_error_t *error); + u_char *start, u_char *end, + nxt_conf_json_error_t *error); static u_char *nxt_conf_json_parse_number(nxt_mp_t *mp, nxt_conf_value_t *value, - u_char *start, u_char *end, nxt_conf_json_error_t *error); + u_char *start, u_char *end, + nxt_conf_json_error_t *error); static void nxt_conf_json_parse_error(nxt_conf_json_error_t *error, u_char *pos, - const char *detail); + const char *detail); static nxt_int_t nxt_conf_copy_value(nxt_mp_t *mp, const nxt_conf_op_t *op, - nxt_conf_value_t *dst, const nxt_conf_value_t *src); + nxt_conf_value_t *dst, + const nxt_conf_value_t *src); static nxt_int_t nxt_conf_copy_array(nxt_mp_t *mp, const nxt_conf_op_t *op, - nxt_conf_value_t *dst, const nxt_conf_value_t *src); + nxt_conf_value_t *dst, + const nxt_conf_value_t *src); static nxt_int_t nxt_conf_copy_object(nxt_mp_t *mp, const nxt_conf_op_t *op, - nxt_conf_value_t *dst, const nxt_conf_value_t *src); + nxt_conf_value_t *dst, + const nxt_conf_value_t *src); static size_t nxt_conf_json_string_length(const nxt_conf_value_t *value); static u_char *nxt_conf_json_print_string(u_char *p, - const nxt_conf_value_t *value); + const nxt_conf_value_t *value); static size_t nxt_conf_json_array_length(const nxt_conf_value_t *value, - nxt_conf_json_pretty_t *pretty); + nxt_conf_json_pretty_t *pretty); static u_char *nxt_conf_json_print_array(u_char *p, - const nxt_conf_value_t *value, nxt_conf_json_pretty_t *pretty); + const nxt_conf_value_t *value, + nxt_conf_json_pretty_t *pretty); static size_t nxt_conf_json_object_length(const nxt_conf_value_t *value, - nxt_conf_json_pretty_t *pretty); + nxt_conf_json_pretty_t *pretty); static u_char *nxt_conf_json_print_object(u_char *p, - const nxt_conf_value_t *value, nxt_conf_json_pretty_t *pretty); + const nxt_conf_value_t *value, + nxt_conf_json_pretty_t *pretty); static size_t nxt_conf_json_escape_length(u_char *p, size_t size); static u_char *nxt_conf_json_escape(u_char *dst, u_char *src, size_t size); +#define nxt_conf_json_newline(p) ((p)[0] = '\r', (p)[1] = '\n', (p) + 2) -#define nxt_conf_json_newline(p) \ - ((p)[0] = '\r', (p)[1] = '\n', (p) + 2) +nxt_inline u_char *nxt_conf_json_indentation(u_char *p, uint32_t level) { + while (level) { + *p++ = '\t'; + level--; + } - -nxt_inline u_char * -nxt_conf_json_indentation(u_char *p, uint32_t level) -{ - while (level) { - *p++ = '\t'; - level--; - } - - return p; + return p; } +void nxt_conf_get_string(const nxt_conf_value_t *value, nxt_str_t *str) { + if (value->type == NXT_CONF_VALUE_SHORT_STRING) { + str->length = value->u.str.length; + str->start = (u_char *)value->u.str.start; -void -nxt_conf_get_string(const nxt_conf_value_t *value, nxt_str_t *str) -{ - if (value->type == NXT_CONF_VALUE_SHORT_STRING) { - str->length = value->u.str.length; - str->start = (u_char *) value->u.str.start; - - } else { - str->length = value->u.string.length; - str->start = (u_char *) value->u.string.start; - } + } else { + str->length = value->u.string.length; + str->start = (u_char *)value->u.string.start; + } } +nxt_str_t *nxt_conf_get_string_dup(const nxt_conf_value_t *value, nxt_mp_t *mp, + nxt_str_t *str) { + nxt_str_t s; -nxt_str_t * -nxt_conf_get_string_dup(const nxt_conf_value_t *value, nxt_mp_t *mp, - nxt_str_t *str) -{ - nxt_str_t s; - - nxt_conf_get_string(value, &s); - return nxt_str_dup(mp, str, &s); + nxt_conf_get_string(value, &s); + return nxt_str_dup(mp, str, &s); } +void nxt_conf_set_string(nxt_conf_value_t *value, const nxt_str_t *str) { + if (str->length > NXT_CONF_MAX_SHORT_STRING) { + value->type = NXT_CONF_VALUE_STRING; + value->u.string.length = str->length; + value->u.string.start = str->start; -void -nxt_conf_set_string(nxt_conf_value_t *value, const nxt_str_t *str) -{ - if (str->length > NXT_CONF_MAX_SHORT_STRING) { - value->type = NXT_CONF_VALUE_STRING; - value->u.string.length = str->length; - value->u.string.start = str->start; - - } else { - value->type = NXT_CONF_VALUE_SHORT_STRING; - value->u.str.length = str->length; + } else { + value->type = NXT_CONF_VALUE_SHORT_STRING; + value->u.str.length = str->length; - nxt_memcpy(value->u.str.start, str->start, str->length); - } + nxt_memcpy(value->u.str.start, str->start, str->length); + } } +nxt_int_t nxt_conf_set_string_dup(nxt_conf_value_t *value, nxt_mp_t *mp, + const nxt_str_t *str) { + nxt_str_t tmp, *ptr; -nxt_int_t -nxt_conf_set_string_dup(nxt_conf_value_t *value, nxt_mp_t *mp, - const nxt_str_t *str) -{ - nxt_str_t tmp, *ptr; + if (str->length > NXT_CONF_MAX_SHORT_STRING) { + value->type = NXT_CONF_VALUE_STRING; - if (str->length > NXT_CONF_MAX_SHORT_STRING) { - value->type = NXT_CONF_VALUE_STRING; - - ptr = nxt_str_dup(mp, &tmp, str); - if (nxt_slow_path(ptr == NULL)) { - return NXT_ERROR; - } + ptr = nxt_str_dup(mp, &tmp, str); + if (nxt_slow_path(ptr == NULL)) { + return NXT_ERROR; + } - value->u.string.length = tmp.length; - value->u.string.start = tmp.start; + value->u.string.length = tmp.length; + value->u.string.start = tmp.start; - } else { - value->type = NXT_CONF_VALUE_SHORT_STRING; - value->u.str.length = str->length; + } else { + value->type = NXT_CONF_VALUE_SHORT_STRING; + value->u.str.length = str->length; - nxt_memcpy(value->u.str.start, str->start, str->length); - } + nxt_memcpy(value->u.str.start, str->start, str->length); + } - return NXT_OK; + return NXT_OK; } - -double -nxt_conf_get_number(nxt_conf_value_t *value) -{ - return nxt_strtod(value->u.number, NULL); +double nxt_conf_get_number(nxt_conf_value_t *value) { + return nxt_strtod(value->u.number, NULL); } - -uint8_t -nxt_conf_get_boolean(nxt_conf_value_t *value) -{ - return value->u.boolean; +uint8_t nxt_conf_get_boolean(nxt_conf_value_t *value) { + return value->u.boolean; } - -nxt_uint_t -nxt_conf_object_members_count(const nxt_conf_value_t *value) -{ - return value->u.object->count; +nxt_uint_t nxt_conf_object_members_count(const nxt_conf_value_t *value) { + return value->u.object->count; } +nxt_conf_value_t *nxt_conf_create_object(nxt_mp_t *mp, nxt_uint_t count) { + size_t size; + nxt_conf_value_t *value; -nxt_conf_value_t * -nxt_conf_create_object(nxt_mp_t *mp, nxt_uint_t count) -{ - size_t size; - nxt_conf_value_t *value; + size = sizeof(nxt_conf_value_t) + sizeof(nxt_conf_object_t) + + count * sizeof(nxt_conf_object_member_t); - size = sizeof(nxt_conf_value_t) - + sizeof(nxt_conf_object_t) - + count * sizeof(nxt_conf_object_member_t); - - value = nxt_mp_get(mp, size); - if (nxt_slow_path(value == NULL)) { - return NULL; - } + value = nxt_mp_get(mp, size); + if (nxt_slow_path(value == NULL)) { + return NULL; + } - value->u.object = nxt_pointer_to(value, sizeof(nxt_conf_value_t)); - value->u.object->count = count; + value->u.object = nxt_pointer_to(value, sizeof(nxt_conf_value_t)); + value->u.object->count = count; - value->type = NXT_CONF_VALUE_OBJECT; + value->type = NXT_CONF_VALUE_OBJECT; - return value; + return value; } +void nxt_conf_set_member(nxt_conf_value_t *object, const nxt_str_t *name, + const nxt_conf_value_t *value, uint32_t index) { + nxt_conf_object_member_t *member; -void -nxt_conf_set_member(nxt_conf_value_t *object, const nxt_str_t *name, - const nxt_conf_value_t *value, uint32_t index) -{ - nxt_conf_object_member_t *member; + member = &object->u.object->members[index]; - member = &object->u.object->members[index]; + nxt_conf_set_string(&member->name, name); - nxt_conf_set_string(&member->name, name); - - member->value = *value; + member->value = *value; } +nxt_int_t nxt_conf_set_member_dup(nxt_conf_value_t *object, nxt_mp_t *mp, + const nxt_str_t *name, + const nxt_conf_value_t *value, + uint32_t index) { + nxt_conf_object_member_t *member; -nxt_int_t -nxt_conf_set_member_dup(nxt_conf_value_t *object, nxt_mp_t *mp, - const nxt_str_t *name, const nxt_conf_value_t *value, uint32_t index) -{ - nxt_conf_object_member_t *member; + member = &object->u.object->members[index]; - member = &object->u.object->members[index]; + member->value = *value; - member->value = *value; - - return nxt_conf_set_string_dup(&member->name, mp, name); + return nxt_conf_set_string_dup(&member->name, mp, name); } +void nxt_conf_set_member_string(nxt_conf_value_t *object, const nxt_str_t *name, + const nxt_str_t *value, uint32_t index) { + nxt_conf_object_member_t *member; -void -nxt_conf_set_member_string(nxt_conf_value_t *object, const nxt_str_t *name, - const nxt_str_t *value, uint32_t index) -{ - nxt_conf_object_member_t *member; + member = &object->u.object->members[index]; - member = &object->u.object->members[index]; + nxt_conf_set_string(&member->name, name); - nxt_conf_set_string(&member->name, name); - - nxt_conf_set_string(&member->value, value); + nxt_conf_set_string(&member->value, value); } +nxt_int_t nxt_conf_set_member_string_dup(nxt_conf_value_t *object, nxt_mp_t *mp, + const nxt_str_t *name, + const nxt_str_t *value, + uint32_t index) { + nxt_conf_object_member_t *member; -nxt_int_t -nxt_conf_set_member_string_dup(nxt_conf_value_t *object, nxt_mp_t *mp, - const nxt_str_t *name, const nxt_str_t *value, uint32_t index) -{ - nxt_conf_object_member_t *member; - - member = &object->u.object->members[index]; + member = &object->u.object->members[index]; - nxt_conf_set_string(&member->name, name); + nxt_conf_set_string(&member->name, name); - return nxt_conf_set_string_dup(&member->value, mp, value); + return nxt_conf_set_string_dup(&member->value, mp, value); } +void nxt_conf_set_member_integer(nxt_conf_value_t *object, + const nxt_str_t *name, int64_t value, + uint32_t index) { + u_char *p, *end; + nxt_conf_object_member_t *member; -void -nxt_conf_set_member_integer(nxt_conf_value_t *object, const nxt_str_t *name, - int64_t value, uint32_t index) -{ - u_char *p, *end; - nxt_conf_object_member_t *member; + member = &object->u.object->members[index]; - member = &object->u.object->members[index]; + nxt_conf_set_string(&member->name, name); - nxt_conf_set_string(&member->name, name); + p = member->value.u.number; + end = p + NXT_CONF_MAX_NUMBER_LEN; - p = member->value.u.number; - end = p + NXT_CONF_MAX_NUMBER_LEN; + end = nxt_sprintf(p, end, "%L", value); + *end = '\0'; - end = nxt_sprintf(p, end, "%L", value); - *end = '\0'; - - member->value.type = NXT_CONF_VALUE_INTEGER; + member->value.type = NXT_CONF_VALUE_INTEGER; } +void nxt_conf_set_member_null(nxt_conf_value_t *object, const nxt_str_t *name, + uint32_t index) { + nxt_conf_object_member_t *member; -void -nxt_conf_set_member_null(nxt_conf_value_t *object, const nxt_str_t *name, - uint32_t index) -{ - nxt_conf_object_member_t *member; - - member = &object->u.object->members[index]; + member = &object->u.object->members[index]; - nxt_conf_set_string(&member->name, name); + nxt_conf_set_string(&member->name, name); - member->value.type = NXT_CONF_VALUE_NULL; + member->value.type = NXT_CONF_VALUE_NULL; } +nxt_conf_value_t *nxt_conf_create_array(nxt_mp_t *mp, nxt_uint_t count) { + size_t size; + nxt_conf_value_t *value; -nxt_conf_value_t * -nxt_conf_create_array(nxt_mp_t *mp, nxt_uint_t count) -{ - size_t size; - nxt_conf_value_t *value; + size = sizeof(nxt_conf_value_t) + sizeof(nxt_conf_array_t) + + count * sizeof(nxt_conf_value_t); - size = sizeof(nxt_conf_value_t) - + sizeof(nxt_conf_array_t) - + count * sizeof(nxt_conf_value_t); - - value = nxt_mp_get(mp, size); - if (nxt_slow_path(value == NULL)) { - return NULL; - } + value = nxt_mp_get(mp, size); + if (nxt_slow_path(value == NULL)) { + return NULL; + } - value->u.array = nxt_pointer_to(value, sizeof(nxt_conf_value_t)); - value->u.array->count = count; + value->u.array = nxt_pointer_to(value, sizeof(nxt_conf_value_t)); + value->u.array->count = count; - value->type = NXT_CONF_VALUE_ARRAY; + value->type = NXT_CONF_VALUE_ARRAY; - return value; + return value; } - -void -nxt_conf_set_element(nxt_conf_value_t *array, nxt_uint_t index, - const nxt_conf_value_t *value) -{ - array->u.array->elements[index] = *value; +void nxt_conf_set_element(nxt_conf_value_t *array, nxt_uint_t index, + const nxt_conf_value_t *value) { + array->u.array->elements[index] = *value; } +nxt_int_t nxt_conf_set_element_string_dup(nxt_conf_value_t *array, nxt_mp_t *mp, + nxt_uint_t index, + const nxt_str_t *value) { + nxt_conf_value_t *element; -nxt_int_t -nxt_conf_set_element_string_dup(nxt_conf_value_t *array, nxt_mp_t *mp, - nxt_uint_t index, const nxt_str_t *value) -{ - nxt_conf_value_t *element; - - element = &array->u.array->elements[index]; + element = &array->u.array->elements[index]; - return nxt_conf_set_string_dup(element, mp, value); + return nxt_conf_set_string_dup(element, mp, value); } - -nxt_uint_t -nxt_conf_array_elements_count(const nxt_conf_value_t *value) -{ - return value->u.array->count; +nxt_uint_t nxt_conf_array_elements_count(const nxt_conf_value_t *value) { + return value->u.array->count; } - -nxt_uint_t -nxt_conf_array_elements_count_or_1(const nxt_conf_value_t *value) -{ - return (value->type == NXT_CONF_VALUE_ARRAY) ? value->u.array->count : 1; +nxt_uint_t nxt_conf_array_elements_count_or_1(const nxt_conf_value_t *value) { + return (value->type == NXT_CONF_VALUE_ARRAY) ? value->u.array->count : 1; } +nxt_uint_t nxt_conf_type(const nxt_conf_value_t *value) { + switch (value->type) { -nxt_uint_t -nxt_conf_type(const nxt_conf_value_t *value) -{ - switch (value->type) { - - case NXT_CONF_VALUE_NULL: - return NXT_CONF_NULL; + case NXT_CONF_VALUE_NULL: + return NXT_CONF_NULL; - case NXT_CONF_VALUE_BOOLEAN: - return NXT_CONF_BOOLEAN; + case NXT_CONF_VALUE_BOOLEAN: + return NXT_CONF_BOOLEAN; - case NXT_CONF_VALUE_INTEGER: - return NXT_CONF_INTEGER; + case NXT_CONF_VALUE_INTEGER: + return NXT_CONF_INTEGER; - case NXT_CONF_VALUE_NUMBER: - return NXT_CONF_NUMBER; + case NXT_CONF_VALUE_NUMBER: + return NXT_CONF_NUMBER; - case NXT_CONF_VALUE_SHORT_STRING: - case NXT_CONF_VALUE_STRING: - return NXT_CONF_STRING; + case NXT_CONF_VALUE_SHORT_STRING: + case NXT_CONF_VALUE_STRING: + return NXT_CONF_STRING; - case NXT_CONF_VALUE_ARRAY: - return NXT_CONF_ARRAY; + case NXT_CONF_VALUE_ARRAY: + return NXT_CONF_ARRAY; - case NXT_CONF_VALUE_OBJECT: - return NXT_CONF_OBJECT; - } + case NXT_CONF_VALUE_OBJECT: + return NXT_CONF_OBJECT; + } - nxt_unreachable(); + nxt_unreachable(); - return 0; + return 0; } +nxt_conf_value_t *nxt_conf_get_path(nxt_conf_value_t *value, + const nxt_str_t *path) { + nxt_str_t token; + nxt_int_t ret, index; + nxt_conf_path_parse_t parse; -nxt_conf_value_t * -nxt_conf_get_path(nxt_conf_value_t *value, const nxt_str_t *path) -{ - nxt_str_t token; - nxt_int_t ret, index; - nxt_conf_path_parse_t parse; - - parse.start = path->start; - parse.end = path->start + path->length; - parse.last = 0; + parse.start = path->start; + parse.end = path->start + path->length; + parse.last = 0; - do { - ret = nxt_conf_path_next_token(&parse, &token); - if (nxt_slow_path(ret != NXT_OK)) { - return NULL; - } + do { + ret = nxt_conf_path_next_token(&parse, &token); + if (nxt_slow_path(ret != NXT_OK)) { + return NULL; + } - if (token.length == 0) { + if (token.length == 0) { - if (parse.last) { - break; - } + if (parse.last) { + break; + } - return NULL; - } + return NULL; + } - switch (value->type) { + switch (value->type) { - case NXT_CONF_VALUE_OBJECT: - value = nxt_conf_get_object_member(value, &token, NULL); - break; + case NXT_CONF_VALUE_OBJECT: + value = nxt_conf_get_object_member(value, &token, NULL); + break; - case NXT_CONF_VALUE_ARRAY: - index = nxt_int_parse(token.start, token.length); + case NXT_CONF_VALUE_ARRAY: + index = nxt_int_parse(token.start, token.length); - if (index < 0 || index > NXT_INT32_T_MAX) { - return NULL; - } + if (index < 0 || index > NXT_INT32_T_MAX) { + return NULL; + } - value = nxt_conf_get_array_element(value, index); - break; + value = nxt_conf_get_array_element(value, index); + break; - default: - return NULL; - } + default: + return NULL; + } - if (value == NULL) { - return NULL; - } + if (value == NULL) { + return NULL; + } - } while (parse.last == 0); + } while (parse.last == 0); - return value; + return value; } +static nxt_int_t nxt_conf_path_next_token(nxt_conf_path_parse_t *parse, + nxt_str_t *token) { + u_char *p, *start, *end; + size_t length; -static nxt_int_t -nxt_conf_path_next_token(nxt_conf_path_parse_t *parse, nxt_str_t *token) -{ - u_char *p, *start, *end; - size_t length; - - start = parse->start + 1; + start = parse->start + 1; - p = start; + p = start; - while (p < parse->end && *p != '/') { - p++; - } + while (p < parse->end && *p != '/') { + p++; + } - parse->start = p; - parse->last = (p >= parse->end); + parse->start = p; + parse->last = (p >= parse->end); - length = p - start; + length = p - start; - if (nxt_slow_path(length > NXT_CONF_MAX_TOKEN_LEN)) { - return NXT_ERROR; - } + if (nxt_slow_path(length > NXT_CONF_MAX_TOKEN_LEN)) { + return NXT_ERROR; + } - end = nxt_decode_uri(parse->buf, start, length); - if (nxt_slow_path(end == NULL)) { - return NXT_ERROR; - } + end = nxt_decode_uri(parse->buf, start, length); + if (nxt_slow_path(end == NULL)) { + return NXT_ERROR; + } - token->length = end - parse->buf; - token->start = parse->buf; + token->length = end - parse->buf; + token->start = parse->buf; - return NXT_OK; + return NXT_OK; } +nxt_conf_value_t *nxt_conf_get_object_member(const nxt_conf_value_t *value, + const nxt_str_t *name, + uint32_t *index) { + nxt_str_t str; + nxt_uint_t n; + nxt_conf_object_t *object; + nxt_conf_object_member_t *member; -nxt_conf_value_t * -nxt_conf_get_object_member(const nxt_conf_value_t *value, const nxt_str_t *name, - uint32_t *index) -{ - nxt_str_t str; - nxt_uint_t n; - nxt_conf_object_t *object; - nxt_conf_object_member_t *member; - - if (value->type != NXT_CONF_VALUE_OBJECT) { - return NULL; - } + if (value->type != NXT_CONF_VALUE_OBJECT) { + return NULL; + } - object = value->u.object; + object = value->u.object; - for (n = 0; n < object->count; n++) { - member = &object->members[n]; + for (n = 0; n < object->count; n++) { + member = &object->members[n]; - nxt_conf_get_string(&member->name, &str); + nxt_conf_get_string(&member->name, &str); - if (nxt_strstr_eq(&str, name)) { + if (nxt_strstr_eq(&str, name)) { - if (index != NULL) { - *index = n; - } + if (index != NULL) { + *index = n; + } - return &member->value; - } + return &member->value; } + } - return NULL; + return NULL; } +nxt_int_t nxt_conf_map_object(nxt_mp_t *mp, const nxt_conf_value_t *value, + const nxt_conf_map_t *map, nxt_uint_t n, + void *data) { + double num; + nxt_str_t str, *s; + nxt_uint_t i; + nxt_conf_value_t *v; -nxt_int_t -nxt_conf_map_object(nxt_mp_t *mp, const nxt_conf_value_t *value, - const nxt_conf_map_t *map, nxt_uint_t n, void *data) -{ - double num; - nxt_str_t str, *s; - nxt_uint_t i; - nxt_conf_value_t *v; - - union { - uint8_t ui8; - int32_t i32; - int64_t i64; - int i; - ssize_t size; - off_t off; - nxt_msec_t msec; - double dbl; - nxt_str_t str; - char *cstrz; - void *v; - } *ptr; - - for (i = 0; i < n; i++) { - - v = nxt_conf_get_object_member(value, &map[i].name, NULL); - - if (v == NULL || v->type == NXT_CONF_VALUE_NULL) { - continue; - } - - ptr = nxt_pointer_to(data, map[i].offset); - - switch (map[i].type) { + union { + uint8_t ui8; + int32_t i32; + int64_t i64; + int i; + ssize_t size; + off_t off; + nxt_msec_t msec; + double dbl; + nxt_str_t str; + char *cstrz; + void *v; + } *ptr; - case NXT_CONF_MAP_INT8: + for (i = 0; i < n; i++) { - if (v->type == NXT_CONF_VALUE_BOOLEAN) { - ptr->ui8 = v->u.boolean; - } + v = nxt_conf_get_object_member(value, &map[i].name, NULL); - break; - - case NXT_CONF_MAP_INT32: - case NXT_CONF_MAP_INT64: - case NXT_CONF_MAP_INT: - case NXT_CONF_MAP_SIZE: - case NXT_CONF_MAP_OFF: - case NXT_CONF_MAP_MSEC: + if (v == NULL || v->type == NXT_CONF_VALUE_NULL) { + continue; + } - if (v->type != NXT_CONF_VALUE_INTEGER) { - break; - } + ptr = nxt_pointer_to(data, map[i].offset); - num = nxt_strtod(v->u.number, NULL); + switch (map[i].type) { - switch (map[i].type) { + case NXT_CONF_MAP_INT8: - case NXT_CONF_MAP_INT32: - ptr->i32 = num; - break; + if (v->type == NXT_CONF_VALUE_BOOLEAN) { + ptr->ui8 = v->u.boolean; + } - case NXT_CONF_MAP_INT64: - ptr->i64 = num; - break; + break; - case NXT_CONF_MAP_INT: - ptr->i = num; - break; + case NXT_CONF_MAP_INT32: + case NXT_CONF_MAP_INT64: + case NXT_CONF_MAP_INT: + case NXT_CONF_MAP_SIZE: + case NXT_CONF_MAP_OFF: + case NXT_CONF_MAP_MSEC: - case NXT_CONF_MAP_SIZE: - ptr->size = num; - break; + if (v->type != NXT_CONF_VALUE_INTEGER) { + break; + } - case NXT_CONF_MAP_OFF: - ptr->off = num; - break; + num = nxt_strtod(v->u.number, NULL); - case NXT_CONF_MAP_MSEC: - ptr->msec = (nxt_msec_t) num * 1000; - break; + switch (map[i].type) { - default: - nxt_unreachable(); - } + case NXT_CONF_MAP_INT32: + ptr->i32 = num; + break; - break; + case NXT_CONF_MAP_INT64: + ptr->i64 = num; + break; - case NXT_CONF_MAP_DOUBLE: + case NXT_CONF_MAP_INT: + ptr->i = num; + break; - if (v->type == NXT_CONF_VALUE_NUMBER) { - ptr->dbl = nxt_strtod(v->u.number, NULL); - } + case NXT_CONF_MAP_SIZE: + ptr->size = num; + break; - break; + case NXT_CONF_MAP_OFF: + ptr->off = num; + break; - case NXT_CONF_MAP_STR: - case NXT_CONF_MAP_STR_COPY: - case NXT_CONF_MAP_CSTRZ: + case NXT_CONF_MAP_MSEC: + ptr->msec = (nxt_msec_t)num * 1000; + break; - if (v->type != NXT_CONF_VALUE_SHORT_STRING - && v->type != NXT_CONF_VALUE_STRING) - { - break; - } + default: + nxt_unreachable(); + } - nxt_conf_get_string(v, &str); + break; - switch (map[i].type) { + case NXT_CONF_MAP_DOUBLE: - case NXT_CONF_MAP_STR: - ptr->str = str; - break; + if (v->type == NXT_CONF_VALUE_NUMBER) { + ptr->dbl = nxt_strtod(v->u.number, NULL); + } - case NXT_CONF_MAP_STR_COPY: + break; - s = nxt_str_dup(mp, &ptr->str, &str); + case NXT_CONF_MAP_STR: + case NXT_CONF_MAP_STR_COPY: + case NXT_CONF_MAP_CSTRZ: - if (nxt_slow_path(s == NULL)) { - return NXT_ERROR; - } + if (v->type != NXT_CONF_VALUE_SHORT_STRING && + v->type != NXT_CONF_VALUE_STRING) { + break; + } - break; + nxt_conf_get_string(v, &str); - case NXT_CONF_MAP_CSTRZ: + switch (map[i].type) { - ptr->cstrz = nxt_str_cstrz(mp, &str); + case NXT_CONF_MAP_STR: + ptr->str = str; + break; - if (nxt_slow_path(ptr->cstrz == NULL)) { - return NXT_ERROR; - } + case NXT_CONF_MAP_STR_COPY: - break; + s = nxt_str_dup(mp, &ptr->str, &str); - default: - nxt_unreachable(); - } + if (nxt_slow_path(s == NULL)) { + return NXT_ERROR; + } - break; + break; - case NXT_CONF_MAP_PTR: + case NXT_CONF_MAP_CSTRZ: - ptr->v = v; + ptr->cstrz = nxt_str_cstrz(mp, &str); - break; + if (nxt_slow_path(ptr->cstrz == NULL)) { + return NXT_ERROR; } - } - return NXT_OK; -} + break; + default: + nxt_unreachable(); + } -nxt_conf_value_t * -nxt_conf_next_object_member(const nxt_conf_value_t *value, nxt_str_t *name, - uint32_t *next) -{ - uint32_t n; - nxt_conf_object_t *object; - nxt_conf_object_member_t *member; + break; - if (value->type != NXT_CONF_VALUE_OBJECT) { - return NULL; - } + case NXT_CONF_MAP_PTR: - n = *next; - object = value->u.object; + ptr->v = v; - if (n >= object->count) { - return NULL; + break; } + } - member = &object->members[n]; - *next = n + 1; - - nxt_conf_get_string(&member->name, name); - - return &member->value; + return NXT_OK; } +nxt_conf_value_t *nxt_conf_next_object_member(const nxt_conf_value_t *value, + nxt_str_t *name, uint32_t *next) { + uint32_t n; + nxt_conf_object_t *object; + nxt_conf_object_member_t *member; -nxt_conf_value_t * -nxt_conf_get_array_element(const nxt_conf_value_t *value, uint32_t index) -{ - nxt_conf_array_t *array; + if (value->type != NXT_CONF_VALUE_OBJECT) { + return NULL; + } - if (value->type != NXT_CONF_VALUE_ARRAY) { - return NULL; - } + n = *next; + object = value->u.object; + + if (n >= object->count) { + return NULL; + } - array = value->u.array; + member = &object->members[n]; + *next = n + 1; - if (index >= array->count) { - return NULL; - } + nxt_conf_get_string(&member->name, name); - return &array->elements[index]; + return &member->value; } +nxt_conf_value_t *nxt_conf_get_array_element(const nxt_conf_value_t *value, + uint32_t index) { + nxt_conf_array_t *array; -nxt_conf_value_t * -nxt_conf_get_array_element_or_itself(nxt_conf_value_t *value, uint32_t index) -{ - nxt_conf_array_t *array; - - if (value->type != NXT_CONF_VALUE_ARRAY) { - return (index == 0) ? value : NULL; - } + if (value->type != NXT_CONF_VALUE_ARRAY) { + return NULL; + } - array = value->u.array; + array = value->u.array; - if (index >= array->count) { - return NULL; - } + if (index >= array->count) { + return NULL; + } - return &array->elements[index]; + return &array->elements[index]; } +nxt_conf_value_t *nxt_conf_get_array_element_or_itself(nxt_conf_value_t *value, + uint32_t index) { + nxt_conf_array_t *array; -void -nxt_conf_array_qsort(const nxt_conf_value_t *value, - int (*compare)(const void *, const void *)) -{ - nxt_conf_array_t *array; + if (value->type != NXT_CONF_VALUE_ARRAY) { + return (index == 0) ? value : NULL; + } - if (value->type != NXT_CONF_VALUE_ARRAY) { - return; - } + array = value->u.array; - array = value->u.array; + if (index >= array->count) { + return NULL; + } - nxt_qsort(array->elements, array->count, sizeof(nxt_conf_value_t), compare); + return &array->elements[index]; } +void nxt_conf_array_qsort(const nxt_conf_value_t *value, + int (*compare)(const void *, const void *)) { + nxt_conf_array_t *array; -nxt_conf_op_ret_t -nxt_conf_op_compile(nxt_mp_t *mp, nxt_conf_op_t **ops, - const nxt_conf_value_t *root, const nxt_str_t *path, - nxt_conf_value_t *value, nxt_bool_t add) -{ - nxt_str_t token; - nxt_int_t ret, index; - nxt_conf_op_t *op, **parent; - nxt_conf_value_t *node; - nxt_conf_path_parse_t parse; - nxt_conf_object_member_t *member; - - parse.start = path->start; - parse.end = path->start + path->length; - parse.last = 0; - - parent = ops; - - for ( ;; ) { - op = nxt_mp_zget(mp, sizeof(nxt_conf_op_t)); - if (nxt_slow_path(op == NULL)) { - return NXT_CONF_OP_ERROR; - } + if (value->type != NXT_CONF_VALUE_ARRAY) { + return; + } - *parent = op; - parent = (nxt_conf_op_t **) &op->ctx; + array = value->u.array; - ret = nxt_conf_path_next_token(&parse, &token); - if (nxt_slow_path(ret != NXT_OK)) { - return NXT_CONF_OP_ERROR; - } + nxt_qsort(array->elements, array->count, sizeof(nxt_conf_value_t), compare); +} - switch (root->type) { +nxt_conf_op_ret_t nxt_conf_op_compile(nxt_mp_t *mp, nxt_conf_op_t **ops, + const nxt_conf_value_t *root, + const nxt_str_t *path, + nxt_conf_value_t *value, nxt_bool_t add) { + nxt_str_t token; + nxt_int_t ret, index; + nxt_conf_op_t *op, **parent; + nxt_conf_value_t *node; + nxt_conf_path_parse_t parse; + nxt_conf_object_member_t *member; - case NXT_CONF_VALUE_OBJECT: - node = nxt_conf_get_object_member(root, &token, &op->index); - break; + parse.start = path->start; + parse.end = path->start + path->length; + parse.last = 0; - case NXT_CONF_VALUE_ARRAY: - index = nxt_int_parse(token.start, token.length); + parent = ops; - if (index < 0 || index > NXT_INT32_T_MAX) { - return NXT_CONF_OP_NOT_FOUND; - } + for (;;) { + op = nxt_mp_zget(mp, sizeof(nxt_conf_op_t)); + if (nxt_slow_path(op == NULL)) { + return NXT_CONF_OP_ERROR; + } - op->index = index; + *parent = op; + parent = (nxt_conf_op_t **)&op->ctx; - node = nxt_conf_get_array_element(root, index); - break; + ret = nxt_conf_path_next_token(&parse, &token); + if (nxt_slow_path(ret != NXT_OK)) { + return NXT_CONF_OP_ERROR; + } - default: - node = NULL; - } + switch (root->type) { - if (parse.last) { - break; - } + case NXT_CONF_VALUE_OBJECT: + node = nxt_conf_get_object_member(root, &token, &op->index); + break; - if (node == NULL) { - return NXT_CONF_OP_NOT_FOUND; - } + case NXT_CONF_VALUE_ARRAY: + index = nxt_int_parse(token.start, token.length); - op->action = NXT_CONF_OP_PASS; - root = node; - } + if (index < 0 || index > NXT_INT32_T_MAX) { + return NXT_CONF_OP_NOT_FOUND; + } - if (value == NULL) { + op->index = index; - if (node == NULL) { - return NXT_CONF_OP_NOT_FOUND; - } + node = nxt_conf_get_array_element(root, index); + break; - op->action = NXT_CONF_OP_DELETE; + default: + node = NULL; + } - return NXT_CONF_OP_OK; + if (parse.last) { + break; } - if (add) { - if (node == NULL) { - return NXT_CONF_OP_NOT_FOUND; - } + if (node == NULL) { + return NXT_CONF_OP_NOT_FOUND; + } - if (node->type != NXT_CONF_VALUE_ARRAY) { - return NXT_CONF_OP_NOT_ALLOWED; - } + op->action = NXT_CONF_OP_PASS; + root = node; + } - op->action = NXT_CONF_OP_PASS; + if (value == NULL) { - op = nxt_mp_zget(mp, sizeof(nxt_conf_op_t)); - if (nxt_slow_path(op == NULL)) { - return NXT_CONF_OP_ERROR; - } + if (node == NULL) { + return NXT_CONF_OP_NOT_FOUND; + } - *parent = op; + op->action = NXT_CONF_OP_DELETE; - op->index = node->u.array->count; - op->action = NXT_CONF_OP_CREATE; - op->ctx = value; + return NXT_CONF_OP_OK; + } - return NXT_CONF_OP_OK; + if (add) { + if (node == NULL) { + return NXT_CONF_OP_NOT_FOUND; } - if (node != NULL) { - op->action = NXT_CONF_OP_REPLACE; - op->ctx = value; - - return NXT_CONF_OP_OK; + if (node->type != NXT_CONF_VALUE_ARRAY) { + return NXT_CONF_OP_NOT_ALLOWED; } - op->action = NXT_CONF_OP_CREATE; - - if (root->type == NXT_CONF_VALUE_ARRAY) { - if (op->index > root->u.array->count) { - return NXT_CONF_OP_NOT_FOUND; - } + op->action = NXT_CONF_OP_PASS; - op->ctx = value; + op = nxt_mp_zget(mp, sizeof(nxt_conf_op_t)); + if (nxt_slow_path(op == NULL)) { + return NXT_CONF_OP_ERROR; + } - } else { - member = nxt_mp_zget(mp, sizeof(nxt_conf_object_member_t)); - if (nxt_slow_path(member == NULL)) { - return NXT_CONF_OP_ERROR; - } + *parent = op; - ret = nxt_conf_set_string_dup(&member->name, mp, &token); - if (nxt_slow_path(ret != NXT_OK)) { - return NXT_CONF_OP_ERROR; - } + op->index = node->u.array->count; + op->action = NXT_CONF_OP_CREATE; + op->ctx = value; - member->value = *value; + return NXT_CONF_OP_OK; + } - op->index = root->u.object->count; - op->ctx = member; - } + if (node != NULL) { + op->action = NXT_CONF_OP_REPLACE; + op->ctx = value; return NXT_CONF_OP_OK; -} - + } -nxt_conf_value_t * -nxt_conf_clone(nxt_mp_t *mp, nxt_conf_op_t *op, const nxt_conf_value_t *value) -{ - nxt_int_t rc; - nxt_conf_value_t *copy; + op->action = NXT_CONF_OP_CREATE; - copy = nxt_mp_get(mp, sizeof(nxt_conf_value_t)); - if (nxt_slow_path(copy == NULL)) { - return NULL; + if (root->type == NXT_CONF_VALUE_ARRAY) { + if (op->index > root->u.array->count) { + return NXT_CONF_OP_NOT_FOUND; } - rc = nxt_conf_copy_value(mp, op, copy, value); + op->ctx = value; - if (nxt_slow_path(rc != NXT_OK)) { - return NULL; + } else { + member = nxt_mp_zget(mp, sizeof(nxt_conf_object_member_t)); + if (nxt_slow_path(member == NULL)) { + return NXT_CONF_OP_ERROR; } - return copy; -} - - -static nxt_int_t -nxt_conf_copy_value(nxt_mp_t *mp, const nxt_conf_op_t *op, - nxt_conf_value_t *dst, const nxt_conf_value_t *src) -{ - if (op != NULL - && src->type != NXT_CONF_VALUE_ARRAY - && src->type != NXT_CONF_VALUE_OBJECT) - { - return NXT_ERROR; + ret = nxt_conf_set_string_dup(&member->name, mp, &token); + if (nxt_slow_path(ret != NXT_OK)) { + return NXT_CONF_OP_ERROR; } - switch (src->type) { - - case NXT_CONF_VALUE_STRING: - - dst->u.string.start = nxt_mp_nget(mp, src->u.string.length); - if (nxt_slow_path(dst->u.string.start == NULL)) { - return NXT_ERROR; - } + member->value = *value; - nxt_memcpy(dst->u.string.start, src->u.string.start, - src->u.string.length); + op->index = root->u.object->count; + op->ctx = member; + } - dst->u.string.length = src->u.string.length; + return NXT_CONF_OP_OK; +} - break; +nxt_conf_value_t *nxt_conf_clone(nxt_mp_t *mp, nxt_conf_op_t *op, + const nxt_conf_value_t *value) { + nxt_int_t rc; + nxt_conf_value_t *copy; - case NXT_CONF_VALUE_ARRAY: - return nxt_conf_copy_array(mp, op, dst, src); - - case NXT_CONF_VALUE_OBJECT: - return nxt_conf_copy_object(mp, op, dst, src); + copy = nxt_mp_get(mp, sizeof(nxt_conf_value_t)); + if (nxt_slow_path(copy == NULL)) { + return NULL; + } - default: - dst->u = src->u; - } + rc = nxt_conf_copy_value(mp, op, copy, value); - dst->type = src->type; + if (nxt_slow_path(rc != NXT_OK)) { + return NULL; + } - return NXT_OK; + return copy; } +static nxt_int_t nxt_conf_copy_value(nxt_mp_t *mp, const nxt_conf_op_t *op, + nxt_conf_value_t *dst, + const nxt_conf_value_t *src) { + if (op != NULL && src->type != NXT_CONF_VALUE_ARRAY && + src->type != NXT_CONF_VALUE_OBJECT) { + return NXT_ERROR; + } -static nxt_int_t -nxt_conf_copy_array(nxt_mp_t *mp, const nxt_conf_op_t *op, - nxt_conf_value_t *dst, const nxt_conf_value_t *src) -{ - size_t size; - nxt_int_t rc; - nxt_uint_t s, d, count, index; - nxt_conf_op_t *pass_op; - nxt_conf_value_t *value; + switch (src->type) { - count = src->u.array->count; + case NXT_CONF_VALUE_STRING: - if (op != NULL) { - if (op->action == NXT_CONF_OP_CREATE) { - count++; - - } else if (op->action == NXT_CONF_OP_DELETE) { - count--; - } + dst->u.string.start = nxt_mp_nget(mp, src->u.string.length); + if (nxt_slow_path(dst->u.string.start == NULL)) { + return NXT_ERROR; } - size = sizeof(nxt_conf_array_t) + count * sizeof(nxt_conf_value_t); + nxt_memcpy(dst->u.string.start, src->u.string.start, src->u.string.length); - dst->u.array = nxt_mp_get(mp, size); - if (nxt_slow_path(dst->u.array == NULL)) { - return NXT_ERROR; - } + dst->u.string.length = src->u.string.length; - dst->u.array->count = count; + break; - s = 0; - d = 0; + case NXT_CONF_VALUE_ARRAY: + return nxt_conf_copy_array(mp, op, dst, src); - pass_op = NULL; + case NXT_CONF_VALUE_OBJECT: + return nxt_conf_copy_object(mp, op, dst, src); - /* - * This initialization is needed only to - * suppress a warning on GCC 4.8 and older. - */ - index = 0; + default: + dst->u = src->u; + } - do { - if (pass_op == NULL) { - index = (op == NULL) ? src->u.array->count : op->index; - } - - while (s != index) { - rc = nxt_conf_copy_value(mp, pass_op, &dst->u.array->elements[d], - &src->u.array->elements[s]); - if (nxt_slow_path(rc != NXT_OK)) { - return NXT_ERROR; - } + dst->type = src->type; - s++; - d++; - } + return NXT_OK; +} - if (pass_op != NULL) { - pass_op = NULL; - continue; - } +static nxt_int_t nxt_conf_copy_array(nxt_mp_t *mp, const nxt_conf_op_t *op, + nxt_conf_value_t *dst, + const nxt_conf_value_t *src) { + size_t size; + nxt_int_t rc; + nxt_uint_t s, d, count, index; + nxt_conf_op_t *pass_op; + nxt_conf_value_t *value; - if (op != NULL) { - switch (op->action) { - case NXT_CONF_OP_PASS: - pass_op = op->ctx; - index++; - break; + count = src->u.array->count; - case NXT_CONF_OP_CREATE: - value = op->ctx; - dst->u.array->elements[d] = *value; + if (op != NULL) { + if (op->action == NXT_CONF_OP_CREATE) { + count++; - d++; - break; + } else if (op->action == NXT_CONF_OP_DELETE) { + count--; + } + } - case NXT_CONF_OP_REPLACE: - value = op->ctx; - dst->u.array->elements[d] = *value; + size = sizeof(nxt_conf_array_t) + count * sizeof(nxt_conf_value_t); - s++; - d++; - break; + dst->u.array = nxt_mp_get(mp, size); + if (nxt_slow_path(dst->u.array == NULL)) { + return NXT_ERROR; + } - case NXT_CONF_OP_DELETE: - s++; - break; - } + dst->u.array->count = count; - op = NULL; - } + s = 0; + d = 0; - } while (d != count); + pass_op = NULL; - dst->type = src->type; + /* + * This initialization is needed only to + * suppress a warning on GCC 4.8 and older. + */ + index = 0; - return NXT_OK; -} + do { + if (pass_op == NULL) { + index = (op == NULL) ? src->u.array->count : op->index; + } + while (s != index) { + rc = nxt_conf_copy_value(mp, pass_op, &dst->u.array->elements[d], + &src->u.array->elements[s]); + if (nxt_slow_path(rc != NXT_OK)) { + return NXT_ERROR; + } -static nxt_int_t -nxt_conf_copy_object(nxt_mp_t *mp, const nxt_conf_op_t *op, - nxt_conf_value_t *dst, const nxt_conf_value_t *src) -{ - size_t size; - nxt_int_t rc; - nxt_uint_t s, d, count, index; - nxt_conf_op_t *pass_op; - nxt_conf_value_t *value; - nxt_conf_object_member_t *member; + s++; + d++; + } - count = src->u.object->count; + if (pass_op != NULL) { + pass_op = NULL; + continue; + } if (op != NULL) { - if (op->action == NXT_CONF_OP_CREATE) { - count++; + switch (op->action) { + case NXT_CONF_OP_PASS: + pass_op = op->ctx; + index++; + break; - } else if (op->action == NXT_CONF_OP_DELETE) { - count--; - } - } + case NXT_CONF_OP_CREATE: + value = op->ctx; + dst->u.array->elements[d] = *value; + + d++; + break; - size = sizeof(nxt_conf_object_t) - + count * sizeof(nxt_conf_object_member_t); + case NXT_CONF_OP_REPLACE: + value = op->ctx; + dst->u.array->elements[d] = *value; - dst->u.object = nxt_mp_get(mp, size); - if (nxt_slow_path(dst->u.object == NULL)) { - return NXT_ERROR; + s++; + d++; + break; + + case NXT_CONF_OP_DELETE: + s++; + break; + } + + op = NULL; } - dst->u.object->count = count; + } while (d != count); - s = 0; - d = 0; + dst->type = src->type; - pass_op = NULL; + return NXT_OK; +} - /* - * This initialization is needed only to - * suppress a warning on GCC 4.8 and older. - */ - index = 0; +static nxt_int_t nxt_conf_copy_object(nxt_mp_t *mp, const nxt_conf_op_t *op, + nxt_conf_value_t *dst, + const nxt_conf_value_t *src) { + size_t size; + nxt_int_t rc; + nxt_uint_t s, d, count, index; + nxt_conf_op_t *pass_op; + nxt_conf_value_t *value; + nxt_conf_object_member_t *member; - do { - if (pass_op == NULL) { - index = (op == NULL) ? src->u.object->count : op->index; - } + count = src->u.object->count; - while (s != index) { - rc = nxt_conf_copy_value(mp, NULL, - &dst->u.object->members[d].name, - &src->u.object->members[s].name); + if (op != NULL) { + if (op->action == NXT_CONF_OP_CREATE) { + count++; - if (nxt_slow_path(rc != NXT_OK)) { - return NXT_ERROR; - } + } else if (op->action == NXT_CONF_OP_DELETE) { + count--; + } + } - rc = nxt_conf_copy_value(mp, pass_op, - &dst->u.object->members[d].value, - &src->u.object->members[s].value); + size = sizeof(nxt_conf_object_t) + count * sizeof(nxt_conf_object_member_t); - if (nxt_slow_path(rc != NXT_OK)) { - return NXT_ERROR; - } + dst->u.object = nxt_mp_get(mp, size); + if (nxt_slow_path(dst->u.object == NULL)) { + return NXT_ERROR; + } - s++; - d++; - } + dst->u.object->count = count; - if (pass_op != NULL) { - pass_op = NULL; - continue; - } + s = 0; + d = 0; - if (op != NULL) { - switch (op->action) { - case NXT_CONF_OP_PASS: - pass_op = op->ctx; - index++; - break; + pass_op = NULL; - case NXT_CONF_OP_CREATE: - member = op->ctx; + /* + * This initialization is needed only to + * suppress a warning on GCC 4.8 and older. + */ + index = 0; - rc = nxt_conf_copy_value(mp, NULL, - &dst->u.object->members[d].name, - &member->name); + do { + if (pass_op == NULL) { + index = (op == NULL) ? src->u.object->count : op->index; + } - if (nxt_slow_path(rc != NXT_OK)) { - return NXT_ERROR; - } + while (s != index) { + rc = nxt_conf_copy_value(mp, NULL, &dst->u.object->members[d].name, + &src->u.object->members[s].name); - dst->u.object->members[d].value = member->value; + if (nxt_slow_path(rc != NXT_OK)) { + return NXT_ERROR; + } - d++; - break; + rc = nxt_conf_copy_value(mp, pass_op, &dst->u.object->members[d].value, + &src->u.object->members[s].value); - case NXT_CONF_OP_REPLACE: - rc = nxt_conf_copy_value(mp, NULL, - &dst->u.object->members[d].name, - &src->u.object->members[s].name); + if (nxt_slow_path(rc != NXT_OK)) { + return NXT_ERROR; + } - if (nxt_slow_path(rc != NXT_OK)) { - return NXT_ERROR; - } + s++; + d++; + } - value = op->ctx; + if (pass_op != NULL) { + pass_op = NULL; + continue; + } - dst->u.object->members[d].value = *value; + if (op != NULL) { + switch (op->action) { + case NXT_CONF_OP_PASS: + pass_op = op->ctx; + index++; + break; - s++; - d++; - break; + case NXT_CONF_OP_CREATE: + member = op->ctx; - case NXT_CONF_OP_DELETE: - s++; - break; - } + rc = nxt_conf_copy_value(mp, NULL, &dst->u.object->members[d].name, + &member->name); - op = NULL; + if (nxt_slow_path(rc != NXT_OK)) { + return NXT_ERROR; } - } while (d != count); + dst->u.object->members[d].value = member->value; - dst->type = src->type; - - return NXT_OK; -} + d++; + break; + case NXT_CONF_OP_REPLACE: + rc = nxt_conf_copy_value(mp, NULL, &dst->u.object->members[d].name, + &src->u.object->members[s].name); -nxt_conf_value_t * -nxt_conf_json_parse(nxt_mp_t *mp, u_char *start, u_char *end, - nxt_conf_json_error_t *error) -{ - u_char *p; - nxt_conf_value_t *value; + if (nxt_slow_path(rc != NXT_OK)) { + return NXT_ERROR; + } - value = nxt_mp_get(mp, sizeof(nxt_conf_value_t)); - if (nxt_slow_path(value == NULL)) { - return NULL; - } + value = op->ctx; - p = nxt_conf_json_skip_space(start, end); + dst->u.object->members[d].value = *value; - if (nxt_slow_path(p == end)) { + s++; + d++; + break; - nxt_conf_json_parse_error(error, start, - "An empty JSON payload isn't allowed. It must be either a literal " - "(null, true, or false), a number, a string (in double quotes " - "\"\"), an array (with brackets []), or an object (with braces {})." - ); + case NXT_CONF_OP_DELETE: + s++; + break; + } - return NULL; + op = NULL; } - p = nxt_conf_json_parse_value(mp, value, p, end, error); + } while (d != count); - if (nxt_slow_path(p == NULL)) { - return NULL; - } + dst->type = src->type; - p = nxt_conf_json_skip_space(p, end); + return NXT_OK; +} - if (nxt_slow_path(p != end)) { +nxt_conf_value_t *nxt_conf_json_parse(nxt_mp_t *mp, u_char *start, u_char *end, + nxt_conf_json_error_t *error) { + u_char *p; + nxt_conf_value_t *value; - nxt_conf_json_parse_error(error, p, - "Unexpected character after the end of a valid JSON value." - ); + value = nxt_mp_get(mp, sizeof(nxt_conf_value_t)); + if (nxt_slow_path(value == NULL)) { + return NULL; + } - return NULL; - } + p = nxt_conf_json_skip_space(start, end); - return value; -} + if (nxt_slow_path(p == end)) { + nxt_conf_json_parse_error( + error, start, + "An empty JSON payload isn't allowed. It must be either a literal " + "(null, true, or false), a number, a string (in double quotes " + "\"\"), an array (with brackets []), or an object (with braces {})."); -static u_char * -nxt_conf_json_skip_space(u_char *start, const u_char *end) -{ - u_char *p, ch; + return NULL; + } - enum { - sw_normal = 0, - sw_after_slash, - sw_single_comment, - sw_multi_comment, - sw_after_asterisk, - } state; + p = nxt_conf_json_parse_value(mp, value, p, end, error); - state = sw_normal; + if (nxt_slow_path(p == NULL)) { + return NULL; + } - for (p = start; nxt_fast_path(p != end); p++) { - ch = *p; + p = nxt_conf_json_skip_space(p, end); - switch (state) { - - case sw_normal: - switch (ch) { - case ' ': - case '\t': - case '\n': - case '\r': - continue; - case '/': - start = p; - state = sw_after_slash; - continue; - } - - break; - - case sw_after_slash: - switch (ch) { - case '/': - state = sw_single_comment; - continue; - case '*': - state = sw_multi_comment; - continue; - } - - break; - - case sw_single_comment: - if (ch == '\n') { - state = sw_normal; - } - - continue; - - case sw_multi_comment: - if (ch == '*') { - state = sw_after_asterisk; - } - - continue; - - case sw_after_asterisk: - switch (ch) { - case '/': - state = sw_normal; - continue; - case '*': - continue; - } - - state = sw_multi_comment; - continue; - } + if (nxt_slow_path(p != end)) { - break; - } + nxt_conf_json_parse_error( + error, p, "Unexpected character after the end of a valid JSON value."); - if (nxt_slow_path(state != sw_normal)) { - return start; - } + return NULL; + } - return p; + return value; } +static u_char *nxt_conf_json_skip_space(u_char *start, const u_char *end) { + u_char *p, ch; + + enum { + sw_normal = 0, + sw_after_slash, + sw_single_comment, + sw_multi_comment, + sw_after_asterisk, + } state; + + state = sw_normal; + + for (p = start; nxt_fast_path(p != end); p++) { + ch = *p; + + switch (state) { + + case sw_normal: + switch (ch) { + case ' ': + case '\t': + case '\n': + case '\r': + continue; + case '/': + start = p; + state = sw_after_slash; + continue; + } + + break; + + case sw_after_slash: + switch (ch) { + case '/': + state = sw_single_comment; + continue; + case '*': + state = sw_multi_comment; + continue; + } + + break; + + case sw_single_comment: + if (ch == '\n') { + state = sw_normal; + } + + continue; + + case sw_multi_comment: + if (ch == '*') { + state = sw_after_asterisk; + } + + continue; + + case sw_after_asterisk: + switch (ch) { + case '/': + state = sw_normal; + continue; + case '*': + continue; + } + + state = sw_multi_comment; + continue; + } + + break; + } + + if (nxt_slow_path(state != sw_normal)) { + return start; + } + + return p; +} -static u_char * -nxt_conf_json_parse_value(nxt_mp_t *mp, nxt_conf_value_t *value, u_char *start, - u_char *end, nxt_conf_json_error_t *error) -{ - u_char ch, *p; - - ch = *start; +static u_char *nxt_conf_json_parse_value(nxt_mp_t *mp, nxt_conf_value_t *value, + u_char *start, u_char *end, + nxt_conf_json_error_t *error) { + u_char ch, *p; - switch (ch) { - case '{': - return nxt_conf_json_parse_object(mp, value, start, end, error); + ch = *start; - case '[': - return nxt_conf_json_parse_array(mp, value, start, end, error); + switch (ch) { + case '{': + return nxt_conf_json_parse_object(mp, value, start, end, error); - case '"': - return nxt_conf_json_parse_string(mp, value, start, end, error); + case '[': + return nxt_conf_json_parse_array(mp, value, start, end, error); - case 't': - if (nxt_fast_path(end - start >= 4 - && memcmp(start, "true", 4) == 0)) - { - value->u.boolean = 1; - value->type = NXT_CONF_VALUE_BOOLEAN; + case '"': + return nxt_conf_json_parse_string(mp, value, start, end, error); - return start + 4; - } + case 't': + if (nxt_fast_path(end - start >= 4 && memcmp(start, "true", 4) == 0)) { + value->u.boolean = 1; + value->type = NXT_CONF_VALUE_BOOLEAN; - goto error; + return start + 4; + } - case 'f': - if (nxt_fast_path(end - start >= 5 - && memcmp(start, "false", 5) == 0)) - { - value->u.boolean = 0; - value->type = NXT_CONF_VALUE_BOOLEAN; + goto error; - return start + 5; - } + case 'f': + if (nxt_fast_path(end - start >= 5 && memcmp(start, "false", 5) == 0)) { + value->u.boolean = 0; + value->type = NXT_CONF_VALUE_BOOLEAN; - goto error; + return start + 5; + } - case 'n': - if (nxt_fast_path(end - start >= 4 - && memcmp(start, "null", 4) == 0)) - { - value->type = NXT_CONF_VALUE_NULL; - return start + 4; - } + goto error; - goto error; + case 'n': + if (nxt_fast_path(end - start >= 4 && memcmp(start, "null", 4) == 0)) { + value->type = NXT_CONF_VALUE_NULL; + return start + 4; + } - case '-': - if (nxt_fast_path(end - start > 1)) { - ch = start[1]; - break; - } + goto error; - goto error; + case '-': + if (nxt_fast_path(end - start > 1)) { + ch = start[1]; + break; } - if (nxt_fast_path((u_char)(ch - '0') <= 9)) { - p = nxt_conf_json_parse_number(mp, value, start, end, error); + goto error; + } - if (nxt_slow_path(p == NULL)) { - return NULL; - } + if (nxt_fast_path((u_char)(ch - '0') <= 9)) { + p = nxt_conf_json_parse_number(mp, value, start, end, error); - if (p == end) { - return end; - } + if (nxt_slow_path(p == NULL)) { + return NULL; + } - switch (*p) { - case ' ': - case '\t': - case '\r': - case '\n': - case ',': - case '}': - case ']': - case '{': - case '[': - case '"': - case '/': - return p; - } + if (p == end) { + return end; + } + + switch (*p) { + case ' ': + case '\t': + case '\r': + case '\n': + case ',': + case '}': + case ']': + case '{': + case '[': + case '"': + case '/': + return p; } + } error: - nxt_conf_json_parse_error(error, start, - "A valid JSON value is expected here. It must be either a literal " - "(null, true, or false), a number, a string (in double quotes \"\"), " - "an array (with brackets []), or an object (with braces {})." - ); + nxt_conf_json_parse_error( + error, start, + "A valid JSON value is expected here. It must be either a literal " + "(null, true, or false), a number, a string (in double quotes \"\"), " + "an array (with brackets []), or an object (with braces {})."); - return NULL; + return NULL; } - -static const nxt_lvlhsh_proto_t nxt_conf_object_hash_proto - nxt_aligned(64) = -{ +static const nxt_lvlhsh_proto_t nxt_conf_object_hash_proto nxt_aligned(64) = { NXT_LVLHSH_DEFAULT, nxt_conf_object_hash_test, nxt_conf_object_hash_alloc, nxt_conf_object_hash_free, }; +static u_char *nxt_conf_json_parse_object(nxt_mp_t *mp, nxt_conf_value_t *value, + u_char *start, u_char *end, + nxt_conf_json_error_t *error) { + u_char *p, *name; + nxt_mp_t *mp_temp; + nxt_int_t rc; + nxt_uint_t count; + nxt_lvlhsh_t hash; + nxt_lvlhsh_each_t lhe; + nxt_conf_object_t *object; + nxt_conf_object_member_t *member, *element; + + mp_temp = nxt_mp_create(1024, 128, 256, 32); + if (nxt_slow_path(mp_temp == NULL)) { + return NULL; + } -static u_char * -nxt_conf_json_parse_object(nxt_mp_t *mp, nxt_conf_value_t *value, u_char *start, - u_char *end, nxt_conf_json_error_t *error) -{ - u_char *p, *name; - nxt_mp_t *mp_temp; - nxt_int_t rc; - nxt_uint_t count; - nxt_lvlhsh_t hash; - nxt_lvlhsh_each_t lhe; - nxt_conf_object_t *object; - nxt_conf_object_member_t *member, *element; - - mp_temp = nxt_mp_create(1024, 128, 256, 32); - if (nxt_slow_path(mp_temp == NULL)) { - return NULL; - } - - nxt_lvlhsh_init(&hash); - - count = 0; - p = start; + nxt_lvlhsh_init(&hash); - for ( ;; ) { - p = nxt_conf_json_skip_space(p + 1, end); + count = 0; + p = start; - if (nxt_slow_path(p == end)) { + for (;;) { + p = nxt_conf_json_skip_space(p + 1, end); - nxt_conf_json_parse_error(error, p, - "Unexpected end of JSON payload. There's an object without " - "a closing brace (})." - ); + if (nxt_slow_path(p == end)) { - goto error; - } + nxt_conf_json_parse_error( + error, p, + "Unexpected end of JSON payload. There's an object without " + "a closing brace (})."); - if (*p != '"') { - if (nxt_fast_path(*p == '}')) { - break; - } + goto error; + } - nxt_conf_json_parse_error(error, p, - "A double quote (\") is expected here. There must be a valid " - "JSON object member starts with a name, which is a string " - "enclosed in double quotes." - ); + if (*p != '"') { + if (nxt_fast_path(*p == '}')) { + break; + } - goto error; - } + nxt_conf_json_parse_error( + error, p, + "A double quote (\") is expected here. There must be a valid " + "JSON object member starts with a name, which is a string " + "enclosed in double quotes."); - name = p; + goto error; + } - count++; + name = p; - member = nxt_mp_get(mp_temp, sizeof(nxt_conf_object_member_t)); - if (nxt_slow_path(member == NULL)) { - goto error; - } + count++; - p = nxt_conf_json_parse_string(mp, &member->name, p, end, error); + member = nxt_mp_get(mp_temp, sizeof(nxt_conf_object_member_t)); + if (nxt_slow_path(member == NULL)) { + goto error; + } - if (nxt_slow_path(p == NULL)) { - goto error; - } + p = nxt_conf_json_parse_string(mp, &member->name, p, end, error); - rc = nxt_conf_object_hash_add(mp_temp, &hash, member); + if (nxt_slow_path(p == NULL)) { + goto error; + } - if (nxt_slow_path(rc != NXT_OK)) { + rc = nxt_conf_object_hash_add(mp_temp, &hash, member); - if (rc == NXT_DECLINED) { - nxt_conf_json_parse_error(error, name, - "Duplicate object member. All JSON object members must " - "have unique names." - ); - } + if (nxt_slow_path(rc != NXT_OK)) { - goto error; - } + if (rc == NXT_DECLINED) { + nxt_conf_json_parse_error( + error, name, + "Duplicate object member. All JSON object members must " + "have unique names."); + } - p = nxt_conf_json_skip_space(p, end); + goto error; + } - if (nxt_slow_path(p == end)) { + p = nxt_conf_json_skip_space(p, end); - nxt_conf_json_parse_error(error, p, - "Unexpected end of JSON payload. There's an object member " - "without a value." - ); + if (nxt_slow_path(p == end)) { - goto error; - } + nxt_conf_json_parse_error( + error, p, + "Unexpected end of JSON payload. There's an object member " + "without a value."); - if (nxt_slow_path(*p != ':')) { + goto error; + } - nxt_conf_json_parse_error(error, p, - "A colon (:) is expected here. There must be a colon after " - "a JSON member name." - ); + if (nxt_slow_path(*p != ':')) { - goto error; - } + nxt_conf_json_parse_error( + error, p, + "A colon (:) is expected here. There must be a colon after " + "a JSON member name."); - p = nxt_conf_json_skip_space(p + 1, end); + goto error; + } - if (nxt_slow_path(p == end)) { + p = nxt_conf_json_skip_space(p + 1, end); - nxt_conf_json_parse_error(error, p, - "Unexpected end of JSON payload. There's an object member " - "without a value." - ); + if (nxt_slow_path(p == end)) { - goto error; - } + nxt_conf_json_parse_error( + error, p, + "Unexpected end of JSON payload. There's an object member " + "without a value."); - p = nxt_conf_json_parse_value(mp, &member->value, p, end, error); + goto error; + } - if (nxt_slow_path(p == NULL)) { - goto error; - } + p = nxt_conf_json_parse_value(mp, &member->value, p, end, error); - p = nxt_conf_json_skip_space(p, end); + if (nxt_slow_path(p == NULL)) { + goto error; + } - if (nxt_slow_path(p == end)) { + p = nxt_conf_json_skip_space(p, end); - nxt_conf_json_parse_error(error, p, - "Unexpected end of JSON payload. There's an object without " - "a closing brace (})." - ); + if (nxt_slow_path(p == end)) { - goto error; - } + nxt_conf_json_parse_error( + error, p, + "Unexpected end of JSON payload. There's an object without " + "a closing brace (})."); - if (*p != ',') { - if (nxt_fast_path(*p == '}')) { - break; - } + goto error; + } - nxt_conf_json_parse_error(error, p, - "Either a closing brace (}) or a comma (,) is expected here. " - "Each JSON object must be enclosed in braces and its members " - "must be separated by commas." - ); + if (*p != ',') { + if (nxt_fast_path(*p == '}')) { + break; + } - goto error; - } - } + nxt_conf_json_parse_error( + error, p, + "Either a closing brace (}) or a comma (,) is expected here. " + "Each JSON object must be enclosed in braces and its members " + "must be separated by commas."); - object = nxt_mp_get(mp, sizeof(nxt_conf_object_t) - + count * sizeof(nxt_conf_object_member_t)); - if (nxt_slow_path(object == NULL)) { - goto error; + goto error; } + } - value->u.object = object; - value->type = NXT_CONF_VALUE_OBJECT; + object = nxt_mp_get(mp, sizeof(nxt_conf_object_t) + + count * sizeof(nxt_conf_object_member_t)); + if (nxt_slow_path(object == NULL)) { + goto error; + } - object->count = count; - member = object->members; + value->u.object = object; + value->type = NXT_CONF_VALUE_OBJECT; - nxt_lvlhsh_each_init(&lhe, &nxt_conf_object_hash_proto); + object->count = count; + member = object->members; - for ( ;; ) { - element = nxt_lvlhsh_each(&hash, &lhe); + nxt_lvlhsh_each_init(&lhe, &nxt_conf_object_hash_proto); - if (element == NULL) { - break; - } + for (;;) { + element = nxt_lvlhsh_each(&hash, &lhe); - *member++ = *element; + if (element == NULL) { + break; } - nxt_mp_destroy(mp_temp); + *member++ = *element; + } + + nxt_mp_destroy(mp_temp); - return p + 1; + return p + 1; error: - nxt_mp_destroy(mp_temp); - return NULL; + nxt_mp_destroy(mp_temp); + return NULL; } +static nxt_int_t nxt_conf_object_hash_add(nxt_mp_t *mp, nxt_lvlhsh_t *lvlhsh, + nxt_conf_object_member_t *member) { + nxt_lvlhsh_query_t lhq; -static nxt_int_t -nxt_conf_object_hash_add(nxt_mp_t *mp, nxt_lvlhsh_t *lvlhsh, - nxt_conf_object_member_t *member) -{ - nxt_lvlhsh_query_t lhq; - - nxt_conf_get_string(&member->name, &lhq.key); + nxt_conf_get_string(&member->name, &lhq.key); - lhq.key_hash = nxt_djb_hash(lhq.key.start, lhq.key.length); - lhq.replace = 0; - lhq.value = member; - lhq.proto = &nxt_conf_object_hash_proto; - lhq.pool = mp; + lhq.key_hash = nxt_djb_hash(lhq.key.start, lhq.key.length); + lhq.replace = 0; + lhq.value = member; + lhq.proto = &nxt_conf_object_hash_proto; + lhq.pool = mp; - return nxt_lvlhsh_insert(lvlhsh, &lhq); + return nxt_lvlhsh_insert(lvlhsh, &lhq); } +static nxt_int_t nxt_conf_object_hash_test(nxt_lvlhsh_query_t *lhq, + void *data) { + nxt_str_t str; + nxt_conf_object_member_t *member; -static nxt_int_t -nxt_conf_object_hash_test(nxt_lvlhsh_query_t *lhq, void *data) -{ - nxt_str_t str; - nxt_conf_object_member_t *member; - - member = data; + member = data; - nxt_conf_get_string(&member->name, &str); + nxt_conf_get_string(&member->name, &str); - return nxt_strstr_eq(&lhq->key, &str) ? NXT_OK : NXT_DECLINED; + return nxt_strstr_eq(&lhq->key, &str) ? NXT_OK : NXT_DECLINED; } +static void *nxt_conf_object_hash_alloc(void *data, size_t size) { + return nxt_mp_align(data, size, size); +} -static void * -nxt_conf_object_hash_alloc(void *data, size_t size) -{ - return nxt_mp_align(data, size, size); +static void nxt_conf_object_hash_free(void *data, void *p) { + nxt_mp_free(data, p); } +static u_char *nxt_conf_json_parse_array(nxt_mp_t *mp, nxt_conf_value_t *value, + u_char *start, u_char *end, + nxt_conf_json_error_t *error) { + u_char *p; + nxt_mp_t *mp_temp; + nxt_uint_t count; + nxt_list_t *list; + nxt_conf_array_t *array; + nxt_conf_value_t *element; + + mp_temp = nxt_mp_create(1024, 128, 256, 32); + if (nxt_slow_path(mp_temp == NULL)) { + return NULL; + } + + list = nxt_list_create(mp_temp, 8, sizeof(nxt_conf_value_t)); + if (nxt_slow_path(list == NULL)) { + goto error; + } -static void -nxt_conf_object_hash_free(void *data, void *p) -{ - nxt_mp_free(data, p); -} + count = 0; + p = start; + for (;;) { + p = nxt_conf_json_skip_space(p + 1, end); -static u_char * -nxt_conf_json_parse_array(nxt_mp_t *mp, nxt_conf_value_t *value, u_char *start, - u_char *end, nxt_conf_json_error_t *error) -{ - u_char *p; - nxt_mp_t *mp_temp; - nxt_uint_t count; - nxt_list_t *list; - nxt_conf_array_t *array; - nxt_conf_value_t *element; + if (nxt_slow_path(p == end)) { - mp_temp = nxt_mp_create(1024, 128, 256, 32); - if (nxt_slow_path(mp_temp == NULL)) { - return NULL; + nxt_conf_json_parse_error( + error, p, + "Unexpected end of JSON payload. There's an array without " + "a closing bracket (])."); + + goto error; } - list = nxt_list_create(mp_temp, 8, sizeof(nxt_conf_value_t)); - if (nxt_slow_path(list == NULL)) { - goto error; + if (*p == ']') { + break; } - count = 0; - p = start; + count++; - for ( ;; ) { - p = nxt_conf_json_skip_space(p + 1, end); + element = nxt_list_add(list); + if (nxt_slow_path(element == NULL)) { + goto error; + } - if (nxt_slow_path(p == end)) { + p = nxt_conf_json_parse_value(mp, element, p, end, error); - nxt_conf_json_parse_error(error, p, - "Unexpected end of JSON payload. There's an array without " - "a closing bracket (])." - ); + if (nxt_slow_path(p == NULL)) { + goto error; + } - goto error; - } + p = nxt_conf_json_skip_space(p, end); - if (*p == ']') { - break; - } + if (nxt_slow_path(p == end)) { - count++; + nxt_conf_json_parse_error( + error, p, + "Unexpected end of JSON payload. There's an array without " + "a closing bracket (])."); - element = nxt_list_add(list); - if (nxt_slow_path(element == NULL)) { - goto error; - } + goto error; + } - p = nxt_conf_json_parse_value(mp, element, p, end, error); + if (*p != ',') { + if (nxt_fast_path(*p == ']')) { + break; + } - if (nxt_slow_path(p == NULL)) { - goto error; - } + nxt_conf_json_parse_error( + error, p, + "Either a closing bracket (]) or a comma (,) is expected " + "here. Each array must be enclosed in brackets and its " + "members must be separated by commas."); - p = nxt_conf_json_skip_space(p, end); + goto error; + } + } - if (nxt_slow_path(p == end)) { + array = nxt_mp_get(mp, sizeof(nxt_conf_array_t) + + count * sizeof(nxt_conf_value_t)); + if (nxt_slow_path(array == NULL)) { + goto error; + } - nxt_conf_json_parse_error(error, p, - "Unexpected end of JSON payload. There's an array without " - "a closing bracket (])." - ); + value->u.array = array; + value->type = NXT_CONF_VALUE_ARRAY; - goto error; - } + array->count = count; + element = array->elements; - if (*p != ',') { - if (nxt_fast_path(*p == ']')) { - break; - } + nxt_list_each(value, list) { *element++ = *value; } + nxt_list_loop; - nxt_conf_json_parse_error(error, p, - "Either a closing bracket (]) or a comma (,) is expected " - "here. Each array must be enclosed in brackets and its " - "members must be separated by commas." - ); + nxt_mp_destroy(mp_temp); - goto error; - } - } + return p + 1; - array = nxt_mp_get(mp, sizeof(nxt_conf_array_t) - + count * sizeof(nxt_conf_value_t)); - if (nxt_slow_path(array == NULL)) { - goto error; - } +error: - value->u.array = array; - value->type = NXT_CONF_VALUE_ARRAY; + nxt_mp_destroy(mp_temp); + return NULL; +} - array->count = count; - element = array->elements; +static u_char *nxt_conf_json_parse_string(nxt_mp_t *mp, nxt_conf_value_t *value, + u_char *start, u_char *end, + nxt_conf_json_error_t *error) { + u_char *p, ch, *last, *s; + size_t size, surplus; + uint32_t utf, utf_high; + nxt_uint_t i; + enum { + sw_usual = 0, + sw_escape, + sw_encoded1, + sw_encoded2, + sw_encoded3, + sw_encoded4, + } state; + + start++; + + state = 0; + surplus = 0; + + for (p = start; nxt_fast_path(p != end); p++) { + ch = *p; + + switch (state) { + + case sw_usual: + + if (ch == '"') { + break; + } + + if (ch == '\\') { + state = sw_escape; + continue; + } + + if (nxt_fast_path(ch >= ' ')) { + continue; + } + + nxt_conf_json_parse_error( + error, p, + "Unexpected character. All control characters in a JSON " + "string must be escaped."); + + return NULL; + + case sw_escape: + + switch (ch) { + case '"': + case '\\': + case '/': + case 'n': + case 'r': + case 't': + case 'b': + case 'f': + surplus++; + state = sw_usual; + continue; + + case 'u': + /* + * Basic unicode 6 bytes "\uXXXX" in JSON + * and up to 3 bytes in UTF-8. + * + * Surrogate pair: 12 bytes "\uXXXX\uXXXX" in JSON + * and 3 or 4 bytes in UTF-8. + */ + surplus += 3; + state = sw_encoded1; + continue; + } + + nxt_conf_json_parse_error( + error, p - 1, + "Unexpected backslash. A literal backslash in a JSON string " + "must be escaped with a second backslash (\\\\)."); + + return NULL; + + case sw_encoded1: + case sw_encoded2: + case sw_encoded3: + case sw_encoded4: + + if (nxt_fast_path((ch >= '0' && ch <= '9') || (ch >= 'A' && ch <= 'F') || + (ch >= 'a' && ch <= 'f'))) { + state = (state == sw_encoded4) ? sw_usual : state + 1; + continue; + } + + nxt_conf_json_parse_error( + error, p, + "Invalid escape sequence. An escape sequence in a JSON " + "string must start with a backslash, followed by the lowercase " + "letter u, followed by four hexadecimal digits (\\uXXXX)."); + + return NULL; + } + + break; + } + + if (nxt_slow_path(p == end)) { + + nxt_conf_json_parse_error( + error, p, + "Unexpected end of JSON payload. There's a string without " + "a final double quote (\")."); - nxt_list_each(value, list) { - *element++ = *value; - } nxt_list_loop; + return NULL; + } - nxt_mp_destroy(mp_temp); + /* Points to the ending quote mark. */ + last = p; - return p + 1; + size = last - start - surplus; -error: + if (size > NXT_CONF_MAX_SHORT_STRING) { - nxt_mp_destroy(mp_temp); - return NULL; -} + if (nxt_slow_path(size > NXT_CONF_MAX_STRING)) { + nxt_conf_json_parse_error( + error, start, + "The string is too long. Such a long JSON string value " + "is not supported."); -static u_char * -nxt_conf_json_parse_string(nxt_mp_t *mp, nxt_conf_value_t *value, u_char *start, - u_char *end, nxt_conf_json_error_t *error) -{ - u_char *p, ch, *last, *s; - size_t size, surplus; - uint32_t utf, utf_high; - nxt_uint_t i; - enum { - sw_usual = 0, - sw_escape, - sw_encoded1, - sw_encoded2, - sw_encoded3, - sw_encoded4, - } state; - - start++; - - state = 0; - surplus = 0; - - for (p = start; nxt_fast_path(p != end); p++) { - ch = *p; + return NULL; + } - switch (state) { - - case sw_usual: - - if (ch == '"') { - break; - } - - if (ch == '\\') { - state = sw_escape; - continue; - } - - if (nxt_fast_path(ch >= ' ')) { - continue; - } - - nxt_conf_json_parse_error(error, p, - "Unexpected character. All control characters in a JSON " - "string must be escaped." - ); - - return NULL; - - case sw_escape: - - switch (ch) { - case '"': - case '\\': - case '/': - case 'n': - case 'r': - case 't': - case 'b': - case 'f': - surplus++; - state = sw_usual; - continue; - - case 'u': - /* - * Basic unicode 6 bytes "\uXXXX" in JSON - * and up to 3 bytes in UTF-8. - * - * Surrogate pair: 12 bytes "\uXXXX\uXXXX" in JSON - * and 3 or 4 bytes in UTF-8. - */ - surplus += 3; - state = sw_encoded1; - continue; - } - - nxt_conf_json_parse_error(error, p - 1, - "Unexpected backslash. A literal backslash in a JSON string " - "must be escaped with a second backslash (\\\\)." - ); - - return NULL; - - case sw_encoded1: - case sw_encoded2: - case sw_encoded3: - case sw_encoded4: - - if (nxt_fast_path((ch >= '0' && ch <= '9') - || (ch >= 'A' && ch <= 'F') - || (ch >= 'a' && ch <= 'f'))) - { - state = (state == sw_encoded4) ? sw_usual : state + 1; - continue; - } - - nxt_conf_json_parse_error(error, p, - "Invalid escape sequence. An escape sequence in a JSON " - "string must start with a backslash, followed by the lowercase " - "letter u, followed by four hexadecimal digits (\\uXXXX)." - ); - - return NULL; - } + value->type = NXT_CONF_VALUE_STRING; - break; + value->u.string.start = nxt_mp_nget(mp, size); + if (nxt_slow_path(value->u.string.start == NULL)) { + return NULL; } - if (nxt_slow_path(p == end)) { + value->u.string.length = size; - nxt_conf_json_parse_error(error, p, - "Unexpected end of JSON payload. There's a string without " - "a final double quote (\")." - ); + s = value->u.string.start; - return NULL; - } + } else { + value->type = NXT_CONF_VALUE_SHORT_STRING; + value->u.str.length = size; - /* Points to the ending quote mark. */ - last = p; + s = value->u.str.start; + } - size = last - start - surplus; + if (surplus == 0) { + nxt_memcpy(s, start, size); + return last + 1; + } - if (size > NXT_CONF_MAX_SHORT_STRING) { + p = start; - if (nxt_slow_path(size > NXT_CONF_MAX_STRING)) { + do { + ch = *p++; - nxt_conf_json_parse_error(error, start, - "The string is too long. Such a long JSON string value " - "is not supported." - ); + if (ch != '\\') { + *s++ = ch; + continue; + } - return NULL; - } + ch = *p++; - value->type = NXT_CONF_VALUE_STRING; + switch (ch) { + case '"': + case '\\': + case '/': + *s++ = ch; + continue; - value->u.string.start = nxt_mp_nget(mp, size); - if (nxt_slow_path(value->u.string.start == NULL)) { - return NULL; - } + case 'n': + *s++ = '\n'; + continue; - value->u.string.length = size; + case 'r': + *s++ = '\r'; + continue; - s = value->u.string.start; + case 't': + *s++ = '\t'; + continue; - } else { - value->type = NXT_CONF_VALUE_SHORT_STRING; - value->u.str.length = size; + case 'b': + *s++ = '\b'; + continue; - s = value->u.str.start; + case 'f': + *s++ = '\f'; + continue; } - if (surplus == 0) { - nxt_memcpy(s, start, size); - return last + 1; - } + utf = 0; + utf_high = 0; - p = start; + for (;;) { + for (i = 0; i < 4; i++) { + utf = (utf << 4) | + (p[i] >= 'A' ? 10 + ((p[i] & ~0x20) - 'A') : p[i] - '0'); + } - do { - ch = *p++; + p += 4; - if (ch != '\\') { - *s++ = ch; - continue; - } + if (utf_high != 0) { + if (nxt_slow_path(utf < 0xDC00 || utf > 0xDFFF)) { - ch = *p++; + nxt_conf_json_parse_error( + error, p - 12, + "Invalid JSON encoding sequence. This 12-byte " + "sequence composes an illegal UTF-16 surrogate pair."); - switch (ch) { - case '"': - case '\\': - case '/': - *s++ = ch; - continue; + return NULL; + } - case 'n': - *s++ = '\n'; - continue; + utf = ((utf_high - 0xD800) << 10) + (utf - 0xDC00) + 0x10000; - case 'r': - *s++ = '\r'; - continue; + break; + } - case 't': - *s++ = '\t'; - continue; + if (utf < 0xD800 || utf > 0xDFFF) { + break; + } - case 'b': - *s++ = '\b'; - continue; + if (utf > 0xDBFF || p[0] != '\\' || p[1] != 'u') { - case 'f': - *s++ = '\f'; - continue; - } + nxt_conf_json_parse_error( + error, p - 6, + "Invalid JSON encoding sequence. This 6-byte sequence " + "does not represent a valid UTF character."); - utf = 0; - utf_high = 0; + return NULL; + } - for ( ;; ) { - for (i = 0; i < 4; i++) { - utf = (utf << 4) | (p[i] >= 'A' ? 10 + ((p[i] & ~0x20) - 'A') - : p[i] - '0'); - } + p += 2; - p += 4; + utf_high = utf; + utf = 0; + } - if (utf_high != 0) { - if (nxt_slow_path(utf < 0xDC00 || utf > 0xDFFF)) { + s = nxt_utf8_encode(s, utf); - nxt_conf_json_parse_error(error, p - 12, - "Invalid JSON encoding sequence. This 12-byte " - "sequence composes an illegal UTF-16 surrogate pair." - ); + } while (p != last); - return NULL; - } + if (size > NXT_CONF_MAX_SHORT_STRING) { + value->u.string.length = s - value->u.string.start; - utf = ((utf_high - 0xD800) << 10) + (utf - 0xDC00) + 0x10000; + } else { + value->u.str.length = s - value->u.str.start; + } - break; - } + return last + 1; +} - if (utf < 0xD800 || utf > 0xDFFF) { - break; - } +static u_char *nxt_conf_json_parse_number(nxt_mp_t *mp, nxt_conf_value_t *value, + u_char *start, u_char *end, + nxt_conf_json_error_t *error) { + u_char *p, *s, ch, c, *dot_pos; + size_t size; + double num; - if (utf > 0xDBFF || p[0] != '\\' || p[1] != 'u') { + s = start; + ch = *s; - nxt_conf_json_parse_error(error, p - 6, - "Invalid JSON encoding sequence. This 6-byte sequence " - "does not represent a valid UTF character." - ); + if (ch == '-') { + s++; + } - return NULL; - } + dot_pos = NULL; - p += 2; + for (p = s; nxt_fast_path(p != end); p++) { + ch = *p; - utf_high = utf; - utf = 0; - } + /* Values below '0' become >= 208. */ + c = ch - '0'; - s = nxt_utf8_encode(s, utf); + if (c > 9) { + if (ch == '.' && nxt_fast_path(dot_pos == NULL)) { + dot_pos = p; + continue; + } - } while (p != last); + break; + } + } - if (size > NXT_CONF_MAX_SHORT_STRING) { - value->u.string.length = s - value->u.string.start; + if (dot_pos != NULL) { + if (nxt_slow_path(p - dot_pos <= 1)) { + nxt_conf_json_parse_error( + error, s, + "The number is invalid. A fraction part in JSON numbers " + "must contain at least one digit."); - } else { - value->u.str.length = s - value->u.str.start; + return NULL; } - return last + 1; -} + } else { + dot_pos = p; + } + + if (nxt_slow_path(dot_pos - s > 1 && *start == '0')) { + nxt_conf_json_parse_error( + error, s, + "The number is invalid. Leading zeros are not allowed in JSON " + "numbers."); + return NULL; + } -static u_char * -nxt_conf_json_parse_number(nxt_mp_t *mp, nxt_conf_value_t *value, u_char *start, - u_char *end, nxt_conf_json_error_t *error) -{ - u_char *p, *s, ch, c, *dot_pos; - size_t size; - double num; + if (ch == 'e' || ch == 'E') { + p++; + s = p; - s = start; - ch = *s; + if (nxt_fast_path(s != end)) { + ch = *s; - if (ch == '-') { + if (ch == '-' || ch == '+') { s++; - } + } - dot_pos = NULL; - - for (p = s; nxt_fast_path(p != end); p++) { + for (p = s; nxt_fast_path(p != end); p++) { ch = *p; /* Values below '0' become >= 208. */ c = ch - '0'; if (c > 9) { - if (ch == '.' && nxt_fast_path(dot_pos == NULL)) { - dot_pos = p; - continue; - } - - break; + break; } + } } - if (dot_pos != NULL) { - if (nxt_slow_path(p - dot_pos <= 1)) { - nxt_conf_json_parse_error(error, s, - "The number is invalid. A fraction part in JSON numbers " - "must contain at least one digit." - ); + if (nxt_slow_path(p == s)) { + nxt_conf_json_parse_error( + error, start, + "The number is invalid. An exponent part in JSON numbers " + "must contain at least one digit."); - return NULL; - } - - } else { - dot_pos = p; - } - - if (nxt_slow_path(dot_pos - s > 1 && *start == '0')) { - nxt_conf_json_parse_error(error, s, - "The number is invalid. Leading zeros are not allowed in JSON " - "numbers." - ); - - return NULL; + return NULL; } + } - if (ch == 'e' || ch == 'E') { - p++; - s = p; + size = p - start; - if (nxt_fast_path(s != end)) { - ch = *s; + if (size > NXT_CONF_MAX_NUMBER_LEN) { + nxt_conf_json_parse_error( + error, start, + "The number is too long. Such a long JSON number value " + "is not supported."); - if (ch == '-' || ch == '+') { - s++; - } - - for (p = s; nxt_fast_path(p != end); p++) { - ch = *p; - - /* Values below '0' become >= 208. */ - c = ch - '0'; - - if (c > 9) { - break; - } - } - } - - if (nxt_slow_path(p == s)) { - nxt_conf_json_parse_error(error, start, - "The number is invalid. An exponent part in JSON numbers " - "must contain at least one digit." - ); - - return NULL; - } - } - - size = p - start; - - if (size > NXT_CONF_MAX_NUMBER_LEN) { - nxt_conf_json_parse_error(error, start, - "The number is too long. Such a long JSON number value " - "is not supported." - ); - - return NULL; - } + return NULL; + } - nxt_memcpy(value->u.number, start, size); - value->u.number[size] = '\0'; + nxt_memcpy(value->u.number, start, size); + value->u.number[size] = '\0'; - nxt_errno = 0; - end = NULL; + nxt_errno = 0; + end = NULL; - num = nxt_strtod(value->u.number, &end); + num = nxt_strtod(value->u.number, &end); - if (nxt_slow_path(nxt_errno == NXT_ERANGE - || fabs(num) > (double) NXT_INT64_T_MAX)) - { - nxt_conf_json_parse_error(error, start, - "The number is out of representable range. Such JSON number " - "value is not supported." - ); + if (nxt_slow_path(nxt_errno == NXT_ERANGE || + fabs(num) > (double)NXT_INT64_T_MAX)) { + nxt_conf_json_parse_error( + error, start, + "The number is out of representable range. Such JSON number " + "value is not supported."); - return NULL; - } + return NULL; + } - if (nxt_slow_path(end == NULL || *end != '\0')) { - nxt_thread_log_alert("strtod(\"%s\", %s) failed %E", value->u.number, - end == NULL ? (u_char *) "NULL" : end, nxt_errno); - return NULL; - } + if (nxt_slow_path(end == NULL || *end != '\0')) { + nxt_thread_log_alert("strtod(\"%s\", %s) failed %E", value->u.number, + end == NULL ? (u_char *)"NULL" : end, nxt_errno); + return NULL; + } - value->type = (num == trunc(num)) ? NXT_CONF_VALUE_INTEGER - : NXT_CONF_VALUE_NUMBER; + value->type = + (num == trunc(num)) ? NXT_CONF_VALUE_INTEGER : NXT_CONF_VALUE_NUMBER; - return p; + return p; } +static void nxt_conf_json_parse_error(nxt_conf_json_error_t *error, u_char *pos, + const char *detail) { + if (error == NULL) { + return; + } -static void -nxt_conf_json_parse_error(nxt_conf_json_error_t *error, u_char *pos, - const char *detail) -{ - if (error == NULL) { - return; - } - - error->pos = pos; - error->detail = (u_char *) detail; + error->pos = pos; + error->detail = (u_char *)detail; } +size_t nxt_conf_json_length(const nxt_conf_value_t *value, + nxt_conf_json_pretty_t *pretty) { + switch (value->type) { -size_t -nxt_conf_json_length(const nxt_conf_value_t *value, - nxt_conf_json_pretty_t *pretty) -{ - switch (value->type) { + case NXT_CONF_VALUE_NULL: + return nxt_length("null"); - case NXT_CONF_VALUE_NULL: - return nxt_length("null"); + case NXT_CONF_VALUE_BOOLEAN: + return value->u.boolean ? nxt_length("true") : nxt_length("false"); - case NXT_CONF_VALUE_BOOLEAN: - return value->u.boolean ? nxt_length("true") : nxt_length("false"); + case NXT_CONF_VALUE_INTEGER: + case NXT_CONF_VALUE_NUMBER: + return nxt_strlen(value->u.number); - case NXT_CONF_VALUE_INTEGER: - case NXT_CONF_VALUE_NUMBER: - return nxt_strlen(value->u.number); + case NXT_CONF_VALUE_SHORT_STRING: + case NXT_CONF_VALUE_STRING: + return nxt_conf_json_string_length(value); - case NXT_CONF_VALUE_SHORT_STRING: - case NXT_CONF_VALUE_STRING: - return nxt_conf_json_string_length(value); + case NXT_CONF_VALUE_ARRAY: + return nxt_conf_json_array_length(value, pretty); - case NXT_CONF_VALUE_ARRAY: - return nxt_conf_json_array_length(value, pretty); - - case NXT_CONF_VALUE_OBJECT: - return nxt_conf_json_object_length(value, pretty); - } + case NXT_CONF_VALUE_OBJECT: + return nxt_conf_json_object_length(value, pretty); + } - nxt_unreachable(); + nxt_unreachable(); - return 0; + return 0; } +u_char *nxt_conf_json_print(u_char *p, const nxt_conf_value_t *value, + nxt_conf_json_pretty_t *pretty) { + switch (value->type) { -u_char * -nxt_conf_json_print(u_char *p, const nxt_conf_value_t *value, - nxt_conf_json_pretty_t *pretty) -{ - switch (value->type) { - - case NXT_CONF_VALUE_NULL: - return nxt_cpymem(p, "null", 4); + case NXT_CONF_VALUE_NULL: + return nxt_cpymem(p, "null", 4); - case NXT_CONF_VALUE_BOOLEAN: - return value->u.boolean ? nxt_cpymem(p, "true", 4) - : nxt_cpymem(p, "false", 5); + case NXT_CONF_VALUE_BOOLEAN: + return value->u.boolean ? nxt_cpymem(p, "true", 4) + : nxt_cpymem(p, "false", 5); - case NXT_CONF_VALUE_INTEGER: - case NXT_CONF_VALUE_NUMBER: - return nxt_cpystr(p, value->u.number); + case NXT_CONF_VALUE_INTEGER: + case NXT_CONF_VALUE_NUMBER: + return nxt_cpystr(p, value->u.number); - case NXT_CONF_VALUE_SHORT_STRING: - case NXT_CONF_VALUE_STRING: - return nxt_conf_json_print_string(p, value); + case NXT_CONF_VALUE_SHORT_STRING: + case NXT_CONF_VALUE_STRING: + return nxt_conf_json_print_string(p, value); - case NXT_CONF_VALUE_ARRAY: - return nxt_conf_json_print_array(p, value, pretty); + case NXT_CONF_VALUE_ARRAY: + return nxt_conf_json_print_array(p, value, pretty); - case NXT_CONF_VALUE_OBJECT: - return nxt_conf_json_print_object(p, value, pretty); - } + case NXT_CONF_VALUE_OBJECT: + return nxt_conf_json_print_object(p, value, pretty); + } - nxt_unreachable(); + nxt_unreachable(); - return p; + return p; } +static size_t nxt_conf_json_string_length(const nxt_conf_value_t *value) { + nxt_str_t str; -static size_t -nxt_conf_json_string_length(const nxt_conf_value_t *value) -{ - nxt_str_t str; + nxt_conf_get_string(value, &str); - nxt_conf_get_string(value, &str); - - return 2 + nxt_conf_json_escape_length(str.start, str.length); + return 2 + nxt_conf_json_escape_length(str.start, str.length); } +static u_char *nxt_conf_json_print_string(u_char *p, + const nxt_conf_value_t *value) { + nxt_str_t str; -static u_char * -nxt_conf_json_print_string(u_char *p, const nxt_conf_value_t *value) -{ - nxt_str_t str; - - nxt_conf_get_string(value, &str); + nxt_conf_get_string(value, &str); - *p++ = '"'; + *p++ = '"'; - p = nxt_conf_json_escape(p, str.start, str.length); + p = nxt_conf_json_escape(p, str.start, str.length); - *p++ = '"'; + *p++ = '"'; - return p; + return p; } +static size_t nxt_conf_json_array_length(const nxt_conf_value_t *value, + nxt_conf_json_pretty_t *pretty) { + size_t len; + nxt_uint_t n; + nxt_conf_array_t *array; -static size_t -nxt_conf_json_array_length(const nxt_conf_value_t *value, - nxt_conf_json_pretty_t *pretty) -{ - size_t len; - nxt_uint_t n; - nxt_conf_array_t *array; - - array = value->u.array; + array = value->u.array; - /* [] */ - len = 2; + /* [] */ + len = 2; - if (pretty != NULL) { - pretty->level++; - } + if (pretty != NULL) { + pretty->level++; + } - value = array->elements; + value = array->elements; - for (n = 0; n < array->count; n++) { - len += nxt_conf_json_length(&value[n], pretty); + for (n = 0; n < array->count; n++) { + len += nxt_conf_json_length(&value[n], pretty); - if (pretty != NULL) { - /* Indentation and new line. */ - len += pretty->level + 2; - } + if (pretty != NULL) { + /* Indentation and new line. */ + len += pretty->level + 2; } + } - if (pretty != NULL) { - pretty->level--; + if (pretty != NULL) { + pretty->level--; - if (n != 0) { - /* Indentation and new line. */ - len += pretty->level + 2; - } + if (n != 0) { + /* Indentation and new line. */ + len += pretty->level + 2; } + } - /* Reserve space for "n" commas. */ - return len + n; + /* Reserve space for "n" commas. */ + return len + n; } +static u_char *nxt_conf_json_print_array(u_char *p, + const nxt_conf_value_t *value, + nxt_conf_json_pretty_t *pretty) { + nxt_uint_t n; + nxt_conf_array_t *array; -static u_char * -nxt_conf_json_print_array(u_char *p, const nxt_conf_value_t *value, - nxt_conf_json_pretty_t *pretty) -{ - nxt_uint_t n; - nxt_conf_array_t *array; - - array = value->u.array; + array = value->u.array; - *p++ = '['; + *p++ = '['; - if (array->count != 0) { - value = array->elements; + if (array->count != 0) { + value = array->elements; - if (pretty != NULL) { - p = nxt_conf_json_newline(p); + if (pretty != NULL) { + p = nxt_conf_json_newline(p); - pretty->level++; - p = nxt_conf_json_indentation(p, pretty->level); - } + pretty->level++; + p = nxt_conf_json_indentation(p, pretty->level); + } - p = nxt_conf_json_print(p, &value[0], pretty); + p = nxt_conf_json_print(p, &value[0], pretty); - for (n = 1; n < array->count; n++) { - *p++ = ','; + for (n = 1; n < array->count; n++) { + *p++ = ','; - if (pretty != NULL) { - p = nxt_conf_json_newline(p); - p = nxt_conf_json_indentation(p, pretty->level); + if (pretty != NULL) { + p = nxt_conf_json_newline(p); + p = nxt_conf_json_indentation(p, pretty->level); - pretty->more_space = 0; - } + pretty->more_space = 0; + } - p = nxt_conf_json_print(p, &value[n], pretty); - } + p = nxt_conf_json_print(p, &value[n], pretty); + } - if (pretty != NULL) { - p = nxt_conf_json_newline(p); + if (pretty != NULL) { + p = nxt_conf_json_newline(p); - pretty->level--; - p = nxt_conf_json_indentation(p, pretty->level); + pretty->level--; + p = nxt_conf_json_indentation(p, pretty->level); - pretty->more_space = 1; - } + pretty->more_space = 1; } + } - *p++ = ']'; + *p++ = ']'; - return p; + return p; } +static size_t nxt_conf_json_object_length(const nxt_conf_value_t *value, + nxt_conf_json_pretty_t *pretty) { + size_t len; + nxt_uint_t n; + nxt_conf_object_t *object; + nxt_conf_object_member_t *member; -static size_t -nxt_conf_json_object_length(const nxt_conf_value_t *value, - nxt_conf_json_pretty_t *pretty) -{ - size_t len; - nxt_uint_t n; - nxt_conf_object_t *object; - nxt_conf_object_member_t *member; - - object = value->u.object; + object = value->u.object; - /* {} */ - len = 2; + /* {} */ + len = 2; - if (pretty != NULL) { - pretty->level++; - } + if (pretty != NULL) { + pretty->level++; + } - member = object->members; + member = object->members; - for (n = 0; n < object->count; n++) { - len += nxt_conf_json_string_length(&member[n].name) + 1 - + nxt_conf_json_length(&member[n].value, pretty) + 1; + for (n = 0; n < object->count; n++) { + len += nxt_conf_json_string_length(&member[n].name) + 1 + + nxt_conf_json_length(&member[n].value, pretty) + 1; - if (pretty != NULL) { - /* - * Indentation, space after ":", new line, and possible - * additional empty line between non-empty objects. - */ - len += pretty->level + 1 + 2 + 2; - } + if (pretty != NULL) { + /* + * Indentation, space after ":", new line, and possible + * additional empty line between non-empty objects. + */ + len += pretty->level + 1 + 2 + 2; } + } - if (pretty != NULL) { - pretty->level--; + if (pretty != NULL) { + pretty->level--; - /* Indentation and new line. */ - len += pretty->level + 2; - } + /* Indentation and new line. */ + len += pretty->level + 2; + } - return len; + return len; } +static u_char *nxt_conf_json_print_object(u_char *p, + const nxt_conf_value_t *value, + nxt_conf_json_pretty_t *pretty) { + nxt_uint_t n; + nxt_conf_object_t *object; + nxt_conf_object_member_t *member; -static u_char * -nxt_conf_json_print_object(u_char *p, const nxt_conf_value_t *value, - nxt_conf_json_pretty_t *pretty) -{ - nxt_uint_t n; - nxt_conf_object_t *object; - nxt_conf_object_member_t *member; - - object = value->u.object; + object = value->u.object; - *p++ = '{'; + *p++ = '{'; - if (object->count != 0) { + if (object->count != 0) { - if (pretty != NULL) { - p = nxt_conf_json_newline(p); - pretty->level++; - } + if (pretty != NULL) { + p = nxt_conf_json_newline(p); + pretty->level++; + } - member = object->members; + member = object->members; - n = 0; + n = 0; - for ( ;; ) { - if (pretty != NULL) { - p = nxt_conf_json_indentation(p, pretty->level); - } + for (;;) { + if (pretty != NULL) { + p = nxt_conf_json_indentation(p, pretty->level); + } - p = nxt_conf_json_print_string(p, &member[n].name); + p = nxt_conf_json_print_string(p, &member[n].name); - *p++ = ':'; + *p++ = ':'; - if (pretty != NULL) { - *p++ = ' '; - } + if (pretty != NULL) { + *p++ = ' '; + } - p = nxt_conf_json_print(p, &member[n].value, pretty); + p = nxt_conf_json_print(p, &member[n].value, pretty); - n++; + n++; - if (n == object->count) { - break; - } + if (n == object->count) { + break; + } - *p++ = ','; + *p++ = ','; - if (pretty != NULL) { - p = nxt_conf_json_newline(p); + if (pretty != NULL) { + p = nxt_conf_json_newline(p); - if (pretty->more_space) { - pretty->more_space = 0; - p = nxt_conf_json_newline(p); - } - } + if (pretty->more_space) { + pretty->more_space = 0; + p = nxt_conf_json_newline(p); } + } + } - if (pretty != NULL) { - p = nxt_conf_json_newline(p); + if (pretty != NULL) { + p = nxt_conf_json_newline(p); - pretty->level--; - p = nxt_conf_json_indentation(p, pretty->level); + pretty->level--; + p = nxt_conf_json_indentation(p, pretty->level); - pretty->more_space = 1; - } + pretty->more_space = 1; } + } - *p++ = '}'; + *p++ = '}'; - return p; + return p; } +static size_t nxt_conf_json_escape_length(u_char *p, size_t size) { + u_char ch; + size_t len; -static size_t -nxt_conf_json_escape_length(u_char *p, size_t size) -{ - u_char ch; - size_t len; - - len = size; + len = size; - while (size) { - ch = *p++; + while (size) { + ch = *p++; - if (ch == '\\' || ch == '"') { - len++; + if (ch == '\\' || ch == '"') { + len++; - } else if (ch <= 0x1F) { + } else if (ch <= 0x1F) { - switch (ch) { - case '\n': - case '\r': - case '\t': - case '\b': - case '\f': - len++; - break; - - default: - len += sizeof("\\u001F") - 2; - } - } + switch (ch) { + case '\n': + case '\r': + case '\t': + case '\b': + case '\f': + len++; + break; - size--; + default: + len += sizeof("\\u001F") - 2; + } } - return len; -} + size--; + } + return len; +} -static u_char * -nxt_conf_json_escape(u_char *dst, u_char *src, size_t size) -{ - u_char ch; +static u_char *nxt_conf_json_escape(u_char *dst, u_char *src, size_t size) { + u_char ch; - while (size) { - ch = *src++; + while (size) { + ch = *src++; - if (ch > 0x1F) { + if (ch > 0x1F) { - if (ch == '\\' || ch == '"') { - *dst++ = '\\'; - } + if (ch == '\\' || ch == '"') { + *dst++ = '\\'; + } - *dst++ = ch; + *dst++ = ch; - } else { - *dst++ = '\\'; + } else { + *dst++ = '\\'; - switch (ch) { - case '\n': - *dst++ = 'n'; - break; + switch (ch) { + case '\n': + *dst++ = 'n'; + break; - case '\r': - *dst++ = 'r'; - break; + case '\r': + *dst++ = 'r'; + break; - case '\t': - *dst++ = 't'; - break; + case '\t': + *dst++ = 't'; + break; - case '\b': - *dst++ = 'b'; - break; + case '\b': + *dst++ = 'b'; + break; - case '\f': - *dst++ = 'f'; - break; + case '\f': + *dst++ = 'f'; + break; - default: - *dst++ = 'u'; *dst++ = '0'; *dst++ = '0'; - *dst++ = '0' + (ch >> 4); + default: + *dst++ = 'u'; + *dst++ = '0'; + *dst++ = '0'; + *dst++ = '0' + (ch >> 4); - ch &= 0xF; + ch &= 0xF; - *dst++ = (ch < 10) ? ('0' + ch) : ('A' + ch - 10); - } - } - - size--; + *dst++ = (ch < 10) ? ('0' + ch) : ('A' + ch - 10); + } } - return dst; -} + size--; + } + return dst; +} -void -nxt_conf_json_position(u_char *start, const u_char *pos, nxt_uint_t *line, - nxt_uint_t *column) -{ - u_char *p; - ssize_t symbols; - nxt_uint_t lines; +void nxt_conf_json_position(u_char *start, const u_char *pos, nxt_uint_t *line, + nxt_uint_t *column) { + u_char *p; + ssize_t symbols; + nxt_uint_t lines; - lines = 1; + lines = 1; - for (p = start; p != pos; p++) { + for (p = start; p != pos; p++) { - if (*p != '\n') { - continue; - } - - lines++; - start = p + 1; + if (*p != '\n') { + continue; } - symbols = nxt_utf8_length(start, p - start); + lines++; + start = p + 1; + } - if (symbols != -1) { - *line = lines; - *column = 1 + symbols; - } + symbols = nxt_utf8_length(start, p - start); + + if (symbols != -1) { + *line = lines; + *column = 1 + symbols; + } } diff --git a/src/nxt_conf.h b/src/nxt_conf.h index 493d64801..414f11964 100644 --- a/src/nxt_conf.h +++ b/src/nxt_conf.h @@ -9,154 +9,154 @@ #ifndef _NXT_CONF_INCLUDED_ #define _NXT_CONF_INCLUDED_ - typedef enum { - NXT_CONF_NULL = 0, - NXT_CONF_BOOLEAN, - NXT_CONF_INTEGER, - NXT_CONF_NUMBER, - NXT_CONF_STRING, - NXT_CONF_ARRAY, - NXT_CONF_OBJECT, + NXT_CONF_NULL = 0, + NXT_CONF_BOOLEAN, + NXT_CONF_INTEGER, + NXT_CONF_NUMBER, + NXT_CONF_STRING, + NXT_CONF_ARRAY, + NXT_CONF_OBJECT, } nxt_conf_type_t; - typedef enum { - NXT_CONF_OP_OK = 0, - NXT_CONF_OP_NOT_FOUND, - NXT_CONF_OP_NOT_ALLOWED, - NXT_CONF_OP_ERROR, + NXT_CONF_OP_OK = 0, + NXT_CONF_OP_NOT_FOUND, + NXT_CONF_OP_NOT_ALLOWED, + NXT_CONF_OP_ERROR, } nxt_conf_op_ret_t; - -typedef struct nxt_conf_value_s nxt_conf_value_t; -typedef struct nxt_conf_op_s nxt_conf_op_t; - +typedef struct nxt_conf_value_s nxt_conf_value_t; +typedef struct nxt_conf_op_s nxt_conf_op_t; typedef struct { - u_char *pos; - u_char *detail; + u_char *pos; + u_char *detail; } nxt_conf_json_error_t; - typedef enum { - NXT_CONF_MAP_INT8, - NXT_CONF_MAP_INT32, - NXT_CONF_MAP_INT64, - NXT_CONF_MAP_INT, - NXT_CONF_MAP_SIZE, - NXT_CONF_MAP_OFF, - NXT_CONF_MAP_MSEC, - NXT_CONF_MAP_DOUBLE, - NXT_CONF_MAP_STR, - NXT_CONF_MAP_STR_COPY, - NXT_CONF_MAP_CSTRZ, - NXT_CONF_MAP_PTR, + NXT_CONF_MAP_INT8, + NXT_CONF_MAP_INT32, + NXT_CONF_MAP_INT64, + NXT_CONF_MAP_INT, + NXT_CONF_MAP_SIZE, + NXT_CONF_MAP_OFF, + NXT_CONF_MAP_MSEC, + NXT_CONF_MAP_DOUBLE, + NXT_CONF_MAP_STR, + NXT_CONF_MAP_STR_COPY, + NXT_CONF_MAP_CSTRZ, + NXT_CONF_MAP_PTR, } nxt_conf_map_type_t; - typedef struct { - nxt_str_t name; - nxt_conf_map_type_t type; - size_t offset; + nxt_str_t name; + nxt_conf_map_type_t type; + size_t offset; } nxt_conf_map_t; - typedef struct { - uint32_t level; - uint8_t more_space; /* 1 bit. */ + uint32_t level; + uint8_t more_space; /* 1 bit. */ } nxt_conf_json_pretty_t; - typedef struct { - nxt_conf_value_t *conf; - nxt_mp_t *pool; - nxt_str_t error; - void *ctx; - nxt_tstr_state_t *tstr_state; - nxt_mp_t *conf_pool; - nxt_uint_t ver; + nxt_conf_value_t *conf; + nxt_mp_t *pool; + nxt_str_t error; + void *ctx; + nxt_tstr_state_t *tstr_state; + nxt_mp_t *conf_pool; + nxt_uint_t ver; } nxt_conf_validation_t; - NXT_EXPORT nxt_uint_t nxt_conf_type(const nxt_conf_value_t *value); NXT_EXPORT nxt_conf_value_t *nxt_conf_get_path(nxt_conf_value_t *value, - const nxt_str_t *path); -NXT_EXPORT nxt_conf_value_t *nxt_conf_get_object_member( - const nxt_conf_value_t *value, const nxt_str_t *name, uint32_t *index); -NXT_EXPORT nxt_conf_value_t *nxt_conf_next_object_member( - const nxt_conf_value_t *value, nxt_str_t *name, uint32_t *next); -NXT_EXPORT nxt_conf_value_t *nxt_conf_get_array_element( - const nxt_conf_value_t *value, uint32_t index); -NXT_EXPORT nxt_conf_value_t *nxt_conf_get_array_element_or_itself( - nxt_conf_value_t *value, uint32_t index); + const nxt_str_t *path); +NXT_EXPORT nxt_conf_value_t * +nxt_conf_get_object_member(const nxt_conf_value_t *value, const nxt_str_t *name, + uint32_t *index); +NXT_EXPORT nxt_conf_value_t * +nxt_conf_next_object_member(const nxt_conf_value_t *value, nxt_str_t *name, + uint32_t *next); +NXT_EXPORT nxt_conf_value_t * +nxt_conf_get_array_element(const nxt_conf_value_t *value, uint32_t index); +NXT_EXPORT nxt_conf_value_t * +nxt_conf_get_array_element_or_itself(nxt_conf_value_t *value, uint32_t index); NXT_EXPORT nxt_int_t nxt_conf_map_object(nxt_mp_t *mp, - const nxt_conf_value_t *value, const nxt_conf_map_t *map, nxt_uint_t n, - void *data); + const nxt_conf_value_t *value, + const nxt_conf_map_t *map, + nxt_uint_t n, void *data); nxt_conf_op_ret_t nxt_conf_op_compile(nxt_mp_t *mp, nxt_conf_op_t **ops, - const nxt_conf_value_t *root, const nxt_str_t *path, nxt_conf_value_t *value, - nxt_bool_t add); + const nxt_conf_value_t *root, + const nxt_str_t *path, + nxt_conf_value_t *value, nxt_bool_t add); nxt_conf_value_t *nxt_conf_clone(nxt_mp_t *mp, nxt_conf_op_t *op, - const nxt_conf_value_t *value); + const nxt_conf_value_t *value); nxt_conf_value_t *nxt_conf_json_parse(nxt_mp_t *mp, u_char *start, u_char *end, - nxt_conf_json_error_t *error); + nxt_conf_json_error_t *error); -#define nxt_conf_json_parse_str(mp, str) \ - nxt_conf_json_parse(mp, (str)->start, (str)->start + (str)->length, NULL) +#define nxt_conf_json_parse_str(mp, str) \ + nxt_conf_json_parse(mp, (str)->start, (str)->start + (str)->length, NULL) size_t nxt_conf_json_length(const nxt_conf_value_t *value, - nxt_conf_json_pretty_t *pretty); + nxt_conf_json_pretty_t *pretty); u_char *nxt_conf_json_print(u_char *p, const nxt_conf_value_t *value, - nxt_conf_json_pretty_t *pretty); + nxt_conf_json_pretty_t *pretty); void nxt_conf_json_position(u_char *start, const u_char *pos, nxt_uint_t *line, - nxt_uint_t *column); + nxt_uint_t *column); nxt_int_t nxt_conf_validate(nxt_conf_validation_t *vldt); NXT_EXPORT void nxt_conf_get_string(const nxt_conf_value_t *value, - nxt_str_t *str); + nxt_str_t *str); NXT_EXPORT nxt_str_t *nxt_conf_get_string_dup(const nxt_conf_value_t *value, - nxt_mp_t *mp, nxt_str_t *str); + nxt_mp_t *mp, nxt_str_t *str); NXT_EXPORT void nxt_conf_set_string(nxt_conf_value_t *value, - const nxt_str_t *str); + const nxt_str_t *str); NXT_EXPORT nxt_int_t nxt_conf_set_string_dup(nxt_conf_value_t *value, - nxt_mp_t *mp, const nxt_str_t *str); + nxt_mp_t *mp, + const nxt_str_t *str); NXT_EXPORT double nxt_conf_get_number(nxt_conf_value_t *value); NXT_EXPORT uint8_t nxt_conf_get_boolean(nxt_conf_value_t *value); // FIXME reimplement and reorder functions below -NXT_EXPORT nxt_uint_t nxt_conf_object_members_count( - const nxt_conf_value_t *value); +NXT_EXPORT nxt_uint_t +nxt_conf_object_members_count(const nxt_conf_value_t *value); nxt_conf_value_t *nxt_conf_create_object(nxt_mp_t *mp, nxt_uint_t count); void nxt_conf_set_member(nxt_conf_value_t *object, const nxt_str_t *name, - const nxt_conf_value_t *value, uint32_t index); + const nxt_conf_value_t *value, uint32_t index); nxt_int_t nxt_conf_set_member_dup(nxt_conf_value_t *object, nxt_mp_t *mp, - const nxt_str_t *name, const nxt_conf_value_t *value, uint32_t index); -void nxt_conf_set_member_string(nxt_conf_value_t *object, - const nxt_str_t *name, const nxt_str_t *value, uint32_t index); -nxt_int_t nxt_conf_set_member_string_dup(nxt_conf_value_t *object, - nxt_mp_t *mp, const nxt_str_t *name, const nxt_str_t *value, - uint32_t index); + const nxt_str_t *name, + const nxt_conf_value_t *value, + uint32_t index); +void nxt_conf_set_member_string(nxt_conf_value_t *object, const nxt_str_t *name, + const nxt_str_t *value, uint32_t index); +nxt_int_t nxt_conf_set_member_string_dup(nxt_conf_value_t *object, nxt_mp_t *mp, + const nxt_str_t *name, + const nxt_str_t *value, + uint32_t index); void nxt_conf_set_member_integer(nxt_conf_value_t *object, - const nxt_str_t *name, int64_t value, uint32_t index); + const nxt_str_t *name, int64_t value, + uint32_t index); void nxt_conf_set_member_null(nxt_conf_value_t *object, const nxt_str_t *name, - uint32_t index); + uint32_t index); nxt_conf_value_t *nxt_conf_create_array(nxt_mp_t *mp, nxt_uint_t count); void nxt_conf_set_element(nxt_conf_value_t *array, nxt_uint_t index, - const nxt_conf_value_t *value); -nxt_int_t nxt_conf_set_element_string_dup(nxt_conf_value_t *array, - nxt_mp_t *mp, nxt_uint_t index, const nxt_str_t *value); -NXT_EXPORT nxt_uint_t nxt_conf_array_elements_count( - const nxt_conf_value_t *value); -NXT_EXPORT nxt_uint_t nxt_conf_array_elements_count_or_1( - const nxt_conf_value_t *value); + const nxt_conf_value_t *value); +nxt_int_t nxt_conf_set_element_string_dup(nxt_conf_value_t *array, nxt_mp_t *mp, + nxt_uint_t index, + const nxt_str_t *value); +NXT_EXPORT nxt_uint_t +nxt_conf_array_elements_count(const nxt_conf_value_t *value); +NXT_EXPORT nxt_uint_t +nxt_conf_array_elements_count_or_1(const nxt_conf_value_t *value); void nxt_conf_array_qsort(const nxt_conf_value_t *value, - int (*compare)(const void *, const void *)); - + int (*compare)(const void *, const void *)); #endif /* _NXT_CONF_INCLUDED_ */ diff --git a/src/nxt_conf_validation.c b/src/nxt_conf_validation.c index 5d7f7c52b..f2eaa15ce 100644 --- a/src/nxt_conf_validation.c +++ b/src/nxt_conf_validation.c @@ -15,31 +15,25 @@ #include #include - typedef enum { - NXT_CONF_VLDT_NULL = 1 << NXT_CONF_NULL, - NXT_CONF_VLDT_BOOLEAN = 1 << NXT_CONF_BOOLEAN, - NXT_CONF_VLDT_INTEGER = 1 << NXT_CONF_INTEGER, - NXT_CONF_VLDT_NUMBER = (1 << NXT_CONF_NUMBER) | NXT_CONF_VLDT_INTEGER, - NXT_CONF_VLDT_STRING = 1 << NXT_CONF_STRING, - NXT_CONF_VLDT_ARRAY = 1 << NXT_CONF_ARRAY, - NXT_CONF_VLDT_OBJECT = 1 << NXT_CONF_OBJECT, + NXT_CONF_VLDT_NULL = 1 << NXT_CONF_NULL, + NXT_CONF_VLDT_BOOLEAN = 1 << NXT_CONF_BOOLEAN, + NXT_CONF_VLDT_INTEGER = 1 << NXT_CONF_INTEGER, + NXT_CONF_VLDT_NUMBER = (1 << NXT_CONF_NUMBER) | NXT_CONF_VLDT_INTEGER, + NXT_CONF_VLDT_STRING = 1 << NXT_CONF_STRING, + NXT_CONF_VLDT_ARRAY = 1 << NXT_CONF_ARRAY, + NXT_CONF_VLDT_OBJECT = 1 << NXT_CONF_OBJECT, } nxt_conf_vldt_type_t; -#define NXT_CONF_VLDT_ANY_TYPE (NXT_CONF_VLDT_NULL \ - |NXT_CONF_VLDT_BOOLEAN \ - |NXT_CONF_VLDT_NUMBER \ - |NXT_CONF_VLDT_STRING \ - |NXT_CONF_VLDT_ARRAY \ - |NXT_CONF_VLDT_OBJECT) - +#define NXT_CONF_VLDT_ANY_TYPE \ + (NXT_CONF_VLDT_NULL | NXT_CONF_VLDT_BOOLEAN | NXT_CONF_VLDT_NUMBER | \ + NXT_CONF_VLDT_STRING | NXT_CONF_VLDT_ARRAY | NXT_CONF_VLDT_OBJECT) typedef enum { - NXT_CONF_VLDT_REQUIRED = 1 << 0, - NXT_CONF_VLDT_TSTR = 1 << 1, + NXT_CONF_VLDT_REQUIRED = 1 << 0, + NXT_CONF_VLDT_TSTR = 1 << 1, } nxt_conf_vldt_flags_t; - typedef nxt_int_t (*nxt_conf_vldt_handler_t)(nxt_conf_validation_t *vldt, nxt_conf_value_t *value, void *data); @@ -49,2864 +43,2789 @@ typedef nxt_int_t (*nxt_conf_vldt_member_t)(nxt_conf_validation_t *vldt, typedef nxt_int_t (*nxt_conf_vldt_element_t)(nxt_conf_validation_t *vldt, nxt_conf_value_t *value); - -typedef struct nxt_conf_vldt_object_s nxt_conf_vldt_object_t; +typedef struct nxt_conf_vldt_object_s nxt_conf_vldt_object_t; struct nxt_conf_vldt_object_s { - nxt_str_t name; - nxt_conf_vldt_type_t type:32; - nxt_conf_vldt_flags_t flags:32; - nxt_conf_vldt_handler_t validator; - - union { - nxt_conf_vldt_object_t *members; - nxt_conf_vldt_object_t *next; - nxt_conf_vldt_member_t object; - nxt_conf_vldt_element_t array; - const char *string; - } u; + nxt_str_t name; + nxt_conf_vldt_type_t type : 32; + nxt_conf_vldt_flags_t flags : 32; + nxt_conf_vldt_handler_t validator; + + union { + nxt_conf_vldt_object_t *members; + nxt_conf_vldt_object_t *next; + nxt_conf_vldt_member_t object; + nxt_conf_vldt_element_t array; + const char *string; + } u; }; - -#define NXT_CONF_VLDT_NEXT(next) { .u.members = next } -#define NXT_CONF_VLDT_END { .name = nxt_null_string } - +#define NXT_CONF_VLDT_NEXT(next) {.u.members = next} +#define NXT_CONF_VLDT_END {.name = nxt_null_string} static nxt_int_t nxt_conf_vldt_type(nxt_conf_validation_t *vldt, - const nxt_str_t *name, nxt_conf_value_t *value, nxt_conf_vldt_type_t type); + const nxt_str_t *name, + nxt_conf_value_t *value, + nxt_conf_vldt_type_t type); static nxt_int_t nxt_conf_vldt_error(nxt_conf_validation_t *vldt, - const char *fmt, ...); + const char *fmt, ...); static nxt_int_t nxt_conf_vldt_var(nxt_conf_validation_t *vldt, - const nxt_str_t *name, nxt_str_t *value); + const nxt_str_t *name, nxt_str_t *value); static nxt_int_t nxt_conf_vldt_if(nxt_conf_validation_t *vldt, - nxt_conf_value_t *value, void *data); + nxt_conf_value_t *value, void *data); nxt_inline nxt_int_t nxt_conf_vldt_unsupported(nxt_conf_validation_t *vldt, - nxt_conf_value_t *value, void *data) - NXT_MAYBE_UNUSED; + nxt_conf_value_t *value, + void *data) NXT_MAYBE_UNUSED; static nxt_int_t nxt_conf_vldt_mtypes(nxt_conf_validation_t *vldt, - nxt_conf_value_t *value, void *data); + nxt_conf_value_t *value, void *data); static nxt_int_t nxt_conf_vldt_mtypes_type(nxt_conf_validation_t *vldt, - nxt_str_t *name, nxt_conf_value_t *value); + nxt_str_t *name, + nxt_conf_value_t *value); static nxt_int_t nxt_conf_vldt_mtypes_extension(nxt_conf_validation_t *vldt, - nxt_conf_value_t *value); + nxt_conf_value_t *value); static nxt_int_t nxt_conf_vldt_listener(nxt_conf_validation_t *vldt, - nxt_str_t *name, nxt_conf_value_t *value); + nxt_str_t *name, + nxt_conf_value_t *value); #if (NXT_TLS) static nxt_int_t nxt_conf_vldt_certificate(nxt_conf_validation_t *vldt, - nxt_conf_value_t *value, void *data); + nxt_conf_value_t *value, void *data); #if (NXT_HAVE_OPENSSL_CONF_CMD) static nxt_int_t nxt_conf_vldt_object_conf_commands(nxt_conf_validation_t *vldt, - nxt_conf_value_t *value, void *data); + nxt_conf_value_t *value, + void *data); #endif static nxt_int_t nxt_conf_vldt_certificate_element(nxt_conf_validation_t *vldt, - nxt_conf_value_t *value); + nxt_conf_value_t *value); static nxt_int_t nxt_conf_vldt_tls_cache_size(nxt_conf_validation_t *vldt, - nxt_conf_value_t *value, void *data); + nxt_conf_value_t *value, + void *data); static nxt_int_t nxt_conf_vldt_tls_timeout(nxt_conf_validation_t *vldt, - nxt_conf_value_t *value, void *data); + nxt_conf_value_t *value, void *data); #if (NXT_HAVE_OPENSSL_TLSEXT) static nxt_int_t nxt_conf_vldt_ticket_key(nxt_conf_validation_t *vldt, - nxt_conf_value_t *value, void *data); + nxt_conf_value_t *value, void *data); static nxt_int_t nxt_conf_vldt_ticket_key_element(nxt_conf_validation_t *vldt, - nxt_conf_value_t *value); + nxt_conf_value_t *value); #endif #endif static nxt_int_t nxt_conf_vldt_action(nxt_conf_validation_t *vldt, - nxt_conf_value_t *value, void *data); + nxt_conf_value_t *value, void *data); static nxt_int_t nxt_conf_vldt_pass(nxt_conf_validation_t *vldt, - nxt_conf_value_t *value, void *data); + nxt_conf_value_t *value, void *data); static nxt_int_t nxt_conf_vldt_return(nxt_conf_validation_t *vldt, - nxt_conf_value_t *value, void *data); + nxt_conf_value_t *value, void *data); static nxt_int_t nxt_conf_vldt_share(nxt_conf_validation_t *vldt, - nxt_conf_value_t *value, void *data); + nxt_conf_value_t *value, void *data); static nxt_int_t nxt_conf_vldt_share_element(nxt_conf_validation_t *vldt, - nxt_conf_value_t *value); + nxt_conf_value_t *value); static nxt_int_t nxt_conf_vldt_proxy(nxt_conf_validation_t *vldt, - nxt_conf_value_t *value, void *data); + nxt_conf_value_t *value, void *data); static nxt_int_t nxt_conf_vldt_python(nxt_conf_validation_t *vldt, - nxt_conf_value_t *value, void *data); + nxt_conf_value_t *value, void *data); static nxt_int_t nxt_conf_vldt_python_path(nxt_conf_validation_t *vldt, - nxt_conf_value_t *value, void *data); + nxt_conf_value_t *value, void *data); static nxt_int_t nxt_conf_vldt_python_path_element(nxt_conf_validation_t *vldt, - nxt_conf_value_t *value); + nxt_conf_value_t *value); static nxt_int_t nxt_conf_vldt_python_protocol(nxt_conf_validation_t *vldt, - nxt_conf_value_t *value, void *data); + nxt_conf_value_t *value, + void *data); static nxt_int_t nxt_conf_vldt_python_prefix(nxt_conf_validation_t *vldt, - nxt_conf_value_t *value, void *data); + nxt_conf_value_t *value, + void *data); static nxt_int_t nxt_conf_vldt_listen_threads(nxt_conf_validation_t *vldt, - nxt_conf_value_t *value, void *data); + nxt_conf_value_t *value, + void *data); static nxt_int_t nxt_conf_vldt_threads(nxt_conf_validation_t *vldt, - nxt_conf_value_t *value, void *data); + nxt_conf_value_t *value, void *data); static nxt_int_t nxt_conf_vldt_thread_stack_size(nxt_conf_validation_t *vldt, - nxt_conf_value_t *value, void *data); + nxt_conf_value_t *value, + void *data); static nxt_int_t nxt_conf_vldt_routes(nxt_conf_validation_t *vldt, - nxt_conf_value_t *value, void *data); + nxt_conf_value_t *value, void *data); static nxt_int_t nxt_conf_vldt_routes_member(nxt_conf_validation_t *vldt, - nxt_str_t *name, nxt_conf_value_t *value); + nxt_str_t *name, + nxt_conf_value_t *value); static nxt_int_t nxt_conf_vldt_route(nxt_conf_validation_t *vldt, - nxt_conf_value_t *value); -static nxt_int_t nxt_conf_vldt_match_encoded_patterns_sets( - nxt_conf_validation_t *vldt, nxt_conf_value_t *value, void *data); -static nxt_int_t nxt_conf_vldt_match_encoded_patterns_set( - nxt_conf_validation_t *vldt, nxt_conf_value_t *value); + nxt_conf_value_t *value); +static nxt_int_t +nxt_conf_vldt_match_encoded_patterns_sets(nxt_conf_validation_t *vldt, + nxt_conf_value_t *value, void *data); +static nxt_int_t +nxt_conf_vldt_match_encoded_patterns_set(nxt_conf_validation_t *vldt, + nxt_conf_value_t *value); static nxt_int_t nxt_conf_vldt_match_encoded_patterns_set_member( nxt_conf_validation_t *vldt, nxt_str_t *name, nxt_conf_value_t *value); -static nxt_int_t nxt_conf_vldt_match_encoded_patterns( - nxt_conf_validation_t *vldt, nxt_conf_value_t *value, void *data); -static nxt_int_t nxt_conf_vldt_match_encoded_pattern( - nxt_conf_validation_t *vldt, nxt_conf_value_t *value); +static nxt_int_t +nxt_conf_vldt_match_encoded_patterns(nxt_conf_validation_t *vldt, + nxt_conf_value_t *value, void *data); +static nxt_int_t +nxt_conf_vldt_match_encoded_pattern(nxt_conf_validation_t *vldt, + nxt_conf_value_t *value); static nxt_int_t nxt_conf_vldt_match_patterns(nxt_conf_validation_t *vldt, - nxt_conf_value_t *value, void *data); + nxt_conf_value_t *value, + void *data); static nxt_int_t nxt_conf_vldt_match_pattern(nxt_conf_validation_t *vldt, - nxt_conf_value_t *value); + nxt_conf_value_t *value); static nxt_int_t nxt_conf_vldt_match_patterns_sets(nxt_conf_validation_t *vldt, - nxt_conf_value_t *value, void *data); + nxt_conf_value_t *value, + void *data); static nxt_int_t nxt_conf_vldt_match_patterns_set(nxt_conf_validation_t *vldt, - nxt_conf_value_t *value); + nxt_conf_value_t *value); static nxt_int_t nxt_conf_vldt_match_patterns_set_member( nxt_conf_validation_t *vldt, nxt_str_t *name, nxt_conf_value_t *value); static nxt_int_t nxt_conf_vldt_match_scheme_pattern(nxt_conf_validation_t *vldt, - nxt_conf_value_t *value, void *data); + nxt_conf_value_t *value, + void *data); static nxt_int_t nxt_conf_vldt_match_addrs(nxt_conf_validation_t *vldt, - nxt_conf_value_t *value, void *data); + nxt_conf_value_t *value, void *data); static nxt_int_t nxt_conf_vldt_match_addr(nxt_conf_validation_t *vldt, - nxt_conf_value_t *value); + nxt_conf_value_t *value); static nxt_int_t nxt_conf_vldt_response_header(nxt_conf_validation_t *vldt, - nxt_str_t *name, nxt_conf_value_t *value); + nxt_str_t *name, + nxt_conf_value_t *value); static nxt_int_t nxt_conf_vldt_app_name(nxt_conf_validation_t *vldt, - nxt_conf_value_t *value, void *data); + nxt_conf_value_t *value, void *data); static nxt_int_t nxt_conf_vldt_forwarded(nxt_conf_validation_t *vldt, - nxt_conf_value_t *value, void *data); + nxt_conf_value_t *value, void *data); static nxt_int_t nxt_conf_vldt_listen_backlog(nxt_conf_validation_t *vldt, - nxt_conf_value_t *value, void *data); -static nxt_int_t nxt_conf_vldt_app(nxt_conf_validation_t *vldt, - nxt_str_t *name, nxt_conf_value_t *value); + nxt_conf_value_t *value, + void *data); +static nxt_int_t nxt_conf_vldt_app(nxt_conf_validation_t *vldt, nxt_str_t *name, + nxt_conf_value_t *value); static nxt_int_t nxt_conf_vldt_object(nxt_conf_validation_t *vldt, - nxt_conf_value_t *value, void *data); + nxt_conf_value_t *value, void *data); static nxt_int_t nxt_conf_vldt_processes(nxt_conf_validation_t *vldt, - nxt_conf_value_t *value, void *data); + nxt_conf_value_t *value, void *data); static nxt_int_t nxt_conf_vldt_object_iterator(nxt_conf_validation_t *vldt, - nxt_conf_value_t *value, void *data); + nxt_conf_value_t *value, + void *data); static nxt_int_t nxt_conf_vldt_array_iterator(nxt_conf_validation_t *vldt, - nxt_conf_value_t *value, void *data); + nxt_conf_value_t *value, + void *data); static nxt_int_t nxt_conf_vldt_environment(nxt_conf_validation_t *vldt, - nxt_str_t *name, nxt_conf_value_t *value); -static nxt_int_t nxt_conf_vldt_targets_exclusive( - nxt_conf_validation_t *vldt, nxt_conf_value_t *value, void *data); + nxt_str_t *name, + nxt_conf_value_t *value); +static nxt_int_t nxt_conf_vldt_targets_exclusive(nxt_conf_validation_t *vldt, + nxt_conf_value_t *value, + void *data); static nxt_int_t nxt_conf_vldt_targets(nxt_conf_validation_t *vldt, - nxt_conf_value_t *value, void *data); + nxt_conf_value_t *value, void *data); static nxt_int_t nxt_conf_vldt_target(nxt_conf_validation_t *vldt, - nxt_str_t *name, nxt_conf_value_t *value); + nxt_str_t *name, nxt_conf_value_t *value); static nxt_int_t nxt_conf_vldt_argument(nxt_conf_validation_t *vldt, - nxt_conf_value_t *value); + nxt_conf_value_t *value); static nxt_int_t nxt_conf_vldt_php(nxt_conf_validation_t *vldt, - nxt_conf_value_t *value, void *data); + nxt_conf_value_t *value, void *data); static nxt_int_t nxt_conf_vldt_php_option(nxt_conf_validation_t *vldt, - nxt_str_t *name, nxt_conf_value_t *value); + nxt_str_t *name, + nxt_conf_value_t *value); static nxt_int_t nxt_conf_vldt_java_classpath(nxt_conf_validation_t *vldt, - nxt_conf_value_t *value); + nxt_conf_value_t *value); static nxt_int_t nxt_conf_vldt_java_option(nxt_conf_validation_t *vldt, - nxt_conf_value_t *value); + nxt_conf_value_t *value); static nxt_int_t nxt_conf_vldt_upstream(nxt_conf_validation_t *vldt, - nxt_str_t *name, nxt_conf_value_t *value); + nxt_str_t *name, + nxt_conf_value_t *value); static nxt_int_t nxt_conf_vldt_server(nxt_conf_validation_t *vldt, - nxt_str_t *name, nxt_conf_value_t *value); + nxt_str_t *name, nxt_conf_value_t *value); static nxt_int_t nxt_conf_vldt_server_weight(nxt_conf_validation_t *vldt, - nxt_conf_value_t *value, void *data); + nxt_conf_value_t *value, + void *data); static nxt_int_t nxt_conf_vldt_access_log(nxt_conf_validation_t *vldt, - nxt_conf_value_t *value, void *data); + nxt_conf_value_t *value, void *data); static nxt_int_t nxt_conf_vldt_isolation(nxt_conf_validation_t *vldt, - nxt_conf_value_t *value, void *data); + nxt_conf_value_t *value, void *data); static nxt_int_t nxt_conf_vldt_clone_namespaces(nxt_conf_validation_t *vldt, - nxt_conf_value_t *value, void *data); + nxt_conf_value_t *value, + void *data); #if (NXT_HAVE_CLONE_NEWUSER) static nxt_int_t nxt_conf_vldt_clone_uidmap(nxt_conf_validation_t *vldt, - nxt_conf_value_t *value); + nxt_conf_value_t *value); static nxt_int_t nxt_conf_vldt_clone_gidmap(nxt_conf_validation_t *vldt, - nxt_conf_value_t *value); + nxt_conf_value_t *value); #endif #if (NXT_HAVE_CGROUP) static nxt_int_t nxt_conf_vldt_cgroup_path(nxt_conf_validation_t *vldt, - nxt_conf_value_t *value, void *data); + nxt_conf_value_t *value, void *data); #endif #if (NXT_HAVE_NJS) static nxt_int_t nxt_conf_vldt_js_module(nxt_conf_validation_t *vldt, - nxt_conf_value_t *value, void *data); + nxt_conf_value_t *value, void *data); static nxt_int_t nxt_conf_vldt_js_module_element(nxt_conf_validation_t *vldt, - nxt_conf_value_t *value); + nxt_conf_value_t *value); #endif - -static nxt_conf_vldt_object_t nxt_conf_vldt_setting_members[]; -static nxt_conf_vldt_object_t nxt_conf_vldt_http_members[]; -static nxt_conf_vldt_object_t nxt_conf_vldt_websocket_members[]; -static nxt_conf_vldt_object_t nxt_conf_vldt_static_members[]; -static nxt_conf_vldt_object_t nxt_conf_vldt_forwarded_members[]; -static nxt_conf_vldt_object_t nxt_conf_vldt_client_ip_members[]; +static nxt_conf_vldt_object_t nxt_conf_vldt_setting_members[]; +static nxt_conf_vldt_object_t nxt_conf_vldt_http_members[]; +static nxt_conf_vldt_object_t nxt_conf_vldt_websocket_members[]; +static nxt_conf_vldt_object_t nxt_conf_vldt_static_members[]; +static nxt_conf_vldt_object_t nxt_conf_vldt_forwarded_members[]; +static nxt_conf_vldt_object_t nxt_conf_vldt_client_ip_members[]; #if (NXT_TLS) -static nxt_conf_vldt_object_t nxt_conf_vldt_tls_members[]; -static nxt_conf_vldt_object_t nxt_conf_vldt_session_members[]; +static nxt_conf_vldt_object_t nxt_conf_vldt_tls_members[]; +static nxt_conf_vldt_object_t nxt_conf_vldt_session_members[]; #endif -static nxt_conf_vldt_object_t nxt_conf_vldt_match_members[]; -static nxt_conf_vldt_object_t nxt_conf_vldt_python_target_members[]; -static nxt_conf_vldt_object_t nxt_conf_vldt_php_common_members[]; -static nxt_conf_vldt_object_t nxt_conf_vldt_php_options_members[]; -static nxt_conf_vldt_object_t nxt_conf_vldt_php_target_members[]; -static nxt_conf_vldt_object_t nxt_conf_vldt_wasm_access_members[]; -static nxt_conf_vldt_object_t nxt_conf_vldt_common_members[]; -static nxt_conf_vldt_object_t nxt_conf_vldt_app_limits_members[]; -static nxt_conf_vldt_object_t nxt_conf_vldt_app_processes_members[]; -static nxt_conf_vldt_object_t nxt_conf_vldt_app_isolation_members[]; -static nxt_conf_vldt_object_t nxt_conf_vldt_app_namespaces_members[]; +static nxt_conf_vldt_object_t nxt_conf_vldt_match_members[]; +static nxt_conf_vldt_object_t nxt_conf_vldt_python_target_members[]; +static nxt_conf_vldt_object_t nxt_conf_vldt_php_common_members[]; +static nxt_conf_vldt_object_t nxt_conf_vldt_php_options_members[]; +static nxt_conf_vldt_object_t nxt_conf_vldt_php_target_members[]; +static nxt_conf_vldt_object_t nxt_conf_vldt_wasm_access_members[]; +static nxt_conf_vldt_object_t nxt_conf_vldt_common_members[]; +static nxt_conf_vldt_object_t nxt_conf_vldt_app_limits_members[]; +static nxt_conf_vldt_object_t nxt_conf_vldt_app_processes_members[]; +static nxt_conf_vldt_object_t nxt_conf_vldt_app_isolation_members[]; +static nxt_conf_vldt_object_t nxt_conf_vldt_app_namespaces_members[]; #if (NXT_HAVE_CGROUP) -static nxt_conf_vldt_object_t nxt_conf_vldt_app_cgroup_members[]; +static nxt_conf_vldt_object_t nxt_conf_vldt_app_cgroup_members[]; #endif #if (NXT_HAVE_ISOLATION_ROOTFS) -static nxt_conf_vldt_object_t nxt_conf_vldt_app_automount_members[]; +static nxt_conf_vldt_object_t nxt_conf_vldt_app_automount_members[]; #endif -static nxt_conf_vldt_object_t nxt_conf_vldt_access_log_members[]; - - -static nxt_conf_vldt_object_t nxt_conf_vldt_root_members[] = { - { - .name = nxt_string("settings"), - .type = NXT_CONF_VLDT_OBJECT, - .validator = nxt_conf_vldt_object, - .u.members = nxt_conf_vldt_setting_members, - }, { - .name = nxt_string("listeners"), - .type = NXT_CONF_VLDT_OBJECT, - .validator = nxt_conf_vldt_object_iterator, - .u.object = nxt_conf_vldt_listener, - }, { - .name = nxt_string("routes"), - .type = NXT_CONF_VLDT_ARRAY | NXT_CONF_VLDT_OBJECT, - .validator = nxt_conf_vldt_routes, - }, { - .name = nxt_string("applications"), - .type = NXT_CONF_VLDT_OBJECT, - .validator = nxt_conf_vldt_object_iterator, - .u.object = nxt_conf_vldt_app, - }, { - .name = nxt_string("upstreams"), - .type = NXT_CONF_VLDT_OBJECT, - .validator = nxt_conf_vldt_object_iterator, - .u.object = nxt_conf_vldt_upstream, - }, { - .name = nxt_string("access_log"), - .type = NXT_CONF_VLDT_STRING | NXT_CONF_VLDT_OBJECT, - .validator = nxt_conf_vldt_access_log, - }, - - NXT_CONF_VLDT_END -}; +static nxt_conf_vldt_object_t nxt_conf_vldt_access_log_members[]; + +static nxt_conf_vldt_object_t nxt_conf_vldt_root_members[] = { + { + .name = nxt_string("settings"), + .type = NXT_CONF_VLDT_OBJECT, + .validator = nxt_conf_vldt_object, + .u.members = nxt_conf_vldt_setting_members, + }, + { + .name = nxt_string("listeners"), + .type = NXT_CONF_VLDT_OBJECT, + .validator = nxt_conf_vldt_object_iterator, + .u.object = nxt_conf_vldt_listener, + }, + { + .name = nxt_string("routes"), + .type = NXT_CONF_VLDT_ARRAY | NXT_CONF_VLDT_OBJECT, + .validator = nxt_conf_vldt_routes, + }, + { + .name = nxt_string("applications"), + .type = NXT_CONF_VLDT_OBJECT, + .validator = nxt_conf_vldt_object_iterator, + .u.object = nxt_conf_vldt_app, + }, + { + .name = nxt_string("upstreams"), + .type = NXT_CONF_VLDT_OBJECT, + .validator = nxt_conf_vldt_object_iterator, + .u.object = nxt_conf_vldt_upstream, + }, + { + .name = nxt_string("access_log"), + .type = NXT_CONF_VLDT_STRING | NXT_CONF_VLDT_OBJECT, + .validator = nxt_conf_vldt_access_log, + }, + NXT_CONF_VLDT_END}; -static nxt_conf_vldt_object_t nxt_conf_vldt_setting_members[] = { +static nxt_conf_vldt_object_t nxt_conf_vldt_setting_members[] = { { - .name = nxt_string("listen_threads"), - .type = NXT_CONF_VLDT_INTEGER, - .validator = nxt_conf_vldt_listen_threads, - }, { - .name = nxt_string("http"), - .type = NXT_CONF_VLDT_OBJECT, - .validator = nxt_conf_vldt_object, - .u.members = nxt_conf_vldt_http_members, + .name = nxt_string("listen_threads"), + .type = NXT_CONF_VLDT_INTEGER, + .validator = nxt_conf_vldt_listen_threads, + }, + { + .name = nxt_string("http"), + .type = NXT_CONF_VLDT_OBJECT, + .validator = nxt_conf_vldt_object, + .u.members = nxt_conf_vldt_http_members, #if (NXT_HAVE_NJS) - }, { - .name = nxt_string("js_module"), - .type = NXT_CONF_VLDT_STRING | NXT_CONF_VLDT_ARRAY, - .validator = nxt_conf_vldt_js_module, + }, + { + .name = nxt_string("js_module"), + .type = NXT_CONF_VLDT_STRING | NXT_CONF_VLDT_ARRAY, + .validator = nxt_conf_vldt_js_module, #endif }, - NXT_CONF_VLDT_END -}; - + NXT_CONF_VLDT_END}; -static nxt_conf_vldt_object_t nxt_conf_vldt_http_members[] = { - { - .name = nxt_string("header_read_timeout"), - .type = NXT_CONF_VLDT_INTEGER, - }, { - .name = nxt_string("body_read_timeout"), - .type = NXT_CONF_VLDT_INTEGER, - }, { - .name = nxt_string("send_timeout"), - .type = NXT_CONF_VLDT_INTEGER, - }, { - .name = nxt_string("idle_timeout"), - .type = NXT_CONF_VLDT_INTEGER, - }, { - .name = nxt_string("large_header_buffer_size"), - .type = NXT_CONF_VLDT_INTEGER, - }, { - .name = nxt_string("large_header_buffers"), - .type = NXT_CONF_VLDT_INTEGER, - }, { - .name = nxt_string("body_buffer_size"), - .type = NXT_CONF_VLDT_INTEGER, - }, { - .name = nxt_string("max_body_size"), - .type = NXT_CONF_VLDT_INTEGER, - }, { - .name = nxt_string("body_temp_path"), - .type = NXT_CONF_VLDT_STRING, - }, { - .name = nxt_string("discard_unsafe_fields"), - .type = NXT_CONF_VLDT_BOOLEAN, - }, { - .name = nxt_string("websocket"), - .type = NXT_CONF_VLDT_OBJECT, - .validator = nxt_conf_vldt_object, - .u.members = nxt_conf_vldt_websocket_members, - }, { - .name = nxt_string("static"), - .type = NXT_CONF_VLDT_OBJECT, - .validator = nxt_conf_vldt_object, - .u.members = nxt_conf_vldt_static_members, - }, { - .name = nxt_string("log_route"), - .type = NXT_CONF_VLDT_BOOLEAN, - }, { - .name = nxt_string("server_version"), - .type = NXT_CONF_VLDT_BOOLEAN, - }, { - .name = nxt_string("chunked_transform"), - .type = NXT_CONF_VLDT_BOOLEAN, - }, - - NXT_CONF_VLDT_END -}; +static nxt_conf_vldt_object_t nxt_conf_vldt_http_members[] = { + { + .name = nxt_string("header_read_timeout"), + .type = NXT_CONF_VLDT_INTEGER, + }, + { + .name = nxt_string("body_read_timeout"), + .type = NXT_CONF_VLDT_INTEGER, + }, + { + .name = nxt_string("send_timeout"), + .type = NXT_CONF_VLDT_INTEGER, + }, + { + .name = nxt_string("idle_timeout"), + .type = NXT_CONF_VLDT_INTEGER, + }, + { + .name = nxt_string("large_header_buffer_size"), + .type = NXT_CONF_VLDT_INTEGER, + }, + { + .name = nxt_string("large_header_buffers"), + .type = NXT_CONF_VLDT_INTEGER, + }, + { + .name = nxt_string("body_buffer_size"), + .type = NXT_CONF_VLDT_INTEGER, + }, + { + .name = nxt_string("max_body_size"), + .type = NXT_CONF_VLDT_INTEGER, + }, + { + .name = nxt_string("body_temp_path"), + .type = NXT_CONF_VLDT_STRING, + }, + { + .name = nxt_string("discard_unsafe_fields"), + .type = NXT_CONF_VLDT_BOOLEAN, + }, + { + .name = nxt_string("websocket"), + .type = NXT_CONF_VLDT_OBJECT, + .validator = nxt_conf_vldt_object, + .u.members = nxt_conf_vldt_websocket_members, + }, + { + .name = nxt_string("static"), + .type = NXT_CONF_VLDT_OBJECT, + .validator = nxt_conf_vldt_object, + .u.members = nxt_conf_vldt_static_members, + }, + { + .name = nxt_string("log_route"), + .type = NXT_CONF_VLDT_BOOLEAN, + }, + { + .name = nxt_string("server_version"), + .type = NXT_CONF_VLDT_BOOLEAN, + }, + { + .name = nxt_string("chunked_transform"), + .type = NXT_CONF_VLDT_BOOLEAN, + }, + NXT_CONF_VLDT_END}; -static nxt_conf_vldt_object_t nxt_conf_vldt_websocket_members[] = { +static nxt_conf_vldt_object_t nxt_conf_vldt_websocket_members[] = { { - .name = nxt_string("read_timeout"), - .type = NXT_CONF_VLDT_INTEGER, - }, { - - .name = nxt_string("keepalive_interval"), - .type = NXT_CONF_VLDT_INTEGER, - }, { - .name = nxt_string("max_frame_size"), - .type = NXT_CONF_VLDT_INTEGER, + .name = nxt_string("read_timeout"), + .type = NXT_CONF_VLDT_INTEGER, }, + { - NXT_CONF_VLDT_END -}; + .name = nxt_string("keepalive_interval"), + .type = NXT_CONF_VLDT_INTEGER, + }, + { + .name = nxt_string("max_frame_size"), + .type = NXT_CONF_VLDT_INTEGER, + }, + NXT_CONF_VLDT_END}; -static nxt_conf_vldt_object_t nxt_conf_vldt_static_members[] = { +static nxt_conf_vldt_object_t nxt_conf_vldt_static_members[] = { { - .name = nxt_string("mime_types"), - .type = NXT_CONF_VLDT_OBJECT, - .validator = nxt_conf_vldt_mtypes, + .name = nxt_string("mime_types"), + .type = NXT_CONF_VLDT_OBJECT, + .validator = nxt_conf_vldt_mtypes, }, - NXT_CONF_VLDT_END -}; - + NXT_CONF_VLDT_END}; -static nxt_conf_vldt_object_t nxt_conf_vldt_listener_members[] = { - { - .name = nxt_string("pass"), - .type = NXT_CONF_VLDT_STRING, - .validator = nxt_conf_vldt_pass, - .flags = NXT_CONF_VLDT_TSTR, - }, { - .name = nxt_string("application"), - .type = NXT_CONF_VLDT_STRING, - .validator = nxt_conf_vldt_app_name, - }, { - .name = nxt_string("forwarded"), - .type = NXT_CONF_VLDT_OBJECT, - .validator = nxt_conf_vldt_forwarded, - }, { - .name = nxt_string("client_ip"), - .type = NXT_CONF_VLDT_OBJECT, - .validator = nxt_conf_vldt_object, - .u.members = nxt_conf_vldt_client_ip_members - }, { - .name = nxt_string("backlog"), - .type = NXT_CONF_VLDT_NUMBER, - .validator = nxt_conf_vldt_listen_backlog, +static nxt_conf_vldt_object_t nxt_conf_vldt_listener_members[] = { + { + .name = nxt_string("pass"), + .type = NXT_CONF_VLDT_STRING, + .validator = nxt_conf_vldt_pass, + .flags = NXT_CONF_VLDT_TSTR, + }, + { + .name = nxt_string("application"), + .type = NXT_CONF_VLDT_STRING, + .validator = nxt_conf_vldt_app_name, + }, + { + .name = nxt_string("forwarded"), + .type = NXT_CONF_VLDT_OBJECT, + .validator = nxt_conf_vldt_forwarded, + }, + {.name = nxt_string("client_ip"), + .type = NXT_CONF_VLDT_OBJECT, + .validator = nxt_conf_vldt_object, + .u.members = nxt_conf_vldt_client_ip_members}, + { + .name = nxt_string("backlog"), + .type = NXT_CONF_VLDT_NUMBER, + .validator = nxt_conf_vldt_listen_backlog, }, #if (NXT_TLS) { - .name = nxt_string("tls"), - .type = NXT_CONF_VLDT_OBJECT, - .validator = nxt_conf_vldt_object, - .u.members = nxt_conf_vldt_tls_members, + .name = nxt_string("tls"), + .type = NXT_CONF_VLDT_OBJECT, + .validator = nxt_conf_vldt_object, + .u.members = nxt_conf_vldt_tls_members, }, #endif - NXT_CONF_VLDT_END -}; - + NXT_CONF_VLDT_END}; -static nxt_conf_vldt_object_t nxt_conf_vldt_forwarded_members[] = { +static nxt_conf_vldt_object_t nxt_conf_vldt_forwarded_members[] = { { - .name = nxt_string("client_ip"), - .type = NXT_CONF_VLDT_STRING, - }, { - .name = nxt_string("protocol"), - .type = NXT_CONF_VLDT_STRING, - }, { - .name = nxt_string("source"), - .type = NXT_CONF_VLDT_STRING | NXT_CONF_VLDT_ARRAY, - .validator = nxt_conf_vldt_match_addrs, - .flags = NXT_CONF_VLDT_REQUIRED - }, { - .name = nxt_string("recursive"), - .type = NXT_CONF_VLDT_BOOLEAN, + .name = nxt_string("client_ip"), + .type = NXT_CONF_VLDT_STRING, + }, + { + .name = nxt_string("protocol"), + .type = NXT_CONF_VLDT_STRING, + }, + {.name = nxt_string("source"), + .type = NXT_CONF_VLDT_STRING | NXT_CONF_VLDT_ARRAY, + .validator = nxt_conf_vldt_match_addrs, + .flags = NXT_CONF_VLDT_REQUIRED}, + { + .name = nxt_string("recursive"), + .type = NXT_CONF_VLDT_BOOLEAN, }, - NXT_CONF_VLDT_END -}; - + NXT_CONF_VLDT_END}; -static nxt_conf_vldt_object_t nxt_conf_vldt_client_ip_members[] = { +static nxt_conf_vldt_object_t nxt_conf_vldt_client_ip_members[] = { + {.name = nxt_string("source"), + .type = NXT_CONF_VLDT_STRING | NXT_CONF_VLDT_ARRAY, + .validator = nxt_conf_vldt_match_addrs, + .flags = NXT_CONF_VLDT_REQUIRED}, + {.name = nxt_string("header"), + .type = NXT_CONF_VLDT_STRING, + .flags = NXT_CONF_VLDT_REQUIRED}, { - .name = nxt_string("source"), - .type = NXT_CONF_VLDT_STRING | NXT_CONF_VLDT_ARRAY, - .validator = nxt_conf_vldt_match_addrs, - .flags = NXT_CONF_VLDT_REQUIRED - }, { - .name = nxt_string("header"), - .type = NXT_CONF_VLDT_STRING, - .flags = NXT_CONF_VLDT_REQUIRED - }, { - .name = nxt_string("recursive"), - .type = NXT_CONF_VLDT_BOOLEAN, + .name = nxt_string("recursive"), + .type = NXT_CONF_VLDT_BOOLEAN, }, - NXT_CONF_VLDT_END -}; - + NXT_CONF_VLDT_END}; #if (NXT_TLS) -static nxt_conf_vldt_object_t nxt_conf_vldt_tls_members[] = { +static nxt_conf_vldt_object_t nxt_conf_vldt_tls_members[] = { + { + .name = nxt_string("certificate"), + .type = NXT_CONF_VLDT_STRING | NXT_CONF_VLDT_ARRAY, + .flags = NXT_CONF_VLDT_REQUIRED, + .validator = nxt_conf_vldt_certificate, + }, { - .name = nxt_string("certificate"), - .type = NXT_CONF_VLDT_STRING | NXT_CONF_VLDT_ARRAY, - .flags = NXT_CONF_VLDT_REQUIRED, - .validator = nxt_conf_vldt_certificate, - }, { - .name = nxt_string("conf_commands"), - .type = NXT_CONF_VLDT_OBJECT, + .name = nxt_string("conf_commands"), + .type = NXT_CONF_VLDT_OBJECT, #if (NXT_HAVE_OPENSSL_CONF_CMD) - .validator = nxt_conf_vldt_object_conf_commands, + .validator = nxt_conf_vldt_object_conf_commands, #else - .validator = nxt_conf_vldt_unsupported, - .u.string = "conf_commands", + .validator = nxt_conf_vldt_unsupported, + .u.string = "conf_commands", #endif - }, { - .name = nxt_string("session"), - .type = NXT_CONF_VLDT_OBJECT, - .validator = nxt_conf_vldt_object, - .u.members = nxt_conf_vldt_session_members, + }, + { + .name = nxt_string("session"), + .type = NXT_CONF_VLDT_OBJECT, + .validator = nxt_conf_vldt_object, + .u.members = nxt_conf_vldt_session_members, }, - NXT_CONF_VLDT_END -}; - + NXT_CONF_VLDT_END}; -static nxt_conf_vldt_object_t nxt_conf_vldt_session_members[] = { - { - .name = nxt_string("cache_size"), - .type = NXT_CONF_VLDT_INTEGER, - .validator = nxt_conf_vldt_tls_cache_size, - }, { - .name = nxt_string("timeout"), - .type = NXT_CONF_VLDT_INTEGER, - .validator = nxt_conf_vldt_tls_timeout, - }, { - .name = nxt_string("tickets"), - .type = NXT_CONF_VLDT_STRING - | NXT_CONF_VLDT_ARRAY - | NXT_CONF_VLDT_BOOLEAN, +static nxt_conf_vldt_object_t nxt_conf_vldt_session_members[] = { + { + .name = nxt_string("cache_size"), + .type = NXT_CONF_VLDT_INTEGER, + .validator = nxt_conf_vldt_tls_cache_size, + }, + { + .name = nxt_string("timeout"), + .type = NXT_CONF_VLDT_INTEGER, + .validator = nxt_conf_vldt_tls_timeout, + }, + { + .name = nxt_string("tickets"), + .type = + NXT_CONF_VLDT_STRING | NXT_CONF_VLDT_ARRAY | NXT_CONF_VLDT_BOOLEAN, #if (NXT_HAVE_OPENSSL_TLSEXT) - .validator = nxt_conf_vldt_ticket_key, + .validator = nxt_conf_vldt_ticket_key, #else - .validator = nxt_conf_vldt_unsupported, - .u.string = "tickets", + .validator = nxt_conf_vldt_unsupported, + .u.string = "tickets", #endif }, - NXT_CONF_VLDT_END -}; - + NXT_CONF_VLDT_END}; -static nxt_int_t -nxt_conf_vldt_tls_cache_size(nxt_conf_validation_t *vldt, - nxt_conf_value_t *value, void *data) -{ - int64_t cache_size; +static nxt_int_t nxt_conf_vldt_tls_cache_size(nxt_conf_validation_t *vldt, + nxt_conf_value_t *value, + void *data) { + int64_t cache_size; - cache_size = nxt_conf_get_number(value); + cache_size = nxt_conf_get_number(value); - if (cache_size < 0) { - return nxt_conf_vldt_error(vldt, "The \"cache_size\" number must not " - "be negative."); - } + if (cache_size < 0) { + return nxt_conf_vldt_error(vldt, "The \"cache_size\" number must not " + "be negative."); + } - return NXT_OK; + return NXT_OK; } +static nxt_int_t nxt_conf_vldt_tls_timeout(nxt_conf_validation_t *vldt, + nxt_conf_value_t *value, + void *data) { + int64_t timeout; -static nxt_int_t -nxt_conf_vldt_tls_timeout(nxt_conf_validation_t *vldt, nxt_conf_value_t *value, - void *data) -{ - int64_t timeout; - - timeout = nxt_conf_get_number(value); + timeout = nxt_conf_get_number(value); - if (timeout <= 0) { - return nxt_conf_vldt_error(vldt, "The \"timeout\" number must be " - "greater than zero."); - } + if (timeout <= 0) { + return nxt_conf_vldt_error(vldt, "The \"timeout\" number must be " + "greater than zero."); + } - return NXT_OK; + return NXT_OK; } #endif #if (NXT_HAVE_OPENSSL_TLSEXT) -static nxt_int_t -nxt_conf_vldt_ticket_key(nxt_conf_validation_t *vldt, nxt_conf_value_t *value, - void *data) -{ - if (nxt_conf_type(value) == NXT_CONF_BOOLEAN) { - return NXT_OK; - } +static nxt_int_t nxt_conf_vldt_ticket_key(nxt_conf_validation_t *vldt, + nxt_conf_value_t *value, void *data) { + if (nxt_conf_type(value) == NXT_CONF_BOOLEAN) { + return NXT_OK; + } - if (nxt_conf_type(value) == NXT_CONF_ARRAY) { - return nxt_conf_vldt_array_iterator(vldt, value, - &nxt_conf_vldt_ticket_key_element); - } + if (nxt_conf_type(value) == NXT_CONF_ARRAY) { + return nxt_conf_vldt_array_iterator(vldt, value, + &nxt_conf_vldt_ticket_key_element); + } - /* NXT_CONF_STRING */ + /* NXT_CONF_STRING */ - return nxt_conf_vldt_ticket_key_element(vldt, value); + return nxt_conf_vldt_ticket_key_element(vldt, value); } +static nxt_int_t nxt_conf_vldt_ticket_key_element(nxt_conf_validation_t *vldt, + nxt_conf_value_t *value) { + ssize_t ret; + nxt_str_t key; -static nxt_int_t -nxt_conf_vldt_ticket_key_element(nxt_conf_validation_t *vldt, - nxt_conf_value_t *value) -{ - ssize_t ret; - nxt_str_t key; - - if (nxt_conf_type(value) != NXT_CONF_STRING) { - return nxt_conf_vldt_error(vldt, "The \"key\" array must " - "contain only string values."); - } + if (nxt_conf_type(value) != NXT_CONF_STRING) { + return nxt_conf_vldt_error(vldt, "The \"key\" array must " + "contain only string values."); + } - nxt_conf_get_string(value, &key); + nxt_conf_get_string(value, &key); - ret = nxt_base64_decode(NULL, key.start, key.length); - if (ret == NXT_ERROR) { - return nxt_conf_vldt_error(vldt, "Invalid Base64 format for the ticket " - "key \"%V\".", &key); - } + ret = nxt_base64_decode(NULL, key.start, key.length); + if (ret == NXT_ERROR) { + return nxt_conf_vldt_error(vldt, + "Invalid Base64 format for the ticket " + "key \"%V\".", + &key); + } - if (ret != 48 && ret != 80) { - return nxt_conf_vldt_error(vldt, "Invalid length %d of the ticket " - "key \"%V\". Must be 48 or 80 bytes.", - ret, &key); - } + if (ret != 48 && ret != 80) { + return nxt_conf_vldt_error(vldt, + "Invalid length %d of the ticket " + "key \"%V\". Must be 48 or 80 bytes.", + ret, &key); + } - return NXT_OK; + return NXT_OK; } #endif - -static nxt_conf_vldt_object_t nxt_conf_vldt_route_members[] = { +static nxt_conf_vldt_object_t nxt_conf_vldt_route_members[] = { { - .name = nxt_string("match"), - .type = NXT_CONF_VLDT_OBJECT, - .validator = nxt_conf_vldt_object, - .u.members = nxt_conf_vldt_match_members, - }, { - .name = nxt_string("action"), - .type = NXT_CONF_VLDT_OBJECT, - .validator = nxt_conf_vldt_action, + .name = nxt_string("match"), + .type = NXT_CONF_VLDT_OBJECT, + .validator = nxt_conf_vldt_object, + .u.members = nxt_conf_vldt_match_members, + }, + { + .name = nxt_string("action"), + .type = NXT_CONF_VLDT_OBJECT, + .validator = nxt_conf_vldt_action, }, - NXT_CONF_VLDT_END -}; - + NXT_CONF_VLDT_END}; -static nxt_conf_vldt_object_t nxt_conf_vldt_match_members[] = { - { - .name = nxt_string("method"), - .type = NXT_CONF_VLDT_STRING | NXT_CONF_VLDT_ARRAY, - .validator = nxt_conf_vldt_match_patterns, - .u.string = "method", - }, { - .name = nxt_string("scheme"), - .type = NXT_CONF_VLDT_STRING, - .validator = nxt_conf_vldt_match_scheme_pattern, - }, { - .name = nxt_string("host"), - .type = NXT_CONF_VLDT_STRING | NXT_CONF_VLDT_ARRAY, - .validator = nxt_conf_vldt_match_patterns, - .u.string = "host", - }, { - .name = nxt_string("source"), - .type = NXT_CONF_VLDT_STRING | NXT_CONF_VLDT_ARRAY, - .validator = nxt_conf_vldt_match_addrs, - }, { - .name = nxt_string("destination"), - .type = NXT_CONF_VLDT_STRING | NXT_CONF_VLDT_ARRAY, - .validator = nxt_conf_vldt_match_addrs, - }, { - .name = nxt_string("uri"), - .type = NXT_CONF_VLDT_STRING | NXT_CONF_VLDT_ARRAY, - .validator = nxt_conf_vldt_match_encoded_patterns, - .u.string = "uri" - }, { - .name = nxt_string("query"), - .type = NXT_CONF_VLDT_STRING | NXT_CONF_VLDT_ARRAY, - .validator = nxt_conf_vldt_match_encoded_patterns, - .u.string = "query" - }, { - .name = nxt_string("arguments"), - .type = NXT_CONF_VLDT_OBJECT | NXT_CONF_VLDT_ARRAY, - .validator = nxt_conf_vldt_match_encoded_patterns_sets, - }, { - .name = nxt_string("headers"), - .type = NXT_CONF_VLDT_OBJECT | NXT_CONF_VLDT_ARRAY, - .validator = nxt_conf_vldt_match_patterns_sets, - .u.string = "headers" - }, { - .name = nxt_string("cookies"), - .type = NXT_CONF_VLDT_OBJECT | NXT_CONF_VLDT_ARRAY, - .validator = nxt_conf_vldt_match_patterns_sets, - .u.string = "cookies" - }, { - .name = nxt_string("if"), - .type = NXT_CONF_VLDT_STRING, - .validator = nxt_conf_vldt_if, - }, - - NXT_CONF_VLDT_END -}; +static nxt_conf_vldt_object_t nxt_conf_vldt_match_members[] = { + { + .name = nxt_string("method"), + .type = NXT_CONF_VLDT_STRING | NXT_CONF_VLDT_ARRAY, + .validator = nxt_conf_vldt_match_patterns, + .u.string = "method", + }, + { + .name = nxt_string("scheme"), + .type = NXT_CONF_VLDT_STRING, + .validator = nxt_conf_vldt_match_scheme_pattern, + }, + { + .name = nxt_string("host"), + .type = NXT_CONF_VLDT_STRING | NXT_CONF_VLDT_ARRAY, + .validator = nxt_conf_vldt_match_patterns, + .u.string = "host", + }, + { + .name = nxt_string("source"), + .type = NXT_CONF_VLDT_STRING | NXT_CONF_VLDT_ARRAY, + .validator = nxt_conf_vldt_match_addrs, + }, + { + .name = nxt_string("destination"), + .type = NXT_CONF_VLDT_STRING | NXT_CONF_VLDT_ARRAY, + .validator = nxt_conf_vldt_match_addrs, + }, + {.name = nxt_string("uri"), + .type = NXT_CONF_VLDT_STRING | NXT_CONF_VLDT_ARRAY, + .validator = nxt_conf_vldt_match_encoded_patterns, + .u.string = "uri"}, + {.name = nxt_string("query"), + .type = NXT_CONF_VLDT_STRING | NXT_CONF_VLDT_ARRAY, + .validator = nxt_conf_vldt_match_encoded_patterns, + .u.string = "query"}, + { + .name = nxt_string("arguments"), + .type = NXT_CONF_VLDT_OBJECT | NXT_CONF_VLDT_ARRAY, + .validator = nxt_conf_vldt_match_encoded_patterns_sets, + }, + {.name = nxt_string("headers"), + .type = NXT_CONF_VLDT_OBJECT | NXT_CONF_VLDT_ARRAY, + .validator = nxt_conf_vldt_match_patterns_sets, + .u.string = "headers"}, + {.name = nxt_string("cookies"), + .type = NXT_CONF_VLDT_OBJECT | NXT_CONF_VLDT_ARRAY, + .validator = nxt_conf_vldt_match_patterns_sets, + .u.string = "cookies"}, + { + .name = nxt_string("if"), + .type = NXT_CONF_VLDT_STRING, + .validator = nxt_conf_vldt_if, + }, + NXT_CONF_VLDT_END}; -static nxt_conf_vldt_object_t nxt_conf_vldt_action_common_members[] = { +static nxt_conf_vldt_object_t nxt_conf_vldt_action_common_members[] = { { - .name = nxt_string("rewrite"), - .type = NXT_CONF_VLDT_STRING, - .flags = NXT_CONF_VLDT_TSTR, + .name = nxt_string("rewrite"), + .type = NXT_CONF_VLDT_STRING, + .flags = NXT_CONF_VLDT_TSTR, }, { - .name = nxt_string("response_headers"), - .type = NXT_CONF_VLDT_OBJECT, - .validator = nxt_conf_vldt_object_iterator, - .u.object = nxt_conf_vldt_response_header, + .name = nxt_string("response_headers"), + .type = NXT_CONF_VLDT_OBJECT, + .validator = nxt_conf_vldt_object_iterator, + .u.object = nxt_conf_vldt_response_header, }, - NXT_CONF_VLDT_END -}; - + NXT_CONF_VLDT_END}; -static nxt_conf_vldt_object_t nxt_conf_vldt_pass_action_members[] = { +static nxt_conf_vldt_object_t nxt_conf_vldt_pass_action_members[] = { { - .name = nxt_string("pass"), - .type = NXT_CONF_VLDT_STRING, - .validator = nxt_conf_vldt_pass, - .flags = NXT_CONF_VLDT_TSTR, + .name = nxt_string("pass"), + .type = NXT_CONF_VLDT_STRING, + .validator = nxt_conf_vldt_pass, + .flags = NXT_CONF_VLDT_TSTR, }, - NXT_CONF_VLDT_NEXT(nxt_conf_vldt_action_common_members) -}; - + NXT_CONF_VLDT_NEXT(nxt_conf_vldt_action_common_members)}; -static nxt_conf_vldt_object_t nxt_conf_vldt_return_action_members[] = { +static nxt_conf_vldt_object_t nxt_conf_vldt_return_action_members[] = { { - .name = nxt_string("return"), - .type = NXT_CONF_VLDT_INTEGER, - .validator = nxt_conf_vldt_return, - }, { - .name = nxt_string("location"), - .type = NXT_CONF_VLDT_STRING, - .flags = NXT_CONF_VLDT_TSTR, + .name = nxt_string("return"), + .type = NXT_CONF_VLDT_INTEGER, + .validator = nxt_conf_vldt_return, + }, + { + .name = nxt_string("location"), + .type = NXT_CONF_VLDT_STRING, + .flags = NXT_CONF_VLDT_TSTR, }, - NXT_CONF_VLDT_NEXT(nxt_conf_vldt_action_common_members) -}; - + NXT_CONF_VLDT_NEXT(nxt_conf_vldt_action_common_members)}; -static nxt_conf_vldt_object_t nxt_conf_vldt_share_action_members[] = { - { - .name = nxt_string("share"), - .type = NXT_CONF_VLDT_STRING | NXT_CONF_VLDT_ARRAY, - .validator = nxt_conf_vldt_share, - }, { - .name = nxt_string("index"), - .type = NXT_CONF_VLDT_STRING, - }, { - .name = nxt_string("types"), - .type = NXT_CONF_VLDT_STRING | NXT_CONF_VLDT_ARRAY, - .validator = nxt_conf_vldt_match_patterns, - }, { - .name = nxt_string("fallback"), - .type = NXT_CONF_VLDT_OBJECT, - .validator = nxt_conf_vldt_action, - }, { - .name = nxt_string("chroot"), - .type = NXT_CONF_VLDT_STRING, +static nxt_conf_vldt_object_t nxt_conf_vldt_share_action_members[] = { + { + .name = nxt_string("share"), + .type = NXT_CONF_VLDT_STRING | NXT_CONF_VLDT_ARRAY, + .validator = nxt_conf_vldt_share, + }, + { + .name = nxt_string("index"), + .type = NXT_CONF_VLDT_STRING, + }, + { + .name = nxt_string("types"), + .type = NXT_CONF_VLDT_STRING | NXT_CONF_VLDT_ARRAY, + .validator = nxt_conf_vldt_match_patterns, + }, + { + .name = nxt_string("fallback"), + .type = NXT_CONF_VLDT_OBJECT, + .validator = nxt_conf_vldt_action, + }, + { + .name = nxt_string("chroot"), + .type = NXT_CONF_VLDT_STRING, #if !(NXT_HAVE_OPENAT2) - .validator = nxt_conf_vldt_unsupported, - .u.string = "chroot", + .validator = nxt_conf_vldt_unsupported, + .u.string = "chroot", #endif - .flags = NXT_CONF_VLDT_TSTR, - }, { - .name = nxt_string("follow_symlinks"), - .type = NXT_CONF_VLDT_BOOLEAN, + .flags = NXT_CONF_VLDT_TSTR, + }, + { + .name = nxt_string("follow_symlinks"), + .type = NXT_CONF_VLDT_BOOLEAN, #if !(NXT_HAVE_OPENAT2) - .validator = nxt_conf_vldt_unsupported, - .u.string = "follow_symlinks", + .validator = nxt_conf_vldt_unsupported, + .u.string = "follow_symlinks", #endif - }, { - .name = nxt_string("traverse_mounts"), - .type = NXT_CONF_VLDT_BOOLEAN, + }, + { + .name = nxt_string("traverse_mounts"), + .type = NXT_CONF_VLDT_BOOLEAN, #if !(NXT_HAVE_OPENAT2) - .validator = nxt_conf_vldt_unsupported, - .u.string = "traverse_mounts", + .validator = nxt_conf_vldt_unsupported, + .u.string = "traverse_mounts", #endif }, - NXT_CONF_VLDT_NEXT(nxt_conf_vldt_action_common_members) -}; - + NXT_CONF_VLDT_NEXT(nxt_conf_vldt_action_common_members)}; -static nxt_conf_vldt_object_t nxt_conf_vldt_proxy_action_members[] = { +static nxt_conf_vldt_object_t nxt_conf_vldt_proxy_action_members[] = { { - .name = nxt_string("proxy"), - .type = NXT_CONF_VLDT_STRING, - .validator = nxt_conf_vldt_proxy, + .name = nxt_string("proxy"), + .type = NXT_CONF_VLDT_STRING, + .validator = nxt_conf_vldt_proxy, }, - NXT_CONF_VLDT_NEXT(nxt_conf_vldt_action_common_members) -}; - + NXT_CONF_VLDT_NEXT(nxt_conf_vldt_action_common_members)}; -static nxt_conf_vldt_object_t nxt_conf_vldt_external_members[] = { +static nxt_conf_vldt_object_t nxt_conf_vldt_external_members[] = { { - .name = nxt_string("executable"), - .type = NXT_CONF_VLDT_STRING, - .flags = NXT_CONF_VLDT_REQUIRED, - }, { - .name = nxt_string("arguments"), - .type = NXT_CONF_VLDT_ARRAY, - .validator = nxt_conf_vldt_array_iterator, - .u.array = nxt_conf_vldt_argument, + .name = nxt_string("executable"), + .type = NXT_CONF_VLDT_STRING, + .flags = NXT_CONF_VLDT_REQUIRED, }, - - NXT_CONF_VLDT_NEXT(nxt_conf_vldt_common_members) -}; - - -static nxt_conf_vldt_object_t nxt_conf_vldt_python_common_members[] = { - { - .name = nxt_string("home"), - .type = NXT_CONF_VLDT_STRING, - }, { - .name = nxt_string("path"), - .type = NXT_CONF_VLDT_STRING | NXT_CONF_VLDT_ARRAY, - .validator = nxt_conf_vldt_python_path, - }, { - .name = nxt_string("protocol"), - .type = NXT_CONF_VLDT_STRING, - .validator = nxt_conf_vldt_python_protocol, - }, { - .name = nxt_string("threads"), - .type = NXT_CONF_VLDT_INTEGER, - .validator = nxt_conf_vldt_threads, - }, { - .name = nxt_string("thread_stack_size"), - .type = NXT_CONF_VLDT_INTEGER, - .validator = nxt_conf_vldt_thread_stack_size, - }, - - NXT_CONF_VLDT_NEXT(nxt_conf_vldt_common_members) -}; - -static nxt_conf_vldt_object_t nxt_conf_vldt_python_members[] = { - { - .name = nxt_string("module"), - .type = NXT_CONF_VLDT_STRING, - .validator = nxt_conf_vldt_targets_exclusive, - .u.string = "module", - }, { - .name = nxt_string("callable"), - .type = NXT_CONF_VLDT_STRING, - .validator = nxt_conf_vldt_targets_exclusive, - .u.string = "callable", - }, { - .name = nxt_string("factory"), - .type = NXT_CONF_VLDT_BOOLEAN, - .validator = nxt_conf_vldt_targets_exclusive, - .u.string = "factory", - }, { - .name = nxt_string("prefix"), - .type = NXT_CONF_VLDT_STRING, - .validator = nxt_conf_vldt_targets_exclusive, - .u.string = "prefix", - }, { - .name = nxt_string("targets"), - .type = NXT_CONF_VLDT_OBJECT, - .validator = nxt_conf_vldt_targets, - .u.members = nxt_conf_vldt_python_target_members - }, - - NXT_CONF_VLDT_NEXT(nxt_conf_vldt_python_common_members) -}; - - -static nxt_conf_vldt_object_t nxt_conf_vldt_python_target_members[] = { { - .name = nxt_string("module"), - .type = NXT_CONF_VLDT_STRING, - .flags = NXT_CONF_VLDT_REQUIRED, - }, { - .name = nxt_string("callable"), - .type = NXT_CONF_VLDT_STRING, - }, { - .name = nxt_string("factory"), - .type = NXT_CONF_VLDT_BOOLEAN, - }, { - .name = nxt_string("prefix"), - .type = NXT_CONF_VLDT_STRING, - .validator = nxt_conf_vldt_python_prefix, + .name = nxt_string("arguments"), + .type = NXT_CONF_VLDT_ARRAY, + .validator = nxt_conf_vldt_array_iterator, + .u.array = nxt_conf_vldt_argument, }, - NXT_CONF_VLDT_END -}; - + NXT_CONF_VLDT_NEXT(nxt_conf_vldt_common_members)}; -static nxt_conf_vldt_object_t nxt_conf_vldt_python_notargets_members[] = { +static nxt_conf_vldt_object_t nxt_conf_vldt_python_common_members[] = { { - .name = nxt_string("module"), - .type = NXT_CONF_VLDT_STRING, - .flags = NXT_CONF_VLDT_REQUIRED, - }, { - .name = nxt_string("callable"), - .type = NXT_CONF_VLDT_STRING, - }, { - .name = nxt_string("factory"), - .type = NXT_CONF_VLDT_BOOLEAN, - }, { - .name = nxt_string("prefix"), - .type = NXT_CONF_VLDT_STRING, - .validator = nxt_conf_vldt_python_prefix, + .name = nxt_string("home"), + .type = NXT_CONF_VLDT_STRING, }, - - NXT_CONF_VLDT_NEXT(nxt_conf_vldt_python_common_members) -}; - - -static nxt_conf_vldt_object_t nxt_conf_vldt_php_members[] = { - { - .name = nxt_string("root"), - .type = NXT_CONF_VLDT_ANY_TYPE, - .validator = nxt_conf_vldt_targets_exclusive, - .u.string = "root", - }, { - .name = nxt_string("script"), - .type = NXT_CONF_VLDT_ANY_TYPE, - .validator = nxt_conf_vldt_targets_exclusive, - .u.string = "script", - }, { - .name = nxt_string("index"), - .type = NXT_CONF_VLDT_ANY_TYPE, - .validator = nxt_conf_vldt_targets_exclusive, - .u.string = "index", - }, { - .name = nxt_string("targets"), - .type = NXT_CONF_VLDT_OBJECT, - .validator = nxt_conf_vldt_targets, - .u.members = nxt_conf_vldt_php_target_members - }, - - NXT_CONF_VLDT_NEXT(nxt_conf_vldt_php_common_members) -}; - - -static nxt_conf_vldt_object_t nxt_conf_vldt_php_common_members[] = { { - .name = nxt_string("options"), - .type = NXT_CONF_VLDT_OBJECT, - .validator = nxt_conf_vldt_object, - .u.members = nxt_conf_vldt_php_options_members, + .name = nxt_string("path"), + .type = NXT_CONF_VLDT_STRING | NXT_CONF_VLDT_ARRAY, + .validator = nxt_conf_vldt_python_path, }, - - NXT_CONF_VLDT_NEXT(nxt_conf_vldt_common_members) -}; - - -static nxt_conf_vldt_object_t nxt_conf_vldt_php_options_members[] = { { - .name = nxt_string("file"), - .type = NXT_CONF_VLDT_STRING, - }, { - .name = nxt_string("admin"), - .type = NXT_CONF_VLDT_OBJECT, - .validator = nxt_conf_vldt_object_iterator, - .u.object = nxt_conf_vldt_php_option, - }, { - .name = nxt_string("user"), - .type = NXT_CONF_VLDT_OBJECT, - .validator = nxt_conf_vldt_object_iterator, - .u.object = nxt_conf_vldt_php_option, + .name = nxt_string("protocol"), + .type = NXT_CONF_VLDT_STRING, + .validator = nxt_conf_vldt_python_protocol, }, - - NXT_CONF_VLDT_END -}; - - -static nxt_conf_vldt_object_t nxt_conf_vldt_php_target_members[] = { { - .name = nxt_string("root"), - .type = NXT_CONF_VLDT_STRING, - .flags = NXT_CONF_VLDT_REQUIRED, - }, { - .name = nxt_string("script"), - .type = NXT_CONF_VLDT_STRING, - }, { - .name = nxt_string("index"), - .type = NXT_CONF_VLDT_STRING, + .name = nxt_string("threads"), + .type = NXT_CONF_VLDT_INTEGER, + .validator = nxt_conf_vldt_threads, }, - - NXT_CONF_VLDT_END -}; - - -static nxt_conf_vldt_object_t nxt_conf_vldt_php_notargets_members[] = { { - .name = nxt_string("root"), - .type = NXT_CONF_VLDT_STRING, - .flags = NXT_CONF_VLDT_REQUIRED, - }, { - .name = nxt_string("script"), - .type = NXT_CONF_VLDT_STRING, - }, { - .name = nxt_string("index"), - .type = NXT_CONF_VLDT_STRING, + .name = nxt_string("thread_stack_size"), + .type = NXT_CONF_VLDT_INTEGER, + .validator = nxt_conf_vldt_thread_stack_size, }, - NXT_CONF_VLDT_NEXT(nxt_conf_vldt_php_common_members) -}; - + NXT_CONF_VLDT_NEXT(nxt_conf_vldt_common_members)}; -static nxt_conf_vldt_object_t nxt_conf_vldt_perl_members[] = { +static nxt_conf_vldt_object_t nxt_conf_vldt_python_members[] = { { - .name = nxt_string("script"), - .type = NXT_CONF_VLDT_STRING, - .flags = NXT_CONF_VLDT_REQUIRED, - }, { - .name = nxt_string("threads"), - .type = NXT_CONF_VLDT_INTEGER, - .validator = nxt_conf_vldt_threads, - }, { - .name = nxt_string("thread_stack_size"), - .type = NXT_CONF_VLDT_INTEGER, - .validator = nxt_conf_vldt_thread_stack_size, + .name = nxt_string("module"), + .type = NXT_CONF_VLDT_STRING, + .validator = nxt_conf_vldt_targets_exclusive, + .u.string = "module", }, - - NXT_CONF_VLDT_NEXT(nxt_conf_vldt_common_members) -}; - - -static nxt_conf_vldt_object_t nxt_conf_vldt_ruby_members[] = { { - .name = nxt_string("script"), - .type = NXT_CONF_VLDT_STRING, - .flags = NXT_CONF_VLDT_REQUIRED, - }, { - .name = nxt_string("threads"), - .type = NXT_CONF_VLDT_INTEGER, - .validator = nxt_conf_vldt_threads, - }, { - .name = nxt_string("hooks"), - .type = NXT_CONF_VLDT_STRING + .name = nxt_string("callable"), + .type = NXT_CONF_VLDT_STRING, + .validator = nxt_conf_vldt_targets_exclusive, + .u.string = "callable", }, - - NXT_CONF_VLDT_NEXT(nxt_conf_vldt_common_members) -}; - - -static nxt_conf_vldt_object_t nxt_conf_vldt_java_members[] = { - { - .name = nxt_string("classpath"), - .type = NXT_CONF_VLDT_ARRAY, - .validator = nxt_conf_vldt_array_iterator, - .u.array = nxt_conf_vldt_java_classpath, - }, { - .name = nxt_string("webapp"), - .type = NXT_CONF_VLDT_STRING, - .flags = NXT_CONF_VLDT_REQUIRED, - }, { - .name = nxt_string("options"), - .type = NXT_CONF_VLDT_ARRAY, - .validator = nxt_conf_vldt_array_iterator, - .u.array = nxt_conf_vldt_java_option, - }, { - .name = nxt_string("unit_jars"), - .type = NXT_CONF_VLDT_STRING, - }, { - .name = nxt_string("threads"), - .type = NXT_CONF_VLDT_INTEGER, - .validator = nxt_conf_vldt_threads, - }, { - .name = nxt_string("thread_stack_size"), - .type = NXT_CONF_VLDT_INTEGER, - .validator = nxt_conf_vldt_thread_stack_size, - }, - - NXT_CONF_VLDT_NEXT(nxt_conf_vldt_common_members) -}; - - -static nxt_conf_vldt_object_t nxt_conf_vldt_wasm_members[] = { - { - .name = nxt_string("module"), - .type = NXT_CONF_VLDT_STRING, - .flags = NXT_CONF_VLDT_REQUIRED, - }, { - .name = nxt_string("request_handler"), - .type = NXT_CONF_VLDT_STRING, - .flags = NXT_CONF_VLDT_REQUIRED, - },{ - .name = nxt_string("malloc_handler"), - .type = NXT_CONF_VLDT_STRING, - .flags = NXT_CONF_VLDT_REQUIRED, - }, { - .name = nxt_string("free_handler"), - .type = NXT_CONF_VLDT_STRING, - .flags = NXT_CONF_VLDT_REQUIRED, - }, { - .name = nxt_string("module_init_handler"), - .type = NXT_CONF_VLDT_STRING, - }, { - .name = nxt_string("module_end_handler"), - .type = NXT_CONF_VLDT_STRING, - }, { - .name = nxt_string("request_init_handler"), - .type = NXT_CONF_VLDT_STRING, - }, { - .name = nxt_string("request_end_handler"), - .type = NXT_CONF_VLDT_STRING, - }, { - .name = nxt_string("response_end_handler"), - .type = NXT_CONF_VLDT_STRING, - }, { - .name = nxt_string("access"), - .type = NXT_CONF_VLDT_OBJECT, - .validator = nxt_conf_vldt_object, - .u.members = nxt_conf_vldt_wasm_access_members, - }, - - NXT_CONF_VLDT_NEXT(nxt_conf_vldt_common_members) -}; - - -static nxt_conf_vldt_object_t nxt_conf_vldt_wasm_wc_members[] = { { - .name = nxt_string("component"), - .type = NXT_CONF_VLDT_STRING, - .flags = NXT_CONF_VLDT_REQUIRED, - }, { - .name = nxt_string("access"), - .type = NXT_CONF_VLDT_OBJECT, - .validator = nxt_conf_vldt_object, - .u.members = nxt_conf_vldt_wasm_access_members, + .name = nxt_string("factory"), + .type = NXT_CONF_VLDT_BOOLEAN, + .validator = nxt_conf_vldt_targets_exclusive, + .u.string = "factory", }, - - NXT_CONF_VLDT_NEXT(nxt_conf_vldt_common_members) -}; - - -static nxt_conf_vldt_object_t nxt_conf_vldt_wasm_access_members[] = { { - .name = nxt_string("filesystem"), - .type = NXT_CONF_VLDT_ARRAY, + .name = nxt_string("prefix"), + .type = NXT_CONF_VLDT_STRING, + .validator = nxt_conf_vldt_targets_exclusive, + .u.string = "prefix", }, + {.name = nxt_string("targets"), + .type = NXT_CONF_VLDT_OBJECT, + .validator = nxt_conf_vldt_targets, + .u.members = nxt_conf_vldt_python_target_members}, - NXT_CONF_VLDT_END -}; - - -static nxt_conf_vldt_object_t nxt_conf_vldt_common_members[] = { - { - .name = nxt_string("type"), - .type = NXT_CONF_VLDT_STRING, - }, { - .name = nxt_string("limits"), - .type = NXT_CONF_VLDT_OBJECT, - .validator = nxt_conf_vldt_object, - .u.members = nxt_conf_vldt_app_limits_members, - }, { - .name = nxt_string("processes"), - .type = NXT_CONF_VLDT_INTEGER | NXT_CONF_VLDT_OBJECT, - .validator = nxt_conf_vldt_processes, - .u.members = nxt_conf_vldt_app_processes_members, - }, { - .name = nxt_string("user"), - .type = NXT_CONF_VLDT_STRING, - }, { - .name = nxt_string("group"), - .type = NXT_CONF_VLDT_STRING, - }, { - .name = nxt_string("working_directory"), - .type = NXT_CONF_VLDT_STRING, - }, { - .name = nxt_string("environment"), - .type = NXT_CONF_VLDT_OBJECT, - .validator = nxt_conf_vldt_object_iterator, - .u.object = nxt_conf_vldt_environment, - }, { - .name = nxt_string("isolation"), - .type = NXT_CONF_VLDT_OBJECT, - .validator = nxt_conf_vldt_isolation, - .u.members = nxt_conf_vldt_app_isolation_members, - }, { - .name = nxt_string("stdout"), - .type = NXT_CONF_VLDT_STRING, - }, { - .name = nxt_string("stderr"), - .type = NXT_CONF_VLDT_STRING, - }, - - NXT_CONF_VLDT_END -}; - + NXT_CONF_VLDT_NEXT(nxt_conf_vldt_python_common_members)}; -static nxt_conf_vldt_object_t nxt_conf_vldt_app_limits_members[] = { +static nxt_conf_vldt_object_t nxt_conf_vldt_python_target_members[] = { { - .name = nxt_string("timeout"), - .type = NXT_CONF_VLDT_INTEGER, - }, { - .name = nxt_string("requests"), - .type = NXT_CONF_VLDT_INTEGER, - }, { - .name = nxt_string("shm"), - .type = NXT_CONF_VLDT_INTEGER, + .name = nxt_string("module"), + .type = NXT_CONF_VLDT_STRING, + .flags = NXT_CONF_VLDT_REQUIRED, }, - - NXT_CONF_VLDT_END -}; - - -static nxt_conf_vldt_object_t nxt_conf_vldt_app_processes_members[] = { { - .name = nxt_string("spare"), - .type = NXT_CONF_VLDT_INTEGER, - }, { - .name = nxt_string("max"), - .type = NXT_CONF_VLDT_INTEGER, - }, { - .name = nxt_string("idle_timeout"), - .type = NXT_CONF_VLDT_INTEGER, + .name = nxt_string("callable"), + .type = NXT_CONF_VLDT_STRING, + }, + { + .name = nxt_string("factory"), + .type = NXT_CONF_VLDT_BOOLEAN, + }, + { + .name = nxt_string("prefix"), + .type = NXT_CONF_VLDT_STRING, + .validator = nxt_conf_vldt_python_prefix, }, - NXT_CONF_VLDT_END -}; - + NXT_CONF_VLDT_END}; -static nxt_conf_vldt_object_t nxt_conf_vldt_app_isolation_members[] = { +static nxt_conf_vldt_object_t nxt_conf_vldt_python_notargets_members[] = { { - .name = nxt_string("namespaces"), - .type = NXT_CONF_VLDT_OBJECT, - .validator = nxt_conf_vldt_clone_namespaces, - .u.members = nxt_conf_vldt_app_namespaces_members, + .name = nxt_string("module"), + .type = NXT_CONF_VLDT_STRING, + .flags = NXT_CONF_VLDT_REQUIRED, }, - -#if (NXT_HAVE_CLONE_NEWUSER) { - .name = nxt_string("uidmap"), - .type = NXT_CONF_VLDT_ARRAY, - .validator = nxt_conf_vldt_array_iterator, - .u.array = nxt_conf_vldt_clone_uidmap, - }, { - .name = nxt_string("gidmap"), - .type = NXT_CONF_VLDT_ARRAY, - .validator = nxt_conf_vldt_array_iterator, - .u.array = nxt_conf_vldt_clone_gidmap, + .name = nxt_string("callable"), + .type = NXT_CONF_VLDT_STRING, }, -#endif - -#if (NXT_HAVE_ISOLATION_ROOTFS) { - .name = nxt_string("rootfs"), - .type = NXT_CONF_VLDT_STRING, - }, { - .name = nxt_string("automount"), - .type = NXT_CONF_VLDT_OBJECT, - .validator = nxt_conf_vldt_object, - .u.members = nxt_conf_vldt_app_automount_members, + .name = nxt_string("factory"), + .type = NXT_CONF_VLDT_BOOLEAN, }, -#endif - -#if (NXT_HAVE_PR_SET_NO_NEW_PRIVS) { - .name = nxt_string("new_privs"), - .type = NXT_CONF_VLDT_BOOLEAN, + .name = nxt_string("prefix"), + .type = NXT_CONF_VLDT_STRING, + .validator = nxt_conf_vldt_python_prefix, }, -#endif -#if (NXT_HAVE_CGROUP) + NXT_CONF_VLDT_NEXT(nxt_conf_vldt_python_common_members)}; + +static nxt_conf_vldt_object_t nxt_conf_vldt_php_members[] = { { - .name = nxt_string("cgroup"), - .type = NXT_CONF_VLDT_OBJECT, - .validator = nxt_conf_vldt_object, - .u.members = nxt_conf_vldt_app_cgroup_members, + .name = nxt_string("root"), + .type = NXT_CONF_VLDT_ANY_TYPE, + .validator = nxt_conf_vldt_targets_exclusive, + .u.string = "root", }, -#endif + { + .name = nxt_string("script"), + .type = NXT_CONF_VLDT_ANY_TYPE, + .validator = nxt_conf_vldt_targets_exclusive, + .u.string = "script", + }, + { + .name = nxt_string("index"), + .type = NXT_CONF_VLDT_ANY_TYPE, + .validator = nxt_conf_vldt_targets_exclusive, + .u.string = "index", + }, + {.name = nxt_string("targets"), + .type = NXT_CONF_VLDT_OBJECT, + .validator = nxt_conf_vldt_targets, + .u.members = nxt_conf_vldt_php_target_members}, - NXT_CONF_VLDT_END -}; + NXT_CONF_VLDT_NEXT(nxt_conf_vldt_php_common_members)}; + +static nxt_conf_vldt_object_t nxt_conf_vldt_php_common_members[] = { + { + .name = nxt_string("options"), + .type = NXT_CONF_VLDT_OBJECT, + .validator = nxt_conf_vldt_object, + .u.members = nxt_conf_vldt_php_options_members, + }, + + NXT_CONF_VLDT_NEXT(nxt_conf_vldt_common_members)}; +static nxt_conf_vldt_object_t nxt_conf_vldt_php_options_members[] = { + { + .name = nxt_string("file"), + .type = NXT_CONF_VLDT_STRING, + }, + { + .name = nxt_string("admin"), + .type = NXT_CONF_VLDT_OBJECT, + .validator = nxt_conf_vldt_object_iterator, + .u.object = nxt_conf_vldt_php_option, + }, + { + .name = nxt_string("user"), + .type = NXT_CONF_VLDT_OBJECT, + .validator = nxt_conf_vldt_object_iterator, + .u.object = nxt_conf_vldt_php_option, + }, -static nxt_conf_vldt_object_t nxt_conf_vldt_app_namespaces_members[] = { + NXT_CONF_VLDT_END}; + +static nxt_conf_vldt_object_t nxt_conf_vldt_php_target_members[] = { + { + .name = nxt_string("root"), + .type = NXT_CONF_VLDT_STRING, + .flags = NXT_CONF_VLDT_REQUIRED, + }, + { + .name = nxt_string("script"), + .type = NXT_CONF_VLDT_STRING, + }, + { + .name = nxt_string("index"), + .type = NXT_CONF_VLDT_STRING, + }, + + NXT_CONF_VLDT_END}; + +static nxt_conf_vldt_object_t nxt_conf_vldt_php_notargets_members[] = { + { + .name = nxt_string("root"), + .type = NXT_CONF_VLDT_STRING, + .flags = NXT_CONF_VLDT_REQUIRED, + }, + { + .name = nxt_string("script"), + .type = NXT_CONF_VLDT_STRING, + }, + { + .name = nxt_string("index"), + .type = NXT_CONF_VLDT_STRING, + }, + + NXT_CONF_VLDT_NEXT(nxt_conf_vldt_php_common_members)}; + +static nxt_conf_vldt_object_t nxt_conf_vldt_perl_members[] = { + { + .name = nxt_string("script"), + .type = NXT_CONF_VLDT_STRING, + .flags = NXT_CONF_VLDT_REQUIRED, + }, + { + .name = nxt_string("threads"), + .type = NXT_CONF_VLDT_INTEGER, + .validator = nxt_conf_vldt_threads, + }, + { + .name = nxt_string("thread_stack_size"), + .type = NXT_CONF_VLDT_INTEGER, + .validator = nxt_conf_vldt_thread_stack_size, + }, + + NXT_CONF_VLDT_NEXT(nxt_conf_vldt_common_members)}; + +static nxt_conf_vldt_object_t nxt_conf_vldt_ruby_members[] = { + { + .name = nxt_string("script"), + .type = NXT_CONF_VLDT_STRING, + .flags = NXT_CONF_VLDT_REQUIRED, + }, + { + .name = nxt_string("threads"), + .type = NXT_CONF_VLDT_INTEGER, + .validator = nxt_conf_vldt_threads, + }, + {.name = nxt_string("hooks"), .type = NXT_CONF_VLDT_STRING}, + + NXT_CONF_VLDT_NEXT(nxt_conf_vldt_common_members)}; + +static nxt_conf_vldt_object_t nxt_conf_vldt_java_members[] = { + { + .name = nxt_string("classpath"), + .type = NXT_CONF_VLDT_ARRAY, + .validator = nxt_conf_vldt_array_iterator, + .u.array = nxt_conf_vldt_java_classpath, + }, + { + .name = nxt_string("webapp"), + .type = NXT_CONF_VLDT_STRING, + .flags = NXT_CONF_VLDT_REQUIRED, + }, + { + .name = nxt_string("options"), + .type = NXT_CONF_VLDT_ARRAY, + .validator = nxt_conf_vldt_array_iterator, + .u.array = nxt_conf_vldt_java_option, + }, + { + .name = nxt_string("unit_jars"), + .type = NXT_CONF_VLDT_STRING, + }, + { + .name = nxt_string("threads"), + .type = NXT_CONF_VLDT_INTEGER, + .validator = nxt_conf_vldt_threads, + }, + { + .name = nxt_string("thread_stack_size"), + .type = NXT_CONF_VLDT_INTEGER, + .validator = nxt_conf_vldt_thread_stack_size, + }, + + NXT_CONF_VLDT_NEXT(nxt_conf_vldt_common_members)}; + +static nxt_conf_vldt_object_t nxt_conf_vldt_wasm_members[] = { + { + .name = nxt_string("module"), + .type = NXT_CONF_VLDT_STRING, + .flags = NXT_CONF_VLDT_REQUIRED, + }, + { + .name = nxt_string("request_handler"), + .type = NXT_CONF_VLDT_STRING, + .flags = NXT_CONF_VLDT_REQUIRED, + }, + { + .name = nxt_string("malloc_handler"), + .type = NXT_CONF_VLDT_STRING, + .flags = NXT_CONF_VLDT_REQUIRED, + }, + { + .name = nxt_string("free_handler"), + .type = NXT_CONF_VLDT_STRING, + .flags = NXT_CONF_VLDT_REQUIRED, + }, + { + .name = nxt_string("module_init_handler"), + .type = NXT_CONF_VLDT_STRING, + }, + { + .name = nxt_string("module_end_handler"), + .type = NXT_CONF_VLDT_STRING, + }, + { + .name = nxt_string("request_init_handler"), + .type = NXT_CONF_VLDT_STRING, + }, + { + .name = nxt_string("request_end_handler"), + .type = NXT_CONF_VLDT_STRING, + }, + { + .name = nxt_string("response_end_handler"), + .type = NXT_CONF_VLDT_STRING, + }, + { + .name = nxt_string("access"), + .type = NXT_CONF_VLDT_OBJECT, + .validator = nxt_conf_vldt_object, + .u.members = nxt_conf_vldt_wasm_access_members, + }, + + NXT_CONF_VLDT_NEXT(nxt_conf_vldt_common_members)}; + +static nxt_conf_vldt_object_t nxt_conf_vldt_wasm_wc_members[] = { + { + .name = nxt_string("component"), + .type = NXT_CONF_VLDT_STRING, + .flags = NXT_CONF_VLDT_REQUIRED, + }, + { + .name = nxt_string("access"), + .type = NXT_CONF_VLDT_OBJECT, + .validator = nxt_conf_vldt_object, + .u.members = nxt_conf_vldt_wasm_access_members, + }, + + NXT_CONF_VLDT_NEXT(nxt_conf_vldt_common_members)}; + +static nxt_conf_vldt_object_t nxt_conf_vldt_wasm_access_members[] = { + { + .name = nxt_string("filesystem"), + .type = NXT_CONF_VLDT_ARRAY, + }, + + NXT_CONF_VLDT_END}; + +static nxt_conf_vldt_object_t nxt_conf_vldt_common_members[] = { + { + .name = nxt_string("type"), + .type = NXT_CONF_VLDT_STRING, + }, + { + .name = nxt_string("limits"), + .type = NXT_CONF_VLDT_OBJECT, + .validator = nxt_conf_vldt_object, + .u.members = nxt_conf_vldt_app_limits_members, + }, + { + .name = nxt_string("processes"), + .type = NXT_CONF_VLDT_INTEGER | NXT_CONF_VLDT_OBJECT, + .validator = nxt_conf_vldt_processes, + .u.members = nxt_conf_vldt_app_processes_members, + }, + { + .name = nxt_string("user"), + .type = NXT_CONF_VLDT_STRING, + }, + { + .name = nxt_string("group"), + .type = NXT_CONF_VLDT_STRING, + }, + { + .name = nxt_string("working_directory"), + .type = NXT_CONF_VLDT_STRING, + }, + { + .name = nxt_string("environment"), + .type = NXT_CONF_VLDT_OBJECT, + .validator = nxt_conf_vldt_object_iterator, + .u.object = nxt_conf_vldt_environment, + }, + { + .name = nxt_string("isolation"), + .type = NXT_CONF_VLDT_OBJECT, + .validator = nxt_conf_vldt_isolation, + .u.members = nxt_conf_vldt_app_isolation_members, + }, + { + .name = nxt_string("stdout"), + .type = NXT_CONF_VLDT_STRING, + }, + { + .name = nxt_string("stderr"), + .type = NXT_CONF_VLDT_STRING, + }, + + NXT_CONF_VLDT_END}; + +static nxt_conf_vldt_object_t nxt_conf_vldt_app_limits_members[] = { + { + .name = nxt_string("timeout"), + .type = NXT_CONF_VLDT_INTEGER, + }, + { + .name = nxt_string("requests"), + .type = NXT_CONF_VLDT_INTEGER, + }, + { + .name = nxt_string("shm"), + .type = NXT_CONF_VLDT_INTEGER, + }, + + NXT_CONF_VLDT_END}; + +static nxt_conf_vldt_object_t nxt_conf_vldt_app_processes_members[] = { + { + .name = nxt_string("spare"), + .type = NXT_CONF_VLDT_INTEGER, + }, + { + .name = nxt_string("max"), + .type = NXT_CONF_VLDT_INTEGER, + }, + { + .name = nxt_string("idle_timeout"), + .type = NXT_CONF_VLDT_INTEGER, + }, + + NXT_CONF_VLDT_END}; + +static nxt_conf_vldt_object_t nxt_conf_vldt_app_isolation_members[] = { + { + .name = nxt_string("namespaces"), + .type = NXT_CONF_VLDT_OBJECT, + .validator = nxt_conf_vldt_clone_namespaces, + .u.members = nxt_conf_vldt_app_namespaces_members, + }, #if (NXT_HAVE_CLONE_NEWUSER) { - .name = nxt_string("credential"), - .type = NXT_CONF_VLDT_BOOLEAN, + .name = nxt_string("uidmap"), + .type = NXT_CONF_VLDT_ARRAY, + .validator = nxt_conf_vldt_array_iterator, + .u.array = nxt_conf_vldt_clone_uidmap, + }, + { + .name = nxt_string("gidmap"), + .type = NXT_CONF_VLDT_ARRAY, + .validator = nxt_conf_vldt_array_iterator, + .u.array = nxt_conf_vldt_clone_gidmap, + }, +#endif + +#if (NXT_HAVE_ISOLATION_ROOTFS) + { + .name = nxt_string("rootfs"), + .type = NXT_CONF_VLDT_STRING, + }, + { + .name = nxt_string("automount"), + .type = NXT_CONF_VLDT_OBJECT, + .validator = nxt_conf_vldt_object, + .u.members = nxt_conf_vldt_app_automount_members, + }, +#endif + +#if (NXT_HAVE_PR_SET_NO_NEW_PRIVS) + { + .name = nxt_string("new_privs"), + .type = NXT_CONF_VLDT_BOOLEAN, + }, +#endif + +#if (NXT_HAVE_CGROUP) + { + .name = nxt_string("cgroup"), + .type = NXT_CONF_VLDT_OBJECT, + .validator = nxt_conf_vldt_object, + .u.members = nxt_conf_vldt_app_cgroup_members, + }, +#endif + + NXT_CONF_VLDT_END}; + +static nxt_conf_vldt_object_t nxt_conf_vldt_app_namespaces_members[] = { + +#if (NXT_HAVE_CLONE_NEWUSER) + { + .name = nxt_string("credential"), + .type = NXT_CONF_VLDT_BOOLEAN, }, #endif #if (NXT_HAVE_CLONE_NEWPID) { - .name = nxt_string("pid"), - .type = NXT_CONF_VLDT_BOOLEAN, + .name = nxt_string("pid"), + .type = NXT_CONF_VLDT_BOOLEAN, }, #endif #if (NXT_HAVE_CLONE_NEWNET) { - .name = nxt_string("network"), - .type = NXT_CONF_VLDT_BOOLEAN, + .name = nxt_string("network"), + .type = NXT_CONF_VLDT_BOOLEAN, }, #endif #if (NXT_HAVE_CLONE_NEWNS) { - .name = nxt_string("mount"), - .type = NXT_CONF_VLDT_BOOLEAN, + .name = nxt_string("mount"), + .type = NXT_CONF_VLDT_BOOLEAN, }, #endif #if (NXT_HAVE_CLONE_NEWUTS) { - .name = nxt_string("uname"), - .type = NXT_CONF_VLDT_BOOLEAN, + .name = nxt_string("uname"), + .type = NXT_CONF_VLDT_BOOLEAN, }, #endif #if (NXT_HAVE_CLONE_NEWCGROUP) { - .name = nxt_string("cgroup"), - .type = NXT_CONF_VLDT_BOOLEAN, + .name = nxt_string("cgroup"), + .type = NXT_CONF_VLDT_BOOLEAN, }, #endif - NXT_CONF_VLDT_END -}; - + NXT_CONF_VLDT_END}; #if (NXT_HAVE_ISOLATION_ROOTFS) -static nxt_conf_vldt_object_t nxt_conf_vldt_app_automount_members[] = { +static nxt_conf_vldt_object_t nxt_conf_vldt_app_automount_members[] = { + { + .name = nxt_string("language_deps"), + .type = NXT_CONF_VLDT_BOOLEAN, + }, { - .name = nxt_string("language_deps"), - .type = NXT_CONF_VLDT_BOOLEAN, - }, { - .name = nxt_string("tmpfs"), - .type = NXT_CONF_VLDT_BOOLEAN, - }, { - .name = nxt_string("procfs"), - .type = NXT_CONF_VLDT_BOOLEAN, + .name = nxt_string("tmpfs"), + .type = NXT_CONF_VLDT_BOOLEAN, + }, + { + .name = nxt_string("procfs"), + .type = NXT_CONF_VLDT_BOOLEAN, }, - NXT_CONF_VLDT_END -}; + NXT_CONF_VLDT_END}; #endif - #if (NXT_HAVE_CGROUP) -static nxt_conf_vldt_object_t nxt_conf_vldt_app_cgroup_members[] = { +static nxt_conf_vldt_object_t nxt_conf_vldt_app_cgroup_members[] = { { - .name = nxt_string("path"), - .type = NXT_CONF_VLDT_STRING, - .flags = NXT_CONF_VLDT_REQUIRED, - .validator = nxt_conf_vldt_cgroup_path, + .name = nxt_string("path"), + .type = NXT_CONF_VLDT_STRING, + .flags = NXT_CONF_VLDT_REQUIRED, + .validator = nxt_conf_vldt_cgroup_path, }, - NXT_CONF_VLDT_END -}; + NXT_CONF_VLDT_END}; #endif - #if (NXT_HAVE_CLONE_NEWUSER) static nxt_conf_vldt_object_t nxt_conf_vldt_app_procmap_members[] = { { - .name = nxt_string("container"), - .type = NXT_CONF_VLDT_INTEGER, - .flags = NXT_CONF_VLDT_REQUIRED, - }, { - .name = nxt_string("host"), - .type = NXT_CONF_VLDT_INTEGER, - .flags = NXT_CONF_VLDT_REQUIRED, - }, { - .name = nxt_string("size"), - .type = NXT_CONF_VLDT_INTEGER, - .flags = NXT_CONF_VLDT_REQUIRED, + .name = nxt_string("container"), + .type = NXT_CONF_VLDT_INTEGER, + .flags = NXT_CONF_VLDT_REQUIRED, + }, + { + .name = nxt_string("host"), + .type = NXT_CONF_VLDT_INTEGER, + .flags = NXT_CONF_VLDT_REQUIRED, + }, + { + .name = nxt_string("size"), + .type = NXT_CONF_VLDT_INTEGER, + .flags = NXT_CONF_VLDT_REQUIRED, }, - NXT_CONF_VLDT_END -}; + NXT_CONF_VLDT_END}; #endif - -static nxt_conf_vldt_object_t nxt_conf_vldt_upstream_members[] = { +static nxt_conf_vldt_object_t nxt_conf_vldt_upstream_members[] = { { - .name = nxt_string("servers"), - .type = NXT_CONF_VLDT_OBJECT, - .validator = nxt_conf_vldt_object_iterator, - .u.object = nxt_conf_vldt_server, + .name = nxt_string("servers"), + .type = NXT_CONF_VLDT_OBJECT, + .validator = nxt_conf_vldt_object_iterator, + .u.object = nxt_conf_vldt_server, }, - NXT_CONF_VLDT_END -}; - + NXT_CONF_VLDT_END}; -static nxt_conf_vldt_object_t nxt_conf_vldt_upstream_server_members[] = { +static nxt_conf_vldt_object_t nxt_conf_vldt_upstream_server_members[] = { { - .name = nxt_string("weight"), - .type = NXT_CONF_VLDT_NUMBER, - .validator = nxt_conf_vldt_server_weight, + .name = nxt_string("weight"), + .type = NXT_CONF_VLDT_NUMBER, + .validator = nxt_conf_vldt_server_weight, }, - NXT_CONF_VLDT_END -}; - + NXT_CONF_VLDT_END}; -static nxt_conf_vldt_object_t nxt_conf_vldt_access_log_members[] = { +static nxt_conf_vldt_object_t nxt_conf_vldt_access_log_members[] = { { - .name = nxt_string("path"), - .type = NXT_CONF_VLDT_STRING, - }, { - .name = nxt_string("format"), - .type = NXT_CONF_VLDT_STRING, - }, { - .name = nxt_string("if"), - .type = NXT_CONF_VLDT_STRING, - .validator = nxt_conf_vldt_if, + .name = nxt_string("path"), + .type = NXT_CONF_VLDT_STRING, + }, + { + .name = nxt_string("format"), + .type = NXT_CONF_VLDT_STRING, + }, + { + .name = nxt_string("if"), + .type = NXT_CONF_VLDT_STRING, + .validator = nxt_conf_vldt_if, }, - NXT_CONF_VLDT_END -}; - + NXT_CONF_VLDT_END}; -nxt_int_t -nxt_conf_validate(nxt_conf_validation_t *vldt) -{ - nxt_int_t ret; - u_char error[NXT_MAX_ERROR_STR]; +nxt_int_t nxt_conf_validate(nxt_conf_validation_t *vldt) { + nxt_int_t ret; + u_char error[NXT_MAX_ERROR_STR]; - vldt->tstr_state = nxt_tstr_state_new(vldt->pool, 1); - if (nxt_slow_path(vldt->tstr_state == NULL)) { - return NXT_ERROR; - } + vldt->tstr_state = nxt_tstr_state_new(vldt->pool, 1); + if (nxt_slow_path(vldt->tstr_state == NULL)) { + return NXT_ERROR; + } - ret = nxt_conf_vldt_type(vldt, NULL, vldt->conf, NXT_CONF_VLDT_OBJECT); - if (ret != NXT_OK) { - return ret; - } + ret = nxt_conf_vldt_type(vldt, NULL, vldt->conf, NXT_CONF_VLDT_OBJECT); + if (ret != NXT_OK) { + return ret; + } - ret = nxt_conf_vldt_object(vldt, vldt->conf, nxt_conf_vldt_root_members); - if (ret != NXT_OK) { - return ret; - } + ret = nxt_conf_vldt_object(vldt, vldt->conf, nxt_conf_vldt_root_members); + if (ret != NXT_OK) { + return ret; + } - ret = nxt_tstr_state_done(vldt->tstr_state, error); - if (ret != NXT_OK) { - ret = nxt_conf_vldt_error(vldt, "%s", error); - return ret; - } + ret = nxt_tstr_state_done(vldt->tstr_state, error); + if (ret != NXT_OK) { + ret = nxt_conf_vldt_error(vldt, "%s", error); + return ret; + } - return NXT_OK; + return NXT_OK; } +#define NXT_CONF_VLDT_ANY_TYPE_STR \ + "either a null, a boolean, an integer, " \ + "a number, a string, an array, or an object" -#define NXT_CONF_VLDT_ANY_TYPE_STR \ - "either a null, a boolean, an integer, " \ - "a number, a string, an array, or an object" +static nxt_int_t nxt_conf_vldt_type(nxt_conf_validation_t *vldt, + const nxt_str_t *name, + nxt_conf_value_t *value, + nxt_conf_vldt_type_t type) { + u_char *p; + nxt_str_t expected; + nxt_bool_t comma; + nxt_uint_t value_type, n, t; + u_char buf[nxt_length(NXT_CONF_VLDT_ANY_TYPE_STR)]; + + static const nxt_str_t type_name[] = { + nxt_string("a null"), + nxt_string("a boolean"), + nxt_string("an integer number"), + nxt_string("a fractional number"), + nxt_string("a string"), + nxt_string("an array"), + nxt_string("an object"), + }; + + value_type = nxt_conf_type(value); + + if ((1 << value_type) & type) { + return NXT_OK; + } + p = buf; -static nxt_int_t -nxt_conf_vldt_type(nxt_conf_validation_t *vldt, const nxt_str_t *name, - nxt_conf_value_t *value, nxt_conf_vldt_type_t type) -{ - u_char *p; - nxt_str_t expected; - nxt_bool_t comma; - nxt_uint_t value_type, n, t; - u_char buf[nxt_length(NXT_CONF_VLDT_ANY_TYPE_STR)]; - - static const nxt_str_t type_name[] = { - nxt_string("a null"), - nxt_string("a boolean"), - nxt_string("an integer number"), - nxt_string("a fractional number"), - nxt_string("a string"), - nxt_string("an array"), - nxt_string("an object"), - }; - - value_type = nxt_conf_type(value); - - if ((1 << value_type) & type) { - return NXT_OK; - } + n = nxt_popcount(type); - p = buf; + if (n > 1) { + p = nxt_cpymem(p, "either ", 7); + } - n = nxt_popcount(type); + comma = (n > 2); - if (n > 1) { - p = nxt_cpymem(p, "either ", 7); - } + for (;;) { + t = __builtin_ffs(type) - 1; - comma = (n > 2); + p = nxt_cpymem(p, type_name[t].start, type_name[t].length); - for ( ;; ) { - t = __builtin_ffs(type) - 1; + n--; - p = nxt_cpymem(p, type_name[t].start, type_name[t].length); + if (n == 0) { + break; + } - n--; + if (comma) { + *p++ = ','; + } - if (n == 0) { - break; - } + if (n == 1) { + p = nxt_cpymem(p, " or", 3); + } - if (comma) { - *p++ = ','; - } + *p++ = ' '; - if (n == 1) { - p = nxt_cpymem(p, " or", 3); - } + type = type & ~(1 << t); + } - *p++ = ' '; + expected.length = p - buf; + expected.start = buf; - type = type & ~(1 << t); - } + if (name == NULL) { + return nxt_conf_vldt_error(vldt, + "The configuration must be %V, but not %V.", + &expected, &type_name[value_type]); + } - expected.length = p - buf; - expected.start = buf; + return nxt_conf_vldt_error(vldt, "The \"%V\" value must be %V, but not %V.", + name, &expected, &type_name[value_type]); +} - if (name == NULL) { - return nxt_conf_vldt_error(vldt, - "The configuration must be %V, but not %V.", - &expected, &type_name[value_type]); - } +static nxt_int_t nxt_conf_vldt_error(nxt_conf_validation_t *vldt, + const char *fmt, ...) { + u_char *p, *end; + size_t size; + va_list args; + u_char error[NXT_MAX_ERROR_STR]; - return nxt_conf_vldt_error(vldt, - "The \"%V\" value must be %V, but not %V.", - name, &expected, &type_name[value_type]); -} + va_start(args, fmt); + end = nxt_vsprintf(error, error + NXT_MAX_ERROR_STR, fmt, args); + va_end(args); + size = end - error; -static nxt_int_t -nxt_conf_vldt_error(nxt_conf_validation_t *vldt, const char *fmt, ...) -{ - u_char *p, *end; - size_t size; - va_list args; - u_char error[NXT_MAX_ERROR_STR]; - - va_start(args, fmt); - end = nxt_vsprintf(error, error + NXT_MAX_ERROR_STR, fmt, args); - va_end(args); - - size = end - error; - - p = nxt_mp_nget(vldt->pool, size); - if (p == NULL) { - return NXT_ERROR; - } + p = nxt_mp_nget(vldt->pool, size); + if (p == NULL) { + return NXT_ERROR; + } - nxt_memcpy(p, error, size); + nxt_memcpy(p, error, size); - vldt->error.length = size; - vldt->error.start = p; + vldt->error.length = size; + vldt->error.start = p; - return NXT_DECLINED; + return NXT_DECLINED; } - -nxt_inline nxt_int_t -nxt_conf_vldt_unsupported(nxt_conf_validation_t *vldt, nxt_conf_value_t *value, - void *data) -{ - return nxt_conf_vldt_error(vldt, "Unit is built without the \"%s\" " - "option support.", data); +nxt_inline nxt_int_t nxt_conf_vldt_unsupported(nxt_conf_validation_t *vldt, + nxt_conf_value_t *value, + void *data) { + return nxt_conf_vldt_error(vldt, + "Unit is built without the \"%s\" " + "option support.", + data); } +static nxt_int_t nxt_conf_vldt_var(nxt_conf_validation_t *vldt, + const nxt_str_t *name, nxt_str_t *value) { + u_char error[NXT_MAX_ERROR_STR]; -static nxt_int_t -nxt_conf_vldt_var(nxt_conf_validation_t *vldt, const nxt_str_t *name, - nxt_str_t *value) -{ - u_char error[NXT_MAX_ERROR_STR]; - - if (nxt_tstr_test(vldt->tstr_state, value, error) != NXT_OK) { - return nxt_conf_vldt_error(vldt, "%s in the \"%V\" value.", - error, name); - } + if (nxt_tstr_test(vldt->tstr_state, value, error) != NXT_OK) { + return nxt_conf_vldt_error(vldt, "%s in the \"%V\" value.", error, name); + } - return NXT_OK; + return NXT_OK; } +static nxt_int_t nxt_conf_vldt_if(nxt_conf_validation_t *vldt, + nxt_conf_value_t *value, void *data) { + nxt_str_t str; -static nxt_int_t -nxt_conf_vldt_if(nxt_conf_validation_t *vldt, nxt_conf_value_t *value, - void *data) -{ - nxt_str_t str; - - static const nxt_str_t if_str = nxt_string("if"); + static const nxt_str_t if_str = nxt_string("if"); - if (nxt_conf_type(value) != NXT_CONF_STRING) { - return nxt_conf_vldt_error(vldt, "The \"if\" must be a string"); - } + if (nxt_conf_type(value) != NXT_CONF_STRING) { + return nxt_conf_vldt_error(vldt, "The \"if\" must be a string"); + } - nxt_conf_get_string(value, &str); + nxt_conf_get_string(value, &str); - if (str.length == 0) { - return NXT_OK; - } + if (str.length == 0) { + return NXT_OK; + } - if (str.start[0] == '!') { - str.start++; - str.length--; - } + if (str.start[0] == '!') { + str.start++; + str.length--; + } - if (nxt_is_tstr(&str)) { - return nxt_conf_vldt_var(vldt, &if_str, &str); - } + if (nxt_is_tstr(&str)) { + return nxt_conf_vldt_var(vldt, &if_str, &str); + } - return NXT_OK; + return NXT_OK; } - typedef struct { - nxt_mp_t *pool; - nxt_str_t *type; - nxt_lvlhsh_t hash; + nxt_mp_t *pool; + nxt_str_t *type; + nxt_lvlhsh_t hash; } nxt_conf_vldt_mtypes_ctx_t; +static nxt_int_t nxt_conf_vldt_mtypes(nxt_conf_validation_t *vldt, + nxt_conf_value_t *value, void *data) { + nxt_int_t ret; + nxt_conf_vldt_mtypes_ctx_t ctx; -static nxt_int_t -nxt_conf_vldt_mtypes(nxt_conf_validation_t *vldt, nxt_conf_value_t *value, - void *data) -{ - nxt_int_t ret; - nxt_conf_vldt_mtypes_ctx_t ctx; - - ctx.pool = nxt_mp_create(1024, 128, 256, 32); - if (nxt_slow_path(ctx.pool == NULL)) { - return NXT_ERROR; - } + ctx.pool = nxt_mp_create(1024, 128, 256, 32); + if (nxt_slow_path(ctx.pool == NULL)) { + return NXT_ERROR; + } - nxt_lvlhsh_init(&ctx.hash); + nxt_lvlhsh_init(&ctx.hash); - vldt->ctx = &ctx; + vldt->ctx = &ctx; - ret = nxt_conf_vldt_object_iterator(vldt, value, - &nxt_conf_vldt_mtypes_type); + ret = nxt_conf_vldt_object_iterator(vldt, value, &nxt_conf_vldt_mtypes_type); - vldt->ctx = NULL; + vldt->ctx = NULL; - nxt_mp_destroy(ctx.pool); + nxt_mp_destroy(ctx.pool); - return ret; + return ret; } +static nxt_int_t nxt_conf_vldt_mtypes_type(nxt_conf_validation_t *vldt, + nxt_str_t *name, + nxt_conf_value_t *value) { + nxt_int_t ret; + nxt_conf_vldt_mtypes_ctx_t *ctx; + + ret = nxt_conf_vldt_type(vldt, name, value, + NXT_CONF_VLDT_STRING | NXT_CONF_VLDT_ARRAY); + if (ret != NXT_OK) { + return ret; + } -static nxt_int_t -nxt_conf_vldt_mtypes_type(nxt_conf_validation_t *vldt, nxt_str_t *name, - nxt_conf_value_t *value) -{ - nxt_int_t ret; - nxt_conf_vldt_mtypes_ctx_t *ctx; - - ret = nxt_conf_vldt_type(vldt, name, value, - NXT_CONF_VLDT_STRING|NXT_CONF_VLDT_ARRAY); - if (ret != NXT_OK) { - return ret; - } + ctx = vldt->ctx; - ctx = vldt->ctx; + ctx->type = nxt_mp_get(ctx->pool, sizeof(nxt_str_t)); + if (nxt_slow_path(ctx->type == NULL)) { + return NXT_ERROR; + } - ctx->type = nxt_mp_get(ctx->pool, sizeof(nxt_str_t)); - if (nxt_slow_path(ctx->type == NULL)) { - return NXT_ERROR; - } + *ctx->type = *name; - *ctx->type = *name; + if (nxt_conf_type(value) == NXT_CONF_ARRAY) { + return nxt_conf_vldt_array_iterator(vldt, value, + &nxt_conf_vldt_mtypes_extension); + } - if (nxt_conf_type(value) == NXT_CONF_ARRAY) { - return nxt_conf_vldt_array_iterator(vldt, value, - &nxt_conf_vldt_mtypes_extension); - } - - /* NXT_CONF_STRING */ + /* NXT_CONF_STRING */ - return nxt_conf_vldt_mtypes_extension(vldt, value); + return nxt_conf_vldt_mtypes_extension(vldt, value); } +static nxt_int_t nxt_conf_vldt_mtypes_extension(nxt_conf_validation_t *vldt, + nxt_conf_value_t *value) { + nxt_str_t exten, *dup_type; + nxt_conf_vldt_mtypes_ctx_t *ctx; -static nxt_int_t -nxt_conf_vldt_mtypes_extension(nxt_conf_validation_t *vldt, - nxt_conf_value_t *value) -{ - nxt_str_t exten, *dup_type; - nxt_conf_vldt_mtypes_ctx_t *ctx; - - ctx = vldt->ctx; + ctx = vldt->ctx; - if (nxt_conf_type(value) != NXT_CONF_STRING) { - return nxt_conf_vldt_error(vldt, "The \"%V\" MIME type array must " - "contain only strings.", ctx->type); - } + if (nxt_conf_type(value) != NXT_CONF_STRING) { + return nxt_conf_vldt_error(vldt, + "The \"%V\" MIME type array must " + "contain only strings.", + ctx->type); + } - nxt_conf_get_string(value, &exten); + nxt_conf_get_string(value, &exten); - if (exten.length == 0) { - return nxt_conf_vldt_error(vldt, "An empty file extension for " - "the \"%V\" MIME type.", ctx->type); - } + if (exten.length == 0) { + return nxt_conf_vldt_error(vldt, + "An empty file extension for " + "the \"%V\" MIME type.", + ctx->type); + } - dup_type = nxt_http_static_mtype_get(&ctx->hash, &exten); + dup_type = nxt_http_static_mtype_get(&ctx->hash, &exten); - if (dup_type->length != 0) { - return nxt_conf_vldt_error(vldt, "The \"%V\" file extension has been " - "declared for \"%V\" and \"%V\" " - "MIME types at the same time.", - &exten, dup_type, ctx->type); - } + if (dup_type->length != 0) { + return nxt_conf_vldt_error(vldt, + "The \"%V\" file extension has been " + "declared for \"%V\" and \"%V\" " + "MIME types at the same time.", + &exten, dup_type, ctx->type); + } - return nxt_http_static_mtypes_hash_add(ctx->pool, &ctx->hash, &exten, - ctx->type); + return nxt_http_static_mtypes_hash_add(ctx->pool, &ctx->hash, &exten, + ctx->type); } +static nxt_int_t nxt_conf_vldt_listener(nxt_conf_validation_t *vldt, + nxt_str_t *name, + nxt_conf_value_t *value) { + nxt_int_t ret; + nxt_str_t str; + nxt_sockaddr_t *sa; + + if (nxt_slow_path(nxt_str_dup(vldt->pool, &str, name) == NULL)) { + return NXT_ERROR; + } + + sa = nxt_sockaddr_parse(vldt->pool, &str); + if (nxt_slow_path(sa == NULL)) { + return nxt_conf_vldt_error(vldt, "The listener address \"%V\" is invalid.", + name); + } + + ret = nxt_conf_vldt_type(vldt, name, value, NXT_CONF_VLDT_OBJECT); + if (ret != NXT_OK) { + return ret; + } -static nxt_int_t -nxt_conf_vldt_listener(nxt_conf_validation_t *vldt, nxt_str_t *name, - nxt_conf_value_t *value) -{ - nxt_int_t ret; - nxt_str_t str; - nxt_sockaddr_t *sa; - - if (nxt_slow_path(nxt_str_dup(vldt->pool, &str, name) == NULL)) { - return NXT_ERROR; - } - - sa = nxt_sockaddr_parse(vldt->pool, &str); - if (nxt_slow_path(sa == NULL)) { - return nxt_conf_vldt_error(vldt, - "The listener address \"%V\" is invalid.", - name); - } + return nxt_conf_vldt_object(vldt, value, nxt_conf_vldt_listener_members); +} - ret = nxt_conf_vldt_type(vldt, name, value, NXT_CONF_VLDT_OBJECT); - if (ret != NXT_OK) { - return ret; - } +static nxt_int_t nxt_conf_vldt_action(nxt_conf_validation_t *vldt, + nxt_conf_value_t *value, void *data) { + nxt_uint_t i; + nxt_conf_value_t *action; + nxt_conf_vldt_object_t *members; - return nxt_conf_vldt_object(vldt, value, nxt_conf_vldt_listener_members); -} + static const struct { + nxt_str_t name; + nxt_conf_vldt_object_t *members; + } actions[] = { + {nxt_string("pass"), nxt_conf_vldt_pass_action_members}, + {nxt_string("return"), nxt_conf_vldt_return_action_members}, + {nxt_string("share"), nxt_conf_vldt_share_action_members}, + {nxt_string("proxy"), nxt_conf_vldt_proxy_action_members}, + }; -static nxt_int_t -nxt_conf_vldt_action(nxt_conf_validation_t *vldt, nxt_conf_value_t *value, - void *data) -{ - nxt_uint_t i; - nxt_conf_value_t *action; - nxt_conf_vldt_object_t *members; - - static const struct { - nxt_str_t name; - nxt_conf_vldt_object_t *members; - - } actions[] = { - { nxt_string("pass"), nxt_conf_vldt_pass_action_members }, - { nxt_string("return"), nxt_conf_vldt_return_action_members }, - { nxt_string("share"), nxt_conf_vldt_share_action_members }, - { nxt_string("proxy"), nxt_conf_vldt_proxy_action_members }, - }; - - members = NULL; - - for (i = 0; i < nxt_nitems(actions); i++) { - action = nxt_conf_get_object_member(value, &actions[i].name, NULL); - - if (action == NULL) { - continue; - } + members = NULL; - if (members != NULL) { - return nxt_conf_vldt_error(vldt, "The \"action\" object must have " - "just one of \"pass\", \"return\", " - "\"share\", or \"proxy\" options set."); - } + for (i = 0; i < nxt_nitems(actions); i++) { + action = nxt_conf_get_object_member(value, &actions[i].name, NULL); - members = actions[i].members; + if (action == NULL) { + continue; } - if (members == NULL) { - return nxt_conf_vldt_error(vldt, "The \"action\" object must have " - "either \"pass\", \"return\", \"share\", " - "or \"proxy\" option set."); + if (members != NULL) { + return nxt_conf_vldt_error(vldt, "The \"action\" object must have " + "just one of \"pass\", \"return\", " + "\"share\", or \"proxy\" options set."); } - return nxt_conf_vldt_object(vldt, value, members); -} + members = actions[i].members; + } + if (members == NULL) { + return nxt_conf_vldt_error(vldt, "The \"action\" object must have " + "either \"pass\", \"return\", \"share\", " + "or \"proxy\" option set."); + } -static nxt_int_t -nxt_conf_vldt_pass(nxt_conf_validation_t *vldt, nxt_conf_value_t *value, - void *data) -{ - nxt_str_t pass; - nxt_int_t ret; - nxt_str_t segments[3]; + return nxt_conf_vldt_object(vldt, value, members); +} - static const nxt_str_t targets_str = nxt_string("targets"); +static nxt_int_t nxt_conf_vldt_pass(nxt_conf_validation_t *vldt, + nxt_conf_value_t *value, void *data) { + nxt_str_t pass; + nxt_int_t ret; + nxt_str_t segments[3]; - nxt_conf_get_string(value, &pass); + static const nxt_str_t targets_str = nxt_string("targets"); - ret = nxt_http_pass_segments(vldt->pool, &pass, segments, 3); + nxt_conf_get_string(value, &pass); - if (ret != NXT_OK) { - if (ret == NXT_DECLINED) { - return nxt_conf_vldt_error(vldt, "Request \"pass\" value \"%V\" " - "is invalid.", &pass); - } + ret = nxt_http_pass_segments(vldt->pool, &pass, segments, 3); - return NXT_ERROR; + if (ret != NXT_OK) { + if (ret == NXT_DECLINED) { + return nxt_conf_vldt_error(vldt, + "Request \"pass\" value \"%V\" " + "is invalid.", + &pass); } - if (nxt_str_eq(&segments[0], "applications", 12)) { + return NXT_ERROR; + } - if (segments[1].length == 0) { - goto error; - } + if (nxt_str_eq(&segments[0], "applications", 12)) { - value = nxt_conf_get_object_member(vldt->conf, &segments[0], NULL); + if (segments[1].length == 0) { + goto error; + } - if (value == NULL) { - goto error; - } + value = nxt_conf_get_object_member(vldt->conf, &segments[0], NULL); - value = nxt_conf_get_object_member(value, &segments[1], NULL); + if (value == NULL) { + goto error; + } - if (value == NULL) { - goto error; - } + value = nxt_conf_get_object_member(value, &segments[1], NULL); - if (segments[2].length > 0) { - value = nxt_conf_get_object_member(value, &targets_str, NULL); + if (value == NULL) { + goto error; + } - if (value == NULL) { - goto error; - } + if (segments[2].length > 0) { + value = nxt_conf_get_object_member(value, &targets_str, NULL); - value = nxt_conf_get_object_member(value, &segments[2], NULL); + if (value == NULL) { + goto error; + } - if (value == NULL) { - goto error; - } - } + value = nxt_conf_get_object_member(value, &segments[2], NULL); - return NXT_OK; + if (value == NULL) { + goto error; + } } - if (nxt_str_eq(&segments[0], "upstreams", 9)) { + return NXT_OK; + } - if (segments[1].length == 0 || segments[2].length != 0) { - goto error; - } + if (nxt_str_eq(&segments[0], "upstreams", 9)) { - value = nxt_conf_get_object_member(vldt->conf, &segments[0], NULL); + if (segments[1].length == 0 || segments[2].length != 0) { + goto error; + } - if (value == NULL) { - goto error; - } + value = nxt_conf_get_object_member(vldt->conf, &segments[0], NULL); - value = nxt_conf_get_object_member(value, &segments[1], NULL); + if (value == NULL) { + goto error; + } - if (value == NULL) { - goto error; - } + value = nxt_conf_get_object_member(value, &segments[1], NULL); - return NXT_OK; + if (value == NULL) { + goto error; } - if (nxt_str_eq(&segments[0], "routes", 6)) { + return NXT_OK; + } - if (segments[2].length != 0) { - goto error; - } + if (nxt_str_eq(&segments[0], "routes", 6)) { - value = nxt_conf_get_object_member(vldt->conf, &segments[0], NULL); + if (segments[2].length != 0) { + goto error; + } - if (value == NULL) { - goto error; - } + value = nxt_conf_get_object_member(vldt->conf, &segments[0], NULL); - if (segments[1].length == 0) { - if (nxt_conf_type(value) != NXT_CONF_ARRAY) { - goto error; - } + if (value == NULL) { + goto error; + } - return NXT_OK; - } + if (segments[1].length == 0) { + if (nxt_conf_type(value) != NXT_CONF_ARRAY) { + goto error; + } - if (nxt_conf_type(value) != NXT_CONF_OBJECT) { - goto error; - } + return NXT_OK; + } - value = nxt_conf_get_object_member(value, &segments[1], NULL); + if (nxt_conf_type(value) != NXT_CONF_OBJECT) { + goto error; + } - if (value == NULL) { - goto error; - } + value = nxt_conf_get_object_member(value, &segments[1], NULL); - return NXT_OK; + if (value == NULL) { + goto error; } + return NXT_OK; + } + error: - return nxt_conf_vldt_error(vldt, "Request \"pass\" points to invalid " - "location \"%V\".", &pass); + return nxt_conf_vldt_error(vldt, + "Request \"pass\" points to invalid " + "location \"%V\".", + &pass); } +static nxt_int_t nxt_conf_vldt_return(nxt_conf_validation_t *vldt, + nxt_conf_value_t *value, void *data) { + int64_t status; -static nxt_int_t -nxt_conf_vldt_return(nxt_conf_validation_t *vldt, nxt_conf_value_t *value, - void *data) -{ - int64_t status; - - status = nxt_conf_get_number(value); + status = nxt_conf_get_number(value); - if (status < NXT_HTTP_INVALID || status > NXT_HTTP_STATUS_MAX) { - return nxt_conf_vldt_error(vldt, "The \"return\" value is out of " - "allowed HTTP status code range 0-999."); - } + if (status < NXT_HTTP_INVALID || status > NXT_HTTP_STATUS_MAX) { + return nxt_conf_vldt_error(vldt, "The \"return\" value is out of " + "allowed HTTP status code range 0-999."); + } - return NXT_OK; + return NXT_OK; } - -static nxt_int_t -nxt_conf_vldt_share(nxt_conf_validation_t *vldt, nxt_conf_value_t *value, - void *data) -{ - if (nxt_conf_type(value) == NXT_CONF_ARRAY) { - if (nxt_conf_array_elements_count(value) == 0) { - return nxt_conf_vldt_error(vldt, "The \"share\" array " +static nxt_int_t nxt_conf_vldt_share(nxt_conf_validation_t *vldt, + nxt_conf_value_t *value, void *data) { + if (nxt_conf_type(value) == NXT_CONF_ARRAY) { + if (nxt_conf_array_elements_count(value) == 0) { + return nxt_conf_vldt_error(vldt, "The \"share\" array " "must contain at least one element."); - } - - return nxt_conf_vldt_array_iterator(vldt, value, - &nxt_conf_vldt_share_element); } - /* NXT_CONF_STRING */ + return nxt_conf_vldt_array_iterator(vldt, value, + &nxt_conf_vldt_share_element); + } - return nxt_conf_vldt_share_element(vldt, value); -} + /* NXT_CONF_STRING */ + return nxt_conf_vldt_share_element(vldt, value); +} -static nxt_int_t -nxt_conf_vldt_share_element(nxt_conf_validation_t *vldt, - nxt_conf_value_t *value) -{ - nxt_str_t str; +static nxt_int_t nxt_conf_vldt_share_element(nxt_conf_validation_t *vldt, + nxt_conf_value_t *value) { + nxt_str_t str; - static const nxt_str_t share = nxt_string("share"); + static const nxt_str_t share = nxt_string("share"); - if (nxt_conf_type(value) != NXT_CONF_STRING) { - return nxt_conf_vldt_error(vldt, "The \"share\" array must " - "contain only string values."); - } + if (nxt_conf_type(value) != NXT_CONF_STRING) { + return nxt_conf_vldt_error(vldt, "The \"share\" array must " + "contain only string values."); + } - nxt_conf_get_string(value, &str); + nxt_conf_get_string(value, &str); - if (nxt_is_tstr(&str)) { - return nxt_conf_vldt_var(vldt, &share, &str); - } + if (nxt_is_tstr(&str)) { + return nxt_conf_vldt_var(vldt, &share, &str); + } - return NXT_OK; + return NXT_OK; } +static nxt_int_t nxt_conf_vldt_proxy(nxt_conf_validation_t *vldt, + nxt_conf_value_t *value, void *data) { + nxt_str_t name, *ret; + nxt_sockaddr_t *sa; -static nxt_int_t -nxt_conf_vldt_proxy(nxt_conf_validation_t *vldt, nxt_conf_value_t *value, - void *data) -{ - nxt_str_t name, *ret; - nxt_sockaddr_t *sa; - - ret = nxt_conf_get_string_dup(value, vldt->pool, &name); - if (nxt_slow_path(ret == NULL)) { - return NXT_ERROR; - } + ret = nxt_conf_get_string_dup(value, vldt->pool, &name); + if (nxt_slow_path(ret == NULL)) { + return NXT_ERROR; + } - if (nxt_str_start(&name, "http://", 7)) { - name.length -= 7; - name.start += 7; + if (nxt_str_start(&name, "http://", 7)) { + name.length -= 7; + name.start += 7; - sa = nxt_sockaddr_parse(vldt->pool, &name); - if (sa != NULL) { - return NXT_OK; - } + sa = nxt_sockaddr_parse(vldt->pool, &name); + if (sa != NULL) { + return NXT_OK; } + } - return nxt_conf_vldt_error(vldt, "The \"proxy\" address is invalid \"%V\"", - &name); + return nxt_conf_vldt_error(vldt, "The \"proxy\" address is invalid \"%V\"", + &name); } +static nxt_int_t nxt_conf_vldt_python(nxt_conf_validation_t *vldt, + nxt_conf_value_t *value, void *data) { + nxt_conf_value_t *targets; -static nxt_int_t -nxt_conf_vldt_python(nxt_conf_validation_t *vldt, nxt_conf_value_t *value, - void *data) -{ - nxt_conf_value_t *targets; - - static const nxt_str_t targets_str = nxt_string("targets"); + static const nxt_str_t targets_str = nxt_string("targets"); - targets = nxt_conf_get_object_member(value, &targets_str, NULL); + targets = nxt_conf_get_object_member(value, &targets_str, NULL); - if (targets != NULL) { - return nxt_conf_vldt_object(vldt, value, nxt_conf_vldt_python_members); - } + if (targets != NULL) { + return nxt_conf_vldt_object(vldt, value, nxt_conf_vldt_python_members); + } - return nxt_conf_vldt_object(vldt, value, - nxt_conf_vldt_python_notargets_members); + return nxt_conf_vldt_object(vldt, value, + nxt_conf_vldt_python_notargets_members); } +static nxt_int_t nxt_conf_vldt_python_path(nxt_conf_validation_t *vldt, + nxt_conf_value_t *value, + void *data) { + if (nxt_conf_type(value) == NXT_CONF_ARRAY) { + return nxt_conf_vldt_array_iterator(vldt, value, + &nxt_conf_vldt_python_path_element); + } -static nxt_int_t -nxt_conf_vldt_python_path(nxt_conf_validation_t *vldt, - nxt_conf_value_t *value, void *data) -{ - if (nxt_conf_type(value) == NXT_CONF_ARRAY) { - return nxt_conf_vldt_array_iterator(vldt, value, - &nxt_conf_vldt_python_path_element); - } - - /* NXT_CONF_STRING */ + /* NXT_CONF_STRING */ - return NXT_OK; + return NXT_OK; } +static nxt_int_t nxt_conf_vldt_python_path_element(nxt_conf_validation_t *vldt, + nxt_conf_value_t *value) { + if (nxt_conf_type(value) != NXT_CONF_STRING) { + return nxt_conf_vldt_error(vldt, "The \"path\" array must contain " + "only string values."); + } -static nxt_int_t -nxt_conf_vldt_python_path_element(nxt_conf_validation_t *vldt, - nxt_conf_value_t *value) -{ - if (nxt_conf_type(value) != NXT_CONF_STRING) { - return nxt_conf_vldt_error(vldt, "The \"path\" array must contain " - "only string values."); - } - - return NXT_OK; + return NXT_OK; } +static nxt_int_t nxt_conf_vldt_python_protocol(nxt_conf_validation_t *vldt, + nxt_conf_value_t *value, + void *data) { + nxt_str_t proto; -static nxt_int_t -nxt_conf_vldt_python_protocol(nxt_conf_validation_t *vldt, - nxt_conf_value_t *value, void *data) -{ - nxt_str_t proto; - - static const nxt_str_t wsgi = nxt_string("wsgi"); - static const nxt_str_t asgi = nxt_string("asgi"); + static const nxt_str_t wsgi = nxt_string("wsgi"); + static const nxt_str_t asgi = nxt_string("asgi"); - nxt_conf_get_string(value, &proto); + nxt_conf_get_string(value, &proto); - if (nxt_strstr_eq(&proto, &wsgi) || nxt_strstr_eq(&proto, &asgi)) { - return NXT_OK; - } + if (nxt_strstr_eq(&proto, &wsgi) || nxt_strstr_eq(&proto, &asgi)) { + return NXT_OK; + } - return nxt_conf_vldt_error(vldt, "The \"protocol\" can either be " - "\"wsgi\" or \"asgi\"."); + return nxt_conf_vldt_error(vldt, "The \"protocol\" can either be " + "\"wsgi\" or \"asgi\"."); } +static nxt_int_t nxt_conf_vldt_python_prefix(nxt_conf_validation_t *vldt, + nxt_conf_value_t *value, + void *data) { + nxt_str_t prefix; -static nxt_int_t -nxt_conf_vldt_python_prefix(nxt_conf_validation_t *vldt, - nxt_conf_value_t *value, void *data) -{ - nxt_str_t prefix; - - if (nxt_conf_type(value) != NXT_CONF_STRING) { - return nxt_conf_vldt_error(vldt, "The \"prefix\" must be a string " - "beginning with \"/\"."); - } + if (nxt_conf_type(value) != NXT_CONF_STRING) { + return nxt_conf_vldt_error(vldt, "The \"prefix\" must be a string " + "beginning with \"/\"."); + } - nxt_conf_get_string(value, &prefix); + nxt_conf_get_string(value, &prefix); - if (!nxt_strchr_start(&prefix, '/')) { - return nxt_conf_vldt_error(vldt, "The \"prefix\" must be a string " - "beginning with \"/\"."); - } + if (!nxt_strchr_start(&prefix, '/')) { + return nxt_conf_vldt_error(vldt, "The \"prefix\" must be a string " + "beginning with \"/\"."); + } - return NXT_OK; + return NXT_OK; } -static nxt_int_t -nxt_conf_vldt_listen_threads(nxt_conf_validation_t *vldt, - nxt_conf_value_t *value, void *data) -{ - int64_t threads; +static nxt_int_t nxt_conf_vldt_listen_threads(nxt_conf_validation_t *vldt, + nxt_conf_value_t *value, + void *data) { + int64_t threads; - threads = nxt_conf_get_number(value); + threads = nxt_conf_get_number(value); - if (threads < 1) { - return nxt_conf_vldt_error(vldt, "The \"listen_threads\" number must " - "be equal to or greater than 1."); - } + if (threads < 1) { + return nxt_conf_vldt_error(vldt, "The \"listen_threads\" number must " + "be equal to or greater than 1."); + } - if (threads > NXT_INT32_T_MAX) { - return nxt_conf_vldt_error(vldt, "The \"listen_threads\" number must " - "not exceed %d.", NXT_INT32_T_MAX); - } + if (threads > NXT_INT32_T_MAX) { + return nxt_conf_vldt_error(vldt, + "The \"listen_threads\" number must " + "not exceed %d.", + NXT_INT32_T_MAX); + } - return NXT_OK; + return NXT_OK; } +static nxt_int_t nxt_conf_vldt_threads(nxt_conf_validation_t *vldt, + nxt_conf_value_t *value, void *data) { + int64_t threads; -static nxt_int_t -nxt_conf_vldt_threads(nxt_conf_validation_t *vldt, nxt_conf_value_t *value, - void *data) -{ - int64_t threads; - - threads = nxt_conf_get_number(value); + threads = nxt_conf_get_number(value); - if (threads < 1) { - return nxt_conf_vldt_error(vldt, "The \"threads\" number must be " - "equal to or greater than 1."); - } + if (threads < 1) { + return nxt_conf_vldt_error(vldt, "The \"threads\" number must be " + "equal to or greater than 1."); + } - if (threads > NXT_INT32_T_MAX) { - return nxt_conf_vldt_error(vldt, "The \"threads\" number must " - "not exceed %d.", NXT_INT32_T_MAX); - } + if (threads > NXT_INT32_T_MAX) { + return nxt_conf_vldt_error(vldt, + "The \"threads\" number must " + "not exceed %d.", + NXT_INT32_T_MAX); + } - return NXT_OK; + return NXT_OK; } +static nxt_int_t nxt_conf_vldt_thread_stack_size(nxt_conf_validation_t *vldt, + nxt_conf_value_t *value, + void *data) { + int64_t size, min_size; -static nxt_int_t -nxt_conf_vldt_thread_stack_size(nxt_conf_validation_t *vldt, - nxt_conf_value_t *value, void *data) -{ - int64_t size, min_size; - - size = nxt_conf_get_number(value); - min_size = sysconf(_SC_THREAD_STACK_MIN); - - if (size < min_size) { - return nxt_conf_vldt_error(vldt, "The \"thread_stack_size\" number " - "must be equal to or greater than %d.", - min_size); - } + size = nxt_conf_get_number(value); + min_size = sysconf(_SC_THREAD_STACK_MIN); - if ((size % nxt_pagesize) != 0) { - return nxt_conf_vldt_error(vldt, "The \"thread_stack_size\" number " - "must be a multiple of the system page size (%d).", - nxt_pagesize); - } + if (size < min_size) { + return nxt_conf_vldt_error(vldt, + "The \"thread_stack_size\" number " + "must be equal to or greater than %d.", + min_size); + } - return NXT_OK; -} + if ((size % nxt_pagesize) != 0) { + return nxt_conf_vldt_error( + vldt, + "The \"thread_stack_size\" number " + "must be a multiple of the system page size (%d).", + nxt_pagesize); + } + return NXT_OK; +} -static nxt_int_t -nxt_conf_vldt_routes(nxt_conf_validation_t *vldt, nxt_conf_value_t *value, - void *data) -{ - if (nxt_conf_type(value) == NXT_CONF_ARRAY) { - return nxt_conf_vldt_array_iterator(vldt, value, - &nxt_conf_vldt_route); - } +static nxt_int_t nxt_conf_vldt_routes(nxt_conf_validation_t *vldt, + nxt_conf_value_t *value, void *data) { + if (nxt_conf_type(value) == NXT_CONF_ARRAY) { + return nxt_conf_vldt_array_iterator(vldt, value, &nxt_conf_vldt_route); + } - /* NXT_CONF_OBJECT */ + /* NXT_CONF_OBJECT */ - return nxt_conf_vldt_object_iterator(vldt, value, - &nxt_conf_vldt_routes_member); + return nxt_conf_vldt_object_iterator(vldt, value, + &nxt_conf_vldt_routes_member); } +static nxt_int_t nxt_conf_vldt_routes_member(nxt_conf_validation_t *vldt, + nxt_str_t *name, + nxt_conf_value_t *value) { + nxt_int_t ret; -static nxt_int_t -nxt_conf_vldt_routes_member(nxt_conf_validation_t *vldt, nxt_str_t *name, - nxt_conf_value_t *value) -{ - nxt_int_t ret; - - ret = nxt_conf_vldt_type(vldt, name, value, NXT_CONF_VLDT_ARRAY); + ret = nxt_conf_vldt_type(vldt, name, value, NXT_CONF_VLDT_ARRAY); - if (ret != NXT_OK) { - return ret; - } + if (ret != NXT_OK) { + return ret; + } - return nxt_conf_vldt_array_iterator(vldt, value, &nxt_conf_vldt_route); + return nxt_conf_vldt_array_iterator(vldt, value, &nxt_conf_vldt_route); } +static nxt_int_t nxt_conf_vldt_route(nxt_conf_validation_t *vldt, + nxt_conf_value_t *value) { + if (nxt_conf_type(value) != NXT_CONF_OBJECT) { + return nxt_conf_vldt_error(vldt, "The \"routes\" array must contain " + "only object values."); + } -static nxt_int_t -nxt_conf_vldt_route(nxt_conf_validation_t *vldt, nxt_conf_value_t *value) -{ - if (nxt_conf_type(value) != NXT_CONF_OBJECT) { - return nxt_conf_vldt_error(vldt, "The \"routes\" array must contain " - "only object values."); - } - - return nxt_conf_vldt_object(vldt, value, nxt_conf_vldt_route_members); + return nxt_conf_vldt_object(vldt, value, nxt_conf_vldt_route_members); } +static nxt_int_t nxt_conf_vldt_match_patterns(nxt_conf_validation_t *vldt, + nxt_conf_value_t *value, + void *data) { + nxt_int_t ret; -static nxt_int_t -nxt_conf_vldt_match_patterns(nxt_conf_validation_t *vldt, - nxt_conf_value_t *value, void *data) -{ - nxt_int_t ret; - - vldt->ctx = data; + vldt->ctx = data; - if (nxt_conf_type(value) == NXT_CONF_ARRAY) { - ret = nxt_conf_vldt_array_iterator(vldt, value, - &nxt_conf_vldt_match_pattern); + if (nxt_conf_type(value) == NXT_CONF_ARRAY) { + ret = + nxt_conf_vldt_array_iterator(vldt, value, &nxt_conf_vldt_match_pattern); - } else { - /* NXT_CONF_STRING */ - ret = nxt_conf_vldt_match_pattern(vldt, value); - } + } else { + /* NXT_CONF_STRING */ + ret = nxt_conf_vldt_match_pattern(vldt, value); + } - vldt->ctx = NULL; + vldt->ctx = NULL; - return ret; + return ret; } - -static nxt_int_t -nxt_conf_vldt_match_pattern(nxt_conf_validation_t *vldt, - nxt_conf_value_t *value) -{ - nxt_str_t pattern; - nxt_uint_t i, first, last; +static nxt_int_t nxt_conf_vldt_match_pattern(nxt_conf_validation_t *vldt, + nxt_conf_value_t *value) { + nxt_str_t pattern; + nxt_uint_t i, first, last; #if (NXT_HAVE_REGEX) - nxt_regex_t *re; - nxt_regex_err_t err; + nxt_regex_t *re; + nxt_regex_err_t err; #endif - if (nxt_conf_type(value) != NXT_CONF_STRING) { - return nxt_conf_vldt_error(vldt, "The \"match\" pattern for \"%s\" " - "must be strings.", vldt->ctx); - } + if (nxt_conf_type(value) != NXT_CONF_STRING) { + return nxt_conf_vldt_error(vldt, + "The \"match\" pattern for \"%s\" " + "must be strings.", + vldt->ctx); + } - nxt_conf_get_string(value, &pattern); + nxt_conf_get_string(value, &pattern); - if (pattern.length == 0) { - return NXT_OK; - } + if (pattern.length == 0) { + return NXT_OK; + } - first = (pattern.start[0] == '!'); + first = (pattern.start[0] == '!'); - if (first < pattern.length && pattern.start[first] == '~') { + if (first < pattern.length && pattern.start[first] == '~') { #if (NXT_HAVE_REGEX) - pattern.start += first + 1; - pattern.length -= first + 1; - - re = nxt_regex_compile(vldt->pool, &pattern, &err); - if (nxt_slow_path(re == NULL)) { - if (err.offset < pattern.length) { - return nxt_conf_vldt_error(vldt, "Invalid regular expression: " - "%s at offset %d", - err.msg, err.offset); - } - - return nxt_conf_vldt_error(vldt, "Invalid regular expression: %s", - err.msg); - } + pattern.start += first + 1; + pattern.length -= first + 1; + + re = nxt_regex_compile(vldt->pool, &pattern, &err); + if (nxt_slow_path(re == NULL)) { + if (err.offset < pattern.length) { + return nxt_conf_vldt_error(vldt, + "Invalid regular expression: " + "%s at offset %d", + err.msg, err.offset); + } - return NXT_OK; + return nxt_conf_vldt_error(vldt, "Invalid regular expression: %s", + err.msg); + } + + return NXT_OK; #else - return nxt_conf_vldt_error(vldt, "Unit is built without support of " - "regular expressions: \"--no-regex\" " - "./configure option was set."); + return nxt_conf_vldt_error(vldt, "Unit is built without support of " + "regular expressions: \"--no-regex\" " + "./configure option was set."); #endif - } + } - last = pattern.length - 1; + last = pattern.length - 1; - for (i = first; i < last; i++) { - if (pattern.start[i] == '*' && pattern.start[i + 1] == '*') { - return nxt_conf_vldt_error(vldt, "The \"match\" pattern must " + for (i = first; i < last; i++) { + if (pattern.start[i] == '*' && pattern.start[i + 1] == '*') { + return nxt_conf_vldt_error(vldt, "The \"match\" pattern must " "not contain double \"*\" markers."); - } } + } - return NXT_OK; + return NXT_OK; } +static nxt_int_t +nxt_conf_vldt_match_encoded_patterns_sets(nxt_conf_validation_t *vldt, + nxt_conf_value_t *value, void *data) { + if (nxt_conf_type(value) == NXT_CONF_ARRAY) { + return nxt_conf_vldt_array_iterator( + vldt, value, &nxt_conf_vldt_match_encoded_patterns_set); + } -static nxt_int_t nxt_conf_vldt_match_encoded_patterns_sets( - nxt_conf_validation_t *vldt, nxt_conf_value_t *value, void *data) -{ - if (nxt_conf_type(value) == NXT_CONF_ARRAY) { - return nxt_conf_vldt_array_iterator(vldt, value, - &nxt_conf_vldt_match_encoded_patterns_set); - } - - /* NXT_CONF_OBJECT */ + /* NXT_CONF_OBJECT */ - return nxt_conf_vldt_match_encoded_patterns_set(vldt, value); + return nxt_conf_vldt_match_encoded_patterns_set(vldt, value); } +static nxt_int_t +nxt_conf_vldt_match_encoded_patterns_set(nxt_conf_validation_t *vldt, + nxt_conf_value_t *value) { + if (nxt_conf_type(value) != NXT_CONF_OBJECT) { + return nxt_conf_vldt_error(vldt, "The \"match\" pattern for " + "\"arguments\" must be an object."); + } -static nxt_int_t nxt_conf_vldt_match_encoded_patterns_set( - nxt_conf_validation_t *vldt, nxt_conf_value_t *value) -{ - if (nxt_conf_type(value) != NXT_CONF_OBJECT) { - return nxt_conf_vldt_error(vldt, "The \"match\" pattern for " - "\"arguments\" must be an object."); - } - - return nxt_conf_vldt_object_iterator(vldt, value, - &nxt_conf_vldt_match_encoded_patterns_set_member); + return nxt_conf_vldt_object_iterator( + vldt, value, &nxt_conf_vldt_match_encoded_patterns_set_member); } +static nxt_int_t nxt_conf_vldt_match_encoded_patterns_set_member( + nxt_conf_validation_t *vldt, nxt_str_t *name, nxt_conf_value_t *value) { + u_char *p, *end; -static nxt_int_t -nxt_conf_vldt_match_encoded_patterns_set_member(nxt_conf_validation_t *vldt, - nxt_str_t *name, nxt_conf_value_t *value) -{ - u_char *p, *end; - - if (nxt_slow_path(name->length == 0)) { - return nxt_conf_vldt_error(vldt, "The \"match\" pattern objects must " - "not contain empty member names."); - } + if (nxt_slow_path(name->length == 0)) { + return nxt_conf_vldt_error(vldt, "The \"match\" pattern objects must " + "not contain empty member names."); + } - p = nxt_mp_nget(vldt->pool, name->length); - if (nxt_slow_path(p == NULL)) { - return NXT_ERROR; - } + p = nxt_mp_nget(vldt->pool, name->length); + if (nxt_slow_path(p == NULL)) { + return NXT_ERROR; + } - end = nxt_decode_uri(p, name->start, name->length); - if (nxt_slow_path(end == NULL)) { - return nxt_conf_vldt_error(vldt, "The \"match\" pattern for " - "\"arguments\" is encoded but is invalid."); - } + end = nxt_decode_uri(p, name->start, name->length); + if (nxt_slow_path(end == NULL)) { + return nxt_conf_vldt_error(vldt, + "The \"match\" pattern for " + "\"arguments\" is encoded but is invalid."); + } - return nxt_conf_vldt_match_encoded_patterns(vldt, value, - (void *) "arguments"); + return nxt_conf_vldt_match_encoded_patterns(vldt, value, (void *)"arguments"); } - static nxt_int_t nxt_conf_vldt_match_encoded_patterns(nxt_conf_validation_t *vldt, - nxt_conf_value_t *value, void *data) -{ - nxt_int_t ret; + nxt_conf_value_t *value, void *data) { + nxt_int_t ret; - vldt->ctx = data; + vldt->ctx = data; - if (nxt_conf_type(value) == NXT_CONF_ARRAY) { - ret = nxt_conf_vldt_array_iterator(vldt, value, - &nxt_conf_vldt_match_encoded_pattern); + if (nxt_conf_type(value) == NXT_CONF_ARRAY) { + ret = nxt_conf_vldt_array_iterator(vldt, value, + &nxt_conf_vldt_match_encoded_pattern); - } else { - /* NXT_CONF_STRING */ - ret = nxt_conf_vldt_match_encoded_pattern(vldt, value); - } + } else { + /* NXT_CONF_STRING */ + ret = nxt_conf_vldt_match_encoded_pattern(vldt, value); + } - vldt->ctx = NULL; + vldt->ctx = NULL; - return ret; + return ret; } - static nxt_int_t nxt_conf_vldt_match_encoded_pattern(nxt_conf_validation_t *vldt, - nxt_conf_value_t *value) -{ - u_char *p, *end; - nxt_int_t ret; - nxt_str_t pattern; - - if (nxt_conf_type(value) != NXT_CONF_STRING) { - return nxt_conf_vldt_error(vldt, "The \"match\" pattern for \"%s\" " - "must be a string.", vldt->ctx); - } + nxt_conf_value_t *value) { + u_char *p, *end; + nxt_int_t ret; + nxt_str_t pattern; - ret = nxt_conf_vldt_match_pattern(vldt, value); - if (nxt_slow_path(ret != NXT_OK)) { - return ret; - } + if (nxt_conf_type(value) != NXT_CONF_STRING) { + return nxt_conf_vldt_error(vldt, + "The \"match\" pattern for \"%s\" " + "must be a string.", + vldt->ctx); + } - nxt_conf_get_string(value, &pattern); + ret = nxt_conf_vldt_match_pattern(vldt, value); + if (nxt_slow_path(ret != NXT_OK)) { + return ret; + } - p = nxt_mp_nget(vldt->pool, pattern.length); - if (nxt_slow_path(p == NULL)) { - return NXT_ERROR; - } + nxt_conf_get_string(value, &pattern); - end = nxt_decode_uri(p, pattern.start, pattern.length); - if (nxt_slow_path(end == NULL)) { - return nxt_conf_vldt_error(vldt, "The \"match\" pattern for \"%s\" " - "is encoded but is invalid.", vldt->ctx); - } + p = nxt_mp_nget(vldt->pool, pattern.length); + if (nxt_slow_path(p == NULL)) { + return NXT_ERROR; + } - return NXT_OK; -} + end = nxt_decode_uri(p, pattern.start, pattern.length); + if (nxt_slow_path(end == NULL)) { + return nxt_conf_vldt_error(vldt, + "The \"match\" pattern for \"%s\" " + "is encoded but is invalid.", + vldt->ctx); + } + return NXT_OK; +} -static nxt_int_t -nxt_conf_vldt_match_addrs(nxt_conf_validation_t *vldt, - nxt_conf_value_t *value, void *data) -{ - if (nxt_conf_type(value) == NXT_CONF_ARRAY) { - return nxt_conf_vldt_array_iterator(vldt, value, - &nxt_conf_vldt_match_addr); - } +static nxt_int_t nxt_conf_vldt_match_addrs(nxt_conf_validation_t *vldt, + nxt_conf_value_t *value, + void *data) { + if (nxt_conf_type(value) == NXT_CONF_ARRAY) { + return nxt_conf_vldt_array_iterator(vldt, value, &nxt_conf_vldt_match_addr); + } - return nxt_conf_vldt_match_addr(vldt, value); + return nxt_conf_vldt_match_addr(vldt, value); } +static nxt_int_t nxt_conf_vldt_match_addr(nxt_conf_validation_t *vldt, + nxt_conf_value_t *value) { + nxt_http_route_addr_pattern_t pattern; -static nxt_int_t -nxt_conf_vldt_match_addr(nxt_conf_validation_t *vldt, - nxt_conf_value_t *value) -{ - nxt_http_route_addr_pattern_t pattern; - - switch (nxt_http_route_addr_pattern_parse(vldt->pool, &pattern, value)) { + switch (nxt_http_route_addr_pattern_parse(vldt->pool, &pattern, value)) { - case NXT_OK: - return NXT_OK; + case NXT_OK: + return NXT_OK; - case NXT_ADDR_PATTERN_PORT_ERROR: - return nxt_conf_vldt_error(vldt, "The \"address\" port an invalid " - "port."); + case NXT_ADDR_PATTERN_PORT_ERROR: + return nxt_conf_vldt_error(vldt, "The \"address\" port an invalid " + "port."); - case NXT_ADDR_PATTERN_CV_TYPE_ERROR: - return nxt_conf_vldt_error(vldt, "The \"match\" pattern for " - "\"address\" must be a string."); + case NXT_ADDR_PATTERN_CV_TYPE_ERROR: + return nxt_conf_vldt_error(vldt, "The \"match\" pattern for " + "\"address\" must be a string."); - case NXT_ADDR_PATTERN_LENGTH_ERROR: - return nxt_conf_vldt_error(vldt, "The \"address\" is too short."); + case NXT_ADDR_PATTERN_LENGTH_ERROR: + return nxt_conf_vldt_error(vldt, "The \"address\" is too short."); - case NXT_ADDR_PATTERN_FORMAT_ERROR: - return nxt_conf_vldt_error(vldt, "The \"address\" format is invalid."); + case NXT_ADDR_PATTERN_FORMAT_ERROR: + return nxt_conf_vldt_error(vldt, "The \"address\" format is invalid."); - case NXT_ADDR_PATTERN_RANGE_OVERLAP_ERROR: - return nxt_conf_vldt_error(vldt, "The \"address\" range is " - "overlapping."); + case NXT_ADDR_PATTERN_RANGE_OVERLAP_ERROR: + return nxt_conf_vldt_error(vldt, "The \"address\" range is " + "overlapping."); - case NXT_ADDR_PATTERN_CIDR_ERROR: - return nxt_conf_vldt_error(vldt, "The \"address\" has an invalid CIDR " - "prefix."); + case NXT_ADDR_PATTERN_CIDR_ERROR: + return nxt_conf_vldt_error(vldt, "The \"address\" has an invalid CIDR " + "prefix."); - case NXT_ADDR_PATTERN_NO_IPv6_ERROR: - return nxt_conf_vldt_error(vldt, "The \"address\" does not support " - "IPv6 with your configuration."); + case NXT_ADDR_PATTERN_NO_IPv6_ERROR: + return nxt_conf_vldt_error(vldt, "The \"address\" does not support " + "IPv6 with your configuration."); - case NXT_ADDR_PATTERN_NO_UNIX_ERROR: - return nxt_conf_vldt_error(vldt, "The \"address\" does not support " - "UNIX domain sockets with your " - "configuration."); + case NXT_ADDR_PATTERN_NO_UNIX_ERROR: + return nxt_conf_vldt_error(vldt, "The \"address\" does not support " + "UNIX domain sockets with your " + "configuration."); - default: - return nxt_conf_vldt_error(vldt, "The \"address\" has an unknown " - "format."); - } + default: + return nxt_conf_vldt_error(vldt, "The \"address\" has an unknown " + "format."); + } } +static nxt_int_t nxt_conf_vldt_match_scheme_pattern(nxt_conf_validation_t *vldt, + nxt_conf_value_t *value, + void *data) { + nxt_str_t scheme; -static nxt_int_t -nxt_conf_vldt_match_scheme_pattern(nxt_conf_validation_t *vldt, - nxt_conf_value_t *value, void *data) -{ - nxt_str_t scheme; - - static const nxt_str_t http = nxt_string("http"); - static const nxt_str_t https = nxt_string("https"); + static const nxt_str_t http = nxt_string("http"); + static const nxt_str_t https = nxt_string("https"); - nxt_conf_get_string(value, &scheme); + nxt_conf_get_string(value, &scheme); - if (nxt_strcasestr_eq(&scheme, &http) - || nxt_strcasestr_eq(&scheme, &https)) - { - return NXT_OK; - } + if (nxt_strcasestr_eq(&scheme, &http) || nxt_strcasestr_eq(&scheme, &https)) { + return NXT_OK; + } - return nxt_conf_vldt_error(vldt, "The \"scheme\" can either be " - "\"http\" or \"https\"."); + return nxt_conf_vldt_error(vldt, "The \"scheme\" can either be " + "\"http\" or \"https\"."); } +static nxt_int_t nxt_conf_vldt_match_patterns_sets(nxt_conf_validation_t *vldt, + nxt_conf_value_t *value, + void *data) { + nxt_int_t ret; -static nxt_int_t -nxt_conf_vldt_match_patterns_sets(nxt_conf_validation_t *vldt, - nxt_conf_value_t *value, void *data) -{ - nxt_int_t ret; - - vldt->ctx = data; + vldt->ctx = data; - if (nxt_conf_type(value) == NXT_CONF_ARRAY) { - ret = nxt_conf_vldt_array_iterator(vldt, value, - &nxt_conf_vldt_match_patterns_set); + if (nxt_conf_type(value) == NXT_CONF_ARRAY) { + ret = nxt_conf_vldt_array_iterator(vldt, value, + &nxt_conf_vldt_match_patterns_set); - } else { - /* NXT_CONF_OBJECT */ - ret = nxt_conf_vldt_match_patterns_set(vldt, value); - } + } else { + /* NXT_CONF_OBJECT */ + ret = nxt_conf_vldt_match_patterns_set(vldt, value); + } - vldt->ctx = NULL; + vldt->ctx = NULL; - return ret; + return ret; } +static nxt_int_t nxt_conf_vldt_match_patterns_set(nxt_conf_validation_t *vldt, + nxt_conf_value_t *value) { + if (nxt_conf_type(value) != NXT_CONF_OBJECT) { + return nxt_conf_vldt_error(vldt, + "The \"match\" patterns for " + "\"%s\" must be objects.", + vldt->ctx); + } -static nxt_int_t -nxt_conf_vldt_match_patterns_set(nxt_conf_validation_t *vldt, - nxt_conf_value_t *value) -{ - if (nxt_conf_type(value) != NXT_CONF_OBJECT) { - return nxt_conf_vldt_error(vldt, "The \"match\" patterns for " - "\"%s\" must be objects.", vldt->ctx); - } - - return nxt_conf_vldt_object_iterator(vldt, value, - &nxt_conf_vldt_match_patterns_set_member); + return nxt_conf_vldt_object_iterator( + vldt, value, &nxt_conf_vldt_match_patterns_set_member); } +static nxt_int_t nxt_conf_vldt_match_patterns_set_member( + nxt_conf_validation_t *vldt, nxt_str_t *name, nxt_conf_value_t *value) { + if (name->length == 0) { + return nxt_conf_vldt_error(vldt, "The \"match\" pattern objects must " + "not contain empty member names."); + } -static nxt_int_t -nxt_conf_vldt_match_patterns_set_member(nxt_conf_validation_t *vldt, - nxt_str_t *name, nxt_conf_value_t *value) -{ - if (name->length == 0) { - return nxt_conf_vldt_error(vldt, "The \"match\" pattern objects must " - "not contain empty member names."); - } - - return nxt_conf_vldt_match_patterns(vldt, value, vldt->ctx); + return nxt_conf_vldt_match_patterns(vldt, value, vldt->ctx); } - #if (NXT_TLS) -static nxt_int_t -nxt_conf_vldt_certificate(nxt_conf_validation_t *vldt, nxt_conf_value_t *value, - void *data) -{ - if (nxt_conf_type(value) == NXT_CONF_ARRAY) { - if (nxt_conf_array_elements_count(value) == 0) { - return nxt_conf_vldt_error(vldt, "The \"certificate\" array " +static nxt_int_t nxt_conf_vldt_certificate(nxt_conf_validation_t *vldt, + nxt_conf_value_t *value, + void *data) { + if (nxt_conf_type(value) == NXT_CONF_ARRAY) { + if (nxt_conf_array_elements_count(value) == 0) { + return nxt_conf_vldt_error(vldt, "The \"certificate\" array " "must contain at least one element."); - } - - return nxt_conf_vldt_array_iterator(vldt, value, - &nxt_conf_vldt_certificate_element); } - /* NXT_CONF_STRING */ + return nxt_conf_vldt_array_iterator(vldt, value, + &nxt_conf_vldt_certificate_element); + } + + /* NXT_CONF_STRING */ - return nxt_conf_vldt_certificate_element(vldt, value); + return nxt_conf_vldt_certificate_element(vldt, value); } +static nxt_int_t nxt_conf_vldt_certificate_element(nxt_conf_validation_t *vldt, + nxt_conf_value_t *value) { + nxt_str_t name; + nxt_conf_value_t *cert; -static nxt_int_t -nxt_conf_vldt_certificate_element(nxt_conf_validation_t *vldt, - nxt_conf_value_t *value) -{ - nxt_str_t name; - nxt_conf_value_t *cert; - - if (nxt_conf_type(value) != NXT_CONF_STRING) { - return nxt_conf_vldt_error(vldt, "The \"certificate\" array must " - "contain only string values."); - } + if (nxt_conf_type(value) != NXT_CONF_STRING) { + return nxt_conf_vldt_error(vldt, "The \"certificate\" array must " + "contain only string values."); + } - nxt_conf_get_string(value, &name); + nxt_conf_get_string(value, &name); - cert = nxt_cert_info_get(&name); + cert = nxt_cert_info_get(&name); - if (cert == NULL) { - return nxt_conf_vldt_error(vldt, "Certificate \"%V\" is not found.", - &name); - } + if (cert == NULL) { + return nxt_conf_vldt_error(vldt, "Certificate \"%V\" is not found.", &name); + } - return NXT_OK; + return NXT_OK; } - #if (NXT_HAVE_OPENSSL_CONF_CMD) -static nxt_int_t -nxt_conf_vldt_object_conf_commands(nxt_conf_validation_t *vldt, - nxt_conf_value_t *value, void *data) -{ - uint32_t index; - nxt_int_t ret; - nxt_str_t name; - nxt_conf_value_t *member; +static nxt_int_t nxt_conf_vldt_object_conf_commands(nxt_conf_validation_t *vldt, + nxt_conf_value_t *value, + void *data) { + uint32_t index; + nxt_int_t ret; + nxt_str_t name; + nxt_conf_value_t *member; - index = 0; + index = 0; - for ( ;; ) { - member = nxt_conf_next_object_member(value, &name, &index); + for (;;) { + member = nxt_conf_next_object_member(value, &name, &index); - if (member == NULL) { - break; - } + if (member == NULL) { + break; + } - ret = nxt_conf_vldt_type(vldt, &name, member, NXT_CONF_VLDT_STRING); - if (ret != NXT_OK) { - return ret; - } + ret = nxt_conf_vldt_type(vldt, &name, member, NXT_CONF_VLDT_STRING); + if (ret != NXT_OK) { + return ret; } + } - return NXT_OK; + return NXT_OK; } #endif #endif +static nxt_int_t nxt_conf_vldt_response_header(nxt_conf_validation_t *vldt, + nxt_str_t *name, + nxt_conf_value_t *value) { + nxt_str_t str; + nxt_uint_t type; -static nxt_int_t -nxt_conf_vldt_response_header(nxt_conf_validation_t *vldt, nxt_str_t *name, - nxt_conf_value_t *value) -{ - nxt_str_t str; - nxt_uint_t type; - - static const nxt_str_t content_length = nxt_string("Content-Length"); - - if (name->length == 0) { - return nxt_conf_vldt_error(vldt, "The response header name " - "must not be empty."); - } - - if (nxt_strstr_eq(name, &content_length)) { - return nxt_conf_vldt_error(vldt, "The \"Content-Length\" response " - "header value is not supported"); - } - - type = nxt_conf_type(value); - - if (type == NXT_CONF_NULL) { - return NXT_OK; - } - - if (type == NXT_CONF_STRING) { - nxt_conf_get_string(value, &str); - - if (nxt_is_tstr(&str)) { - return nxt_conf_vldt_var(vldt, name, &str); - } - - return NXT_OK; - } - - return nxt_conf_vldt_error(vldt, "The \"%V\" response header value " - "must either be a string or a null", name); -} - - -static nxt_int_t -nxt_conf_vldt_app_name(nxt_conf_validation_t *vldt, nxt_conf_value_t *value, - void *data) -{ - nxt_str_t name; - nxt_conf_value_t *apps, *app; + static const nxt_str_t content_length = nxt_string("Content-Length"); - static const nxt_str_t apps_str = nxt_string("applications"); + if (name->length == 0) { + return nxt_conf_vldt_error(vldt, "The response header name " + "must not be empty."); + } - nxt_conf_get_string(value, &name); + if (nxt_strstr_eq(name, &content_length)) { + return nxt_conf_vldt_error(vldt, "The \"Content-Length\" response " + "header value is not supported"); + } - apps = nxt_conf_get_object_member(vldt->conf, &apps_str, NULL); + type = nxt_conf_type(value); - if (nxt_slow_path(apps == NULL)) { - goto error; - } + if (type == NXT_CONF_NULL) { + return NXT_OK; + } - app = nxt_conf_get_object_member(apps, &name, NULL); + if (type == NXT_CONF_STRING) { + nxt_conf_get_string(value, &str); - if (nxt_slow_path(app == NULL)) { - goto error; + if (nxt_is_tstr(&str)) { + return nxt_conf_vldt_var(vldt, name, &str); } return NXT_OK; + } -error: - - return nxt_conf_vldt_error(vldt, "Listening socket is assigned for " - "a non existing application \"%V\".", - &name); + return nxt_conf_vldt_error(vldt, + "The \"%V\" response header value " + "must either be a string or a null", + name); } +static nxt_int_t nxt_conf_vldt_app_name(nxt_conf_validation_t *vldt, + nxt_conf_value_t *value, void *data) { + nxt_str_t name; + nxt_conf_value_t *apps, *app; -static nxt_int_t -nxt_conf_vldt_forwarded(nxt_conf_validation_t *vldt, nxt_conf_value_t *value, - void *data) -{ - nxt_conf_value_t *client_ip, *protocol; + static const nxt_str_t apps_str = nxt_string("applications"); - static const nxt_str_t client_ip_str = nxt_string("client_ip"); - static const nxt_str_t protocol_str = nxt_string("protocol"); + nxt_conf_get_string(value, &name); - client_ip = nxt_conf_get_object_member(value, &client_ip_str, NULL); - protocol = nxt_conf_get_object_member(value, &protocol_str, NULL); + apps = nxt_conf_get_object_member(vldt->conf, &apps_str, NULL); - if (client_ip == NULL && protocol == NULL) { - return nxt_conf_vldt_error(vldt, "The \"forwarded\" object must have " - "either \"client_ip\" or \"protocol\" " - "option set."); - } + if (nxt_slow_path(apps == NULL)) { + goto error; + } - return nxt_conf_vldt_object(vldt, value, nxt_conf_vldt_forwarded_members); -} + app = nxt_conf_get_object_member(apps, &name, NULL); + if (nxt_slow_path(app == NULL)) { + goto error; + } -static nxt_int_t -nxt_conf_vldt_listen_backlog(nxt_conf_validation_t *vldt, - nxt_conf_value_t *value, void *data) -{ - int64_t backlog; - - backlog = nxt_conf_get_number(value); - - /* - * POSIX allows this to be 0 and some systems use -1 to - * indicate to use the OS's default value. - */ - if (backlog < -1) { - return nxt_conf_vldt_error(vldt, "The \"backlog\" number must be " - "equal to or greater than -1."); - } + return NXT_OK; - if (backlog > NXT_INT32_T_MAX) { - return nxt_conf_vldt_error(vldt, "The \"backlog\" number must " - "not exceed %d.", NXT_INT32_T_MAX); - } +error: - return NXT_OK; + return nxt_conf_vldt_error(vldt, + "Listening socket is assigned for " + "a non existing application \"%V\".", + &name); } +static nxt_int_t nxt_conf_vldt_forwarded(nxt_conf_validation_t *vldt, + nxt_conf_value_t *value, void *data) { + nxt_conf_value_t *client_ip, *protocol; -static nxt_int_t -nxt_conf_vldt_app(nxt_conf_validation_t *vldt, nxt_str_t *name, - nxt_conf_value_t *value) -{ - nxt_int_t ret; - nxt_str_t type; - nxt_thread_t *thread; - nxt_conf_value_t *type_value; - nxt_app_lang_module_t *lang; - - static const nxt_str_t type_str = nxt_string("type"); - - static const struct { - nxt_conf_vldt_handler_t validator; - nxt_conf_vldt_object_t *members; - - } types[] = { - { nxt_conf_vldt_object, nxt_conf_vldt_external_members }, - { nxt_conf_vldt_python, NULL }, - { nxt_conf_vldt_php, NULL }, - { nxt_conf_vldt_object, nxt_conf_vldt_perl_members }, - { nxt_conf_vldt_object, nxt_conf_vldt_ruby_members }, - { nxt_conf_vldt_object, nxt_conf_vldt_java_members }, - { nxt_conf_vldt_object, nxt_conf_vldt_wasm_members }, - { nxt_conf_vldt_object, nxt_conf_vldt_wasm_wc_members }, - }; - - ret = nxt_conf_vldt_type(vldt, name, value, NXT_CONF_VLDT_OBJECT); + static const nxt_str_t client_ip_str = nxt_string("client_ip"); + static const nxt_str_t protocol_str = nxt_string("protocol"); - if (ret != NXT_OK) { - return ret; - } + client_ip = nxt_conf_get_object_member(value, &client_ip_str, NULL); + protocol = nxt_conf_get_object_member(value, &protocol_str, NULL); - type_value = nxt_conf_get_object_member(value, &type_str, NULL); + if (client_ip == NULL && protocol == NULL) { + return nxt_conf_vldt_error(vldt, "The \"forwarded\" object must have " + "either \"client_ip\" or \"protocol\" " + "option set."); + } - if (type_value == NULL) { - return nxt_conf_vldt_error(vldt, - "Application must have the \"type\" property set."); - } + return nxt_conf_vldt_object(vldt, value, nxt_conf_vldt_forwarded_members); +} - ret = nxt_conf_vldt_type(vldt, &type_str, type_value, NXT_CONF_VLDT_STRING); +static nxt_int_t nxt_conf_vldt_listen_backlog(nxt_conf_validation_t *vldt, + nxt_conf_value_t *value, + void *data) { + int64_t backlog; + + backlog = nxt_conf_get_number(value); + + /* + * POSIX allows this to be 0 and some systems use -1 to + * indicate to use the OS's default value. + */ + if (backlog < -1) { + return nxt_conf_vldt_error(vldt, "The \"backlog\" number must be " + "equal to or greater than -1."); + } + + if (backlog > NXT_INT32_T_MAX) { + return nxt_conf_vldt_error(vldt, + "The \"backlog\" number must " + "not exceed %d.", + NXT_INT32_T_MAX); + } + + return NXT_OK; +} + +static nxt_int_t nxt_conf_vldt_app(nxt_conf_validation_t *vldt, nxt_str_t *name, + nxt_conf_value_t *value) { + nxt_int_t ret; + nxt_str_t type; + nxt_thread_t *thread; + nxt_conf_value_t *type_value; + nxt_app_lang_module_t *lang; + + static const nxt_str_t type_str = nxt_string("type"); + + static const struct { + nxt_conf_vldt_handler_t validator; + nxt_conf_vldt_object_t *members; + + } types[] = { + {nxt_conf_vldt_object, nxt_conf_vldt_external_members}, + {nxt_conf_vldt_python, NULL}, + {nxt_conf_vldt_php, NULL}, + {nxt_conf_vldt_object, nxt_conf_vldt_perl_members}, + {nxt_conf_vldt_object, nxt_conf_vldt_ruby_members}, + {nxt_conf_vldt_object, nxt_conf_vldt_java_members}, + {nxt_conf_vldt_object, nxt_conf_vldt_wasm_members}, + {nxt_conf_vldt_object, nxt_conf_vldt_wasm_wc_members}, + }; + + ret = nxt_conf_vldt_type(vldt, name, value, NXT_CONF_VLDT_OBJECT); + + if (ret != NXT_OK) { + return ret; + } - if (ret != NXT_OK) { - return ret; - } + type_value = nxt_conf_get_object_member(value, &type_str, NULL); - nxt_conf_get_string(type_value, &type); + if (type_value == NULL) { + return nxt_conf_vldt_error( + vldt, "Application must have the \"type\" property set."); + } - thread = nxt_thread(); + ret = nxt_conf_vldt_type(vldt, &type_str, type_value, NXT_CONF_VLDT_STRING); - lang = nxt_app_lang_module(thread->runtime, &type); - if (lang == NULL) { - return nxt_conf_vldt_error(vldt, - "The module to run \"%V\" is not found " - "among the available application modules.", - &type); - } + if (ret != NXT_OK) { + return ret; + } - return types[lang->type].validator(vldt, value, types[lang->type].members); -} + nxt_conf_get_string(type_value, &type); + thread = nxt_thread(); -static nxt_int_t -nxt_conf_vldt_object(nxt_conf_validation_t *vldt, nxt_conf_value_t *value, - void *data) -{ - uint32_t index; - nxt_int_t ret; - nxt_str_t name, var; - nxt_conf_value_t *member; - nxt_conf_vldt_object_t *vals; + lang = nxt_app_lang_module(thread->runtime, &type); + if (lang == NULL) { + return nxt_conf_vldt_error(vldt, + "The module to run \"%V\" is not found " + "among the available application modules.", + &type); + } - vals = data; + return types[lang->type].validator(vldt, value, types[lang->type].members); +} - for ( ;; ) { - if (vals->name.length == 0) { +static nxt_int_t nxt_conf_vldt_object(nxt_conf_validation_t *vldt, + nxt_conf_value_t *value, void *data) { + uint32_t index; + nxt_int_t ret; + nxt_str_t name, var; + nxt_conf_value_t *member; + nxt_conf_vldt_object_t *vals; - if (vals->u.members != NULL) { - vals = vals->u.members; - continue; - } + vals = data; - break; - } + for (;;) { + if (vals->name.length == 0) { - if (vals->flags & NXT_CONF_VLDT_REQUIRED) { - member = nxt_conf_get_object_member(value, &vals->name, NULL); + if (vals->u.members != NULL) { + vals = vals->u.members; + continue; + } - if (member == NULL) { - return nxt_conf_vldt_error(vldt, "Required parameter \"%V\" " - "is missing.", &vals->name); - } - } + break; + } - vals++; + if (vals->flags & NXT_CONF_VLDT_REQUIRED) { + member = nxt_conf_get_object_member(value, &vals->name, NULL); + + if (member == NULL) { + return nxt_conf_vldt_error(vldt, + "Required parameter \"%V\" " + "is missing.", + &vals->name); + } } - index = 0; + vals++; + } - for ( ;; ) { - member = nxt_conf_next_object_member(value, &name, &index); + index = 0; - if (member == NULL) { - return NXT_OK; - } + for (;;) { + member = nxt_conf_next_object_member(value, &name, &index); - vals = data; + if (member == NULL) { + return NXT_OK; + } - for ( ;; ) { - if (vals->name.length == 0) { + vals = data; - if (vals->u.members != NULL) { - vals = vals->u.members; - continue; - } + for (;;) { + if (vals->name.length == 0) { - return nxt_conf_vldt_error(vldt, "Unknown parameter \"%V\".", - &name); - } + if (vals->u.members != NULL) { + vals = vals->u.members; + continue; + } - if (!nxt_strstr_eq(&vals->name, &name)) { - vals++; - continue; - } + return nxt_conf_vldt_error(vldt, "Unknown parameter \"%V\".", &name); + } - if (vals->flags & NXT_CONF_VLDT_TSTR - && nxt_conf_type(member) == NXT_CONF_STRING) - { - nxt_conf_get_string(member, &var); + if (!nxt_strstr_eq(&vals->name, &name)) { + vals++; + continue; + } - if (nxt_is_tstr(&var)) { - ret = nxt_conf_vldt_var(vldt, &name, &var); - if (ret != NXT_OK) { - return ret; - } + if (vals->flags & NXT_CONF_VLDT_TSTR && + nxt_conf_type(member) == NXT_CONF_STRING) { + nxt_conf_get_string(member, &var); - break; - } - } + if (nxt_is_tstr(&var)) { + ret = nxt_conf_vldt_var(vldt, &name, &var); + if (ret != NXT_OK) { + return ret; + } - ret = nxt_conf_vldt_type(vldt, &name, member, vals->type); - if (ret != NXT_OK) { - return ret; - } + break; + } + } - if (vals->validator != NULL) { - ret = vals->validator(vldt, member, vals->u.members); + ret = nxt_conf_vldt_type(vldt, &name, member, vals->type); + if (ret != NXT_OK) { + return ret; + } - if (ret != NXT_OK) { - return ret; - } - } + if (vals->validator != NULL) { + ret = vals->validator(vldt, member, vals->u.members); - break; + if (ret != NXT_OK) { + return ret; } + } + + break; } + } } - typedef struct { - int64_t spare; - int64_t max; - int64_t idle_timeout; + int64_t spare; + int64_t max; + int64_t idle_timeout; } nxt_conf_vldt_processes_conf_t; - -static nxt_conf_map_t nxt_conf_vldt_processes_conf_map[] = { +static nxt_conf_map_t nxt_conf_vldt_processes_conf_map[] = { { nxt_string("spare"), NXT_CONF_MAP_INT64, @@ -2926,550 +2845,512 @@ static nxt_conf_map_t nxt_conf_vldt_processes_conf_map[] = { }, }; +static nxt_int_t nxt_conf_vldt_processes(nxt_conf_validation_t *vldt, + nxt_conf_value_t *value, void *data) { + int64_t int_value; + nxt_int_t ret; + nxt_conf_vldt_processes_conf_t proc; -static nxt_int_t -nxt_conf_vldt_processes(nxt_conf_validation_t *vldt, nxt_conf_value_t *value, - void *data) -{ - int64_t int_value; - nxt_int_t ret; - nxt_conf_vldt_processes_conf_t proc; - - if (nxt_conf_type(value) == NXT_CONF_INTEGER) { - int_value = nxt_conf_get_number(value); - - if (int_value < 1) { - return nxt_conf_vldt_error(vldt, "The \"processes\" number must be " - "equal to or greater than 1."); - } - - if (int_value > NXT_INT32_T_MAX) { - return nxt_conf_vldt_error(vldt, "The \"processes\" number must " - "not exceed %d.", NXT_INT32_T_MAX); - } + if (nxt_conf_type(value) == NXT_CONF_INTEGER) { + int_value = nxt_conf_get_number(value); - return NXT_OK; + if (int_value < 1) { + return nxt_conf_vldt_error(vldt, "The \"processes\" number must be " + "equal to or greater than 1."); } - ret = nxt_conf_vldt_object(vldt, value, data); - if (ret != NXT_OK) { - return ret; + if (int_value > NXT_INT32_T_MAX) { + return nxt_conf_vldt_error(vldt, + "The \"processes\" number must " + "not exceed %d.", + NXT_INT32_T_MAX); } - proc.spare = 0; - proc.max = 1; - proc.idle_timeout = 15; - - ret = nxt_conf_map_object(vldt->pool, value, - nxt_conf_vldt_processes_conf_map, - nxt_nitems(nxt_conf_vldt_processes_conf_map), - &proc); - if (ret != NXT_OK) { - return ret; - } + return NXT_OK; + } - if (proc.spare < 0) { - return nxt_conf_vldt_error(vldt, "The \"spare\" number must not be " - "negative."); - } + ret = nxt_conf_vldt_object(vldt, value, data); + if (ret != NXT_OK) { + return ret; + } - if (proc.spare > NXT_INT32_T_MAX) { - return nxt_conf_vldt_error(vldt, "The \"spare\" number must not " - "exceed %d.", NXT_INT32_T_MAX); - } + proc.spare = 0; + proc.max = 1; + proc.idle_timeout = 15; - if (proc.max < 1) { - return nxt_conf_vldt_error(vldt, "The \"max\" number must be equal " - "to or greater than 1."); - } + ret = + nxt_conf_map_object(vldt->pool, value, nxt_conf_vldt_processes_conf_map, + nxt_nitems(nxt_conf_vldt_processes_conf_map), &proc); + if (ret != NXT_OK) { + return ret; + } - if (proc.max > NXT_INT32_T_MAX) { - return nxt_conf_vldt_error(vldt, "The \"max\" number must not " - "exceed %d.", NXT_INT32_T_MAX); - } + if (proc.spare < 0) { + return nxt_conf_vldt_error(vldt, "The \"spare\" number must not be " + "negative."); + } - if (proc.max < proc.spare) { - return nxt_conf_vldt_error(vldt, "The \"spare\" number must be " - "less than or equal to \"max\"."); - } + if (proc.spare > NXT_INT32_T_MAX) { + return nxt_conf_vldt_error(vldt, + "The \"spare\" number must not " + "exceed %d.", + NXT_INT32_T_MAX); + } - if (proc.idle_timeout < 0) { - return nxt_conf_vldt_error(vldt, "The \"idle_timeout\" number must not " - "be negative."); - } + if (proc.max < 1) { + return nxt_conf_vldt_error(vldt, "The \"max\" number must be equal " + "to or greater than 1."); + } - if (proc.idle_timeout > NXT_INT32_T_MAX / 1000) { - return nxt_conf_vldt_error(vldt, "The \"idle_timeout\" number must not " - "exceed %d.", NXT_INT32_T_MAX / 1000); - } + if (proc.max > NXT_INT32_T_MAX) { + return nxt_conf_vldt_error(vldt, + "The \"max\" number must not " + "exceed %d.", + NXT_INT32_T_MAX); + } + + if (proc.max < proc.spare) { + return nxt_conf_vldt_error(vldt, "The \"spare\" number must be " + "less than or equal to \"max\"."); + } + + if (proc.idle_timeout < 0) { + return nxt_conf_vldt_error(vldt, "The \"idle_timeout\" number must not " + "be negative."); + } + + if (proc.idle_timeout > NXT_INT32_T_MAX / 1000) { + return nxt_conf_vldt_error(vldt, + "The \"idle_timeout\" number must not " + "exceed %d.", + NXT_INT32_T_MAX / 1000); + } - return NXT_OK; + return NXT_OK; } +static nxt_int_t nxt_conf_vldt_object_iterator(nxt_conf_validation_t *vldt, + nxt_conf_value_t *value, + void *data) { + uint32_t index; + nxt_int_t ret; + nxt_str_t name; + nxt_conf_value_t *member; + nxt_conf_vldt_member_t validator; -static nxt_int_t -nxt_conf_vldt_object_iterator(nxt_conf_validation_t *vldt, - nxt_conf_value_t *value, void *data) -{ - uint32_t index; - nxt_int_t ret; - nxt_str_t name; - nxt_conf_value_t *member; - nxt_conf_vldt_member_t validator; - - validator = (nxt_conf_vldt_member_t) data; - index = 0; - - for ( ;; ) { - member = nxt_conf_next_object_member(value, &name, &index); - if (member == NULL) { - return NXT_OK; - } + validator = (nxt_conf_vldt_member_t)data; + index = 0; - ret = validator(vldt, &name, member); - if (ret != NXT_OK) { - return ret; - } + for (;;) { + member = nxt_conf_next_object_member(value, &name, &index); + if (member == NULL) { + return NXT_OK; } -} + ret = validator(vldt, &name, member); + if (ret != NXT_OK) { + return ret; + } + } +} -static nxt_int_t -nxt_conf_vldt_array_iterator(nxt_conf_validation_t *vldt, - nxt_conf_value_t *value, void *data) -{ - uint32_t index; - nxt_int_t ret; - nxt_conf_value_t *element; - nxt_conf_vldt_element_t validator; +static nxt_int_t nxt_conf_vldt_array_iterator(nxt_conf_validation_t *vldt, + nxt_conf_value_t *value, + void *data) { + uint32_t index; + nxt_int_t ret; + nxt_conf_value_t *element; + nxt_conf_vldt_element_t validator; - validator = (nxt_conf_vldt_element_t) data; + validator = (nxt_conf_vldt_element_t)data; - for (index = 0; /* void */ ; index++) { - element = nxt_conf_get_array_element(value, index); + for (index = 0; /* void */; index++) { + element = nxt_conf_get_array_element(value, index); - if (element == NULL) { - return NXT_OK; - } + if (element == NULL) { + return NXT_OK; + } - ret = validator(vldt, element); + ret = validator(vldt, element); - if (ret != NXT_OK) { - return ret; - } + if (ret != NXT_OK) { + return ret; } + } } +static nxt_int_t nxt_conf_vldt_environment(nxt_conf_validation_t *vldt, + nxt_str_t *name, + nxt_conf_value_t *value) { + nxt_str_t str; -static nxt_int_t -nxt_conf_vldt_environment(nxt_conf_validation_t *vldt, nxt_str_t *name, - nxt_conf_value_t *value) -{ - nxt_str_t str; - - if (name->length == 0) { - return nxt_conf_vldt_error(vldt, - "The environment name must not be empty."); - } + if (name->length == 0) { + return nxt_conf_vldt_error(vldt, "The environment name must not be empty."); + } - if (memchr(name->start, '\0', name->length) != NULL) { - return nxt_conf_vldt_error(vldt, "The environment name must not " - "contain null character."); - } + if (memchr(name->start, '\0', name->length) != NULL) { + return nxt_conf_vldt_error(vldt, "The environment name must not " + "contain null character."); + } - if (memchr(name->start, '=', name->length) != NULL) { - return nxt_conf_vldt_error(vldt, "The environment name must not " - "contain '=' character."); - } + if (memchr(name->start, '=', name->length) != NULL) { + return nxt_conf_vldt_error(vldt, "The environment name must not " + "contain '=' character."); + } - if (nxt_conf_type(value) != NXT_CONF_STRING) { - return nxt_conf_vldt_error(vldt, "The \"%V\" environment value must be " - "a string.", name); - } + if (nxt_conf_type(value) != NXT_CONF_STRING) { + return nxt_conf_vldt_error(vldt, + "The \"%V\" environment value must be " + "a string.", + name); + } - nxt_conf_get_string(value, &str); + nxt_conf_get_string(value, &str); - if (memchr(str.start, '\0', str.length) != NULL) { - return nxt_conf_vldt_error(vldt, "The \"%V\" environment value must " - "not contain null character.", name); - } + if (memchr(str.start, '\0', str.length) != NULL) { + return nxt_conf_vldt_error(vldt, + "The \"%V\" environment value must " + "not contain null character.", + name); + } - return NXT_OK; + return NXT_OK; } - -static nxt_int_t -nxt_conf_vldt_targets_exclusive(nxt_conf_validation_t *vldt, - nxt_conf_value_t *value, void *data) -{ - return nxt_conf_vldt_error(vldt, "The \"%s\" option is mutually exclusive " - "with the \"targets\" object.", data); +static nxt_int_t nxt_conf_vldt_targets_exclusive(nxt_conf_validation_t *vldt, + nxt_conf_value_t *value, + void *data) { + return nxt_conf_vldt_error(vldt, + "The \"%s\" option is mutually exclusive " + "with the \"targets\" object.", + data); } +static nxt_int_t nxt_conf_vldt_targets(nxt_conf_validation_t *vldt, + nxt_conf_value_t *value, void *data) { + nxt_int_t ret; + nxt_uint_t n; -static nxt_int_t -nxt_conf_vldt_targets(nxt_conf_validation_t *vldt, nxt_conf_value_t *value, - void *data) -{ - nxt_int_t ret; - nxt_uint_t n; - - n = nxt_conf_object_members_count(value); + n = nxt_conf_object_members_count(value); - if (n > 254) { - return nxt_conf_vldt_error(vldt, "The \"targets\" object must not " - "contain more than 254 members."); - } + if (n > 254) { + return nxt_conf_vldt_error(vldt, "The \"targets\" object must not " + "contain more than 254 members."); + } - vldt->ctx = data; + vldt->ctx = data; - ret = nxt_conf_vldt_object_iterator(vldt, value, &nxt_conf_vldt_target); + ret = nxt_conf_vldt_object_iterator(vldt, value, &nxt_conf_vldt_target); - vldt->ctx = NULL; + vldt->ctx = NULL; - return ret; + return ret; } +static nxt_int_t nxt_conf_vldt_target(nxt_conf_validation_t *vldt, + nxt_str_t *name, + nxt_conf_value_t *value) { + if (name->length == 0) { + return nxt_conf_vldt_error(vldt, "The target name must not be empty."); + } -static nxt_int_t -nxt_conf_vldt_target(nxt_conf_validation_t *vldt, nxt_str_t *name, - nxt_conf_value_t *value) -{ - if (name->length == 0) { - return nxt_conf_vldt_error(vldt, - "The target name must not be empty."); - } - - if (nxt_conf_type(value) != NXT_CONF_OBJECT) { - return nxt_conf_vldt_error(vldt, "The \"%V\" target must be " - "an object.", name); - } + if (nxt_conf_type(value) != NXT_CONF_OBJECT) { + return nxt_conf_vldt_error(vldt, + "The \"%V\" target must be " + "an object.", + name); + } - return nxt_conf_vldt_object(vldt, value, vldt->ctx); + return nxt_conf_vldt_object(vldt, value, vldt->ctx); } - #if (NXT_HAVE_CGROUP) -static nxt_int_t -nxt_conf_vldt_cgroup_path(nxt_conf_validation_t *vldt, nxt_conf_value_t *value, - void *data) -{ - char path[NXT_MAX_PATH_LEN]; - nxt_str_t cgpath; - - nxt_conf_get_string(value, &cgpath); - if (cgpath.length >= NXT_MAX_PATH_LEN - strlen(NXT_CGROUP_ROOT) - 1) { - return nxt_conf_vldt_error(vldt, "The cgroup path \"%V\" is too long.", - &cgpath); - } +static nxt_int_t nxt_conf_vldt_cgroup_path(nxt_conf_validation_t *vldt, + nxt_conf_value_t *value, + void *data) { + char path[NXT_MAX_PATH_LEN]; + nxt_str_t cgpath; - sprintf(path, "/%*s/", (int) cgpath.length, cgpath.start); + nxt_conf_get_string(value, &cgpath); + if (cgpath.length >= NXT_MAX_PATH_LEN - strlen(NXT_CGROUP_ROOT) - 1) { + return nxt_conf_vldt_error(vldt, "The cgroup path \"%V\" is too long.", + &cgpath); + } - if (cgpath.length == 0 || strstr(path, "/../") != NULL) { - return nxt_conf_vldt_error(vldt, - "The cgroup path \"%V\" is invalid.", - &cgpath); - } + sprintf(path, "/%*s/", (int)cgpath.length, cgpath.start); - return NXT_OK; + if (cgpath.length == 0 || strstr(path, "/../") != NULL) { + return nxt_conf_vldt_error(vldt, "The cgroup path \"%V\" is invalid.", + &cgpath); + } + + return NXT_OK; } #endif - -static nxt_int_t -nxt_conf_vldt_clone_namespaces(nxt_conf_validation_t *vldt, - nxt_conf_value_t *value, void *data) -{ - return nxt_conf_vldt_object(vldt, value, data); +static nxt_int_t nxt_conf_vldt_clone_namespaces(nxt_conf_validation_t *vldt, + nxt_conf_value_t *value, + void *data) { + return nxt_conf_vldt_object(vldt, value, data); } - -static nxt_int_t -nxt_conf_vldt_isolation(nxt_conf_validation_t *vldt, nxt_conf_value_t *value, - void *data) -{ - return nxt_conf_vldt_object(vldt, value, data); +static nxt_int_t nxt_conf_vldt_isolation(nxt_conf_validation_t *vldt, + nxt_conf_value_t *value, void *data) { + return nxt_conf_vldt_object(vldt, value, data); } - #if (NXT_HAVE_CLONE_NEWUSER) -static nxt_int_t -nxt_conf_vldt_clone_uidmap(nxt_conf_validation_t *vldt, nxt_conf_value_t *value) -{ - nxt_int_t ret; +static nxt_int_t nxt_conf_vldt_clone_uidmap(nxt_conf_validation_t *vldt, + nxt_conf_value_t *value) { + nxt_int_t ret; - if (nxt_conf_type(value) != NXT_CONF_OBJECT) { - return nxt_conf_vldt_error(vldt, "The \"uidmap\" array " - "must contain only object values."); - } + if (nxt_conf_type(value) != NXT_CONF_OBJECT) { + return nxt_conf_vldt_error(vldt, "The \"uidmap\" array " + "must contain only object values."); + } - ret = nxt_conf_vldt_object(vldt, value, - (void *) nxt_conf_vldt_app_procmap_members); - if (nxt_slow_path(ret != NXT_OK)) { - return ret; - } + ret = nxt_conf_vldt_object(vldt, value, + (void *)nxt_conf_vldt_app_procmap_members); + if (nxt_slow_path(ret != NXT_OK)) { + return ret; + } - return NXT_OK; + return NXT_OK; } +static nxt_int_t nxt_conf_vldt_clone_gidmap(nxt_conf_validation_t *vldt, + nxt_conf_value_t *value) { + nxt_int_t ret; -static nxt_int_t -nxt_conf_vldt_clone_gidmap(nxt_conf_validation_t *vldt, nxt_conf_value_t *value) -{ - nxt_int_t ret; - - if (nxt_conf_type(value) != NXT_CONF_OBJECT) { - return nxt_conf_vldt_error(vldt, "The \"gidmap\" array " - "must contain only object values."); - } + if (nxt_conf_type(value) != NXT_CONF_OBJECT) { + return nxt_conf_vldt_error(vldt, "The \"gidmap\" array " + "must contain only object values."); + } - ret = nxt_conf_vldt_object(vldt, value, - (void *) nxt_conf_vldt_app_procmap_members); - if (nxt_slow_path(ret != NXT_OK)) { - return ret; - } + ret = nxt_conf_vldt_object(vldt, value, + (void *)nxt_conf_vldt_app_procmap_members); + if (nxt_slow_path(ret != NXT_OK)) { + return ret; + } - return NXT_OK; + return NXT_OK; } #endif +static nxt_int_t nxt_conf_vldt_argument(nxt_conf_validation_t *vldt, + nxt_conf_value_t *value) { + nxt_str_t str; -static nxt_int_t -nxt_conf_vldt_argument(nxt_conf_validation_t *vldt, nxt_conf_value_t *value) -{ - nxt_str_t str; - - if (nxt_conf_type(value) != NXT_CONF_STRING) { - return nxt_conf_vldt_error(vldt, "The \"arguments\" array " - "must contain only string values."); - } + if (nxt_conf_type(value) != NXT_CONF_STRING) { + return nxt_conf_vldt_error(vldt, "The \"arguments\" array " + "must contain only string values."); + } - nxt_conf_get_string(value, &str); + nxt_conf_get_string(value, &str); - if (memchr(str.start, '\0', str.length) != NULL) { - return nxt_conf_vldt_error(vldt, "The \"arguments\" array must not " - "contain strings with null character."); - } + if (memchr(str.start, '\0', str.length) != NULL) { + return nxt_conf_vldt_error(vldt, "The \"arguments\" array must not " + "contain strings with null character."); + } - return NXT_OK; + return NXT_OK; } +static nxt_int_t nxt_conf_vldt_php(nxt_conf_validation_t *vldt, + nxt_conf_value_t *value, void *data) { + nxt_conf_value_t *targets; -static nxt_int_t -nxt_conf_vldt_php(nxt_conf_validation_t *vldt, nxt_conf_value_t *value, - void *data) -{ - nxt_conf_value_t *targets; - - static const nxt_str_t targets_str = nxt_string("targets"); + static const nxt_str_t targets_str = nxt_string("targets"); - targets = nxt_conf_get_object_member(value, &targets_str, NULL); + targets = nxt_conf_get_object_member(value, &targets_str, NULL); - if (targets != NULL) { - return nxt_conf_vldt_object(vldt, value, nxt_conf_vldt_php_members); - } + if (targets != NULL) { + return nxt_conf_vldt_object(vldt, value, nxt_conf_vldt_php_members); + } - return nxt_conf_vldt_object(vldt, value, - nxt_conf_vldt_php_notargets_members); + return nxt_conf_vldt_object(vldt, value, nxt_conf_vldt_php_notargets_members); } +static nxt_int_t nxt_conf_vldt_php_option(nxt_conf_validation_t *vldt, + nxt_str_t *name, + nxt_conf_value_t *value) { + if (name->length == 0) { + return nxt_conf_vldt_error(vldt, "The PHP option name must not be empty."); + } -static nxt_int_t -nxt_conf_vldt_php_option(nxt_conf_validation_t *vldt, nxt_str_t *name, - nxt_conf_value_t *value) -{ - if (name->length == 0) { - return nxt_conf_vldt_error(vldt, - "The PHP option name must not be empty."); - } - - if (nxt_conf_type(value) != NXT_CONF_STRING) { - return nxt_conf_vldt_error(vldt, "The \"%V\" PHP option must be " - "a string.", name); - } + if (nxt_conf_type(value) != NXT_CONF_STRING) { + return nxt_conf_vldt_error(vldt, + "The \"%V\" PHP option must be " + "a string.", + name); + } - return NXT_OK; + return NXT_OK; } +static nxt_int_t nxt_conf_vldt_java_classpath(nxt_conf_validation_t *vldt, + nxt_conf_value_t *value) { + nxt_str_t str; -static nxt_int_t -nxt_conf_vldt_java_classpath(nxt_conf_validation_t *vldt, - nxt_conf_value_t *value) -{ - nxt_str_t str; - - if (nxt_conf_type(value) != NXT_CONF_STRING) { - return nxt_conf_vldt_error(vldt, "The \"classpath\" array " - "must contain only string values."); - } + if (nxt_conf_type(value) != NXT_CONF_STRING) { + return nxt_conf_vldt_error(vldt, "The \"classpath\" array " + "must contain only string values."); + } - nxt_conf_get_string(value, &str); + nxt_conf_get_string(value, &str); - if (memchr(str.start, '\0', str.length) != NULL) { - return nxt_conf_vldt_error(vldt, "The \"classpath\" array must not " - "contain strings with null character."); - } + if (memchr(str.start, '\0', str.length) != NULL) { + return nxt_conf_vldt_error(vldt, "The \"classpath\" array must not " + "contain strings with null character."); + } - return NXT_OK; + return NXT_OK; } +static nxt_int_t nxt_conf_vldt_java_option(nxt_conf_validation_t *vldt, + nxt_conf_value_t *value) { + nxt_str_t str; -static nxt_int_t -nxt_conf_vldt_java_option(nxt_conf_validation_t *vldt, nxt_conf_value_t *value) -{ - nxt_str_t str; - - if (nxt_conf_type(value) != NXT_CONF_STRING) { - return nxt_conf_vldt_error(vldt, "The \"options\" array " - "must contain only string values."); - } + if (nxt_conf_type(value) != NXT_CONF_STRING) { + return nxt_conf_vldt_error(vldt, "The \"options\" array " + "must contain only string values."); + } - nxt_conf_get_string(value, &str); + nxt_conf_get_string(value, &str); - if (memchr(str.start, '\0', str.length) != NULL) { - return nxt_conf_vldt_error(vldt, "The \"options\" array must not " - "contain strings with null character."); - } + if (memchr(str.start, '\0', str.length) != NULL) { + return nxt_conf_vldt_error(vldt, "The \"options\" array must not " + "contain strings with null character."); + } - return NXT_OK; + return NXT_OK; } +static nxt_int_t nxt_conf_vldt_upstream(nxt_conf_validation_t *vldt, + nxt_str_t *name, + nxt_conf_value_t *value) { + nxt_int_t ret; + nxt_conf_value_t *conf; -static nxt_int_t -nxt_conf_vldt_upstream(nxt_conf_validation_t *vldt, nxt_str_t *name, - nxt_conf_value_t *value) -{ - nxt_int_t ret; - nxt_conf_value_t *conf; - - static const nxt_str_t servers = nxt_string("servers"); + static const nxt_str_t servers = nxt_string("servers"); - ret = nxt_conf_vldt_type(vldt, name, value, NXT_CONF_VLDT_OBJECT); + ret = nxt_conf_vldt_type(vldt, name, value, NXT_CONF_VLDT_OBJECT); - if (ret != NXT_OK) { - return ret; - } + if (ret != NXT_OK) { + return ret; + } - ret = nxt_conf_vldt_object(vldt, value, nxt_conf_vldt_upstream_members); + ret = nxt_conf_vldt_object(vldt, value, nxt_conf_vldt_upstream_members); - if (ret != NXT_OK) { - return ret; - } + if (ret != NXT_OK) { + return ret; + } - conf = nxt_conf_get_object_member(value, &servers, NULL); - if (conf == NULL) { - return nxt_conf_vldt_error(vldt, "The \"%V\" upstream must contain " - "\"servers\" object value.", name); - } + conf = nxt_conf_get_object_member(value, &servers, NULL); + if (conf == NULL) { + return nxt_conf_vldt_error(vldt, + "The \"%V\" upstream must contain " + "\"servers\" object value.", + name); + } - return NXT_OK; + return NXT_OK; } +static nxt_int_t nxt_conf_vldt_server(nxt_conf_validation_t *vldt, + nxt_str_t *name, + nxt_conf_value_t *value) { + nxt_int_t ret; + nxt_str_t str; + nxt_sockaddr_t *sa; + + ret = nxt_conf_vldt_type(vldt, name, value, NXT_CONF_VLDT_OBJECT); + if (ret != NXT_OK) { + return ret; + } -static nxt_int_t -nxt_conf_vldt_server(nxt_conf_validation_t *vldt, nxt_str_t *name, - nxt_conf_value_t *value) -{ - nxt_int_t ret; - nxt_str_t str; - nxt_sockaddr_t *sa; - - ret = nxt_conf_vldt_type(vldt, name, value, NXT_CONF_VLDT_OBJECT); - if (ret != NXT_OK) { - return ret; - } - - if (nxt_slow_path(nxt_str_dup(vldt->pool, &str, name) == NULL)) { - return NXT_ERROR; - } + if (nxt_slow_path(nxt_str_dup(vldt->pool, &str, name) == NULL)) { + return NXT_ERROR; + } - sa = nxt_sockaddr_parse(vldt->pool, &str); - if (sa == NULL) { - return nxt_conf_vldt_error(vldt, "The \"%V\" is not valid " - "server address.", name); - } + sa = nxt_sockaddr_parse(vldt->pool, &str); + if (sa == NULL) { + return nxt_conf_vldt_error(vldt, + "The \"%V\" is not valid " + "server address.", + name); + } - return nxt_conf_vldt_object(vldt, value, - nxt_conf_vldt_upstream_server_members); + return nxt_conf_vldt_object(vldt, value, + nxt_conf_vldt_upstream_server_members); } +static nxt_int_t nxt_conf_vldt_server_weight(nxt_conf_validation_t *vldt, + nxt_conf_value_t *value, + void *data) { + double num_value; -static nxt_int_t -nxt_conf_vldt_server_weight(nxt_conf_validation_t *vldt, - nxt_conf_value_t *value, void *data) -{ - double num_value; - - num_value = nxt_conf_get_number(value); + num_value = nxt_conf_get_number(value); - if (num_value < 0) { - return nxt_conf_vldt_error(vldt, "The \"weight\" number must be " - "positive."); - } + if (num_value < 0) { + return nxt_conf_vldt_error(vldt, "The \"weight\" number must be " + "positive."); + } - if (num_value > 1000000) { - return nxt_conf_vldt_error(vldt, "The \"weight\" number must " - "not exceed 1,000,000"); - } + if (num_value > 1000000) { + return nxt_conf_vldt_error(vldt, "The \"weight\" number must " + "not exceed 1,000,000"); + } - return NXT_OK; + return NXT_OK; } - #if (NXT_HAVE_NJS) -static nxt_int_t -nxt_conf_vldt_js_module(nxt_conf_validation_t *vldt, nxt_conf_value_t *value, - void *data) -{ - if (nxt_conf_type(value) == NXT_CONF_ARRAY) { - return nxt_conf_vldt_array_iterator(vldt, value, - &nxt_conf_vldt_js_module_element); - } +static nxt_int_t nxt_conf_vldt_js_module(nxt_conf_validation_t *vldt, + nxt_conf_value_t *value, void *data) { + if (nxt_conf_type(value) == NXT_CONF_ARRAY) { + return nxt_conf_vldt_array_iterator(vldt, value, + &nxt_conf_vldt_js_module_element); + } - /* NXT_CONF_STRING */ + /* NXT_CONF_STRING */ - return nxt_conf_vldt_js_module_element(vldt, value); + return nxt_conf_vldt_js_module_element(vldt, value); } +static nxt_int_t nxt_conf_vldt_js_module_element(nxt_conf_validation_t *vldt, + nxt_conf_value_t *value) { + nxt_str_t name; + nxt_conf_value_t *module; -static nxt_int_t -nxt_conf_vldt_js_module_element(nxt_conf_validation_t *vldt, - nxt_conf_value_t *value) -{ - nxt_str_t name; - nxt_conf_value_t *module; - - if (nxt_conf_type(value) != NXT_CONF_STRING) { - return nxt_conf_vldt_error(vldt, "The \"js_module\" array must " - "contain only string values."); - } + if (nxt_conf_type(value) != NXT_CONF_STRING) { + return nxt_conf_vldt_error(vldt, "The \"js_module\" array must " + "contain only string values."); + } - nxt_conf_get_string(value, &name); + nxt_conf_get_string(value, &name); - module = nxt_script_info_get(&name); - if (module == NULL) { - return nxt_conf_vldt_error(vldt, "JS module \"%V\" is not found.", - &name); - } + module = nxt_script_info_get(&name); + if (module == NULL) { + return nxt_conf_vldt_error(vldt, "JS module \"%V\" is not found.", &name); + } - return NXT_OK; + return NXT_OK; } #endif - typedef struct { - nxt_str_t path; - nxt_str_t format; + nxt_str_t path; + nxt_str_t format; } nxt_conf_vldt_access_log_conf_t; - -static nxt_conf_map_t nxt_conf_vldt_access_log_map[] = { +static nxt_conf_map_t nxt_conf_vldt_access_log_map[] = { { nxt_string("path"), NXT_CONF_MAP_STR, @@ -3483,43 +3364,37 @@ static nxt_conf_map_t nxt_conf_vldt_access_log_map[] = { }, }; +static nxt_int_t nxt_conf_vldt_access_log(nxt_conf_validation_t *vldt, + nxt_conf_value_t *value, void *data) { + nxt_int_t ret; + nxt_conf_vldt_access_log_conf_t conf; -static nxt_int_t -nxt_conf_vldt_access_log(nxt_conf_validation_t *vldt, nxt_conf_value_t *value, - void *data) -{ - nxt_int_t ret; - nxt_conf_vldt_access_log_conf_t conf; - - static const nxt_str_t format_str = nxt_string("format"); + static const nxt_str_t format_str = nxt_string("format"); - if (nxt_conf_type(value) == NXT_CONF_STRING) { - return NXT_OK; - } + if (nxt_conf_type(value) == NXT_CONF_STRING) { + return NXT_OK; + } - ret = nxt_conf_vldt_object(vldt, value, nxt_conf_vldt_access_log_members); - if (ret != NXT_OK) { - return ret; - } + ret = nxt_conf_vldt_object(vldt, value, nxt_conf_vldt_access_log_members); + if (ret != NXT_OK) { + return ret; + } - nxt_memzero(&conf, sizeof(nxt_conf_vldt_access_log_conf_t)); + nxt_memzero(&conf, sizeof(nxt_conf_vldt_access_log_conf_t)); - ret = nxt_conf_map_object(vldt->pool, value, - nxt_conf_vldt_access_log_map, - nxt_nitems(nxt_conf_vldt_access_log_map), - &conf); - if (ret != NXT_OK) { - return ret; - } + ret = nxt_conf_map_object(vldt->pool, value, nxt_conf_vldt_access_log_map, + nxt_nitems(nxt_conf_vldt_access_log_map), &conf); + if (ret != NXT_OK) { + return ret; + } - if (conf.path.length == 0) { - return nxt_conf_vldt_error(vldt, - "The \"path\" string must not be empty."); - } + if (conf.path.length == 0) { + return nxt_conf_vldt_error(vldt, "The \"path\" string must not be empty."); + } - if (nxt_is_tstr(&conf.format)) { - return nxt_conf_vldt_var(vldt, &format_str, &conf.format); - } + if (nxt_is_tstr(&conf.format)) { + return nxt_conf_vldt_var(vldt, &format_str, &conf.format); + } - return NXT_OK; + return NXT_OK; } diff --git a/src/nxt_conn.c b/src/nxt_conn.c index 498d7d5c5..99fdfc6fc 100644 --- a/src/nxt_conn.c +++ b/src/nxt_conn.c @@ -6,8 +6,7 @@ #include - -nxt_conn_io_t nxt_unix_conn_io = { +nxt_conn_io_t nxt_unix_conn_io = { .connect = nxt_conn_io_connect, .accept = nxt_conn_io_accept, @@ -38,148 +37,133 @@ nxt_conn_io_t nxt_unix_conn_io = { .send = nxt_event_conn_io_send, }; +nxt_conn_t *nxt_conn_create(nxt_mp_t *mp, nxt_task_t *task) { + nxt_conn_t *c; + nxt_thread_t *thr; -nxt_conn_t * -nxt_conn_create(nxt_mp_t *mp, nxt_task_t *task) -{ - nxt_conn_t *c; - nxt_thread_t *thr; + c = nxt_mp_zget(mp, sizeof(nxt_conn_t)); + if (nxt_slow_path(c == NULL)) { + return NULL; + } - c = nxt_mp_zget(mp, sizeof(nxt_conn_t)); - if (nxt_slow_path(c == NULL)) { - return NULL; - } + c->mem_pool = mp; - c->mem_pool = mp; + c->socket.fd = -1; - c->socket.fd = -1; + c->socket.log = &c->log; + c->log = *task->log; - c->socket.log = &c->log; - c->log = *task->log; + /* The while loop skips possible uint32_t overflow. */ - /* The while loop skips possible uint32_t overflow. */ + while (c->log.ident == 0) { + c->log.ident = nxt_task_next_ident(); + } - while (c->log.ident == 0) { - c->log.ident = nxt_task_next_ident(); - } + thr = nxt_thread(); + thr->engine->connections++; - thr = nxt_thread(); - thr->engine->connections++; + c->task.thread = thr; + c->task.log = &c->log; + c->task.ident = c->log.ident; + c->socket.task = &c->task; + c->read_timer.task = &c->task; + c->write_timer.task = &c->task; - c->task.thread = thr; - c->task.log = &c->log; - c->task.ident = c->log.ident; - c->socket.task = &c->task; - c->read_timer.task = &c->task; - c->write_timer.task = &c->task; + c->io = thr->engine->event.io; + c->max_chunk = NXT_INT32_T_MAX; + c->sendfile = NXT_CONN_SENDFILE_UNSET; - c->io = thr->engine->event.io; - c->max_chunk = NXT_INT32_T_MAX; - c->sendfile = NXT_CONN_SENDFILE_UNSET; + c->socket.read_work_queue = &thr->engine->fast_work_queue; + c->socket.write_work_queue = &thr->engine->fast_work_queue; - c->socket.read_work_queue = &thr->engine->fast_work_queue; - c->socket.write_work_queue = &thr->engine->fast_work_queue; + nxt_conn_timer_init(&c->read_timer, c, c->socket.read_work_queue); + nxt_conn_timer_init(&c->write_timer, c, c->socket.write_work_queue); - nxt_conn_timer_init(&c->read_timer, c, c->socket.read_work_queue); - nxt_conn_timer_init(&c->write_timer, c, c->socket.write_work_queue); + nxt_log_debug(&c->log, "connections: %uD", thr->engine->connections); - nxt_log_debug(&c->log, "connections: %uD", thr->engine->connections); - - return c; + return c; } +void nxt_conn_free(nxt_task_t *task, nxt_conn_t *c) { + nxt_mp_t *mp; -void -nxt_conn_free(nxt_task_t *task, nxt_conn_t *c) -{ - nxt_mp_t *mp; - - task->thread->engine->connections--; + task->thread->engine->connections--; - mp = c->mem_pool; - nxt_mp_release(mp); + mp = c->mem_pool; + nxt_mp_release(mp); } +void nxt_conn_timer(nxt_event_engine_t *engine, nxt_conn_t *c, + const nxt_conn_state_t *state, nxt_timer_t *timer) { + nxt_msec_t value; -void -nxt_conn_timer(nxt_event_engine_t *engine, nxt_conn_t *c, - const nxt_conn_state_t *state, nxt_timer_t *timer) -{ - nxt_msec_t value; + if (state->timer_value != NULL) { + value = state->timer_value(c, state->timer_data); - if (state->timer_value != NULL) { - value = state->timer_value(c, state->timer_data); - - if (value != 0) { - timer->handler = state->timer_handler; - nxt_timer_add(engine, timer, value); - } + if (value != 0) { + timer->handler = state->timer_handler; + nxt_timer_add(engine, timer, value); } + } } - -void -nxt_conn_work_queue_set(nxt_conn_t *c, nxt_work_queue_t *wq) -{ - c->read_work_queue = wq; - c->write_work_queue = wq; - c->read_timer.work_queue = wq; - c->write_timer.work_queue = wq; +void nxt_conn_work_queue_set(nxt_conn_t *c, nxt_work_queue_t *wq) { + c->read_work_queue = wq; + c->write_work_queue = wq; + c->read_timer.work_queue = wq; + c->write_timer.work_queue = wq; } +nxt_sockaddr_t *nxt_conn_local_addr(nxt_task_t *task, nxt_conn_t *c) { + int ret; + size_t size, length; + socklen_t socklen; + nxt_sockaddr_t *sa; -nxt_sockaddr_t * -nxt_conn_local_addr(nxt_task_t *task, nxt_conn_t *c) -{ - int ret; - size_t size, length; - socklen_t socklen; - nxt_sockaddr_t *sa; + if (c->local != NULL) { + return c->local; + } - if (c->local != NULL) { - return c->local; - } + /* AF_UNIX should not get in here. */ - /* AF_UNIX should not get in here. */ - - switch (c->remote->u.sockaddr.sa_family) { + switch (c->remote->u.sockaddr.sa_family) { #if (NXT_INET6) - case AF_INET6: - socklen = sizeof(struct sockaddr_in6); - length = NXT_INET6_ADDR_STR_LEN; - size = offsetof(nxt_sockaddr_t, u) + socklen + length; - break; + case AF_INET6: + socklen = sizeof(struct sockaddr_in6); + length = NXT_INET6_ADDR_STR_LEN; + size = offsetof(nxt_sockaddr_t, u) + socklen + length; + break; #endif - case AF_INET: - default: - socklen = sizeof(struct sockaddr_in); - length = NXT_INET_ADDR_STR_LEN; - size = offsetof(nxt_sockaddr_t, u) + socklen + length; - break; - } - - sa = nxt_mp_get(c->mem_pool, size); - if (nxt_slow_path(sa == NULL)) { - return NULL; - } - - sa->socklen = socklen; - sa->length = length; - - ret = getsockname(c->socket.fd, &sa->u.sockaddr, &socklen); - if (nxt_slow_path(ret != 0)) { - nxt_alert(task, "getsockname(%d) failed", c->socket.fd); - return NULL; - } - - c->local = sa; - - nxt_sockaddr_text(sa); - - /* - * TODO: here we can adjust the end of non-freeable block - * in c->mem_pool to the end of actual sockaddr length. - */ - - return sa; + case AF_INET: + default: + socklen = sizeof(struct sockaddr_in); + length = NXT_INET_ADDR_STR_LEN; + size = offsetof(nxt_sockaddr_t, u) + socklen + length; + break; + } + + sa = nxt_mp_get(c->mem_pool, size); + if (nxt_slow_path(sa == NULL)) { + return NULL; + } + + sa->socklen = socklen; + sa->length = length; + + ret = getsockname(c->socket.fd, &sa->u.sockaddr, &socklen); + if (nxt_slow_path(ret != 0)) { + nxt_alert(task, "getsockname(%d) failed", c->socket.fd); + return NULL; + } + + c->local = sa; + + nxt_sockaddr_text(sa); + + /* + * TODO: here we can adjust the end of non-freeable block + * in c->mem_pool to the end of actual sockaddr length. + */ + + return sa; } diff --git a/src/nxt_conn.h b/src/nxt_conn.h index 5717d3c99..4e39a5ff6 100644 --- a/src/nxt_conn.h +++ b/src/nxt_conn.h @@ -7,227 +7,207 @@ #ifndef _NXT_CONN_H_INCLUDED_ #define _NXT_CONN_H_INCLUDED_ - typedef ssize_t (*nxt_conn_io_read_t)(nxt_task_t *task, nxt_conn_t *c); typedef nxt_msec_t (*nxt_conn_timer_value_t)(nxt_conn_t *c, uintptr_t data); - typedef struct { - nxt_work_handler_t ready_handler; - nxt_work_handler_t close_handler; - nxt_work_handler_t error_handler; + nxt_work_handler_t ready_handler; + nxt_work_handler_t close_handler; + nxt_work_handler_t error_handler; - nxt_conn_io_read_t io_read_handler; + nxt_conn_io_read_t io_read_handler; - nxt_work_handler_t timer_handler; - nxt_conn_timer_value_t timer_value; - uintptr_t timer_data; + nxt_work_handler_t timer_handler; + nxt_conn_timer_value_t timer_value; + uintptr_t timer_data; - uint8_t timer_autoreset; + uint8_t timer_autoreset; } nxt_conn_state_t; - typedef struct { - double average; - size_t limit; - size_t limit_after; - size_t max_limit; - nxt_msec_t last; + double average; + size_t limit; + size_t limit_after; + size_t max_limit; + nxt_msec_t last; } nxt_event_write_rate_t; - typedef struct { - nxt_work_handler_t connect; - nxt_work_handler_t accept; - - /* - * The read() with NULL c->read buffer waits readiness of a connection - * to avoid allocation of read buffer if the connection will time out - * or will be closed with error. The kqueue-specific read() can also - * detect case if a client did not sent anything and has just closed the - * connection without errors. In the latter case state's close_handler - * is called. - */ - nxt_work_handler_t read; - - ssize_t (*recvbuf)(nxt_conn_t *c, nxt_buf_t *b); - - ssize_t (*recv)(nxt_conn_t *c, void *buf, - size_t size, nxt_uint_t flags); - - /* The write() is an interface to write a buffer chain. */ - nxt_work_handler_t write; - - /* - * The sendbuf() is an interface for OS-specific sendfile - * implementations or simple writev(). - */ - ssize_t (*sendbuf)(nxt_task_t *task, - nxt_sendbuf_t *sb); - /* - * The sendbuf() is an interface for OS-specific sendfile - * implementations or simple writev(). - */ - ssize_t (*old_sendbuf)(nxt_conn_t *c, nxt_buf_t *b, - size_t limit); - /* - * The writev() is an interface to write several nxt_iobuf_t buffers. - */ - ssize_t (*writev)(nxt_conn_t *c, - nxt_iobuf_t *iob, nxt_uint_t niob); - /* - * The send() is an interface to write a single buffer. SSL/TLS - * libraries' send() interface handles also the libraries' errors. - */ - ssize_t (*send)(nxt_conn_t *c, void *buf, - size_t size); - - nxt_work_handler_t shutdown; + nxt_work_handler_t connect; + nxt_work_handler_t accept; + + /* + * The read() with NULL c->read buffer waits readiness of a connection + * to avoid allocation of read buffer if the connection will time out + * or will be closed with error. The kqueue-specific read() can also + * detect case if a client did not sent anything and has just closed the + * connection without errors. In the latter case state's close_handler + * is called. + */ + nxt_work_handler_t read; + + ssize_t (*recvbuf)(nxt_conn_t *c, nxt_buf_t *b); + + ssize_t (*recv)(nxt_conn_t *c, void *buf, size_t size, nxt_uint_t flags); + + /* The write() is an interface to write a buffer chain. */ + nxt_work_handler_t write; + + /* + * The sendbuf() is an interface for OS-specific sendfile + * implementations or simple writev(). + */ + ssize_t (*sendbuf)(nxt_task_t *task, nxt_sendbuf_t *sb); + /* + * The sendbuf() is an interface for OS-specific sendfile + * implementations or simple writev(). + */ + ssize_t (*old_sendbuf)(nxt_conn_t *c, nxt_buf_t *b, size_t limit); + /* + * The writev() is an interface to write several nxt_iobuf_t buffers. + */ + ssize_t (*writev)(nxt_conn_t *c, nxt_iobuf_t *iob, nxt_uint_t niob); + /* + * The send() is an interface to write a single buffer. SSL/TLS + * libraries' send() interface handles also the libraries' errors. + */ + ssize_t (*send)(nxt_conn_t *c, void *buf, size_t size); + + nxt_work_handler_t shutdown; } nxt_conn_io_t; - /* * The nxt_listen_event_t is separated from nxt_listen_socket_t * because nxt_listen_socket_t is one per process whilst each worker * thread uses own nxt_listen_event_t. */ typedef struct { - /* Must be the first field. */ - nxt_fd_event_t socket; + /* Must be the first field. */ + nxt_fd_event_t socket; - nxt_task_t task; + nxt_task_t task; - uint32_t ready; - uint32_t batch; - uint32_t count; + uint32_t ready; + uint32_t batch; + uint32_t count; - /* An accept() interface is cached to minimize memory accesses. */ - nxt_work_handler_t accept; + /* An accept() interface is cached to minimize memory accesses. */ + nxt_work_handler_t accept; - nxt_listen_socket_t *listen; - nxt_conn_t *next; - nxt_work_queue_t *work_queue; + nxt_listen_socket_t *listen; + nxt_conn_t *next; + nxt_work_queue_t *work_queue; - nxt_timer_t timer; + nxt_timer_t timer; - nxt_queue_link_t link; + nxt_queue_link_t link; } nxt_listen_event_t; - struct nxt_conn_s { - /* - * Must be the first field, since nxt_fd_event_t - * and nxt_conn_t are used interchangeably. - */ - nxt_fd_event_t socket; - - nxt_buf_t *read; - const nxt_conn_state_t *read_state; - nxt_work_queue_t *read_work_queue; - nxt_timer_t read_timer; - - nxt_buf_t *write; - const nxt_conn_state_t *write_state; - nxt_work_queue_t *write_work_queue; - nxt_event_write_rate_t *rate; - nxt_timer_t write_timer; - - nxt_off_t sent; - uint32_t max_chunk; - uint32_t nbytes; - - nxt_conn_io_t *io; - - union { + /* + * Must be the first field, since nxt_fd_event_t + * and nxt_conn_t are used interchangeably. + */ + nxt_fd_event_t socket; + + nxt_buf_t *read; + const nxt_conn_state_t *read_state; + nxt_work_queue_t *read_work_queue; + nxt_timer_t read_timer; + + nxt_buf_t *write; + const nxt_conn_state_t *write_state; + nxt_work_queue_t *write_work_queue; + nxt_event_write_rate_t *rate; + nxt_timer_t write_timer; + + nxt_off_t sent; + uint32_t max_chunk; + uint32_t nbytes; + + nxt_conn_io_t *io; + + union { #if (NXT_TLS) - void *tls; + void *tls; #endif - nxt_thread_pool_t *thread_pool; - } u; + nxt_thread_pool_t *thread_pool; + } u; - nxt_mp_t *mem_pool; + nxt_mp_t *mem_pool; - nxt_task_t task; - nxt_log_t log; + nxt_task_t task; + nxt_log_t log; - nxt_listen_event_t *listen; + nxt_listen_event_t *listen; - nxt_sockaddr_t *remote; - nxt_sockaddr_t *local; - const char *action; + nxt_sockaddr_t *remote; + nxt_sockaddr_t *local; + const char *action; - uint8_t block_read; /* 1 bit */ - uint8_t block_write; /* 1 bit */ - uint8_t delayed; /* 1 bit */ - uint8_t idle; /* 1 bit */ + uint8_t block_read; /* 1 bit */ + uint8_t block_write; /* 1 bit */ + uint8_t delayed; /* 1 bit */ + uint8_t idle; /* 1 bit */ -#define NXT_CONN_SENDFILE_OFF 0 -#define NXT_CONN_SENDFILE_ON 1 -#define NXT_CONN_SENDFILE_UNSET 3 +#define NXT_CONN_SENDFILE_OFF 0 +#define NXT_CONN_SENDFILE_ON 1 +#define NXT_CONN_SENDFILE_UNSET 3 - uint8_t sendfile; /* 2 bits */ - uint8_t tcp_nodelay; /* 1 bit */ + uint8_t sendfile; /* 2 bits */ + uint8_t tcp_nodelay; /* 1 bit */ - nxt_queue_link_t link; + nxt_queue_link_t link; }; +#define nxt_conn_timer_init(ev, c, wq) \ + do { \ + (ev)->work_queue = (wq); \ + (ev)->log = &(c)->log; \ + (ev)->bias = NXT_TIMER_DEFAULT_BIAS; \ + } while (0) -#define nxt_conn_timer_init(ev, c, wq) \ - do { \ - (ev)->work_queue = (wq); \ - (ev)->log = &(c)->log; \ - (ev)->bias = NXT_TIMER_DEFAULT_BIAS; \ - } while (0) - - -#define nxt_read_timer_conn(ev) \ - nxt_timer_data(ev, nxt_conn_t, read_timer) - - -#define nxt_write_timer_conn(ev) \ - nxt_timer_data(ev, nxt_conn_t, write_timer) +#define nxt_read_timer_conn(ev) nxt_timer_data(ev, nxt_conn_t, read_timer) +#define nxt_write_timer_conn(ev) nxt_timer_data(ev, nxt_conn_t, write_timer) #if (NXT_HAVE_UNIX_DOMAIN) -#define nxt_conn_tcp_nodelay_on(task, c) \ - do { \ - nxt_int_t ret; \ - \ - if ((c)->remote->u.sockaddr.sa_family != AF_UNIX) { \ - ret = nxt_socket_setsockopt(task, (c)->socket.fd, IPPROTO_TCP, \ - TCP_NODELAY, 1); \ - \ - (c)->tcp_nodelay = (ret == NXT_OK); \ - } \ - } while (0) - +#define nxt_conn_tcp_nodelay_on(task, c) \ + do { \ + nxt_int_t ret; \ + \ + if ((c)->remote->u.sockaddr.sa_family != AF_UNIX) { \ + ret = nxt_socket_setsockopt(task, (c)->socket.fd, IPPROTO_TCP, \ + TCP_NODELAY, 1); \ + \ + (c)->tcp_nodelay = (ret == NXT_OK); \ + } \ + } while (0) #else -#define nxt_conn_tcp_nodelay_on(task, c) \ - do { \ - nxt_int_t ret; \ - \ - ret = nxt_socket_setsockopt(task, (c)->socket.fd, IPPROTO_TCP, \ - TCP_NODELAY, 1); \ - \ - (c)->tcp_nodelay = (ret == NXT_OK); \ - } while (0) +#define nxt_conn_tcp_nodelay_on(task, c) \ + do { \ + nxt_int_t ret; \ + \ + ret = nxt_socket_setsockopt(task, (c)->socket.fd, IPPROTO_TCP, \ + TCP_NODELAY, 1); \ + \ + (c)->tcp_nodelay = (ret == NXT_OK); \ + } while (0) #endif - NXT_EXPORT nxt_conn_t *nxt_conn_create(nxt_mp_t *mp, nxt_task_t *task); NXT_EXPORT void nxt_conn_free(nxt_task_t *task, nxt_conn_t *c); NXT_EXPORT void nxt_conn_close(nxt_event_engine_t *engine, nxt_conn_t *c); NXT_EXPORT void nxt_conn_timer(nxt_event_engine_t *engine, nxt_conn_t *c, - const nxt_conn_state_t *state, nxt_timer_t *tev); + const nxt_conn_state_t *state, nxt_timer_t *tev); NXT_EXPORT void nxt_conn_work_queue_set(nxt_conn_t *c, nxt_work_queue_t *wq); -NXT_EXPORT nxt_sockaddr_t *nxt_conn_local_addr(nxt_task_t *task, - nxt_conn_t *c); +NXT_EXPORT nxt_sockaddr_t *nxt_conn_local_addr(nxt_task_t *task, nxt_conn_t *c); void nxt_conn_sys_socket(nxt_task_t *task, void *obj, void *data); void nxt_conn_io_connect(nxt_task_t *task, void *obj, void *data); @@ -236,129 +216,118 @@ void nxt_conn_connect_test(nxt_task_t *task, void *obj, void *data); void nxt_conn_connect_error(nxt_task_t *task, void *obj, void *data); NXT_EXPORT nxt_listen_event_t *nxt_listen_event(nxt_task_t *task, - nxt_listen_socket_t *ls); + nxt_listen_socket_t *ls); void nxt_conn_io_accept(nxt_task_t *task, void *obj, void *data); NXT_EXPORT void nxt_conn_accept(nxt_task_t *task, nxt_listen_event_t *lev, - nxt_conn_t *c); + nxt_conn_t *c); void nxt_conn_accept_error(nxt_task_t *task, nxt_listen_event_t *lev, - const char *accept_syscall, nxt_err_t err); + const char *accept_syscall, nxt_err_t err); void nxt_conn_wait(nxt_conn_t *c); void nxt_conn_io_read(nxt_task_t *task, void *obj, void *data); ssize_t nxt_conn_io_recvbuf(nxt_conn_t *c, nxt_buf_t *b); ssize_t nxt_conn_io_recv(nxt_conn_t *c, void *buf, size_t size, - nxt_uint_t flags); + nxt_uint_t flags); void nxt_conn_io_write(nxt_task_t *task, void *obj, void *data); ssize_t nxt_conn_io_sendbuf(nxt_task_t *task, nxt_sendbuf_t *sb); ssize_t nxt_conn_io_writev(nxt_task_t *task, nxt_sendbuf_t *sb, - nxt_iobuf_t *iob, nxt_uint_t niob); + nxt_iobuf_t *iob, nxt_uint_t niob); ssize_t nxt_conn_io_send(nxt_task_t *task, nxt_sendbuf_t *sb, void *buf, - size_t size); + size_t size); size_t nxt_event_conn_write_limit(nxt_conn_t *c); nxt_bool_t nxt_event_conn_write_delayed(nxt_event_engine_t *engine, - nxt_conn_t *c, size_t sent); + nxt_conn_t *c, size_t sent); ssize_t nxt_event_conn_io_writev(nxt_conn_t *c, nxt_iobuf_t *iob, - nxt_uint_t niob); + nxt_uint_t niob); ssize_t nxt_event_conn_io_send(nxt_conn_t *c, void *buf, size_t size); -NXT_EXPORT void nxt_event_conn_job_sendfile(nxt_task_t *task, - nxt_conn_t *c); - - -#define nxt_conn_connect(engine, c) \ - nxt_work_queue_add(&engine->socket_work_queue, nxt_conn_sys_socket, \ - c->socket.task, c, c->socket.data) - - -#define nxt_conn_read(engine, c) \ - do { \ - nxt_event_engine_t *e = engine; \ - \ - c->socket.read_work_queue = &e->read_work_queue; \ - \ - nxt_work_queue_add(&e->read_work_queue, c->io->read, \ - c->socket.task, c, c->socket.data); \ - } while (0) - - -#define nxt_conn_write(engine, c) \ - do { \ - nxt_event_engine_t *e = engine; \ - \ - c->socket.write_work_queue = &e->write_work_queue; \ - \ - nxt_work_queue_add(&e->write_work_queue, c->io->write, \ - c->socket.task, c, c->socket.data); \ - } while (0) - - -#define nxt_conn_idle(engine, c) \ - do { \ - nxt_event_engine_t *e = engine; \ - \ - nxt_queue_insert_head(&e->idle_connections, &c->link); \ - \ - c->idle = 1; \ - e->idle_conns_cnt++; \ - } while (0) - - -#define nxt_conn_active(engine, c) \ - do { \ - nxt_event_engine_t *e = engine; \ - \ - nxt_queue_remove(&c->link); \ - \ - e->idle_conns_cnt -= c->idle; \ - } while (0) - - -extern nxt_conn_io_t nxt_unix_conn_io; - +NXT_EXPORT void nxt_event_conn_job_sendfile(nxt_task_t *task, nxt_conn_t *c); + +#define nxt_conn_connect(engine, c) \ + nxt_work_queue_add(&engine->socket_work_queue, nxt_conn_sys_socket, \ + c->socket.task, c, c->socket.data) + +#define nxt_conn_read(engine, c) \ + do { \ + nxt_event_engine_t *e = engine; \ + \ + c->socket.read_work_queue = &e->read_work_queue; \ + \ + nxt_work_queue_add(&e->read_work_queue, c->io->read, c->socket.task, c, \ + c->socket.data); \ + } while (0) + +#define nxt_conn_write(engine, c) \ + do { \ + nxt_event_engine_t *e = engine; \ + \ + c->socket.write_work_queue = &e->write_work_queue; \ + \ + nxt_work_queue_add(&e->write_work_queue, c->io->write, c->socket.task, c, \ + c->socket.data); \ + } while (0) + +#define nxt_conn_idle(engine, c) \ + do { \ + nxt_event_engine_t *e = engine; \ + \ + nxt_queue_insert_head(&e->idle_connections, &c->link); \ + \ + c->idle = 1; \ + e->idle_conns_cnt++; \ + } while (0) + +#define nxt_conn_active(engine, c) \ + do { \ + nxt_event_engine_t *e = engine; \ + \ + nxt_queue_remove(&c->link); \ + \ + e->idle_conns_cnt -= c->idle; \ + } while (0) + +extern nxt_conn_io_t nxt_unix_conn_io; typedef struct { - /* - * Client and peer connections are not embedded because already - * existent connections can be switched to the event connection proxy. - */ - nxt_conn_t *client; - nxt_conn_t *peer; - nxt_buf_t *client_buffer; - nxt_buf_t *peer_buffer; - - size_t client_buffer_size; - size_t peer_buffer_size; - - nxt_msec_t client_wait_timeout; - nxt_msec_t connect_timeout; - nxt_msec_t reconnect_timeout; - nxt_msec_t peer_wait_timeout; - nxt_msec_t client_write_timeout; - nxt_msec_t peer_write_timeout; - - uint8_t connected; /* 1 bit */ - uint8_t delayed; /* 1 bit */ - uint8_t retries; /* 8 bits */ - uint8_t retain; /* 2 bits */ - - nxt_work_handler_t completion_handler; + /* + * Client and peer connections are not embedded because already + * existent connections can be switched to the event connection proxy. + */ + nxt_conn_t *client; + nxt_conn_t *peer; + nxt_buf_t *client_buffer; + nxt_buf_t *peer_buffer; + + size_t client_buffer_size; + size_t peer_buffer_size; + + nxt_msec_t client_wait_timeout; + nxt_msec_t connect_timeout; + nxt_msec_t reconnect_timeout; + nxt_msec_t peer_wait_timeout; + nxt_msec_t client_write_timeout; + nxt_msec_t peer_write_timeout; + + uint8_t connected; /* 1 bit */ + uint8_t delayed; /* 1 bit */ + uint8_t retries; /* 8 bits */ + uint8_t retain; /* 2 bits */ + + nxt_work_handler_t completion_handler; } nxt_conn_proxy_t; - NXT_EXPORT nxt_conn_proxy_t *nxt_conn_proxy_create(nxt_conn_t *c); NXT_EXPORT void nxt_conn_proxy(nxt_task_t *task, nxt_conn_proxy_t *p); - /* STUB */ -#define nxt_event_conn_t nxt_conn_t -#define nxt_event_conn_state_t nxt_conn_state_t -#define nxt_event_conn_proxy_t nxt_conn_proxy_t -#define nxt_event_conn_read nxt_conn_read -#define nxt_event_conn_write nxt_conn_write -#define nxt_event_conn_close nxt_conn_close - +#define nxt_event_conn_t nxt_conn_t +#define nxt_event_conn_state_t nxt_conn_state_t +#define nxt_event_conn_proxy_t nxt_conn_proxy_t +#define nxt_event_conn_read nxt_conn_read +#define nxt_event_conn_write nxt_conn_write +#define nxt_event_conn_close nxt_conn_close #endif /* _NXT_CONN_H_INCLUDED_ */ diff --git a/src/nxt_conn_accept.c b/src/nxt_conn_accept.c index 720c7b647..503179b69 100644 --- a/src/nxt_conn_accept.c +++ b/src/nxt_conn_accept.c @@ -6,7 +6,6 @@ #include - /* * A listen socket handler calls an event facility specific io_accept() * method. The method accept()s a new connection and then calls @@ -17,370 +16,333 @@ * then new connections will not be accept()ed for 1 second. */ - static nxt_conn_t *nxt_conn_accept_alloc(nxt_task_t *task, - nxt_listen_event_t *lev); -static void nxt_conn_listen_handler(nxt_task_t *task, void *obj, - void *data); + nxt_listen_event_t *lev); +static void nxt_conn_listen_handler(nxt_task_t *task, void *obj, void *data); static nxt_conn_t *nxt_conn_accept_next(nxt_task_t *task, - nxt_listen_event_t *lev); + nxt_listen_event_t *lev); static void nxt_conn_accept_close_idle(nxt_task_t *task, - nxt_listen_event_t *lev); + nxt_listen_event_t *lev); static void nxt_conn_accept_close_idle_handler(nxt_task_t *task, void *obj, - void *data); + void *data); static void nxt_conn_listen_event_error(nxt_task_t *task, void *obj, - void *data); + void *data); static void nxt_conn_listen_timer_handler(nxt_task_t *task, void *obj, - void *data); - + void *data); -nxt_listen_event_t * -nxt_listen_event(nxt_task_t *task, nxt_listen_socket_t *ls) -{ - nxt_listen_event_t *lev; - nxt_event_engine_t *engine; +nxt_listen_event_t *nxt_listen_event(nxt_task_t *task, + nxt_listen_socket_t *ls) { + nxt_listen_event_t *lev; + nxt_event_engine_t *engine; - lev = nxt_zalloc(sizeof(nxt_listen_event_t)); + lev = nxt_zalloc(sizeof(nxt_listen_event_t)); - if (nxt_fast_path(lev != NULL)) { - lev->socket.fd = ls->socket; + if (nxt_fast_path(lev != NULL)) { + lev->socket.fd = ls->socket; - engine = task->thread->engine; - lev->batch = engine->batch; - lev->count = 1; - - lev->socket.read_work_queue = &engine->accept_work_queue; - lev->socket.read_handler = nxt_conn_listen_handler; - lev->socket.error_handler = nxt_conn_listen_event_error; - lev->socket.log = &nxt_main_log; + engine = task->thread->engine; + lev->batch = engine->batch; + lev->count = 1; - lev->accept = engine->event.io->accept; + lev->socket.read_work_queue = &engine->accept_work_queue; + lev->socket.read_handler = nxt_conn_listen_handler; + lev->socket.error_handler = nxt_conn_listen_event_error; + lev->socket.log = &nxt_main_log; - lev->listen = ls; - lev->work_queue = &engine->read_work_queue; + lev->accept = engine->event.io->accept; - lev->timer.work_queue = &engine->fast_work_queue; - lev->timer.handler = nxt_conn_listen_timer_handler; - lev->timer.log = &nxt_main_log; + lev->listen = ls; + lev->work_queue = &engine->read_work_queue; - lev->task.thread = task->thread; - lev->task.log = &nxt_main_log; - lev->task.ident = nxt_task_next_ident(); - lev->socket.task = &lev->task; - lev->timer.task = &lev->task; + lev->timer.work_queue = &engine->fast_work_queue; + lev->timer.handler = nxt_conn_listen_timer_handler; + lev->timer.log = &nxt_main_log; - if (nxt_conn_accept_alloc(task, lev) != NULL) { - nxt_fd_event_enable_accept(engine, &lev->socket); + lev->task.thread = task->thread; + lev->task.log = &nxt_main_log; + lev->task.ident = nxt_task_next_ident(); + lev->socket.task = &lev->task; + lev->timer.task = &lev->task; - nxt_queue_insert_tail(&engine->listen_connections, &lev->link); - } + if (nxt_conn_accept_alloc(task, lev) != NULL) { + nxt_fd_event_enable_accept(engine, &lev->socket); - return lev; + nxt_queue_insert_tail(&engine->listen_connections, &lev->link); } - return NULL; -} + return lev; + } + return NULL; +} -static nxt_conn_t * -nxt_conn_accept_alloc(nxt_task_t *task, nxt_listen_event_t *lev) -{ - nxt_mp_t *mp; - nxt_conn_t *c; - nxt_event_engine_t *engine; +static nxt_conn_t *nxt_conn_accept_alloc(nxt_task_t *task, + nxt_listen_event_t *lev) { + nxt_mp_t *mp; + nxt_conn_t *c; + nxt_event_engine_t *engine; - engine = task->thread->engine; + engine = task->thread->engine; - if (engine->connections < engine->max_connections) { + if (engine->connections < engine->max_connections) { - mp = nxt_mp_create(1024, 128, 256, 32); + mp = nxt_mp_create(1024, 128, 256, 32); - if (nxt_fast_path(mp != NULL)) { - c = nxt_conn_create(mp, lev->socket.task); - if (nxt_slow_path(c == NULL)) { - nxt_mp_destroy(mp); + if (nxt_fast_path(mp != NULL)) { + c = nxt_conn_create(mp, lev->socket.task); + if (nxt_slow_path(c == NULL)) { + nxt_mp_destroy(mp); - return NULL; - } + return NULL; + } - c->socket.read_work_queue = lev->socket.read_work_queue; - c->socket.write_ready = 1; + c->socket.read_work_queue = lev->socket.read_work_queue; + c->socket.write_ready = 1; - c->remote = nxt_sockaddr_cache_alloc(engine, lev->listen); - if (nxt_fast_path(c->remote != NULL)) { - lev->next = c; - return c; - } + c->remote = nxt_sockaddr_cache_alloc(engine, lev->listen); + if (nxt_fast_path(c->remote != NULL)) { + lev->next = c; + return c; + } - nxt_conn_free(task, c); - } + nxt_conn_free(task, c); } + } - return NULL; + return NULL; } +static void nxt_conn_listen_handler(nxt_task_t *task, void *obj, void *data) { + nxt_listen_event_t *lev; -static void -nxt_conn_listen_handler(nxt_task_t *task, void *obj, void *data) -{ - nxt_listen_event_t *lev; + lev = obj; + lev->ready = lev->batch; - lev = obj; - lev->ready = lev->batch; - - lev->accept(task, lev, data); + lev->accept(task, lev, data); } - -void -nxt_conn_io_accept(nxt_task_t *task, void *obj, void *data) -{ - socklen_t socklen; - nxt_conn_t *c; - nxt_socket_t s; - struct sockaddr *sa; - nxt_listen_event_t *lev; - - lev = obj; - c = lev->next; - - lev->ready--; - lev->socket.read_ready = (lev->ready != 0); - - sa = &c->remote->u.sockaddr; - socklen = c->remote->socklen; - /* - * The returned socklen is ignored here, because sockaddr_in and - * sockaddr_in6 socklens are not changed. As to unspecified sockaddr_un - * it is 3 byte length and already prepared, because old BSDs return zero - * socklen and do not update the sockaddr_un at all; Linux returns 2 byte - * socklen and updates only the sa_family part; other systems copy 3 bytes - * and truncate surplus zero part. Only bound sockaddr_un will be really - * truncated here. - */ - s = accept(lev->socket.fd, sa, &socklen); - - if (s == -1) { - nxt_conn_accept_error(task, lev, "accept", nxt_socket_errno); - return; - } - - c->socket.fd = s; +void nxt_conn_io_accept(nxt_task_t *task, void *obj, void *data) { + socklen_t socklen; + nxt_conn_t *c; + nxt_socket_t s; + struct sockaddr *sa; + nxt_listen_event_t *lev; + + lev = obj; + c = lev->next; + + lev->ready--; + lev->socket.read_ready = (lev->ready != 0); + + sa = &c->remote->u.sockaddr; + socklen = c->remote->socklen; + /* + * The returned socklen is ignored here, because sockaddr_in and + * sockaddr_in6 socklens are not changed. As to unspecified sockaddr_un + * it is 3 byte length and already prepared, because old BSDs return zero + * socklen and do not update the sockaddr_un at all; Linux returns 2 byte + * socklen and updates only the sa_family part; other systems copy 3 bytes + * and truncate surplus zero part. Only bound sockaddr_un will be really + * truncated here. + */ + s = accept(lev->socket.fd, sa, &socklen); + + if (s == -1) { + nxt_conn_accept_error(task, lev, "accept", nxt_socket_errno); + return; + } + + c->socket.fd = s; #if (NXT_LINUX) - /* - * Linux does not inherit non-blocking mode - * from listen socket for accept()ed socket. - */ - if (nxt_slow_path(nxt_socket_nonblocking(task, s) != NXT_OK)) { - nxt_socket_close(task, s); - } + /* + * Linux does not inherit non-blocking mode + * from listen socket for accept()ed socket. + */ + if (nxt_slow_path(nxt_socket_nonblocking(task, s) != NXT_OK)) { + nxt_socket_close(task, s); + } #endif - nxt_debug(task, "accept(%d): %d", lev->socket.fd, s); + nxt_debug(task, "accept(%d): %d", lev->socket.fd, s); - nxt_conn_accept(task, lev, c); + nxt_conn_accept(task, lev, c); } +void nxt_conn_accept(nxt_task_t *task, nxt_listen_event_t *lev, nxt_conn_t *c) { + nxt_conn_t *next; + nxt_event_engine_t *engine; -void -nxt_conn_accept(nxt_task_t *task, nxt_listen_event_t *lev, nxt_conn_t *c) -{ - nxt_conn_t *next; - nxt_event_engine_t *engine; - - nxt_sockaddr_text(c->remote); + nxt_sockaddr_text(c->remote); - nxt_debug(task, "client: %*s", - (size_t) c->remote->address_length, - nxt_sockaddr_address(c->remote)); + nxt_debug(task, "client: %*s", (size_t)c->remote->address_length, + nxt_sockaddr_address(c->remote)); - engine = task->thread->engine; + engine = task->thread->engine; - engine->accepted_conns_cnt++; + engine->accepted_conns_cnt++; - nxt_conn_idle(engine, c); + nxt_conn_idle(engine, c); - c->listen = lev; - lev->count++; - lev->next = NULL; - c->socket.data = NULL; + c->listen = lev; + lev->count++; + lev->next = NULL; + c->socket.data = NULL; - c->read_work_queue = lev->work_queue; - c->write_work_queue = lev->work_queue; + c->read_work_queue = lev->work_queue; + c->write_work_queue = lev->work_queue; - if (lev->listen->read_after_accept) { + if (lev->listen->read_after_accept) { - //c->socket.read_ready = 1; -// lev->listen->handler(task, c, lev); - nxt_work_queue_add(c->read_work_queue, lev->listen->handler, - &c->task, c, lev); + // c->socket.read_ready = 1; + // lev->listen->handler(task, c, lev); + nxt_work_queue_add(c->read_work_queue, lev->listen->handler, &c->task, c, + lev); - } else { - nxt_work_queue_add(c->write_work_queue, lev->listen->handler, - &c->task, c, lev); - } + } else { + nxt_work_queue_add(c->write_work_queue, lev->listen->handler, &c->task, c, + lev); + } - next = nxt_conn_accept_next(task, lev); + next = nxt_conn_accept_next(task, lev); - if (next != NULL && lev->socket.read_ready) { - nxt_work_queue_add(lev->socket.read_work_queue, - lev->accept, task, lev, next); - } + if (next != NULL && lev->socket.read_ready) { + nxt_work_queue_add(lev->socket.read_work_queue, lev->accept, task, lev, + next); + } } +static nxt_conn_t *nxt_conn_accept_next(nxt_task_t *task, + nxt_listen_event_t *lev) { + nxt_conn_t *c; -static nxt_conn_t * -nxt_conn_accept_next(nxt_task_t *task, nxt_listen_event_t *lev) -{ - nxt_conn_t *c; - - c = lev->next; + c = lev->next; - if (c == NULL) { - c = nxt_conn_accept_alloc(task, lev); + if (c == NULL) { + c = nxt_conn_accept_alloc(task, lev); - if (nxt_slow_path(c == NULL)) { - nxt_conn_accept_close_idle(task, lev); - } + if (nxt_slow_path(c == NULL)) { + nxt_conn_accept_close_idle(task, lev); } + } - return c; + return c; } +static void nxt_conn_accept_close_idle(nxt_task_t *task, + nxt_listen_event_t *lev) { + nxt_event_engine_t *engine; -static void -nxt_conn_accept_close_idle(nxt_task_t *task, nxt_listen_event_t *lev) -{ - nxt_event_engine_t *engine; - - engine = task->thread->engine; + engine = task->thread->engine; - nxt_work_queue_add(&engine->close_work_queue, - nxt_conn_accept_close_idle_handler, task, NULL, NULL); + nxt_work_queue_add(&engine->close_work_queue, + nxt_conn_accept_close_idle_handler, task, NULL, NULL); - nxt_timer_add(engine, &lev->timer, 100); + nxt_timer_add(engine, &lev->timer, 100); - nxt_fd_event_disable_read(engine, &lev->socket); + nxt_fd_event_disable_read(engine, &lev->socket); - nxt_alert(task, "new connections are not accepted within 100ms"); + nxt_alert(task, "new connections are not accepted within 100ms"); } +static void nxt_conn_accept_close_idle_handler(nxt_task_t *task, void *obj, + void *data) { + nxt_uint_t times; + nxt_conn_t *c; + nxt_queue_t *idle; + nxt_queue_link_t *link, *next; + nxt_event_engine_t *engine; -static void -nxt_conn_accept_close_idle_handler(nxt_task_t *task, void *obj, void *data) -{ - nxt_uint_t times; - nxt_conn_t *c; - nxt_queue_t *idle; - nxt_queue_link_t *link, *next; - nxt_event_engine_t *engine; - - static nxt_log_moderation_t nxt_idle_close_log_moderation = { - NXT_LOG_INFO, 2, "idle connections closed", NXT_LOG_MODERATION - }; + static nxt_log_moderation_t nxt_idle_close_log_moderation = { + NXT_LOG_INFO, 2, "idle connections closed", NXT_LOG_MODERATION}; - times = 10; - engine = task->thread->engine; - idle = &engine->idle_connections; + times = 10; + engine = task->thread->engine; + idle = &engine->idle_connections; - for (link = nxt_queue_last(idle); - link != nxt_queue_head(idle); - link = next) - { - next = nxt_queue_next(link); + for (link = nxt_queue_last(idle); link != nxt_queue_head(idle); link = next) { + next = nxt_queue_next(link); - c = nxt_queue_link_data(link, nxt_conn_t, link); + c = nxt_queue_link_data(link, nxt_conn_t, link); - nxt_debug(c->socket.task, "idle connection: %d rdy:%d", - c->socket.fd, c->socket.read_ready); + nxt_debug(c->socket.task, "idle connection: %d rdy:%d", c->socket.fd, + c->socket.read_ready); - if (!c->socket.read_ready) { - nxt_log_moderate(&nxt_idle_close_log_moderation, NXT_LOG_INFO, - task->log, "no available connections, " - "close idle connection"); + if (!c->socket.read_ready) { + nxt_log_moderate(&nxt_idle_close_log_moderation, NXT_LOG_INFO, task->log, + "no available connections, " + "close idle connection"); - c->read_state->close_handler(c->socket.task, c, c->socket.data); + c->read_state->close_handler(c->socket.task, c, c->socket.data); - times--; + times--; - if (times == 0) { - break; - } - } + if (times == 0) { + break; + } } + } } +void nxt_conn_accept_error(nxt_task_t *task, nxt_listen_event_t *lev, + const char *accept_syscall, nxt_err_t err) { + static nxt_log_moderation_t nxt_accept_log_moderation = { + NXT_LOG_INFO, 2, "accept() failed", NXT_LOG_MODERATION}; -void -nxt_conn_accept_error(nxt_task_t *task, nxt_listen_event_t *lev, - const char *accept_syscall, nxt_err_t err) -{ - static nxt_log_moderation_t nxt_accept_log_moderation = { - NXT_LOG_INFO, 2, "accept() failed", NXT_LOG_MODERATION - }; - - lev->socket.read_ready = 0; + lev->socket.read_ready = 0; - switch (err) { + switch (err) { - case NXT_EAGAIN: - nxt_debug(task, "%s(%d) %E", accept_syscall, lev->socket.fd, err); - return; + case NXT_EAGAIN: + nxt_debug(task, "%s(%d) %E", accept_syscall, lev->socket.fd, err); + return; - case ECONNABORTED: - nxt_log_moderate(&nxt_accept_log_moderation, NXT_LOG_WARN, - task->log, "%s(%d) failed %E", - accept_syscall, lev->socket.fd, err); - return; + case ECONNABORTED: + nxt_log_moderate(&nxt_accept_log_moderation, NXT_LOG_WARN, task->log, + "%s(%d) failed %E", accept_syscall, lev->socket.fd, err); + return; - case EMFILE: - case ENFILE: - case ENOBUFS: - case ENOMEM: - nxt_alert(task, "%s(%d) failed %E", - accept_syscall, lev->socket.fd, err); + case EMFILE: + case ENFILE: + case ENOBUFS: + case ENOMEM: + nxt_alert(task, "%s(%d) failed %E", accept_syscall, lev->socket.fd, err); - nxt_conn_accept_close_idle(task, lev); - return; + nxt_conn_accept_close_idle(task, lev); + return; - default: - nxt_alert(task, "%s(%d) failed %E", - accept_syscall, lev->socket.fd, err); - return; - } + default: + nxt_alert(task, "%s(%d) failed %E", accept_syscall, lev->socket.fd, err); + return; + } } +static void nxt_conn_listen_timer_handler(nxt_task_t *task, void *obj, + void *data) { + nxt_conn_t *c; + nxt_timer_t *timer; + nxt_listen_event_t *lev; -static void -nxt_conn_listen_timer_handler(nxt_task_t *task, void *obj, void *data) -{ - nxt_conn_t *c; - nxt_timer_t *timer; - nxt_listen_event_t *lev; - - timer = obj; + timer = obj; - lev = nxt_timer_data(timer, nxt_listen_event_t, timer); + lev = nxt_timer_data(timer, nxt_listen_event_t, timer); - c = nxt_conn_accept_next(task, lev); - if (c == NULL) { - return; - } + c = nxt_conn_accept_next(task, lev); + if (c == NULL) { + return; + } - nxt_fd_event_enable_accept(task->thread->engine, &lev->socket); + nxt_fd_event_enable_accept(task->thread->engine, &lev->socket); - lev->accept(task, lev, c); + lev->accept(task, lev, c); } +static void nxt_conn_listen_event_error(nxt_task_t *task, void *obj, + void *data) { + nxt_fd_event_t *ev; -static void -nxt_conn_listen_event_error(nxt_task_t *task, void *obj, void *data) -{ - nxt_fd_event_t *ev; - - ev = obj; + ev = obj; - nxt_alert(task, "accept(%d) event error", ev->fd); + nxt_alert(task, "accept(%d) event error", ev->fd); } diff --git a/src/nxt_conn_close.c b/src/nxt_conn_close.c index bdd669515..b9331c11b 100644 --- a/src/nxt_conn_close.c +++ b/src/nxt_conn_close.c @@ -6,169 +6,155 @@ #include - static void nxt_conn_shutdown_handler(nxt_task_t *task, void *obj, void *data); static void nxt_conn_close_handler(nxt_task_t *task, void *obj, void *data); static void nxt_conn_close_timer_handler(nxt_task_t *task, void *obj, - void *data); + void *data); static void nxt_conn_close_error_ignore(nxt_task_t *task, void *obj, - void *data); + void *data); +void nxt_conn_close(nxt_event_engine_t *engine, nxt_conn_t *c) { + int ret; + nxt_work_queue_t *wq; + nxt_work_handler_t handler; -void -nxt_conn_close(nxt_event_engine_t *engine, nxt_conn_t *c) -{ - int ret; - nxt_work_queue_t *wq; - nxt_work_handler_t handler; + static const struct linger linger_off = { + .l_onoff = 1, + .l_linger = 0, + }; - static const struct linger linger_off = { - .l_onoff = 1, - .l_linger = 0, - }; + nxt_debug(c->socket.task, "conn close fd:%d, to:%d", c->socket.fd, + c->socket.timedout); - nxt_debug(c->socket.task, "conn close fd:%d, to:%d", - c->socket.fd, c->socket.timedout); + /* + * Disable all pending write operations because on success they + * will incorrectly call a ready handler set for nxt_conn_close(). + */ + c->write = NULL; + if (c->socket.timedout) { /* - * Disable all pending write operations because on success they - * will incorrectly call a ready handler set for nxt_conn_close(). + * Resetting of timed out connection on close + * releases kernel memory associated with socket. + * This also causes sending TCP/IP RST to a peer. */ - c->write = NULL; - - if (c->socket.timedout) { - /* - * Resetting of timed out connection on close - * releases kernel memory associated with socket. - * This also causes sending TCP/IP RST to a peer. - */ - ret = setsockopt(c->socket.fd, SOL_SOCKET, SO_LINGER, &linger_off, - sizeof(struct linger)); - - if (nxt_slow_path(ret != 0)) { - nxt_alert(c->socket.task, "setsockopt(%d, SO_LINGER) failed %E", - c->socket.fd, nxt_socket_errno); - } + ret = setsockopt(c->socket.fd, SOL_SOCKET, SO_LINGER, &linger_off, + sizeof(struct linger)); + + if (nxt_slow_path(ret != 0)) { + nxt_alert(c->socket.task, "setsockopt(%d, SO_LINGER) failed %E", + c->socket.fd, nxt_socket_errno); } + } - /* - * Event errors should be ignored here to avoid repeated nxt_conn_close() - * calls. nxt_conn_close_handler() or nxt_conn_close_timer_handler() - * will eventually close socket. - */ - c->socket.error_handler = nxt_conn_close_error_ignore; + /* + * Event errors should be ignored here to avoid repeated nxt_conn_close() + * calls. nxt_conn_close_handler() or nxt_conn_close_timer_handler() + * will eventually close socket. + */ + c->socket.error_handler = nxt_conn_close_error_ignore; - if (c->socket.error == 0 && !c->socket.closed && !c->socket.shutdown) { - wq = &engine->shutdown_work_queue; - handler = nxt_conn_shutdown_handler; + if (c->socket.error == 0 && !c->socket.closed && !c->socket.shutdown) { + wq = &engine->shutdown_work_queue; + handler = nxt_conn_shutdown_handler; - } else { - wq = &engine->close_work_queue; - handler = nxt_conn_close_handler; - } + } else { + wq = &engine->close_work_queue; + handler = nxt_conn_close_handler; + } - nxt_work_queue_add(wq, handler, c->socket.task, c, engine); + nxt_work_queue_add(wq, handler, c->socket.task, c, engine); } +static void nxt_conn_shutdown_handler(nxt_task_t *task, void *obj, void *data) { + nxt_conn_t *c; + nxt_event_engine_t *engine; -static void -nxt_conn_shutdown_handler(nxt_task_t *task, void *obj, void *data) -{ - nxt_conn_t *c; - nxt_event_engine_t *engine; - - c = obj; - engine = data; + c = obj; + engine = data; - nxt_debug(task, "conn shutdown handler fd:%d", c->socket.fd); + nxt_debug(task, "conn shutdown handler fd:%d", c->socket.fd); - c->socket.shutdown = 1; + c->socket.shutdown = 1; - nxt_socket_shutdown(task, c->socket.fd, SHUT_RDWR); + nxt_socket_shutdown(task, c->socket.fd, SHUT_RDWR); - nxt_work_queue_add(&engine->close_work_queue, nxt_conn_close_handler, - task, c, engine); + nxt_work_queue_add(&engine->close_work_queue, nxt_conn_close_handler, task, c, + engine); } +static void nxt_conn_close_handler(nxt_task_t *task, void *obj, void *data) { + nxt_uint_t events_pending, timers_pending; + nxt_conn_t *c; + nxt_event_engine_t *engine; -static void -nxt_conn_close_handler(nxt_task_t *task, void *obj, void *data) -{ - nxt_uint_t events_pending, timers_pending; - nxt_conn_t *c; - nxt_event_engine_t *engine; - - c = obj; - engine = data; + c = obj; + engine = data; - nxt_debug(task, "conn close handler fd:%d", c->socket.fd); + nxt_debug(task, "conn close handler fd:%d", c->socket.fd); - /* - * Socket should be closed only after all pending socket event operations - * will be processed by the kernel. This could be achieved with zero-timer - * handler. Pending timer operations associated with the socket are - * processed before going to the kernel. - */ + /* + * Socket should be closed only after all pending socket event operations + * will be processed by the kernel. This could be achieved with zero-timer + * handler. Pending timer operations associated with the socket are + * processed before going to the kernel. + */ - timers_pending = nxt_timer_delete(engine, &c->read_timer); - timers_pending += nxt_timer_delete(engine, &c->write_timer); + timers_pending = nxt_timer_delete(engine, &c->read_timer); + timers_pending += nxt_timer_delete(engine, &c->write_timer); - events_pending = nxt_fd_event_close(engine, &c->socket); + events_pending = nxt_fd_event_close(engine, &c->socket); - if (events_pending == 0) { - nxt_socket_close(task, c->socket.fd); - c->socket.fd = -1; + if (events_pending == 0) { + nxt_socket_close(task, c->socket.fd); + c->socket.fd = -1; - if (c->idle) { - engine->closed_conns_cnt++; - } + if (c->idle) { + engine->closed_conns_cnt++; + } - if (timers_pending == 0) { - nxt_work_queue_add(&engine->fast_work_queue, - c->write_state->ready_handler, - task, c, c->socket.data); - return; - } + if (timers_pending == 0) { + nxt_work_queue_add(&engine->fast_work_queue, + c->write_state->ready_handler, task, c, + c->socket.data); + return; } + } - c->write_timer.handler = nxt_conn_close_timer_handler; - c->write_timer.work_queue = &engine->fast_work_queue; + c->write_timer.handler = nxt_conn_close_timer_handler; + c->write_timer.work_queue = &engine->fast_work_queue; - nxt_timer_add(engine, &c->write_timer, 0); + nxt_timer_add(engine, &c->write_timer, 0); } +static void nxt_conn_close_timer_handler(nxt_task_t *task, void *obj, + void *data) { + nxt_conn_t *c; + nxt_timer_t *timer; + nxt_event_engine_t *engine; -static void -nxt_conn_close_timer_handler(nxt_task_t *task, void *obj, void *data) -{ - nxt_conn_t *c; - nxt_timer_t *timer; - nxt_event_engine_t *engine; - - timer = obj; + timer = obj; - c = nxt_write_timer_conn(timer); + c = nxt_write_timer_conn(timer); - nxt_debug(task, "conn close timer handler fd:%d", c->socket.fd); + nxt_debug(task, "conn close timer handler fd:%d", c->socket.fd); - engine = task->thread->engine; + engine = task->thread->engine; - if (c->socket.fd != -1) { - nxt_socket_close(task, c->socket.fd); - c->socket.fd = -1; + if (c->socket.fd != -1) { + nxt_socket_close(task, c->socket.fd); + c->socket.fd = -1; - if (c->idle) { - engine->closed_conns_cnt++; - } + if (c->idle) { + engine->closed_conns_cnt++; } + } - nxt_work_queue_add(&engine->fast_work_queue, c->write_state->ready_handler, - task, c, c->socket.data); + nxt_work_queue_add(&engine->fast_work_queue, c->write_state->ready_handler, + task, c, c->socket.data); } - -static void -nxt_conn_close_error_ignore(nxt_task_t *task, void *obj, void *data) -{ - nxt_debug(task, "conn close error ignore"); +static void nxt_conn_close_error_ignore(nxt_task_t *task, void *obj, + void *data) { + nxt_debug(task, "conn close error ignore"); } diff --git a/src/nxt_conn_connect.c b/src/nxt_conn_connect.c index 220fb5f9d..04b26b641 100644 --- a/src/nxt_conn_connect.c +++ b/src/nxt_conn_connect.c @@ -6,198 +6,179 @@ #include - static nxt_err_t nxt_conn_connect_test_error(nxt_task_t *task, nxt_conn_t *c); +void nxt_conn_sys_socket(nxt_task_t *task, void *obj, void *data) { + nxt_conn_t *c; + nxt_work_handler_t handler; -void -nxt_conn_sys_socket(nxt_task_t *task, void *obj, void *data) -{ - nxt_conn_t *c; - nxt_work_handler_t handler; - - c = obj; + c = obj; - if (nxt_conn_socket(task, c) == NXT_OK) { - c->socket.write_work_queue = c->write_work_queue; - handler = c->io->connect; + if (nxt_conn_socket(task, c) == NXT_OK) { + c->socket.write_work_queue = c->write_work_queue; + handler = c->io->connect; - } else { - handler = c->write_state->error_handler; - } + } else { + handler = c->write_state->error_handler; + } - nxt_work_queue_add(&task->thread->engine->connect_work_queue, - handler, task, c, data); + nxt_work_queue_add(&task->thread->engine->connect_work_queue, handler, task, + c, data); } +void nxt_conn_io_connect(nxt_task_t *task, void *obj, void *data) { + nxt_conn_t *c; + nxt_work_handler_t handler; + nxt_event_engine_t *engine; + const nxt_conn_state_t *state; -void -nxt_conn_io_connect(nxt_task_t *task, void *obj, void *data) -{ - nxt_conn_t *c; - nxt_work_handler_t handler; - nxt_event_engine_t *engine; - const nxt_conn_state_t *state; + c = obj; - c = obj; + state = c->write_state; - state = c->write_state; + switch (nxt_socket_connect(task, c->socket.fd, c->remote)) { - switch (nxt_socket_connect(task, c->socket.fd, c->remote)) { + case NXT_OK: + c->socket.write_ready = 1; + handler = state->ready_handler; + break; - case NXT_OK: - c->socket.write_ready = 1; - handler = state->ready_handler; - break; + case NXT_AGAIN: + c->socket.write_handler = nxt_conn_connect_test; + c->socket.error_handler = nxt_conn_connect_error; - case NXT_AGAIN: - c->socket.write_handler = nxt_conn_connect_test; - c->socket.error_handler = nxt_conn_connect_error; + engine = task->thread->engine; - engine = task->thread->engine; + nxt_conn_timer(engine, c, state, &c->write_timer); - nxt_conn_timer(engine, c, state, &c->write_timer); + nxt_fd_event_enable_write(engine, &c->socket); + return; - nxt_fd_event_enable_write(engine, &c->socket); - return; + case NXT_DECLINED: + handler = state->close_handler; + break; - case NXT_DECLINED: - handler = state->close_handler; - break; - - default: /* NXT_ERROR */ - handler = state->error_handler; - break; - } + default: /* NXT_ERROR */ + handler = state->error_handler; + break; + } - nxt_work_queue_add(c->write_work_queue, handler, task, c, data); + nxt_work_queue_add(c->write_work_queue, handler, task, c, data); } +nxt_int_t nxt_conn_socket(nxt_task_t *task, nxt_conn_t *c) { + nxt_uint_t family; + nxt_socket_t s; -nxt_int_t -nxt_conn_socket(nxt_task_t *task, nxt_conn_t *c) -{ - nxt_uint_t family; - nxt_socket_t s; + nxt_debug(task, "event conn socket"); - nxt_debug(task, "event conn socket"); + family = c->remote->u.sockaddr.sa_family; - family = c->remote->u.sockaddr.sa_family; + s = nxt_socket_create(task, family, c->remote->type, 0, NXT_NONBLOCK); - s = nxt_socket_create(task, family, c->remote->type, 0, NXT_NONBLOCK); + if (nxt_slow_path(s == -1)) { + return NXT_ERROR; + } - if (nxt_slow_path(s == -1)) { - return NXT_ERROR; - } - - c->sendfile = 1; + c->sendfile = 1; #if (NXT_HAVE_UNIX_DOMAIN && NXT_SOLARIS) - if (family == AF_UNIX) { - /* Solaris AF_UNIX does not support sendfilev(). */ - c->sendfile = 0; - } + if (family == AF_UNIX) { + /* Solaris AF_UNIX does not support sendfilev(). */ + c->sendfile = 0; + } #endif - c->socket.fd = s; + c->socket.fd = s; - c->socket.task = task; - c->read_timer.task = task; - c->write_timer.task = task; + c->socket.task = task; + c->read_timer.task = task; + c->write_timer.task = task; - if (c->local != NULL) { - if (nxt_slow_path(nxt_socket_bind(task, s, c->local) != NXT_OK)) { - nxt_socket_close(task, s); - return NXT_ERROR; - } + if (c->local != NULL) { + if (nxt_slow_path(nxt_socket_bind(task, s, c->local) != NXT_OK)) { + nxt_socket_close(task, s); + return NXT_ERROR; } + } - return NXT_OK; + return NXT_OK; } +void nxt_conn_connect_test(nxt_task_t *task, void *obj, void *data) { + nxt_err_t err; + nxt_conn_t *c; -void -nxt_conn_connect_test(nxt_task_t *task, void *obj, void *data) -{ - nxt_err_t err; - nxt_conn_t *c; - - c = obj; + c = obj; - nxt_debug(task, "event connect test fd:%d", c->socket.fd); + nxt_debug(task, "event connect test fd:%d", c->socket.fd); - nxt_fd_event_block_write(task->thread->engine, &c->socket); + nxt_fd_event_block_write(task->thread->engine, &c->socket); - if (c->write_state->timer_autoreset) { - nxt_timer_disable(task->thread->engine, &c->write_timer); - } + if (c->write_state->timer_autoreset) { + nxt_timer_disable(task->thread->engine, &c->write_timer); + } - err = nxt_conn_connect_test_error(task, c); + err = nxt_conn_connect_test_error(task, c); - if (err == 0) { - nxt_work_queue_add(c->write_work_queue, c->write_state->ready_handler, - task, c, data); - } else { - nxt_conn_connect_error(task, c, data); - } + if (err == 0) { + nxt_work_queue_add(c->write_work_queue, c->write_state->ready_handler, task, + c, data); + } else { + nxt_conn_connect_error(task, c, data); + } } +void nxt_conn_connect_error(nxt_task_t *task, void *obj, void *data) { + nxt_err_t err; + nxt_conn_t *c; + nxt_work_handler_t handler; + const nxt_conn_state_t *state; -void -nxt_conn_connect_error(nxt_task_t *task, void *obj, void *data) -{ - nxt_err_t err; - nxt_conn_t *c; - nxt_work_handler_t handler; - const nxt_conn_state_t *state; + c = obj; + err = c->socket.error; - c = obj; - err = c->socket.error; - - if (err == 0) { - err = nxt_conn_connect_test_error(task, c); - } + if (err == 0) { + err = nxt_conn_connect_test_error(task, c); + } - state = c->write_state; + state = c->write_state; - switch (err) { + switch (err) { - case NXT_ECONNREFUSED: + case NXT_ECONNREFUSED: #if (NXT_LINUX) - case NXT_EAGAIN: - /* - * Linux returns EAGAIN instead of ECONNREFUSED - * for UNIX sockets if a listen queue is full. - */ + case NXT_EAGAIN: + /* + * Linux returns EAGAIN instead of ECONNREFUSED + * for UNIX sockets if a listen queue is full. + */ #endif - handler = state->close_handler; - break; + handler = state->close_handler; + break; - default: - handler = state->error_handler; - break; - } + default: + handler = state->error_handler; + break; + } - nxt_work_queue_add(c->write_work_queue, handler, task, c, data); + nxt_work_queue_add(c->write_work_queue, handler, task, c, data); } +static nxt_err_t nxt_conn_connect_test_error(nxt_task_t *task, nxt_conn_t *c) { + nxt_err_t err; -static nxt_err_t -nxt_conn_connect_test_error(nxt_task_t *task, nxt_conn_t *c) -{ - nxt_err_t err; + err = nxt_socket_error(c->socket.fd); - err = nxt_socket_error(c->socket.fd); + if (err != 0) { + c->socket.error = err; - if (err != 0) { - c->socket.error = err; - - nxt_log(task, nxt_socket_error_level(err), "connect(%d, %*s) failed %E", - c->socket.fd, (size_t) c->remote->length, - nxt_sockaddr_start(c->remote), err); - } + nxt_log(task, nxt_socket_error_level(err), "connect(%d, %*s) failed %E", + c->socket.fd, (size_t)c->remote->length, + nxt_sockaddr_start(c->remote), err); + } - return err; + return err; } diff --git a/src/nxt_conn_proxy.c b/src/nxt_conn_proxy.c index 055a288d3..ca74f54ed 100644 --- a/src/nxt_conn_proxy.c +++ b/src/nxt_conn_proxy.c @@ -6,279 +6,255 @@ #include - static void nxt_conn_proxy_client_buffer_alloc(nxt_task_t *task, void *obj, - void *data); + void *data); static void nxt_conn_proxy_peer_connect(nxt_task_t *task, void *obj, - void *data); + void *data); static void nxt_conn_proxy_connected(nxt_task_t *task, void *obj, void *data); static void nxt_conn_proxy_peer_read(nxt_task_t *task, void *obj, void *data); static void nxt_conn_proxy_client_read_ready(nxt_task_t *task, void *obj, - void *data); + void *data); static void nxt_conn_proxy_peer_read_ready(nxt_task_t *task, void *obj, - void *data); + void *data); static void nxt_conn_proxy_read_process(nxt_task_t *task, nxt_conn_proxy_t *p, - nxt_conn_t *source, nxt_conn_t *sink); + nxt_conn_t *source, nxt_conn_t *sink); static void nxt_conn_proxy_write_add(nxt_conn_t *c, nxt_buf_t *b); static void nxt_conn_proxy_read(nxt_task_t *task, void *obj, void *data); static void nxt_conn_proxy_client_write_ready(nxt_task_t *task, void *obj, - void *data); + void *data); static void nxt_conn_proxy_peer_write_ready(nxt_task_t *task, void *obj, - void *data); + void *data); static void nxt_conn_proxy_write_process(nxt_task_t *task, nxt_conn_proxy_t *p, - nxt_conn_t *sink, nxt_conn_t *source); + nxt_conn_t *sink, nxt_conn_t *source); static void nxt_conn_proxy_read_add(nxt_conn_t *c, nxt_buf_t *b); static void nxt_conn_proxy_close(nxt_task_t *task, void *obj, void *data); static void nxt_conn_proxy_error(nxt_task_t *task, void *obj, void *data); static void nxt_conn_proxy_read_timeout(nxt_task_t *task, void *obj, - void *data); + void *data); static void nxt_conn_proxy_write_timeout(nxt_task_t *task, void *obj, - void *data); + void *data); static nxt_msec_t nxt_conn_proxy_timeout_value(nxt_conn_t *c, uintptr_t data); static void nxt_conn_proxy_refused(nxt_task_t *task, void *obj, void *data); static void nxt_conn_proxy_reconnect_handler(nxt_task_t *task, void *obj, - void *data); + void *data); static void nxt_conn_proxy_shutdown(nxt_task_t *task, nxt_conn_proxy_t *p, - nxt_conn_t *source, nxt_conn_t *sink); + nxt_conn_t *source, nxt_conn_t *sink); static void nxt_conn_proxy_read_error(nxt_task_t *task, void *obj, void *data); static void nxt_conn_proxy_write_error(nxt_task_t *task, void *obj, void *data); static void nxt_conn_proxy_complete(nxt_task_t *task, nxt_conn_proxy_t *p); static void nxt_conn_proxy_completion(nxt_task_t *task, void *obj, void *data); - -static const nxt_conn_state_t nxt_conn_proxy_client_wait_state; -static const nxt_conn_state_t nxt_conn_proxy_client_first_read_state; -static const nxt_conn_state_t nxt_conn_proxy_peer_connect_state; -static const nxt_conn_state_t nxt_conn_proxy_peer_wait_state; -static const nxt_conn_state_t nxt_conn_proxy_client_read_state; -static const nxt_conn_state_t nxt_conn_proxy_peer_read_state; -static const nxt_conn_state_t nxt_conn_proxy_client_write_state; -static const nxt_conn_state_t nxt_conn_proxy_peer_write_state; - - -nxt_conn_proxy_t * -nxt_conn_proxy_create(nxt_conn_t *client) -{ - nxt_conn_t *peer; - nxt_thread_t *thr; - nxt_conn_proxy_t *p; - - p = nxt_mp_zget(client->mem_pool, sizeof(nxt_conn_proxy_t)); - if (nxt_slow_path(p == NULL)) { - return NULL; - } - - peer = nxt_conn_create(client->mem_pool, client->socket.task); - if (nxt_slow_path(peer == NULL)) { - return NULL; - } - - thr = nxt_thread(); - - client->read_work_queue = &thr->engine->read_work_queue; - client->write_work_queue = &thr->engine->write_work_queue; - client->socket.read_work_queue = &thr->engine->read_work_queue; - client->socket.write_work_queue = &thr->engine->write_work_queue; - peer->socket.read_work_queue = &thr->engine->read_work_queue; - peer->socket.write_work_queue = &thr->engine->write_work_queue; - - peer->socket.data = client->socket.data; - - peer->read_work_queue = client->read_work_queue; - peer->write_work_queue = client->write_work_queue; - peer->read_timer.work_queue = client->read_work_queue; - peer->write_timer.work_queue = client->write_work_queue; - - p->client = client; - p->peer = peer; - - return p; +static const nxt_conn_state_t nxt_conn_proxy_client_wait_state; +static const nxt_conn_state_t nxt_conn_proxy_client_first_read_state; +static const nxt_conn_state_t nxt_conn_proxy_peer_connect_state; +static const nxt_conn_state_t nxt_conn_proxy_peer_wait_state; +static const nxt_conn_state_t nxt_conn_proxy_client_read_state; +static const nxt_conn_state_t nxt_conn_proxy_peer_read_state; +static const nxt_conn_state_t nxt_conn_proxy_client_write_state; +static const nxt_conn_state_t nxt_conn_proxy_peer_write_state; + +nxt_conn_proxy_t *nxt_conn_proxy_create(nxt_conn_t *client) { + nxt_conn_t *peer; + nxt_thread_t *thr; + nxt_conn_proxy_t *p; + + p = nxt_mp_zget(client->mem_pool, sizeof(nxt_conn_proxy_t)); + if (nxt_slow_path(p == NULL)) { + return NULL; + } + + peer = nxt_conn_create(client->mem_pool, client->socket.task); + if (nxt_slow_path(peer == NULL)) { + return NULL; + } + + thr = nxt_thread(); + + client->read_work_queue = &thr->engine->read_work_queue; + client->write_work_queue = &thr->engine->write_work_queue; + client->socket.read_work_queue = &thr->engine->read_work_queue; + client->socket.write_work_queue = &thr->engine->write_work_queue; + peer->socket.read_work_queue = &thr->engine->read_work_queue; + peer->socket.write_work_queue = &thr->engine->write_work_queue; + + peer->socket.data = client->socket.data; + + peer->read_work_queue = client->read_work_queue; + peer->write_work_queue = client->write_work_queue; + peer->read_timer.work_queue = client->read_work_queue; + peer->write_timer.work_queue = client->write_work_queue; + + p->client = client; + p->peer = peer; + + return p; } +void nxt_conn_proxy(nxt_task_t *task, nxt_conn_proxy_t *p) { + nxt_conn_t *peer; -void -nxt_conn_proxy(nxt_task_t *task, nxt_conn_proxy_t *p) -{ - nxt_conn_t *peer; + /* + * Peer read event: not connected, disabled. + * Peer write event: not connected, disabled. + */ + if (p->client_wait_timeout == 0) { /* - * Peer read event: not connected, disabled. - * Peer write event: not connected, disabled. + * Peer write event: waiting for connection + * to be established with connect_timeout. */ + peer = p->peer; + peer->write_state = &nxt_conn_proxy_peer_connect_state; - if (p->client_wait_timeout == 0) { - /* - * Peer write event: waiting for connection - * to be established with connect_timeout. - */ - peer = p->peer; - peer->write_state = &nxt_conn_proxy_peer_connect_state; + nxt_conn_connect(task->thread->engine, peer); + } - nxt_conn_connect(task->thread->engine, peer); - } + /* + * Client read event: waiting for client data with + * client_wait_timeout before buffer allocation. + */ + p->client->read_state = &nxt_conn_proxy_client_wait_state; - /* - * Client read event: waiting for client data with - * client_wait_timeout before buffer allocation. - */ - p->client->read_state = &nxt_conn_proxy_client_wait_state; - - nxt_conn_wait(p->client); + nxt_conn_wait(p->client); } +static const nxt_conn_state_t + nxt_conn_proxy_client_wait_state nxt_aligned(64) = { + .ready_handler = nxt_conn_proxy_client_buffer_alloc, + .close_handler = nxt_conn_proxy_close, + .error_handler = nxt_conn_proxy_error, -static const nxt_conn_state_t nxt_conn_proxy_client_wait_state - nxt_aligned(64) = -{ - .ready_handler = nxt_conn_proxy_client_buffer_alloc, - .close_handler = nxt_conn_proxy_close, - .error_handler = nxt_conn_proxy_error, - - .timer_handler = nxt_conn_proxy_read_timeout, - .timer_value = nxt_conn_proxy_timeout_value, - .timer_data = offsetof(nxt_conn_proxy_t, client_wait_timeout), + .timer_handler = nxt_conn_proxy_read_timeout, + .timer_value = nxt_conn_proxy_timeout_value, + .timer_data = offsetof(nxt_conn_proxy_t, client_wait_timeout), }; +static void nxt_conn_proxy_client_buffer_alloc(nxt_task_t *task, void *obj, + void *data) { + nxt_buf_t *b; + nxt_conn_t *client; + nxt_conn_proxy_t *p; -static void -nxt_conn_proxy_client_buffer_alloc(nxt_task_t *task, void *obj, void *data) -{ - nxt_buf_t *b; - nxt_conn_t *client; - nxt_conn_proxy_t *p; - - client = obj; - p = data; + client = obj; + p = data; - nxt_debug(task, "conn proxy client first read fd:%d", client->socket.fd); + nxt_debug(task, "conn proxy client first read fd:%d", client->socket.fd); - b = nxt_buf_mem_alloc(client->mem_pool, p->client_buffer_size, 0); - if (nxt_slow_path(b == NULL)) { - /* An error completion. */ - nxt_conn_proxy_complete(task, p); - return; - } + b = nxt_buf_mem_alloc(client->mem_pool, p->client_buffer_size, 0); + if (nxt_slow_path(b == NULL)) { + /* An error completion. */ + nxt_conn_proxy_complete(task, p); + return; + } - p->client_buffer = b; - client->read = b; + p->client_buffer = b; + client->read = b; - if (p->peer->socket.fd != -1) { - /* - * Client read event: waiting, no timeout. - * Client write event: blocked. - * Peer read event: disabled. - * Peer write event: waiting for connection to be established - * or blocked after the connection has established. - */ - client->read_state = &nxt_conn_proxy_client_read_state; + if (p->peer->socket.fd != -1) { + /* + * Client read event: waiting, no timeout. + * Client write event: blocked. + * Peer read event: disabled. + * Peer write event: waiting for connection to be established + * or blocked after the connection has established. + */ + client->read_state = &nxt_conn_proxy_client_read_state; - } else { - /* - * Client read event: waiting for data with client_wait_timeout - * before connecting to a peer. - * Client write event: blocked. - * Peer read event: not connected, disabled. - * Peer write event: not connected, disabled. - */ - client->read_state = &nxt_conn_proxy_client_first_read_state; - } + } else { + /* + * Client read event: waiting for data with client_wait_timeout + * before connecting to a peer. + * Client write event: blocked. + * Peer read event: not connected, disabled. + * Peer write event: not connected, disabled. + */ + client->read_state = &nxt_conn_proxy_client_first_read_state; + } - nxt_conn_read(task->thread->engine, client); + nxt_conn_read(task->thread->engine, client); } +static const nxt_conn_state_t + nxt_conn_proxy_client_first_read_state nxt_aligned(64) = { + .ready_handler = nxt_conn_proxy_peer_connect, + .close_handler = nxt_conn_proxy_close, + .error_handler = nxt_conn_proxy_error, -static const nxt_conn_state_t nxt_conn_proxy_client_first_read_state - nxt_aligned(64) = -{ - .ready_handler = nxt_conn_proxy_peer_connect, - .close_handler = nxt_conn_proxy_close, - .error_handler = nxt_conn_proxy_error, - - .timer_handler = nxt_conn_proxy_read_timeout, - .timer_value = nxt_conn_proxy_timeout_value, - .timer_data = offsetof(nxt_conn_proxy_t, client_wait_timeout), - .timer_autoreset = 1, + .timer_handler = nxt_conn_proxy_read_timeout, + .timer_value = nxt_conn_proxy_timeout_value, + .timer_data = offsetof(nxt_conn_proxy_t, client_wait_timeout), + .timer_autoreset = 1, }; +static void nxt_conn_proxy_peer_connect(nxt_task_t *task, void *obj, + void *data) { + nxt_conn_t *client; + nxt_conn_proxy_t *p; -static void -nxt_conn_proxy_peer_connect(nxt_task_t *task, void *obj, void *data) -{ - nxt_conn_t *client; - nxt_conn_proxy_t *p; + client = obj; + p = data; - client = obj; - p = data; + /* + * Client read event: waiting, no timeout. + * Client write event: blocked. + * Peer read event: disabled. + * Peer write event: waiting for connection to be established + * with connect_timeout. + */ + client->read_state = &nxt_conn_proxy_client_read_state; - /* - * Client read event: waiting, no timeout. - * Client write event: blocked. - * Peer read event: disabled. - * Peer write event: waiting for connection to be established - * with connect_timeout. - */ - client->read_state = &nxt_conn_proxy_client_read_state; - - p->peer->write_state = &nxt_conn_proxy_peer_connect_state; + p->peer->write_state = &nxt_conn_proxy_peer_connect_state; - nxt_conn_connect(task->thread->engine, p->peer); + nxt_conn_connect(task->thread->engine, p->peer); } +static const nxt_conn_state_t + nxt_conn_proxy_peer_connect_state nxt_aligned(64) = { + .ready_handler = nxt_conn_proxy_connected, + .close_handler = nxt_conn_proxy_refused, + .error_handler = nxt_conn_proxy_error, -static const nxt_conn_state_t nxt_conn_proxy_peer_connect_state - nxt_aligned(64) = -{ - .ready_handler = nxt_conn_proxy_connected, - .close_handler = nxt_conn_proxy_refused, - .error_handler = nxt_conn_proxy_error, - - .timer_handler = nxt_conn_proxy_write_timeout, - .timer_value = nxt_conn_proxy_timeout_value, - .timer_data = offsetof(nxt_conn_proxy_t, connect_timeout), - .timer_autoreset = 1, + .timer_handler = nxt_conn_proxy_write_timeout, + .timer_value = nxt_conn_proxy_timeout_value, + .timer_data = offsetof(nxt_conn_proxy_t, connect_timeout), + .timer_autoreset = 1, }; +static void nxt_conn_proxy_connected(nxt_task_t *task, void *obj, void *data) { + nxt_conn_t *client, *peer; + nxt_conn_proxy_t *p; -static void -nxt_conn_proxy_connected(nxt_task_t *task, void *obj, void *data) -{ - nxt_conn_t *client, *peer; - nxt_conn_proxy_t *p; - - peer = obj; - p = data; + peer = obj; + p = data; - nxt_debug(task, "conn proxy connected fd:%d", peer->socket.fd); + nxt_debug(task, "conn proxy connected fd:%d", peer->socket.fd); - p->connected = 1; + p->connected = 1; - nxt_conn_tcp_nodelay_on(task, peer); - nxt_conn_tcp_nodelay_on(task, p->client); + nxt_conn_tcp_nodelay_on(task, peer); + nxt_conn_tcp_nodelay_on(task, p->client); - /* Peer read event: waiting with peer_wait_timeout. */ + /* Peer read event: waiting with peer_wait_timeout. */ - peer->read_state = &nxt_conn_proxy_peer_wait_state; - peer->write_state = &nxt_conn_proxy_peer_write_state; + peer->read_state = &nxt_conn_proxy_peer_wait_state; + peer->write_state = &nxt_conn_proxy_peer_write_state; - nxt_conn_wait(peer); + nxt_conn_wait(peer); - if (p->client_buffer != NULL) { - client = p->client; + if (p->client_buffer != NULL) { + client = p->client; - client->read_state = &nxt_conn_proxy_client_read_state; - client->write_state = &nxt_conn_proxy_client_write_state; - /* - * Send a client read data to the connected peer. - * Client write event: blocked. - */ - nxt_conn_proxy_read_process(task, p, client, peer); - } + client->read_state = &nxt_conn_proxy_client_read_state; + client->write_state = &nxt_conn_proxy_client_write_state; + /* + * Send a client read data to the connected peer. + * Client write event: blocked. + */ + nxt_conn_proxy_read_process(task, p, client, peer); + } } - -static const nxt_conn_state_t nxt_conn_proxy_peer_wait_state - nxt_aligned(64) = -{ +static const nxt_conn_state_t nxt_conn_proxy_peer_wait_state nxt_aligned(64) = { .ready_handler = nxt_conn_proxy_peer_read, .close_handler = nxt_conn_proxy_close, .error_handler = nxt_conn_proxy_error, @@ -288,700 +264,627 @@ static const nxt_conn_state_t nxt_conn_proxy_peer_wait_state .timer_data = offsetof(nxt_conn_proxy_t, peer_wait_timeout), }; - -static void -nxt_conn_proxy_peer_read(nxt_task_t *task, void *obj, void *data) -{ - nxt_buf_t *b; - nxt_conn_t *peer; - nxt_conn_proxy_t *p; - - peer = obj; - p = data; - - nxt_debug(task, "conn proxy peer read fd:%d", peer->socket.fd); - - b = nxt_buf_mem_alloc(peer->mem_pool, p->peer_buffer_size, 0); - if (nxt_slow_path(b == NULL)) { - /* An error completion. */ - nxt_conn_proxy_complete(task, p); - return; - } - - p->peer_buffer = b; - peer->read = b; - - p->client->write_state = &nxt_conn_proxy_client_write_state; - peer->read_state = &nxt_conn_proxy_peer_read_state; - peer->write_state = &nxt_conn_proxy_peer_write_state; - - /* - * Client read event: waiting, no timeout. - * Client write event: blocked. - * Peer read event: waiting with possible peer_wait_timeout. - * Peer write event: blocked. - */ - nxt_conn_read(task->thread->engine, peer); +static void nxt_conn_proxy_peer_read(nxt_task_t *task, void *obj, void *data) { + nxt_buf_t *b; + nxt_conn_t *peer; + nxt_conn_proxy_t *p; + + peer = obj; + p = data; + + nxt_debug(task, "conn proxy peer read fd:%d", peer->socket.fd); + + b = nxt_buf_mem_alloc(peer->mem_pool, p->peer_buffer_size, 0); + if (nxt_slow_path(b == NULL)) { + /* An error completion. */ + nxt_conn_proxy_complete(task, p); + return; + } + + p->peer_buffer = b; + peer->read = b; + + p->client->write_state = &nxt_conn_proxy_client_write_state; + peer->read_state = &nxt_conn_proxy_peer_read_state; + peer->write_state = &nxt_conn_proxy_peer_write_state; + + /* + * Client read event: waiting, no timeout. + * Client write event: blocked. + * Peer read event: waiting with possible peer_wait_timeout. + * Peer write event: blocked. + */ + nxt_conn_read(task->thread->engine, peer); } - -static const nxt_conn_state_t nxt_conn_proxy_client_read_state - nxt_aligned(64) = -{ - .ready_handler = nxt_conn_proxy_client_read_ready, - .close_handler = nxt_conn_proxy_close, - .error_handler = nxt_conn_proxy_read_error, +static const nxt_conn_state_t + nxt_conn_proxy_client_read_state nxt_aligned(64) = { + .ready_handler = nxt_conn_proxy_client_read_ready, + .close_handler = nxt_conn_proxy_close, + .error_handler = nxt_conn_proxy_read_error, }; +static void nxt_conn_proxy_client_read_ready(nxt_task_t *task, void *obj, + void *data) { + nxt_conn_t *client; + nxt_conn_proxy_t *p; -static void -nxt_conn_proxy_client_read_ready(nxt_task_t *task, void *obj, void *data) -{ - nxt_conn_t *client; - nxt_conn_proxy_t *p; - - client = obj; - p = data; + client = obj; + p = data; - nxt_debug(task, "conn proxy client read ready fd:%d", client->socket.fd); + nxt_debug(task, "conn proxy client read ready fd:%d", client->socket.fd); - nxt_conn_proxy_read_process(task, p, client, p->peer); + nxt_conn_proxy_read_process(task, p, client, p->peer); } - -static const nxt_conn_state_t nxt_conn_proxy_peer_read_state - nxt_aligned(64) = -{ +static const nxt_conn_state_t nxt_conn_proxy_peer_read_state nxt_aligned(64) = { .ready_handler = nxt_conn_proxy_peer_read_ready, .close_handler = nxt_conn_proxy_close, .error_handler = nxt_conn_proxy_read_error, }; +static void nxt_conn_proxy_peer_read_ready(nxt_task_t *task, void *obj, + void *data) { + nxt_conn_t *peer; + nxt_conn_proxy_t *p; -static void -nxt_conn_proxy_peer_read_ready(nxt_task_t *task, void *obj, void *data) -{ - nxt_conn_t *peer; - nxt_conn_proxy_t *p; - - peer = obj; - p = data; + peer = obj; + p = data; - nxt_debug(task, "conn proxy peer read ready fd:%d", peer->socket.fd); + nxt_debug(task, "conn proxy peer read ready fd:%d", peer->socket.fd); - nxt_conn_proxy_read_process(task, p, peer, p->client); + nxt_conn_proxy_read_process(task, p, peer, p->client); } +static void nxt_conn_proxy_read_process(nxt_task_t *task, nxt_conn_proxy_t *p, + nxt_conn_t *source, nxt_conn_t *sink) { + nxt_buf_t *rb, *wb; -static void -nxt_conn_proxy_read_process(nxt_task_t *task, nxt_conn_proxy_t *p, - nxt_conn_t *source, nxt_conn_t *sink) -{ - nxt_buf_t *rb, *wb; - - if (sink->socket.error != 0) { - nxt_debug(task, "conn proxy sink fd:%d error:%d", - sink->socket.fd, sink->socket.error); - - nxt_conn_proxy_write_error(task, sink, sink->socket.data); - return; - } - - while (source->read != NULL) { + if (sink->socket.error != 0) { + nxt_debug(task, "conn proxy sink fd:%d error:%d", sink->socket.fd, + sink->socket.error); - rb = source->read; + nxt_conn_proxy_write_error(task, sink, sink->socket.data); + return; + } - if (rb->mem.pos != rb->mem.free) { + while (source->read != NULL) { - /* Add a read part to a write chain. */ + rb = source->read; - wb = nxt_buf_mem_alloc(source->mem_pool, 0, 0); - if (wb == NULL) { - /* An error completion. */ - nxt_conn_proxy_complete(task, p); - return; - } + if (rb->mem.pos != rb->mem.free) { - wb->mem.pos = rb->mem.pos; - wb->mem.free = rb->mem.free; - wb->mem.start = rb->mem.pos; - wb->mem.end = rb->mem.free; + /* Add a read part to a write chain. */ - rb->mem.pos = rb->mem.free; - rb->mem.start = rb->mem.free; + wb = nxt_buf_mem_alloc(source->mem_pool, 0, 0); + if (wb == NULL) { + /* An error completion. */ + nxt_conn_proxy_complete(task, p); + return; + } - nxt_conn_proxy_write_add(sink, wb); - } + wb->mem.pos = rb->mem.pos; + wb->mem.free = rb->mem.free; + wb->mem.start = rb->mem.pos; + wb->mem.end = rb->mem.free; - if (rb->mem.start != rb->mem.end) { - nxt_work_queue_add(source->read_work_queue, nxt_conn_proxy_read, - task, source, source->socket.data); - break; - } + rb->mem.pos = rb->mem.free; + rb->mem.start = rb->mem.free; - source->read = rb->next; - nxt_buf_free(source->mem_pool, rb); + nxt_conn_proxy_write_add(sink, wb); } - if (p->connected) { - nxt_conn_write(task->thread->engine, sink); + if (rb->mem.start != rb->mem.end) { + nxt_work_queue_add(source->read_work_queue, nxt_conn_proxy_read, task, + source, source->socket.data); + break; } -} + source->read = rb->next; + nxt_buf_free(source->mem_pool, rb); + } -static void -nxt_conn_proxy_write_add(nxt_conn_t *c, nxt_buf_t *b) -{ - nxt_buf_t *first, *second, *prev; + if (p->connected) { + nxt_conn_write(task->thread->engine, sink); + } +} - first = c->write; +static void nxt_conn_proxy_write_add(nxt_conn_t *c, nxt_buf_t *b) { + nxt_buf_t *first, *second, *prev; - if (first == NULL) { - c->write = b; - return; - } + first = c->write; - /* - * A event conn proxy maintains a buffer per each direction. - * The buffer is divided by read and write parts. These parts are - * linked in buffer chains. There can be no more than two buffers - * in write chain at any time, because an added buffer is coalesced - * with the last buffer if possible. - */ + if (first == NULL) { + c->write = b; + return; + } - second = first->next; + /* + * A event conn proxy maintains a buffer per each direction. + * The buffer is divided by read and write parts. These parts are + * linked in buffer chains. There can be no more than two buffers + * in write chain at any time, because an added buffer is coalesced + * with the last buffer if possible. + */ - if (second == NULL) { + second = first->next; - if (first->mem.end != b->mem.start) { - first->next = b; - return; - } + if (second == NULL) { - /* - * The first buffer is just before the added buffer, so - * expand the first buffer to the end of the added buffer. - */ - prev = first; + if (first->mem.end != b->mem.start) { + first->next = b; + return; + } - } else { - if (second->mem.end != b->mem.start) { - nxt_thread_log_alert("event conn proxy write: second buffer end:%p " - "is not equal to added buffer start:%p", - second->mem.end, b->mem.start); - return; - } - - /* - * "second->mem.end == b->mem.start" must be always true here, - * that is the second buffer is just before the added buffer, - * so expand the second buffer to the end of added buffer. - */ - prev = second; + /* + * The first buffer is just before the added buffer, so + * expand the first buffer to the end of the added buffer. + */ + prev = first; + + } else { + if (second->mem.end != b->mem.start) { + nxt_thread_log_alert("event conn proxy write: second buffer end:%p " + "is not equal to added buffer start:%p", + second->mem.end, b->mem.start); + return; } - prev->mem.free = b->mem.end; - prev->mem.end = b->mem.end; + /* + * "second->mem.end == b->mem.start" must be always true here, + * that is the second buffer is just before the added buffer, + * so expand the second buffer to the end of added buffer. + */ + prev = second; + } + + prev->mem.free = b->mem.end; + prev->mem.end = b->mem.end; - nxt_buf_free(c->mem_pool, b); + nxt_buf_free(c->mem_pool, b); } +static void nxt_conn_proxy_read(nxt_task_t *task, void *obj, void *data) { + nxt_conn_t *source, *sink; + nxt_conn_proxy_t *p; -static void -nxt_conn_proxy_read(nxt_task_t *task, void *obj, void *data) -{ - nxt_conn_t *source, *sink; - nxt_conn_proxy_t *p; - - source = obj; - p = data; + source = obj; + p = data; - nxt_debug(task, "conn proxy read fd:%d", source->socket.fd); + nxt_debug(task, "conn proxy read fd:%d", source->socket.fd); - if (!source->socket.closed) { - sink = (source == p->client) ? p->peer : p->client; + if (!source->socket.closed) { + sink = (source == p->client) ? p->peer : p->client; - if (sink->socket.error == 0) { - nxt_conn_read(task->thread->engine, source); - } + if (sink->socket.error == 0) { + nxt_conn_read(task->thread->engine, source); } + } } +static const nxt_conn_state_t + nxt_conn_proxy_client_write_state nxt_aligned(64) = { + .ready_handler = nxt_conn_proxy_client_write_ready, + .error_handler = nxt_conn_proxy_write_error, -static const nxt_conn_state_t nxt_conn_proxy_client_write_state - nxt_aligned(64) = -{ - .ready_handler = nxt_conn_proxy_client_write_ready, - .error_handler = nxt_conn_proxy_write_error, - - .timer_handler = nxt_conn_proxy_write_timeout, - .timer_value = nxt_conn_proxy_timeout_value, - .timer_data = offsetof(nxt_conn_proxy_t, client_write_timeout), - .timer_autoreset = 1, + .timer_handler = nxt_conn_proxy_write_timeout, + .timer_value = nxt_conn_proxy_timeout_value, + .timer_data = offsetof(nxt_conn_proxy_t, client_write_timeout), + .timer_autoreset = 1, }; +static void nxt_conn_proxy_client_write_ready(nxt_task_t *task, void *obj, + void *data) { + nxt_conn_t *client; + nxt_conn_proxy_t *p; -static void -nxt_conn_proxy_client_write_ready(nxt_task_t *task, void *obj, void *data) -{ - nxt_conn_t *client; - nxt_conn_proxy_t *p; - - client = obj; - p = data; + client = obj; + p = data; - nxt_debug(task, "conn proxy client write ready fd:%d", client->socket.fd); + nxt_debug(task, "conn proxy client write ready fd:%d", client->socket.fd); - nxt_conn_proxy_write_process(task, p, client, p->peer); + nxt_conn_proxy_write_process(task, p, client, p->peer); } +static const nxt_conn_state_t + nxt_conn_proxy_peer_write_state nxt_aligned(64) = { + .ready_handler = nxt_conn_proxy_peer_write_ready, + .error_handler = nxt_conn_proxy_write_error, -static const nxt_conn_state_t nxt_conn_proxy_peer_write_state - nxt_aligned(64) = -{ - .ready_handler = nxt_conn_proxy_peer_write_ready, - .error_handler = nxt_conn_proxy_write_error, - - .timer_handler = nxt_conn_proxy_write_timeout, - .timer_value = nxt_conn_proxy_timeout_value, - .timer_data = offsetof(nxt_conn_proxy_t, peer_write_timeout), - .timer_autoreset = 1, + .timer_handler = nxt_conn_proxy_write_timeout, + .timer_value = nxt_conn_proxy_timeout_value, + .timer_data = offsetof(nxt_conn_proxy_t, peer_write_timeout), + .timer_autoreset = 1, }; +static void nxt_conn_proxy_peer_write_ready(nxt_task_t *task, void *obj, + void *data) { + nxt_conn_t *peer; + nxt_conn_proxy_t *p; -static void -nxt_conn_proxy_peer_write_ready(nxt_task_t *task, void *obj, void *data) -{ - nxt_conn_t *peer; - nxt_conn_proxy_t *p; - - peer = obj; - p = data; + peer = obj; + p = data; - nxt_debug(task, "conn proxy peer write ready fd:%d", peer->socket.fd); + nxt_debug(task, "conn proxy peer write ready fd:%d", peer->socket.fd); - nxt_conn_proxy_write_process(task, p, peer, p->client); + nxt_conn_proxy_write_process(task, p, peer, p->client); } +static void nxt_conn_proxy_write_process(nxt_task_t *task, nxt_conn_proxy_t *p, + nxt_conn_t *sink, nxt_conn_t *source) { + nxt_buf_t *rb, *wb; -static void -nxt_conn_proxy_write_process(nxt_task_t *task, nxt_conn_proxy_t *p, - nxt_conn_t *sink, nxt_conn_t *source) -{ - nxt_buf_t *rb, *wb; - - while (sink->write != NULL) { - - wb = sink->write; + while (sink->write != NULL) { - if (nxt_buf_is_sync(wb)) { + wb = sink->write; - /* A sync buffer marks the end of stream. */ + if (nxt_buf_is_sync(wb)) { - sink->write = NULL; - nxt_buf_free(sink->mem_pool, wb); - nxt_conn_proxy_shutdown(task, p, source, sink); - return; - } + /* A sync buffer marks the end of stream. */ - if (wb->mem.start != wb->mem.pos) { + sink->write = NULL; + nxt_buf_free(sink->mem_pool, wb); + nxt_conn_proxy_shutdown(task, p, source, sink); + return; + } - /* Add a written part to a read chain. */ + if (wb->mem.start != wb->mem.pos) { - rb = nxt_buf_mem_alloc(sink->mem_pool, 0, 0); - if (rb == NULL) { - /* An error completion. */ - nxt_conn_proxy_complete(task, p); - return; - } + /* Add a written part to a read chain. */ - rb->mem.pos = wb->mem.start; - rb->mem.free = wb->mem.start; - rb->mem.start = wb->mem.start; - rb->mem.end = wb->mem.pos; + rb = nxt_buf_mem_alloc(sink->mem_pool, 0, 0); + if (rb == NULL) { + /* An error completion. */ + nxt_conn_proxy_complete(task, p); + return; + } - wb->mem.start = wb->mem.pos; + rb->mem.pos = wb->mem.start; + rb->mem.free = wb->mem.start; + rb->mem.start = wb->mem.start; + rb->mem.end = wb->mem.pos; - nxt_conn_proxy_read_add(source, rb); - } + wb->mem.start = wb->mem.pos; - if (wb->mem.pos != wb->mem.free) { - nxt_conn_write(task->thread->engine, sink); + nxt_conn_proxy_read_add(source, rb); + } - break; - } + if (wb->mem.pos != wb->mem.free) { + nxt_conn_write(task->thread->engine, sink); - sink->write = wb->next; - nxt_buf_free(sink->mem_pool, wb); + break; } - nxt_work_queue_add(source->read_work_queue, nxt_conn_proxy_read, - task, source, source->socket.data); -} + sink->write = wb->next; + nxt_buf_free(sink->mem_pool, wb); + } + nxt_work_queue_add(source->read_work_queue, nxt_conn_proxy_read, task, source, + source->socket.data); +} -static void -nxt_conn_proxy_read_add(nxt_conn_t *c, nxt_buf_t *b) -{ - nxt_buf_t *first, *second; +static void nxt_conn_proxy_read_add(nxt_conn_t *c, nxt_buf_t *b) { + nxt_buf_t *first, *second; + + first = c->read; + + if (first == NULL) { + c->read = b; + return; + } + + /* + * A event conn proxy maintains a buffer per each direction. + * The buffer is divided by read and write parts. These parts are + * linked in buffer chains. There can be no more than two buffers + * in read chain at any time, because an added buffer is coalesced + * with the last buffer if possible. The first and the second + * buffers are also coalesced if possible. + */ + + second = first->next; + + if (second == NULL) { + + if (first->mem.start == b->mem.end) { + /* + * The added buffer is just before the first buffer, so expand + * the first buffer to the beginning of the added buffer. + */ + first->mem.pos = b->mem.start; + first->mem.free = b->mem.start; + first->mem.start = b->mem.start; + + } else if (first->mem.end == b->mem.start) { + /* + * The added buffer is just after the first buffer, so + * expand the first buffer to the end of the added buffer. + */ + first->mem.end = b->mem.end; - first = c->read; + } else { + first->next = b; + return; + } - if (first == NULL) { - c->read = b; - return; + } else { + if (second->mem.end != b->mem.start) { + nxt_thread_log_alert("event conn proxy read: second buffer end:%p " + "is not equal to added buffer start:%p", + second->mem.end, b->mem.start); + return; } /* - * A event conn proxy maintains a buffer per each direction. - * The buffer is divided by read and write parts. These parts are - * linked in buffer chains. There can be no more than two buffers - * in read chain at any time, because an added buffer is coalesced - * with the last buffer if possible. The first and the second - * buffers are also coalesced if possible. + * The added buffer is just after the second buffer, so + * expand the second buffer to the end of the added buffer. */ - - second = first->next; - - if (second == NULL) { - - if (first->mem.start == b->mem.end) { - /* - * The added buffer is just before the first buffer, so expand - * the first buffer to the beginning of the added buffer. - */ - first->mem.pos = b->mem.start; - first->mem.free = b->mem.start; - first->mem.start = b->mem.start; - - } else if (first->mem.end == b->mem.start) { - /* - * The added buffer is just after the first buffer, so - * expand the first buffer to the end of the added buffer. - */ - first->mem.end = b->mem.end; - - } else { - first->next = b; - return; - } - - } else { - if (second->mem.end != b->mem.start) { - nxt_thread_log_alert("event conn proxy read: second buffer end:%p " - "is not equal to added buffer start:%p", - second->mem.end, b->mem.start); - return; - } - - /* - * The added buffer is just after the second buffer, so - * expand the second buffer to the end of the added buffer. - */ - second->mem.end = b->mem.end; - - if (first->mem.start == second->mem.end) { - /* - * The second buffer is just before the first buffer, so expand - * the first buffer to the beginning of the second buffer. - */ - first->mem.pos = second->mem.start; - first->mem.free = second->mem.start; - first->mem.start = second->mem.start; - first->next = NULL; - - nxt_buf_free(c->mem_pool, second); - } + second->mem.end = b->mem.end; + + if (first->mem.start == second->mem.end) { + /* + * The second buffer is just before the first buffer, so expand + * the first buffer to the beginning of the second buffer. + */ + first->mem.pos = second->mem.start; + first->mem.free = second->mem.start; + first->mem.start = second->mem.start; + first->next = NULL; + + nxt_buf_free(c->mem_pool, second); } + } - nxt_buf_free(c->mem_pool, b); + nxt_buf_free(c->mem_pool, b); } +static void nxt_conn_proxy_close(nxt_task_t *task, void *obj, void *data) { + nxt_buf_t *b; + nxt_conn_t *source, *sink; + nxt_conn_proxy_t *p; -static void -nxt_conn_proxy_close(nxt_task_t *task, void *obj, void *data) -{ - nxt_buf_t *b; - nxt_conn_t *source, *sink; - nxt_conn_proxy_t *p; + source = obj; + p = data; - source = obj; - p = data; + nxt_debug(task, "conn proxy close fd:%d", source->socket.fd); - nxt_debug(task, "conn proxy close fd:%d", source->socket.fd); + sink = (source == p->client) ? p->peer : p->client; - sink = (source == p->client) ? p->peer : p->client; + if (sink->write == NULL) { + nxt_conn_proxy_shutdown(task, p, source, sink); + return; + } - if (sink->write == NULL) { - nxt_conn_proxy_shutdown(task, p, source, sink); - return; - } + b = nxt_buf_sync_alloc(source->mem_pool, 0); + if (b == NULL) { + /* An error completion. */ + nxt_conn_proxy_complete(task, p); + return; + } - b = nxt_buf_sync_alloc(source->mem_pool, 0); - if (b == NULL) { - /* An error completion. */ - nxt_conn_proxy_complete(task, p); - return; - } - - nxt_buf_chain_add(&sink->write, b); + nxt_buf_chain_add(&sink->write, b); } +static void nxt_conn_proxy_error(nxt_task_t *task, void *obj, void *data) { + nxt_conn_t *c; + nxt_conn_proxy_t *p; -static void -nxt_conn_proxy_error(nxt_task_t *task, void *obj, void *data) -{ - nxt_conn_t *c; - nxt_conn_proxy_t *p; - - c = obj; - p = data; + c = obj; + p = data; - nxt_debug(task, "conn proxy error fd:%d", c->socket.fd); + nxt_debug(task, "conn proxy error fd:%d", c->socket.fd); - nxt_conn_proxy_close(task, c, p); + nxt_conn_proxy_close(task, c, p); } +static void nxt_conn_proxy_read_timeout(nxt_task_t *task, void *obj, + void *data) { + nxt_conn_t *c; + nxt_timer_t *timer; -static void -nxt_conn_proxy_read_timeout(nxt_task_t *task, void *obj, void *data) -{ - nxt_conn_t *c; - nxt_timer_t *timer; - - timer = obj; + timer = obj; - c = nxt_read_timer_conn(timer); - c->socket.timedout = 1; - c->socket.closed = 1; + c = nxt_read_timer_conn(timer); + c->socket.timedout = 1; + c->socket.closed = 1; - nxt_debug(task, "conn proxy read timeout fd:%d", c->socket.fd); + nxt_debug(task, "conn proxy read timeout fd:%d", c->socket.fd); - nxt_conn_proxy_close(task, c, c->socket.data); + nxt_conn_proxy_close(task, c, c->socket.data); } +static void nxt_conn_proxy_write_timeout(nxt_task_t *task, void *obj, + void *data) { + nxt_conn_t *c; + nxt_timer_t *timer; -static void -nxt_conn_proxy_write_timeout(nxt_task_t *task, void *obj, void *data) -{ - nxt_conn_t *c; - nxt_timer_t *timer; - - timer = obj; + timer = obj; - c = nxt_write_timer_conn(timer); - c->socket.timedout = 1; - c->socket.closed = 1; + c = nxt_write_timer_conn(timer); + c->socket.timedout = 1; + c->socket.closed = 1; - nxt_debug(task, "conn proxy write timeout fd:%d", c->socket.fd); + nxt_debug(task, "conn proxy write timeout fd:%d", c->socket.fd); - nxt_conn_proxy_close(task, c, c->socket.data); + nxt_conn_proxy_close(task, c, c->socket.data); } - -static nxt_msec_t -nxt_conn_proxy_timeout_value(nxt_conn_t *c, uintptr_t data) -{ - return nxt_value_at(nxt_msec_t, c->socket.data, data); +static nxt_msec_t nxt_conn_proxy_timeout_value(nxt_conn_t *c, uintptr_t data) { + return nxt_value_at(nxt_msec_t, c->socket.data, data); } +static void nxt_conn_proxy_refused(nxt_task_t *task, void *obj, void *data) { + nxt_conn_t *peer; + nxt_conn_proxy_t *p; -static void -nxt_conn_proxy_refused(nxt_task_t *task, void *obj, void *data) -{ - nxt_conn_t *peer; - nxt_conn_proxy_t *p; + peer = obj; + p = data; - peer = obj; - p = data; + nxt_debug(task, "conn proxy refused fd:%d", peer->socket.fd); - nxt_debug(task, "conn proxy refused fd:%d", peer->socket.fd); + if (p->retries == 0) { + /* An error completion. */ + nxt_conn_proxy_complete(task, p); + return; + } - if (p->retries == 0) { - /* An error completion. */ - nxt_conn_proxy_complete(task, p); - return; - } - - p->retries--; + p->retries--; - nxt_socket_close(task, peer->socket.fd); - peer->socket.fd = -1; - peer->socket.error = 0; + nxt_socket_close(task, peer->socket.fd); + peer->socket.fd = -1; + peer->socket.error = 0; - p->delayed = 1; + p->delayed = 1; - peer->write_timer.handler = nxt_conn_proxy_reconnect_handler; - nxt_timer_add(task->thread->engine, &peer->write_timer, - p->reconnect_timeout); + peer->write_timer.handler = nxt_conn_proxy_reconnect_handler; + nxt_timer_add(task->thread->engine, &peer->write_timer, p->reconnect_timeout); } +static void nxt_conn_proxy_reconnect_handler(nxt_task_t *task, void *obj, + void *data) { + nxt_conn_t *peer; + nxt_timer_t *timer; + nxt_conn_proxy_t *p; -static void -nxt_conn_proxy_reconnect_handler(nxt_task_t *task, void *obj, void *data) -{ - nxt_conn_t *peer; - nxt_timer_t *timer; - nxt_conn_proxy_t *p; - - timer = obj; + timer = obj; - nxt_debug(task, "conn proxy reconnect timer"); + nxt_debug(task, "conn proxy reconnect timer"); - peer = nxt_write_timer_conn(timer); - p = peer->socket.data; + peer = nxt_write_timer_conn(timer); + p = peer->socket.data; - if (p->client->socket.closed) { - nxt_conn_proxy_complete(task, p); - return; - } + if (p->client->socket.closed) { + nxt_conn_proxy_complete(task, p); + return; + } - p->delayed = 0; + p->delayed = 0; - peer->write_state = &nxt_conn_proxy_peer_connect_state; - /* - * Peer read event: disabled. - * Peer write event: waiting for connection with connect_timeout. - */ - nxt_conn_connect(task->thread->engine, peer); + peer->write_state = &nxt_conn_proxy_peer_connect_state; + /* + * Peer read event: disabled. + * Peer write event: waiting for connection with connect_timeout. + */ + nxt_conn_connect(task->thread->engine, peer); } - -static void -nxt_conn_proxy_shutdown(nxt_task_t *task, nxt_conn_proxy_t *p, - nxt_conn_t *source, nxt_conn_t *sink) -{ - nxt_buf_t *b; - - nxt_debug(source->socket.task, - "conn proxy shutdown source fd:%d cl:%d err:%d", - source->socket.fd, source->socket.closed, source->socket.error); - - nxt_debug(sink->socket.task, - "conn proxy shutdown sink fd:%d cl:%d err:%d", - sink->socket.fd, sink->socket.closed, sink->socket.error); - - if (!p->connected || p->delayed) { - nxt_conn_proxy_complete(task, p); - return; - } - - if (sink->socket.error == 0 && !sink->socket.closed) { - sink->socket.shutdown = 1; - nxt_socket_shutdown(task, sink->socket.fd, SHUT_WR); - } - - if (sink->socket.error != 0 - || (sink->socket.closed && source->write == NULL)) - { - /* The opposite direction also has been already closed. */ - nxt_conn_proxy_complete(task, p); - return; - } - - nxt_debug(source->socket.task, "free source buffer"); - - /* Free the direction's buffer. */ - b = (source == p->client) ? p->client_buffer : p->peer_buffer; - nxt_mp_free(source->mem_pool, b); +static void nxt_conn_proxy_shutdown(nxt_task_t *task, nxt_conn_proxy_t *p, + nxt_conn_t *source, nxt_conn_t *sink) { + nxt_buf_t *b; + + nxt_debug(source->socket.task, + "conn proxy shutdown source fd:%d cl:%d err:%d", source->socket.fd, + source->socket.closed, source->socket.error); + + nxt_debug(sink->socket.task, "conn proxy shutdown sink fd:%d cl:%d err:%d", + sink->socket.fd, sink->socket.closed, sink->socket.error); + + if (!p->connected || p->delayed) { + nxt_conn_proxy_complete(task, p); + return; + } + + if (sink->socket.error == 0 && !sink->socket.closed) { + sink->socket.shutdown = 1; + nxt_socket_shutdown(task, sink->socket.fd, SHUT_WR); + } + + if (sink->socket.error != 0 || + (sink->socket.closed && source->write == NULL)) { + /* The opposite direction also has been already closed. */ + nxt_conn_proxy_complete(task, p); + return; + } + + nxt_debug(source->socket.task, "free source buffer"); + + /* Free the direction's buffer. */ + b = (source == p->client) ? p->client_buffer : p->peer_buffer; + nxt_mp_free(source->mem_pool, b); } +static void nxt_conn_proxy_read_error(nxt_task_t *task, void *obj, void *data) { + nxt_conn_t *c; + nxt_conn_proxy_t *p; -static void -nxt_conn_proxy_read_error(nxt_task_t *task, void *obj, void *data) -{ - nxt_conn_t *c; - nxt_conn_proxy_t *p; + c = obj; + p = data; - c = obj; - p = data; + nxt_debug(task, "conn proxy read error fd:%d", c->socket.fd); - nxt_debug(task, "conn proxy read error fd:%d", c->socket.fd); - - nxt_conn_proxy_close(task, c, p); + nxt_conn_proxy_close(task, c, p); } +static void nxt_conn_proxy_write_error(nxt_task_t *task, void *obj, + void *data) { + nxt_conn_t *source, *sink; + nxt_conn_proxy_t *p; -static void -nxt_conn_proxy_write_error(nxt_task_t *task, void *obj, void *data) -{ - nxt_conn_t *source, *sink; - nxt_conn_proxy_t *p; - - sink = obj; - p = data; + sink = obj; + p = data; - nxt_debug(task, "conn proxy write error fd:%d", sink->socket.fd); + nxt_debug(task, "conn proxy write error fd:%d", sink->socket.fd); - /* Clear data for the direction sink. */ - sink->write = NULL; + /* Clear data for the direction sink. */ + sink->write = NULL; - /* Block the direction source. */ - source = (sink == p->client) ? p->peer : p->client; - nxt_fd_event_block_read(task->thread->engine, &source->socket); + /* Block the direction source. */ + source = (sink == p->client) ? p->peer : p->client; + nxt_fd_event_block_read(task->thread->engine, &source->socket); - if (source->write == NULL) { - /* - * There is no data for the opposite direction and - * the next read from the sink will most probably fail. - */ - nxt_conn_proxy_complete(task, p); - } + if (source->write == NULL) { + /* + * There is no data for the opposite direction and + * the next read from the sink will most probably fail. + */ + nxt_conn_proxy_complete(task, p); + } } - -static const nxt_conn_state_t nxt_conn_proxy_close_state - nxt_aligned(64) = -{ +static const nxt_conn_state_t nxt_conn_proxy_close_state nxt_aligned(64) = { .ready_handler = nxt_conn_proxy_completion, }; +static void nxt_conn_proxy_complete(nxt_task_t *task, nxt_conn_proxy_t *p) { + nxt_event_engine_t *engine; -static void -nxt_conn_proxy_complete(nxt_task_t *task, nxt_conn_proxy_t *p) -{ - nxt_event_engine_t *engine; + engine = task->thread->engine; - engine = task->thread->engine; - - nxt_debug(p->client->socket.task, "conn proxy complete %d:%d", - p->client->socket.fd, p->peer->socket.fd); - - if (p->delayed) { - p->delayed = 0; - nxt_queue_remove(&p->peer->link); - } + nxt_debug(p->client->socket.task, "conn proxy complete %d:%d", + p->client->socket.fd, p->peer->socket.fd); - if (p->client->socket.fd != -1) { - p->retain = 1; - p->client->write_state = &nxt_conn_proxy_close_state; - nxt_conn_close(engine, p->client); - } - - if (p->peer->socket.fd != -1) { - p->retain++; - p->peer->write_state = &nxt_conn_proxy_close_state; - nxt_conn_close(engine, p->peer); - } + if (p->delayed) { + p->delayed = 0; + nxt_queue_remove(&p->peer->link); + } + + if (p->client->socket.fd != -1) { + p->retain = 1; + p->client->write_state = &nxt_conn_proxy_close_state; + nxt_conn_close(engine, p->client); + } + + if (p->peer->socket.fd != -1) { + p->retain++; + p->peer->write_state = &nxt_conn_proxy_close_state; + nxt_conn_close(engine, p->peer); + } } +static void nxt_conn_proxy_completion(nxt_task_t *task, void *obj, void *data) { + nxt_conn_proxy_t *p; -static void -nxt_conn_proxy_completion(nxt_task_t *task, void *obj, void *data) -{ - nxt_conn_proxy_t *p; - - p = data; + p = data; - nxt_debug(p->client->socket.task, "conn proxy completion %d:%d:%d", - p->retain, p->client->socket.fd, p->peer->socket.fd); + nxt_debug(p->client->socket.task, "conn proxy completion %d:%d:%d", p->retain, + p->client->socket.fd, p->peer->socket.fd); - p->retain--; + p->retain--; - if (p->retain == 0) { - nxt_mp_free(p->client->mem_pool, p->client_buffer); - nxt_mp_free(p->client->mem_pool, p->peer_buffer); + if (p->retain == 0) { + nxt_mp_free(p->client->mem_pool, p->client_buffer); + nxt_mp_free(p->client->mem_pool, p->peer_buffer); - p->completion_handler(task, p, NULL); - } + p->completion_handler(task, p, NULL); + } } diff --git a/src/nxt_conn_read.c b/src/nxt_conn_read.c index 3285abcd1..39c964181 100644 --- a/src/nxt_conn_read.c +++ b/src/nxt_conn_read.c @@ -6,247 +6,235 @@ #include +void nxt_conn_wait(nxt_conn_t *c) { + nxt_event_engine_t *engine; + const nxt_conn_state_t *state; -void -nxt_conn_wait(nxt_conn_t *c) -{ - nxt_event_engine_t *engine; - const nxt_conn_state_t *state; + nxt_debug(c->socket.task, "conn wait fd:%d rdy:%d", c->socket.fd, + c->socket.read_ready); - nxt_debug(c->socket.task, "conn wait fd:%d rdy:%d", - c->socket.fd, c->socket.read_ready); + engine = c->socket.task->thread->engine; + state = c->read_state; - engine = c->socket.task->thread->engine; - state = c->read_state; + if (c->socket.read_ready) { + nxt_work_queue_add(&engine->fast_work_queue, state->ready_handler, + c->socket.task, c, c->socket.data); + return; + } - if (c->socket.read_ready) { - nxt_work_queue_add(&engine->fast_work_queue, state->ready_handler, - c->socket.task, c, c->socket.data); - return; - } + c->socket.read_handler = state->ready_handler; + c->socket.error_handler = state->error_handler; - c->socket.read_handler = state->ready_handler; - c->socket.error_handler = state->error_handler; - - nxt_conn_timer(engine, c, state, &c->read_timer); + nxt_conn_timer(engine, c, state, &c->read_timer); - nxt_fd_event_enable_read(engine, &c->socket); + nxt_fd_event_enable_read(engine, &c->socket); } +void nxt_conn_io_read(nxt_task_t *task, void *obj, void *data) { + ssize_t n; + nxt_conn_t *c; + nxt_event_engine_t *engine; + nxt_work_handler_t handler; + const nxt_conn_state_t *state; -void -nxt_conn_io_read(nxt_task_t *task, void *obj, void *data) -{ - ssize_t n; - nxt_conn_t *c; - nxt_event_engine_t *engine; - nxt_work_handler_t handler; - const nxt_conn_state_t *state; + c = obj; - c = obj; + nxt_debug(task, "conn read fd:%d rdy:%d cl:%d er:%d bl:%d", c->socket.fd, + c->socket.read_ready, c->socket.closed, c->socket.error, + c->block_read); - nxt_debug(task, "conn read fd:%d rdy:%d cl:%d er:%d bl:%d", - c->socket.fd, c->socket.read_ready, c->socket.closed, - c->socket.error, c->block_read); + if (c->socket.error != 0 || c->block_read) { + return; + } - if (c->socket.error != 0 || c->block_read) { - return; - } + engine = task->thread->engine; - engine = task->thread->engine; + /* + * Here c->io->read() is assigned instead of direct nxt_conn_io_read() + * because the function can be called by nxt_kqueue_conn_io_read(). + */ + c->socket.read_handler = c->io->read; + state = c->read_state; + c->socket.error_handler = state->error_handler; - /* - * Here c->io->read() is assigned instead of direct nxt_conn_io_read() - * because the function can be called by nxt_kqueue_conn_io_read(). - */ - c->socket.read_handler = c->io->read; - state = c->read_state; - c->socket.error_handler = state->error_handler; + if (c->socket.read_ready) { - if (c->socket.read_ready) { + if (state->io_read_handler == NULL) { + n = c->io->recvbuf(c, c->read); - if (state->io_read_handler == NULL) { - n = c->io->recvbuf(c, c->read); - - } else { - n = state->io_read_handler(task, c); - /* The state can be changed by io_read_handler. */ - state = c->read_state; - } + } else { + n = state->io_read_handler(task, c); + /* The state can be changed by io_read_handler. */ + state = c->read_state; + } - if (n > 0) { - c->nbytes = n; + if (n > 0) { + c->nbytes = n; - nxt_recvbuf_update(c->read, n); + nxt_recvbuf_update(c->read, n); - nxt_fd_event_block_read(engine, &c->socket); + nxt_fd_event_block_read(engine, &c->socket); - if (state->timer_autoreset) { - nxt_timer_disable(engine, &c->read_timer); - } + if (state->timer_autoreset) { + nxt_timer_disable(engine, &c->read_timer); + } - nxt_work_queue_add(c->read_work_queue, - state->ready_handler, task, c, data); - return; - } + nxt_work_queue_add(c->read_work_queue, state->ready_handler, task, c, + data); + return; + } - if (n != NXT_AGAIN) { - /* n == 0 or n == NXT_ERROR. */ - handler = (n == 0) ? state->close_handler : state->error_handler; + if (n != NXT_AGAIN) { + /* n == 0 or n == NXT_ERROR. */ + handler = (n == 0) ? state->close_handler : state->error_handler; - nxt_fd_event_block_read(engine, &c->socket); - nxt_timer_disable(engine, &c->read_timer); + nxt_fd_event_block_read(engine, &c->socket); + nxt_timer_disable(engine, &c->read_timer); - nxt_work_queue_add(&engine->fast_work_queue, - handler, task, c, data); - return; - } + nxt_work_queue_add(&engine->fast_work_queue, handler, task, c, data); + return; + } - /* n == NXT_AGAIN. */ + /* n == NXT_AGAIN. */ - if (c->socket.read_ready) { - /* - * SSL/TLS library can return NXT_AGAIN if renegotiation - * occured during read operation, it toggled write event - * internally so only read timer should be set. - */ - if (!c->read_timer.enabled) { - nxt_conn_timer(engine, c, state, &c->read_timer); - } + if (c->socket.read_ready) { + /* + * SSL/TLS library can return NXT_AGAIN if renegotiation + * occured during read operation, it toggled write event + * internally so only read timer should be set. + */ + if (!c->read_timer.enabled) { + nxt_conn_timer(engine, c, state, &c->read_timer); + } - return; - } + return; } + } - if (nxt_fd_event_is_disabled(c->socket.read)) { - nxt_fd_event_enable_read(engine, &c->socket); - } + if (nxt_fd_event_is_disabled(c->socket.read)) { + nxt_fd_event_enable_read(engine, &c->socket); + } - if (state->timer_autoreset || !c->read_timer.enabled) { - nxt_conn_timer(engine, c, state, &c->read_timer); - } + if (state->timer_autoreset || !c->read_timer.enabled) { + nxt_conn_timer(engine, c, state, &c->read_timer); + } } +ssize_t nxt_conn_io_recvbuf(nxt_conn_t *c, nxt_buf_t *b) { + ssize_t n; + nxt_err_t err; + nxt_uint_t niov; + struct iovec iov[NXT_IOBUF_MAX]; + nxt_recvbuf_coalesce_t rb; -ssize_t -nxt_conn_io_recvbuf(nxt_conn_t *c, nxt_buf_t *b) -{ - ssize_t n; - nxt_err_t err; - nxt_uint_t niov; - struct iovec iov[NXT_IOBUF_MAX]; - nxt_recvbuf_coalesce_t rb; - - rb.buf = b; - rb.iobuf = iov; - rb.nmax = NXT_IOBUF_MAX; - rb.size = 0; + rb.buf = b; + rb.iobuf = iov; + rb.nmax = NXT_IOBUF_MAX; + rb.size = 0; - niov = nxt_recvbuf_mem_coalesce(&rb); + niov = nxt_recvbuf_mem_coalesce(&rb); - if (niov == 1) { - /* Disposal of surplus kernel iovec copy-in operation. */ - return nxt_conn_io_recv(c, iov->iov_base, iov->iov_len, 0); - } + if (niov == 1) { + /* Disposal of surplus kernel iovec copy-in operation. */ + return nxt_conn_io_recv(c, iov->iov_base, iov->iov_len, 0); + } - for ( ;; ) { - n = readv(c->socket.fd, iov, niov); + for (;;) { + n = readv(c->socket.fd, iov, niov); - err = (n == -1) ? nxt_socket_errno : 0; + err = (n == -1) ? nxt_socket_errno : 0; - nxt_debug(c->socket.task, "readv(%d, %ui): %z", c->socket.fd, niov, n); + nxt_debug(c->socket.task, "readv(%d, %ui): %z", c->socket.fd, niov, n); - if (n > 0) { - if ((size_t) n < rb.size) { - c->socket.read_ready = 0; - } + if (n > 0) { + if ((size_t)n < rb.size) { + c->socket.read_ready = 0; + } - return n; - } + return n; + } - if (n == 0) { - c->socket.closed = 1; - c->socket.read_ready = 0; - return n; - } + if (n == 0) { + c->socket.closed = 1; + c->socket.read_ready = 0; + return n; + } - /* n == -1 */ + /* n == -1 */ - switch (err) { + switch (err) { - case NXT_EAGAIN: - nxt_debug(c->socket.task, "readv() %E", err); - c->socket.read_ready = 0; - return NXT_AGAIN; + case NXT_EAGAIN: + nxt_debug(c->socket.task, "readv() %E", err); + c->socket.read_ready = 0; + return NXT_AGAIN; - case NXT_EINTR: - nxt_debug(c->socket.task, "readv() %E", err); - continue; + case NXT_EINTR: + nxt_debug(c->socket.task, "readv() %E", err); + continue; - default: - c->socket.error = err; - nxt_log(c->socket.task, nxt_socket_error_level(err), - "readv(%d, %ui) failed %E", c->socket.fd, niov, err); + default: + c->socket.error = err; + nxt_log(c->socket.task, nxt_socket_error_level(err), + "readv(%d, %ui) failed %E", c->socket.fd, niov, err); - return NXT_ERROR; - } + return NXT_ERROR; } + } } +ssize_t nxt_conn_io_recv(nxt_conn_t *c, void *buf, size_t size, + nxt_uint_t flags) { + ssize_t n; + nxt_err_t err; -ssize_t -nxt_conn_io_recv(nxt_conn_t *c, void *buf, size_t size, nxt_uint_t flags) -{ - ssize_t n; - nxt_err_t err; + for (;;) { + n = recv(c->socket.fd, buf, size, flags); - for ( ;; ) { - n = recv(c->socket.fd, buf, size, flags); + err = (n == -1) ? nxt_socket_errno : 0; - err = (n == -1) ? nxt_socket_errno : 0; + nxt_debug(c->socket.task, "recv(%d, %p, %uz, 0x%ui): %z", c->socket.fd, buf, + size, flags, n); - nxt_debug(c->socket.task, "recv(%d, %p, %uz, 0x%ui): %z", - c->socket.fd, buf, size, flags, n); + if (n > 0) { + if ((size_t)n < size && (flags & MSG_PEEK) == 0) { + c->socket.read_ready = 0; + } - if (n > 0) { - if ((size_t) n < size && (flags & MSG_PEEK) == 0) { - c->socket.read_ready = 0; - } - - return n; - } + return n; + } - if (n == 0) { - c->socket.closed = 1; + if (n == 0) { + c->socket.closed = 1; - if ((flags & MSG_PEEK) == 0) { - c->socket.read_ready = 0; - } + if ((flags & MSG_PEEK) == 0) { + c->socket.read_ready = 0; + } - return n; - } + return n; + } - /* n == -1 */ + /* n == -1 */ - switch (err) { + switch (err) { - case NXT_EAGAIN: - nxt_debug(c->socket.task, "recv() %E", err); - c->socket.read_ready = 0; + case NXT_EAGAIN: + nxt_debug(c->socket.task, "recv() %E", err); + c->socket.read_ready = 0; - return NXT_AGAIN; + return NXT_AGAIN; - case NXT_EINTR: - nxt_debug(c->socket.task, "recv() %E", err); - continue; + case NXT_EINTR: + nxt_debug(c->socket.task, "recv() %E", err); + continue; - default: - c->socket.error = err; - nxt_log(c->socket.task, nxt_socket_error_level(err), - "recv(%d, %p, %uz, %ui) failed %E", - c->socket.fd, buf, size, flags, err); + default: + c->socket.error = err; + nxt_log(c->socket.task, nxt_socket_error_level(err), + "recv(%d, %p, %uz, %ui) failed %E", c->socket.fd, buf, size, + flags, err); - return NXT_ERROR; - } + return NXT_ERROR; } + } } diff --git a/src/nxt_conn_write.c b/src/nxt_conn_write.c index 7d0a579f2..6fd8ce9ef 100644 --- a/src/nxt_conn_write.c +++ b/src/nxt_conn_write.c @@ -6,539 +6,504 @@ #include - static void nxt_conn_write_timer_handler(nxt_task_t *task, void *obj, - void *data); + void *data); static ssize_t nxt_conn_io_sendfile(nxt_task_t *task, nxt_sendbuf_t *sb); static ssize_t nxt_sendfile(int fd, int s, off_t pos, size_t size); +void nxt_conn_io_write(nxt_task_t *task, void *obj, void *data) { + ssize_t ret; + nxt_buf_t *b; + nxt_conn_t *c; + nxt_sendbuf_t sb; + nxt_event_engine_t *engine; -void -nxt_conn_io_write(nxt_task_t *task, void *obj, void *data) -{ - ssize_t ret; - nxt_buf_t *b; - nxt_conn_t *c; - nxt_sendbuf_t sb; - nxt_event_engine_t *engine; - - c = obj; + c = obj; - nxt_debug(task, "conn write fd:%d er:%d bl:%d", - c->socket.fd, c->socket.error, c->block_write); + nxt_debug(task, "conn write fd:%d er:%d bl:%d", c->socket.fd, c->socket.error, + c->block_write); - if (c->socket.error != 0 || c->block_write) { - goto error; - } + if (c->socket.error != 0 || c->block_write) { + goto error; + } - if (!c->socket.write_ready || c->write == NULL) { - return; - } + if (!c->socket.write_ready || c->write == NULL) { + return; + } - engine = task->thread->engine; + engine = task->thread->engine; - c->socket.write_handler = nxt_conn_io_write; - c->socket.error_handler = c->write_state->error_handler; + c->socket.write_handler = nxt_conn_io_write; + c->socket.error_handler = c->write_state->error_handler; - b = c->write; + b = c->write; - sb.socket = c->socket.fd; - sb.error = 0; - sb.sent = 0; - sb.size = 0; - sb.buf = b; + sb.socket = c->socket.fd; + sb.error = 0; + sb.sent = 0; + sb.size = 0; + sb.buf = b; #if (NXT_TLS) - sb.tls = c->u.tls; + sb.tls = c->u.tls; #endif - sb.limit = 10 * 1024 * 1024; - sb.ready = 1; - sb.sync = 0; + sb.limit = 10 * 1024 * 1024; + sb.ready = 1; + sb.sync = 0; - do { - ret = c->io->sendbuf(task, &sb); + do { + ret = c->io->sendbuf(task, &sb); - c->socket.write_ready = sb.ready; - c->socket.error = sb.error; + c->socket.write_ready = sb.ready; + c->socket.error = sb.error; - if (ret < 0) { - /* ret == NXT_AGAIN || ret == NXT_ERROR. */ - break; - } + if (ret < 0) { + /* ret == NXT_AGAIN || ret == NXT_ERROR. */ + break; + } - sb.sent += ret; - sb.limit -= ret; + sb.sent += ret; + sb.limit -= ret; - b = nxt_sendbuf_update(b, ret); + b = nxt_sendbuf_update(b, ret); - if (b == NULL) { - nxt_fd_event_block_write(engine, &c->socket); - break; - } + if (b == NULL) { + nxt_fd_event_block_write(engine, &c->socket); + break; + } - sb.buf = b; + sb.buf = b; - if (!c->socket.write_ready) { - ret = NXT_AGAIN; - break; - } + if (!c->socket.write_ready) { + ret = NXT_AGAIN; + break; + } - } while (sb.limit != 0); + } while (sb.limit != 0); - nxt_debug(task, "event conn: %z sent:%O", ret, sb.sent); + nxt_debug(task, "event conn: %z sent:%O", ret, sb.sent); - if (sb.sent != 0) { - if (c->write_state->timer_autoreset) { - nxt_timer_disable(engine, &c->write_timer); - } + if (sb.sent != 0) { + if (c->write_state->timer_autoreset) { + nxt_timer_disable(engine, &c->write_timer); } - - if (ret != NXT_ERROR) { - - if (sb.limit == 0) { - /* - * Postpone writing until next event poll to allow to - * process other received events and to get new events. - */ - c->write_timer.handler = nxt_conn_write_timer_handler; - nxt_timer_add(engine, &c->write_timer, 0); - - } else if (ret == NXT_AGAIN) { - /* - * SSL libraries can require to toggle either write or read - * event if renegotiation occurs during SSL write operation. - * This case is handled on the c->io->send() level. Timer - * can be set here because it should be set only for write - * direction. - */ - nxt_conn_timer(engine, c, c->write_state, &c->write_timer); - - if (nxt_fd_event_is_disabled(c->socket.write)) { - nxt_fd_event_enable_write(engine, &c->socket); - } - } + } + + if (ret != NXT_ERROR) { + + if (sb.limit == 0) { + /* + * Postpone writing until next event poll to allow to + * process other received events and to get new events. + */ + c->write_timer.handler = nxt_conn_write_timer_handler; + nxt_timer_add(engine, &c->write_timer, 0); + + } else if (ret == NXT_AGAIN) { + /* + * SSL libraries can require to toggle either write or read + * event if renegotiation occurs during SSL write operation. + * This case is handled on the c->io->send() level. Timer + * can be set here because it should be set only for write + * direction. + */ + nxt_conn_timer(engine, c, c->write_state, &c->write_timer); + + if (nxt_fd_event_is_disabled(c->socket.write)) { + nxt_fd_event_enable_write(engine, &c->socket); + } } + } - if (ret == 0 || sb.sent != 0) { - /* - * ret == 0 means a sync buffer was processed. - * ret == NXT_ERROR is ignored here if some data was sent, - * the error will be handled on the next nxt_conn_write() call. - */ - c->sent += sb.sent; - nxt_work_queue_add(c->write_work_queue, c->write_state->ready_handler, - task, c, data); - return; - } + if (ret == 0 || sb.sent != 0) { + /* + * ret == 0 means a sync buffer was processed. + * ret == NXT_ERROR is ignored here if some data was sent, + * the error will be handled on the next nxt_conn_write() call. + */ + c->sent += sb.sent; + nxt_work_queue_add(c->write_work_queue, c->write_state->ready_handler, task, + c, data); + return; + } - if (ret != NXT_ERROR) { - return; - } + if (ret != NXT_ERROR) { + return; + } - nxt_fd_event_block_write(engine, &c->socket); + nxt_fd_event_block_write(engine, &c->socket); error: - nxt_work_queue_add(c->write_work_queue, c->write_state->error_handler, - task, c, data); + nxt_work_queue_add(c->write_work_queue, c->write_state->error_handler, task, + c, data); } +static void nxt_conn_write_timer_handler(nxt_task_t *task, void *obj, + void *data) { + nxt_conn_t *c; + nxt_timer_t *timer; -static void -nxt_conn_write_timer_handler(nxt_task_t *task, void *obj, void *data) -{ - nxt_conn_t *c; - nxt_timer_t *timer; - - timer = obj; + timer = obj; - nxt_debug(task, "conn write timer"); + nxt_debug(task, "conn write timer"); - c = nxt_write_timer_conn(timer); - c->delayed = 0; + c = nxt_write_timer_conn(timer); + c->delayed = 0; - c->io->write(task, c, c->socket.data); + c->io->write(task, c, c->socket.data); } +ssize_t nxt_conn_io_sendbuf(nxt_task_t *task, nxt_sendbuf_t *sb) { + nxt_uint_t niov; + struct iovec iov[NXT_IOBUF_MAX]; -ssize_t -nxt_conn_io_sendbuf(nxt_task_t *task, nxt_sendbuf_t *sb) -{ - nxt_uint_t niov; - struct iovec iov[NXT_IOBUF_MAX]; + niov = nxt_sendbuf_mem_coalesce0(task, sb, iov, NXT_IOBUF_MAX); - niov = nxt_sendbuf_mem_coalesce0(task, sb, iov, NXT_IOBUF_MAX); - - if (niov == 0 && sb->sync) { - return 0; - } + if (niov == 0 && sb->sync) { + return 0; + } - /* - * XXX Temporary fix for - */ - if (niov == 0 && sb->buf == NULL) { - return 0; - } + /* + * XXX Temporary fix for + */ + if (niov == 0 && sb->buf == NULL) { + return 0; + } - if (niov == 0 && nxt_buf_is_file(sb->buf)) { - return nxt_conn_io_sendfile(task, sb); - } + if (niov == 0 && nxt_buf_is_file(sb->buf)) { + return nxt_conn_io_sendfile(task, sb); + } - return nxt_conn_io_writev(task, sb, iov, niov); + return nxt_conn_io_writev(task, sb, iov, niov); } +static ssize_t nxt_conn_io_sendfile(nxt_task_t *task, nxt_sendbuf_t *sb) { + size_t size; + ssize_t n; + nxt_buf_t *b; + nxt_err_t err; -static ssize_t -nxt_conn_io_sendfile(nxt_task_t *task, nxt_sendbuf_t *sb) -{ - size_t size; - ssize_t n; - nxt_buf_t *b; - nxt_err_t err; - - b = sb->buf; + b = sb->buf; - for ( ;; ) { - size = b->file_end - b->file_pos; + for (;;) { + size = b->file_end - b->file_pos; - n = nxt_sendfile(b->file->fd, sb->socket, b->file_pos, size); + n = nxt_sendfile(b->file->fd, sb->socket, b->file_pos, size); - err = (n == -1) ? nxt_errno : 0; + err = (n == -1) ? nxt_errno : 0; - nxt_debug(task, "sendfile(%FD, %d, @%O, %uz): %z", - b->file->fd, sb->socket, b->file_pos, size, n); + nxt_debug(task, "sendfile(%FD, %d, @%O, %uz): %z", b->file->fd, sb->socket, + b->file_pos, size, n); - if (n > 0) { - if (n < (ssize_t) size) { - sb->ready = 0; - } + if (n > 0) { + if (n < (ssize_t)size) { + sb->ready = 0; + } - return n; - } + return n; + } - if (nxt_slow_path(n == 0)) { - nxt_alert(task, "sendfile() reported that file was truncated at %O", - b->file_pos); + if (nxt_slow_path(n == 0)) { + nxt_alert(task, "sendfile() reported that file was truncated at %O", + b->file_pos); - return NXT_ERROR; - } + return NXT_ERROR; + } - /* n == -1 */ + /* n == -1 */ - switch (err) { + switch (err) { - case NXT_EAGAIN: - sb->ready = 0; - nxt_debug(task, "sendfile() %E", err); + case NXT_EAGAIN: + sb->ready = 0; + nxt_debug(task, "sendfile() %E", err); - return NXT_AGAIN; + return NXT_AGAIN; - case NXT_EINTR: - nxt_debug(task, "sendfile() %E", err); - continue; + case NXT_EINTR: + nxt_debug(task, "sendfile() %E", err); + continue; - default: - sb->error = err; - nxt_log(task, nxt_socket_error_level(err), - "sendfile(%FD, %d, @%O, %uz) failed %E", - b->file->fd, sb->socket, b->file_pos, size, err); + default: + sb->error = err; + nxt_log(task, nxt_socket_error_level(err), + "sendfile(%FD, %d, @%O, %uz) failed %E", b->file->fd, sb->socket, + b->file_pos, size, err); - return NXT_ERROR; - } + return NXT_ERROR; } + } } - -static ssize_t -nxt_sendfile(int fd, int s, off_t pos, size_t size) -{ - ssize_t res; +static ssize_t nxt_sendfile(int fd, int s, off_t pos, size_t size) { + ssize_t res; #if (NXT_HAVE_MACOSX_SENDFILE) - off_t sent = size; + off_t sent = size; - int rc = sendfile(fd, s, pos, &sent, NULL, 0); + int rc = sendfile(fd, s, pos, &sent, NULL, 0); - res = (rc == 0 || sent > 0) ? sent : -1; + res = (rc == 0 || sent > 0) ? sent : -1; #elif (NXT_HAVE_FREEBSD_SENDFILE) - off_t sent = 0; + off_t sent = 0; - int rc = sendfile(fd, s, pos, size, NULL, &sent, 0); + int rc = sendfile(fd, s, pos, size, NULL, &sent, 0); - res = (rc == 0 || sent > 0) ? sent : -1; + res = (rc == 0 || sent > 0) ? sent : -1; #elif (NXT_HAVE_LINUX_SENDFILE) - res = sendfile(s, fd, &pos, size); + res = sendfile(s, fd, &pos, size); #else - int err; - void *map; - off_t page_off; + int err; + void *map; + off_t page_off; - page_off = pos % nxt_pagesize; + page_off = pos % nxt_pagesize; - map = nxt_mem_mmap(NULL, size + page_off, PROT_READ, MAP_SHARED, fd, - pos - page_off); - if (nxt_slow_path(map == MAP_FAILED)) { - return -1; - } + map = nxt_mem_mmap(NULL, size + page_off, PROT_READ, MAP_SHARED, fd, + pos - page_off); + if (nxt_slow_path(map == MAP_FAILED)) { + return -1; + } - res = write(s, nxt_pointer_to(map, page_off), size); + res = write(s, nxt_pointer_to(map, page_off), size); - /* Backup and restore errno to catch socket errors in the upper level. */ - err = errno; - nxt_mem_munmap(map, size + page_off); - errno = err; + /* Backup and restore errno to catch socket errors in the upper level. */ + err = errno; + nxt_mem_munmap(map, size + page_off); + errno = err; #endif - return res; + return res; } +ssize_t nxt_conn_io_writev(nxt_task_t *task, nxt_sendbuf_t *sb, + struct iovec *iov, nxt_uint_t niov) { + ssize_t n; + nxt_err_t err; -ssize_t -nxt_conn_io_writev(nxt_task_t *task, nxt_sendbuf_t *sb, struct iovec *iov, - nxt_uint_t niov) -{ - ssize_t n; - nxt_err_t err; + if (niov == 1) { + /* Disposal of surplus kernel iovec copy-in operation. */ + return nxt_conn_io_send(task, sb, iov[0].iov_base, iov[0].iov_len); + } - if (niov == 1) { - /* Disposal of surplus kernel iovec copy-in operation. */ - return nxt_conn_io_send(task, sb, iov[0].iov_base, iov[0].iov_len); - } - - for ( ;; ) { - n = writev(sb->socket, iov, niov); + for (;;) { + n = writev(sb->socket, iov, niov); - err = (n == -1) ? nxt_socket_errno : 0; + err = (n == -1) ? nxt_socket_errno : 0; - nxt_debug(task, "writev(%d, %ui): %z", sb->socket, niov, n); + nxt_debug(task, "writev(%d, %ui): %z", sb->socket, niov, n); - if (n > 0) { - return n; - } + if (n > 0) { + return n; + } - /* n == -1 */ + /* n == -1 */ - switch (err) { + switch (err) { - case NXT_EAGAIN: - sb->ready = 0; - nxt_debug(task, "writev() %E", err); + case NXT_EAGAIN: + sb->ready = 0; + nxt_debug(task, "writev() %E", err); - return NXT_AGAIN; + return NXT_AGAIN; - case NXT_EINTR: - nxt_debug(task, "writev() %E", err); - continue; + case NXT_EINTR: + nxt_debug(task, "writev() %E", err); + continue; - default: - sb->error = err; - nxt_log(task, nxt_socket_error_level(err), - "writev(%d, %ui) failed %E", sb->socket, niov, err); + default: + sb->error = err; + nxt_log(task, nxt_socket_error_level(err), "writev(%d, %ui) failed %E", + sb->socket, niov, err); - return NXT_ERROR; - } + return NXT_ERROR; } + } } +ssize_t nxt_conn_io_send(nxt_task_t *task, nxt_sendbuf_t *sb, void *buf, + size_t size) { + ssize_t n; + nxt_err_t err; -ssize_t -nxt_conn_io_send(nxt_task_t *task, nxt_sendbuf_t *sb, void *buf, size_t size) -{ - ssize_t n; - nxt_err_t err; + for (;;) { + n = send(sb->socket, buf, size, 0); - for ( ;; ) { - n = send(sb->socket, buf, size, 0); + err = (n == -1) ? nxt_socket_errno : 0; - err = (n == -1) ? nxt_socket_errno : 0; + nxt_debug(task, "send(%d, %p, %uz): %z", sb->socket, buf, size, n); - nxt_debug(task, "send(%d, %p, %uz): %z", sb->socket, buf, size, n); - - if (n > 0) { - return n; - } + if (n > 0) { + return n; + } - /* n == -1 */ + /* n == -1 */ - switch (err) { + switch (err) { - case NXT_EAGAIN: - sb->ready = 0; - nxt_debug(task, "send() %E", err); + case NXT_EAGAIN: + sb->ready = 0; + nxt_debug(task, "send() %E", err); - return NXT_AGAIN; + return NXT_AGAIN; - case NXT_EINTR: - nxt_debug(task, "send() %E", err); - continue; + case NXT_EINTR: + nxt_debug(task, "send() %E", err); + continue; - default: - sb->error = err; - nxt_log(task, nxt_socket_error_level(err), - "send(%d, %p, %uz) failed %E", sb->socket, buf, size, err); + default: + sb->error = err; + nxt_log(task, nxt_socket_error_level(err), "send(%d, %p, %uz) failed %E", + sb->socket, buf, size, err); - return NXT_ERROR; - } + return NXT_ERROR; } + } } - /* Obsolete interfaces. */ -size_t -nxt_event_conn_write_limit(nxt_conn_t *c) -{ - ssize_t limit, correction; - nxt_event_write_rate_t *rate; +size_t nxt_event_conn_write_limit(nxt_conn_t *c) { + ssize_t limit, correction; + nxt_event_write_rate_t *rate; - rate = c->rate; + rate = c->rate; - if (rate == NULL) { - return c->max_chunk; - } + if (rate == NULL) { + return c->max_chunk; + } - limit = rate->limit; - correction = limit - (size_t) rate->average; + limit = rate->limit; + correction = limit - (size_t)rate->average; - nxt_debug(c->socket.task, "event conn correction:%z average:%0.3f", - correction, rate->average); + nxt_debug(c->socket.task, "event conn correction:%z average:%0.3f", + correction, rate->average); - limit += correction; + limit += correction; - if (limit <= 0) { - return 0; - } + if (limit <= 0) { + return 0; + } - if (rate->limit_after != 0) { - limit += rate->limit_after; - limit = nxt_min((size_t) limit, rate->max_limit); - } + if (rate->limit_after != 0) { + limit += rate->limit_after; + limit = nxt_min((size_t)limit, rate->max_limit); + } - return nxt_min((size_t) limit, c->max_chunk); + return nxt_min((size_t)limit, c->max_chunk); } - -nxt_bool_t -nxt_event_conn_write_delayed(nxt_event_engine_t *engine, nxt_conn_t *c, - size_t sent) -{ - return 0; +nxt_bool_t nxt_event_conn_write_delayed(nxt_event_engine_t *engine, + nxt_conn_t *c, size_t sent) { + return 0; } +ssize_t nxt_event_conn_io_sendbuf(nxt_conn_t *c, nxt_buf_t *b, size_t limit) { + nxt_uint_t niob; + struct iovec iob[NXT_IOBUF_MAX]; + nxt_sendbuf_coalesce_t sb; -ssize_t -nxt_event_conn_io_sendbuf(nxt_conn_t *c, nxt_buf_t *b, size_t limit) -{ - nxt_uint_t niob; - struct iovec iob[NXT_IOBUF_MAX]; - nxt_sendbuf_coalesce_t sb; + sb.buf = b; + sb.iobuf = iob; + sb.nmax = NXT_IOBUF_MAX; + sb.sync = 0; + sb.size = 0; + sb.limit = limit; - sb.buf = b; - sb.iobuf = iob; - sb.nmax = NXT_IOBUF_MAX; - sb.sync = 0; - sb.size = 0; - sb.limit = limit; - - niob = nxt_sendbuf_mem_coalesce(c->socket.task, &sb); + niob = nxt_sendbuf_mem_coalesce(c->socket.task, &sb); - if (niob == 0 && sb.sync) { - return 0; - } + if (niob == 0 && sb.sync) { + return 0; + } - return nxt_event_conn_io_writev(c, iob, niob); + return nxt_event_conn_io_writev(c, iob, niob); } +ssize_t nxt_event_conn_io_writev(nxt_conn_t *c, nxt_iobuf_t *iob, + nxt_uint_t niob) { + ssize_t n; + nxt_err_t err; -ssize_t -nxt_event_conn_io_writev(nxt_conn_t *c, nxt_iobuf_t *iob, nxt_uint_t niob) -{ - ssize_t n; - nxt_err_t err; - - if (niob == 1) { - /* Disposal of surplus kernel iovec copy-in operation. */ - return nxt_event_conn_io_send(c, iob->iov_base, iob->iov_len); - } + if (niob == 1) { + /* Disposal of surplus kernel iovec copy-in operation. */ + return nxt_event_conn_io_send(c, iob->iov_base, iob->iov_len); + } - for ( ;; ) { - n = writev(c->socket.fd, iob, niob); + for (;;) { + n = writev(c->socket.fd, iob, niob); - err = (n == -1) ? nxt_socket_errno : 0; + err = (n == -1) ? nxt_socket_errno : 0; - nxt_debug(c->socket.task, "writev(%d, %ui): %z", c->socket.fd, niob, n); + nxt_debug(c->socket.task, "writev(%d, %ui): %z", c->socket.fd, niob, n); - if (n > 0) { - return n; - } + if (n > 0) { + return n; + } - /* n == -1 */ + /* n == -1 */ - switch (err) { + switch (err) { - case NXT_EAGAIN: - nxt_debug(c->socket.task, "writev() %E", err); - c->socket.write_ready = 0; - return NXT_AGAIN; + case NXT_EAGAIN: + nxt_debug(c->socket.task, "writev() %E", err); + c->socket.write_ready = 0; + return NXT_AGAIN; - case NXT_EINTR: - nxt_debug(c->socket.task, "writev() %E", err); - continue; + case NXT_EINTR: + nxt_debug(c->socket.task, "writev() %E", err); + continue; - default: - c->socket.error = err; - nxt_log(c->socket.task, nxt_socket_error_level(err), - "writev(%d, %ui) failed %E", c->socket.fd, niob, err); - return NXT_ERROR; - } + default: + c->socket.error = err; + nxt_log(c->socket.task, nxt_socket_error_level(err), + "writev(%d, %ui) failed %E", c->socket.fd, niob, err); + return NXT_ERROR; } + } } +ssize_t nxt_event_conn_io_send(nxt_conn_t *c, void *buf, size_t size) { + ssize_t n; + nxt_err_t err; -ssize_t -nxt_event_conn_io_send(nxt_conn_t *c, void *buf, size_t size) -{ - ssize_t n; - nxt_err_t err; - - for ( ;; ) { - n = send(c->socket.fd, buf, size, 0); + for (;;) { + n = send(c->socket.fd, buf, size, 0); - err = (n == -1) ? nxt_socket_errno : 0; + err = (n == -1) ? nxt_socket_errno : 0; - nxt_debug(c->socket.task, "send(%d, %p, %uz): %z", - c->socket.fd, buf, size, n); + nxt_debug(c->socket.task, "send(%d, %p, %uz): %z", c->socket.fd, buf, size, + n); - if (n > 0) { - return n; - } + if (n > 0) { + return n; + } - /* n == -1 */ + /* n == -1 */ - switch (err) { + switch (err) { - case NXT_EAGAIN: - nxt_debug(c->socket.task, "send() %E", err); - c->socket.write_ready = 0; - return NXT_AGAIN; + case NXT_EAGAIN: + nxt_debug(c->socket.task, "send() %E", err); + c->socket.write_ready = 0; + return NXT_AGAIN; - case NXT_EINTR: - nxt_debug(c->socket.task, "send() %E", err); - continue; + case NXT_EINTR: + nxt_debug(c->socket.task, "send() %E", err); + continue; - default: - c->socket.error = err; - nxt_log(c->socket.task, nxt_socket_error_level(err), - "send(%d, %p, %uz) failed %E", - c->socket.fd, buf, size, err); - return NXT_ERROR; - } + default: + c->socket.error = err; + nxt_log(c->socket.task, nxt_socket_error_level(err), + "send(%d, %p, %uz) failed %E", c->socket.fd, buf, size, err); + return NXT_ERROR; } + } } diff --git a/src/nxt_controller.c b/src/nxt_controller.c index 1ffcf815a..d62e988ab 100644 --- a/src/nxt_controller.c +++ b/src/nxt_controller.c @@ -13,670 +13,639 @@ #include #include - typedef struct { - nxt_conf_value_t *root; - nxt_mp_t *pool; + nxt_conf_value_t *root; + nxt_mp_t *pool; } nxt_controller_conf_t; - typedef struct { - nxt_http_request_parse_t parser; - size_t length; - nxt_controller_conf_t conf; - nxt_conn_t *conn; - nxt_queue_link_t link; + nxt_http_request_parse_t parser; + size_t length; + nxt_controller_conf_t conf; + nxt_conn_t *conn; + nxt_queue_link_t link; } nxt_controller_request_t; - typedef struct { - nxt_uint_t status; - nxt_conf_value_t *conf; - - u_char *title; - nxt_str_t detail; - ssize_t offset; - nxt_uint_t line; - nxt_uint_t column; + nxt_uint_t status; + nxt_conf_value_t *conf; + + u_char *title; + nxt_str_t detail; + ssize_t offset; + nxt_uint_t line; + nxt_uint_t column; } nxt_controller_response_t; - static nxt_int_t nxt_controller_prefork(nxt_task_t *task, - nxt_process_t *process, nxt_mp_t *mp); + nxt_process_t *process, nxt_mp_t *mp); static nxt_int_t nxt_controller_file_read(nxt_task_t *task, const char *name, - nxt_str_t *str, nxt_mp_t *mp); + nxt_str_t *str, nxt_mp_t *mp); static nxt_int_t nxt_controller_start(nxt_task_t *task, - nxt_process_data_t *data); + nxt_process_data_t *data); static void nxt_controller_process_new_port_handler(nxt_task_t *task, - nxt_port_recv_msg_t *msg); + nxt_port_recv_msg_t *msg); static void nxt_controller_send_current_conf(nxt_task_t *task); static void nxt_controller_router_ready_handler(nxt_task_t *task, - nxt_port_recv_msg_t *msg); + nxt_port_recv_msg_t *msg); static void nxt_controller_remove_pid_handler(nxt_task_t *task, - nxt_port_recv_msg_t *msg); + nxt_port_recv_msg_t *msg); static nxt_int_t nxt_controller_conf_default(void); static void nxt_controller_conf_init_handler(nxt_task_t *task, - nxt_port_recv_msg_t *msg, void *data); + nxt_port_recv_msg_t *msg, + void *data); static void nxt_controller_flush_requests(nxt_task_t *task); static nxt_int_t nxt_controller_conf_send(nxt_task_t *task, nxt_mp_t *mp, - nxt_conf_value_t *conf, nxt_port_rpc_handler_t handler, void *data); + nxt_conf_value_t *conf, + nxt_port_rpc_handler_t handler, + void *data); static void nxt_controller_conn_init(nxt_task_t *task, void *obj, void *data); static void nxt_controller_conn_read(nxt_task_t *task, void *obj, void *data); static nxt_msec_t nxt_controller_conn_timeout_value(nxt_conn_t *c, - uintptr_t data); + uintptr_t data); static void nxt_controller_conn_read_error(nxt_task_t *task, void *obj, - void *data); + void *data); static void nxt_controller_conn_read_timeout(nxt_task_t *task, void *obj, - void *data); + void *data); static void nxt_controller_conn_body_read(nxt_task_t *task, void *obj, - void *data); + void *data); static void nxt_controller_conn_write(nxt_task_t *task, void *obj, void *data); static void nxt_controller_conn_write_error(nxt_task_t *task, void *obj, - void *data); + void *data); static void nxt_controller_conn_write_timeout(nxt_task_t *task, void *obj, - void *data); + void *data); static void nxt_controller_conn_close(nxt_task_t *task, void *obj, void *data); static void nxt_controller_conn_free(nxt_task_t *task, void *obj, void *data); static nxt_int_t nxt_controller_request_content_length(void *ctx, - nxt_http_field_t *field, uintptr_t data); + nxt_http_field_t *field, + uintptr_t data); static void nxt_controller_process_request(nxt_task_t *task, - nxt_controller_request_t *req); + nxt_controller_request_t *req); static void nxt_controller_process_config(nxt_task_t *task, - nxt_controller_request_t *req, nxt_str_t *path); + nxt_controller_request_t *req, + nxt_str_t *path); static nxt_bool_t nxt_controller_check_postpone_request(nxt_task_t *task); static void nxt_controller_process_status(nxt_task_t *task, - nxt_controller_request_t *req); + nxt_controller_request_t *req); static void nxt_controller_status_handler(nxt_task_t *task, - nxt_port_recv_msg_t *msg, void *data); + nxt_port_recv_msg_t *msg, void *data); static void nxt_controller_status_response(nxt_task_t *task, - nxt_controller_request_t *req, nxt_str_t *path); + nxt_controller_request_t *req, + nxt_str_t *path); #if (NXT_TLS) static void nxt_controller_process_cert(nxt_task_t *task, - nxt_controller_request_t *req, nxt_str_t *path); + nxt_controller_request_t *req, + nxt_str_t *path); static void nxt_controller_process_cert_save(nxt_task_t *task, - nxt_port_recv_msg_t *msg, void *data); + nxt_port_recv_msg_t *msg, + void *data); static nxt_bool_t nxt_controller_cert_in_use(nxt_str_t *name); static void nxt_controller_cert_cleanup(nxt_task_t *task, void *obj, - void *data); + void *data); #endif #if (NXT_HAVE_NJS) static void nxt_controller_process_script(nxt_task_t *task, - nxt_controller_request_t *req, nxt_str_t *path); + nxt_controller_request_t *req, + nxt_str_t *path); static void nxt_controller_process_script_save(nxt_task_t *task, - nxt_port_recv_msg_t *msg, void *data); + nxt_port_recv_msg_t *msg, + void *data); static nxt_bool_t nxt_controller_script_in_use(nxt_str_t *name); static void nxt_controller_script_cleanup(nxt_task_t *task, void *obj, - void *data); + void *data); #endif static void nxt_controller_process_control(nxt_task_t *task, - nxt_controller_request_t *req, nxt_str_t *path); + nxt_controller_request_t *req, + nxt_str_t *path); static void nxt_controller_app_restart_handler(nxt_task_t *task, - nxt_port_recv_msg_t *msg, void *data); + nxt_port_recv_msg_t *msg, + void *data); static void nxt_controller_conf_handler(nxt_task_t *task, - nxt_port_recv_msg_t *msg, void *data); -static void nxt_controller_conf_store(nxt_task_t *task, - nxt_conf_value_t *conf); + nxt_port_recv_msg_t *msg, void *data); +static void nxt_controller_conf_store(nxt_task_t *task, nxt_conf_value_t *conf); static void nxt_controller_response(nxt_task_t *task, - nxt_controller_request_t *req, nxt_controller_response_t *resp); + nxt_controller_request_t *req, + nxt_controller_response_t *resp); static u_char *nxt_controller_date(u_char *buf, nxt_realtime_t *now, - struct tm *tm, size_t size, const char *format); - + struct tm *tm, size_t size, + const char *format); -static nxt_http_field_proc_t nxt_controller_request_fields[] = { - { nxt_string("Content-Length"), - &nxt_controller_request_content_length, 0 }, +static nxt_http_field_proc_t nxt_controller_request_fields[] = { + {nxt_string("Content-Length"), &nxt_controller_request_content_length, 0}, }; -static nxt_lvlhsh_t nxt_controller_fields_hash; - -static nxt_uint_t nxt_controller_listening; -static nxt_uint_t nxt_controller_router_ready; -static nxt_controller_conf_t nxt_controller_conf; -static nxt_queue_t nxt_controller_waiting_requests; -static nxt_bool_t nxt_controller_waiting_init_conf; -static nxt_conf_value_t *nxt_controller_status; - - -static const nxt_event_conn_state_t nxt_controller_conn_read_state; -static const nxt_event_conn_state_t nxt_controller_conn_body_read_state; -static const nxt_event_conn_state_t nxt_controller_conn_write_state; -static const nxt_event_conn_state_t nxt_controller_conn_close_state; - - -static const nxt_port_handlers_t nxt_controller_process_port_handlers = { - .quit = nxt_signal_quit_handler, - .new_port = nxt_controller_process_new_port_handler, - .change_file = nxt_port_change_log_file_handler, - .mmap = nxt_port_mmap_handler, - .process_ready = nxt_controller_router_ready_handler, - .data = nxt_port_data_handler, - .remove_pid = nxt_controller_remove_pid_handler, - .rpc_ready = nxt_port_rpc_handler, - .rpc_error = nxt_port_rpc_handler, +static nxt_lvlhsh_t nxt_controller_fields_hash; + +static nxt_uint_t nxt_controller_listening; +static nxt_uint_t nxt_controller_router_ready; +static nxt_controller_conf_t nxt_controller_conf; +static nxt_queue_t nxt_controller_waiting_requests; +static nxt_bool_t nxt_controller_waiting_init_conf; +static nxt_conf_value_t *nxt_controller_status; + +static const nxt_event_conn_state_t nxt_controller_conn_read_state; +static const nxt_event_conn_state_t nxt_controller_conn_body_read_state; +static const nxt_event_conn_state_t nxt_controller_conn_write_state; +static const nxt_event_conn_state_t nxt_controller_conn_close_state; + +static const nxt_port_handlers_t nxt_controller_process_port_handlers = { + .quit = nxt_signal_quit_handler, + .new_port = nxt_controller_process_new_port_handler, + .change_file = nxt_port_change_log_file_handler, + .mmap = nxt_port_mmap_handler, + .process_ready = nxt_controller_router_ready_handler, + .data = nxt_port_data_handler, + .remove_pid = nxt_controller_remove_pid_handler, + .rpc_ready = nxt_port_rpc_handler, + .rpc_error = nxt_port_rpc_handler, }; - -const nxt_process_init_t nxt_controller_process = { - .name = "controller", - .type = NXT_PROCESS_CONTROLLER, - .prefork = nxt_controller_prefork, - .restart = 1, - .setup = nxt_process_core_setup, - .start = nxt_controller_start, - .port_handlers = &nxt_controller_process_port_handlers, - .signals = nxt_process_signals, +const nxt_process_init_t nxt_controller_process = { + .name = "controller", + .type = NXT_PROCESS_CONTROLLER, + .prefork = nxt_controller_prefork, + .restart = 1, + .setup = nxt_process_core_setup, + .start = nxt_controller_start, + .port_handlers = &nxt_controller_process_port_handlers, + .signals = nxt_process_signals, }; +static nxt_int_t nxt_controller_prefork(nxt_task_t *task, + nxt_process_t *process, nxt_mp_t *mp) { + nxt_str_t ver; + nxt_int_t ret, num; + nxt_runtime_t *rt; + nxt_controller_init_t ctrl_init; -static nxt_int_t -nxt_controller_prefork(nxt_task_t *task, nxt_process_t *process, nxt_mp_t *mp) -{ - nxt_str_t ver; - nxt_int_t ret, num; - nxt_runtime_t *rt; - nxt_controller_init_t ctrl_init; + nxt_log(task, NXT_LOG_INFO, "controller started"); - nxt_log(task, NXT_LOG_INFO, "controller started"); + rt = task->thread->runtime; - rt = task->thread->runtime; + nxt_memzero(&ctrl_init, sizeof(nxt_controller_init_t)); - nxt_memzero(&ctrl_init, sizeof(nxt_controller_init_t)); + /* + * Since configuration version has only been introduced in 1.26, + * set the default version to 1.25. + */ + nxt_conf_ver = 12500; - /* - * Since configuration version has only been introduced in 1.26, - * set the default version to 1.25. - */ - nxt_conf_ver = 12500; + ret = nxt_controller_file_read(task, rt->conf, &ctrl_init.conf, mp); + if (nxt_slow_path(ret == NXT_ERROR)) { + return NXT_ERROR; + } - ret = nxt_controller_file_read(task, rt->conf, &ctrl_init.conf, mp); + if (ret == NXT_OK) { + ret = nxt_controller_file_read(task, rt->ver, &ver, mp); if (nxt_slow_path(ret == NXT_ERROR)) { - return NXT_ERROR; + return NXT_ERROR; } if (ret == NXT_OK) { - ret = nxt_controller_file_read(task, rt->ver, &ver, mp); - if (nxt_slow_path(ret == NXT_ERROR)) { - return NXT_ERROR; - } - - if (ret == NXT_OK) { - num = nxt_int_parse(ver.start, ver.length); + num = nxt_int_parse(ver.start, ver.length); - if (nxt_slow_path(num < 0)) { - nxt_alert(task, "failed to restore previous configuration: " - "invalid version string \"%V\"", &ver); + if (nxt_slow_path(num < 0)) { + nxt_alert(task, + "failed to restore previous configuration: " + "invalid version string \"%V\"", + &ver); - nxt_str_null(&ctrl_init.conf); + nxt_str_null(&ctrl_init.conf); - } else { - nxt_conf_ver = num; - } - } + } else { + nxt_conf_ver = num; + } } + } #if (NXT_TLS) - ctrl_init.certs = nxt_cert_store_load(task, mp); + ctrl_init.certs = nxt_cert_store_load(task, mp); - nxt_mp_cleanup(mp, nxt_controller_cert_cleanup, task, ctrl_init.certs, rt); + nxt_mp_cleanup(mp, nxt_controller_cert_cleanup, task, ctrl_init.certs, rt); #endif #if (NXT_HAVE_NJS) - ctrl_init.scripts = nxt_script_store_load(task, mp); + ctrl_init.scripts = nxt_script_store_load(task, mp); - nxt_mp_cleanup(mp, nxt_controller_script_cleanup, task, ctrl_init.scripts, - rt); + nxt_mp_cleanup(mp, nxt_controller_script_cleanup, task, ctrl_init.scripts, + rt); #endif - process->data.controller = ctrl_init; + process->data.controller = ctrl_init; - return NXT_OK; + return NXT_OK; } +static nxt_int_t nxt_controller_file_read(nxt_task_t *task, const char *name, + nxt_str_t *str, nxt_mp_t *mp) { + ssize_t n; + nxt_int_t ret; + nxt_file_t file; + nxt_file_info_t fi; -static nxt_int_t -nxt_controller_file_read(nxt_task_t *task, const char *name, nxt_str_t *str, - nxt_mp_t *mp) -{ - ssize_t n; - nxt_int_t ret; - nxt_file_t file; - nxt_file_info_t fi; - - nxt_memzero(&file, sizeof(nxt_file_t)); - - file.name = (nxt_file_name_t *) name; + nxt_memzero(&file, sizeof(nxt_file_t)); - ret = nxt_file_open(task, &file, NXT_FILE_RDONLY, NXT_FILE_OPEN, 0); + file.name = (nxt_file_name_t *)name; - if (ret == NXT_OK) { - ret = nxt_file_info(&file, &fi); - if (nxt_slow_path(ret != NXT_OK)) { - goto fail; - } + ret = nxt_file_open(task, &file, NXT_FILE_RDONLY, NXT_FILE_OPEN, 0); - if (nxt_fast_path(nxt_is_file(&fi))) { - str->length = nxt_file_size(&fi); - str->start = nxt_mp_nget(mp, str->length); - if (nxt_slow_path(str->start == NULL)) { - goto fail; - } + if (ret == NXT_OK) { + ret = nxt_file_info(&file, &fi); + if (nxt_slow_path(ret != NXT_OK)) { + goto fail; + } - n = nxt_file_read(&file, str->start, str->length, 0); - if (nxt_slow_path(n != (ssize_t) str->length)) { - goto fail; - } + if (nxt_fast_path(nxt_is_file(&fi))) { + str->length = nxt_file_size(&fi); + str->start = nxt_mp_nget(mp, str->length); + if (nxt_slow_path(str->start == NULL)) { + goto fail; + } - nxt_file_close(task, &file); + n = nxt_file_read(&file, str->start, str->length, 0); + if (nxt_slow_path(n != (ssize_t)str->length)) { + goto fail; + } - return NXT_OK; - } + nxt_file_close(task, &file); - nxt_file_close(task, &file); + return NXT_OK; } - return NXT_DECLINED; + nxt_file_close(task, &file); + } + + return NXT_DECLINED; fail: - nxt_file_close(task, &file); + nxt_file_close(task, &file); - return NXT_ERROR; + return NXT_ERROR; } - #if (NXT_TLS) -static void -nxt_controller_cert_cleanup(nxt_task_t *task, void *obj, void *data) -{ - pid_t main_pid; - nxt_array_t *certs; - nxt_runtime_t *rt; +static void nxt_controller_cert_cleanup(nxt_task_t *task, void *obj, + void *data) { + pid_t main_pid; + nxt_array_t *certs; + nxt_runtime_t *rt; - certs = obj; - rt = data; + certs = obj; + rt = data; - main_pid = rt->port_by_type[NXT_PROCESS_MAIN]->pid; + main_pid = rt->port_by_type[NXT_PROCESS_MAIN]->pid; - if (nxt_pid == main_pid && certs != NULL) { - nxt_cert_store_release(certs); - } + if (nxt_pid == main_pid && certs != NULL) { + nxt_cert_store_release(certs); + } } #endif +static nxt_int_t nxt_controller_start(nxt_task_t *task, + nxt_process_data_t *data) { + nxt_mp_t *mp; + nxt_int_t ret; + nxt_str_t *json; + nxt_conf_value_t *conf; + nxt_conf_validation_t vldt; + nxt_controller_init_t *init; + + ret = nxt_http_fields_hash(&nxt_controller_fields_hash, + nxt_controller_request_fields, + nxt_nitems(nxt_controller_request_fields)); + + if (nxt_slow_path(ret != NXT_OK)) { + return NXT_ERROR; + } -static nxt_int_t -nxt_controller_start(nxt_task_t *task, nxt_process_data_t *data) -{ - nxt_mp_t *mp; - nxt_int_t ret; - nxt_str_t *json; - nxt_conf_value_t *conf; - nxt_conf_validation_t vldt; - nxt_controller_init_t *init; - - ret = nxt_http_fields_hash(&nxt_controller_fields_hash, - nxt_controller_request_fields, - nxt_nitems(nxt_controller_request_fields)); - - if (nxt_slow_path(ret != NXT_OK)) { - return NXT_ERROR; - } - - nxt_queue_init(&nxt_controller_waiting_requests); + nxt_queue_init(&nxt_controller_waiting_requests); - init = &data->controller; + init = &data->controller; #if (NXT_TLS) - if (init->certs != NULL) { - nxt_cert_info_init(task, init->certs); - nxt_cert_store_release(init->certs); - } + if (init->certs != NULL) { + nxt_cert_info_init(task, init->certs); + nxt_cert_store_release(init->certs); + } #endif #if (NXT_HAVE_NJS) - if (init->scripts != NULL) { - nxt_script_info_init(task, init->scripts); - nxt_script_store_release(init->scripts); - } + if (init->scripts != NULL) { + nxt_script_info_init(task, init->scripts); + nxt_script_store_release(init->scripts); + } #endif - json = &init->conf; - - if (json->start == NULL) { - return NXT_OK; - } - - mp = nxt_mp_create(1024, 128, 256, 32); - if (nxt_slow_path(mp == NULL)) { - return NXT_ERROR; - } + json = &init->conf; - conf = nxt_conf_json_parse_str(mp, json); - if (nxt_slow_path(conf == NULL)) { - nxt_alert(task, "failed to restore previous configuration: " - "file is corrupted or not enough memory"); + if (json->start == NULL) { + return NXT_OK; + } - nxt_mp_destroy(mp); - return NXT_OK; - } + mp = nxt_mp_create(1024, 128, 256, 32); + if (nxt_slow_path(mp == NULL)) { + return NXT_ERROR; + } - nxt_memzero(&vldt, sizeof(nxt_conf_validation_t)); + conf = nxt_conf_json_parse_str(mp, json); + if (nxt_slow_path(conf == NULL)) { + nxt_alert(task, "failed to restore previous configuration: " + "file is corrupted or not enough memory"); - vldt.pool = nxt_mp_create(1024, 128, 256, 32); - if (nxt_slow_path(vldt.pool == NULL)) { - nxt_mp_destroy(mp); - return NXT_ERROR; - } + nxt_mp_destroy(mp); + return NXT_OK; + } - vldt.conf = conf; - vldt.conf_pool = mp; - vldt.ver = nxt_conf_ver; + nxt_memzero(&vldt, sizeof(nxt_conf_validation_t)); - ret = nxt_conf_validate(&vldt); + vldt.pool = nxt_mp_create(1024, 128, 256, 32); + if (nxt_slow_path(vldt.pool == NULL)) { + nxt_mp_destroy(mp); + return NXT_ERROR; + } - if (nxt_slow_path(ret != NXT_OK)) { + vldt.conf = conf; + vldt.conf_pool = mp; + vldt.ver = nxt_conf_ver; - if (ret == NXT_DECLINED) { - nxt_alert(task, "the previous configuration is invalid: %V", - &vldt.error); + ret = nxt_conf_validate(&vldt); - nxt_mp_destroy(vldt.pool); - nxt_mp_destroy(mp); + if (nxt_slow_path(ret != NXT_OK)) { - return NXT_OK; - } + if (ret == NXT_DECLINED) { + nxt_alert(task, "the previous configuration is invalid: %V", &vldt.error); - /* ret == NXT_ERROR */ + nxt_mp_destroy(vldt.pool); + nxt_mp_destroy(mp); - return NXT_ERROR; + return NXT_OK; } - nxt_mp_destroy(vldt.pool); - - nxt_controller_conf.root = conf; - nxt_controller_conf.pool = mp; - - return NXT_OK; -} + /* ret == NXT_ERROR */ + return NXT_ERROR; + } -static void -nxt_controller_process_new_port_handler(nxt_task_t *task, - nxt_port_recv_msg_t *msg) -{ - nxt_port_new_port_handler(task, msg); + nxt_mp_destroy(vldt.pool); - if (msg->u.new_port->type != NXT_PROCESS_ROUTER - || !nxt_controller_router_ready) - { - return; - } + nxt_controller_conf.root = conf; + nxt_controller_conf.pool = mp; - nxt_controller_send_current_conf(task); + return NXT_OK; } +static void nxt_controller_process_new_port_handler(nxt_task_t *task, + nxt_port_recv_msg_t *msg) { + nxt_port_new_port_handler(task, msg); -static void -nxt_controller_send_current_conf(nxt_task_t *task) -{ - nxt_int_t rc; - nxt_runtime_t *rt; - nxt_conf_value_t *conf; + if (msg->u.new_port->type != NXT_PROCESS_ROUTER || + !nxt_controller_router_ready) { + return; + } - conf = nxt_controller_conf.root; + nxt_controller_send_current_conf(task); +} - if (conf != NULL) { - rc = nxt_controller_conf_send(task, nxt_controller_conf.pool, conf, - nxt_controller_conf_init_handler, NULL); +static void nxt_controller_send_current_conf(nxt_task_t *task) { + nxt_int_t rc; + nxt_runtime_t *rt; + nxt_conf_value_t *conf; - if (nxt_fast_path(rc == NXT_OK)) { - nxt_controller_waiting_init_conf = 1; + conf = nxt_controller_conf.root; - return; - } + if (conf != NULL) { + rc = nxt_controller_conf_send(task, nxt_controller_conf.pool, conf, + nxt_controller_conf_init_handler, NULL); - nxt_mp_destroy(nxt_controller_conf.pool); + if (nxt_fast_path(rc == NXT_OK)) { + nxt_controller_waiting_init_conf = 1; - if (nxt_slow_path(nxt_controller_conf_default() != NXT_OK)) { - nxt_abort(); - } + return; } + nxt_mp_destroy(nxt_controller_conf.pool); + if (nxt_slow_path(nxt_controller_conf_default() != NXT_OK)) { - nxt_abort(); + nxt_abort(); } + } - rt = task->thread->runtime; + if (nxt_slow_path(nxt_controller_conf_default() != NXT_OK)) { + nxt_abort(); + } - if (nxt_slow_path(nxt_listen_event(task, rt->controller_socket) == NULL)) { - nxt_abort(); - } + rt = task->thread->runtime; - nxt_controller_listening = 1; + if (nxt_slow_path(nxt_listen_event(task, rt->controller_socket) == NULL)) { + nxt_abort(); + } - nxt_controller_flush_requests(task); -} + nxt_controller_listening = 1; + nxt_controller_flush_requests(task); +} -static void -nxt_controller_router_ready_handler(nxt_task_t *task, - nxt_port_recv_msg_t *msg) -{ - nxt_port_t *router_port; - nxt_runtime_t *rt; +static void nxt_controller_router_ready_handler(nxt_task_t *task, + nxt_port_recv_msg_t *msg) { + nxt_port_t *router_port; + nxt_runtime_t *rt; - rt = task->thread->runtime; + rt = task->thread->runtime; - router_port = rt->port_by_type[NXT_PROCESS_ROUTER]; + router_port = rt->port_by_type[NXT_PROCESS_ROUTER]; - nxt_controller_router_ready = 1; + nxt_controller_router_ready = 1; - if (router_port != NULL) { - nxt_controller_send_current_conf(task); - } + if (router_port != NULL) { + nxt_controller_send_current_conf(task); + } } +static void nxt_controller_remove_pid_handler(nxt_task_t *task, + nxt_port_recv_msg_t *msg) { + nxt_pid_t pid; + nxt_process_t *process; + nxt_runtime_t *rt; -static void -nxt_controller_remove_pid_handler(nxt_task_t *task, nxt_port_recv_msg_t *msg) -{ - nxt_pid_t pid; - nxt_process_t *process; - nxt_runtime_t *rt; - - rt = task->thread->runtime; + rt = task->thread->runtime; - nxt_assert(nxt_buf_used_size(msg->buf) == sizeof(pid)); + nxt_assert(nxt_buf_used_size(msg->buf) == sizeof(pid)); - nxt_memcpy(&pid, msg->buf->mem.pos, sizeof(pid)); + nxt_memcpy(&pid, msg->buf->mem.pos, sizeof(pid)); - process = nxt_runtime_process_find(rt, pid); - if (process != NULL && nxt_process_type(process) == NXT_PROCESS_ROUTER) { - nxt_controller_router_ready = 0; - } + process = nxt_runtime_process_find(rt, pid); + if (process != NULL && nxt_process_type(process) == NXT_PROCESS_ROUTER) { + nxt_controller_router_ready = 0; + } - nxt_port_remove_pid_handler(task, msg); + nxt_port_remove_pid_handler(task, msg); } +static nxt_int_t nxt_controller_conf_default(void) { + nxt_mp_t *mp; + nxt_conf_value_t *conf; -static nxt_int_t -nxt_controller_conf_default(void) -{ - nxt_mp_t *mp; - nxt_conf_value_t *conf; + static const nxt_str_t json = + nxt_string("{ \"listeners\": {}, \"routes\": [], \"applications\": {} }"); - static const nxt_str_t json = nxt_string( - "{ \"listeners\": {}, \"routes\": [], \"applications\": {} }" - ); + mp = nxt_mp_create(1024, 128, 256, 32); - mp = nxt_mp_create(1024, 128, 256, 32); - - if (nxt_slow_path(mp == NULL)) { - return NXT_ERROR; - } + if (nxt_slow_path(mp == NULL)) { + return NXT_ERROR; + } - conf = nxt_conf_json_parse_str(mp, &json); + conf = nxt_conf_json_parse_str(mp, &json); - if (nxt_slow_path(conf == NULL)) { - return NXT_ERROR; - } + if (nxt_slow_path(conf == NULL)) { + return NXT_ERROR; + } - nxt_controller_conf.root = conf; - nxt_controller_conf.pool = mp; + nxt_controller_conf.root = conf; + nxt_controller_conf.pool = mp; - return NXT_OK; + return NXT_OK; } +static void nxt_controller_conf_init_handler(nxt_task_t *task, + nxt_port_recv_msg_t *msg, + void *data) { + nxt_runtime_t *rt; -static void -nxt_controller_conf_init_handler(nxt_task_t *task, nxt_port_recv_msg_t *msg, - void *data) -{ - nxt_runtime_t *rt; - - nxt_controller_waiting_init_conf = 0; + nxt_controller_waiting_init_conf = 0; - if (msg->port_msg.type != NXT_PORT_MSG_RPC_READY) { - nxt_alert(task, "failed to apply previous configuration"); + if (msg->port_msg.type != NXT_PORT_MSG_RPC_READY) { + nxt_alert(task, "failed to apply previous configuration"); - nxt_mp_destroy(nxt_controller_conf.pool); + nxt_mp_destroy(nxt_controller_conf.pool); - if (nxt_slow_path(nxt_controller_conf_default() != NXT_OK)) { - nxt_abort(); - } + if (nxt_slow_path(nxt_controller_conf_default() != NXT_OK)) { + nxt_abort(); } + } - if (nxt_controller_listening == 0) { - rt = task->thread->runtime; - - if (nxt_slow_path(nxt_listen_event(task, rt->controller_socket) - == NULL)) - { - nxt_abort(); - } + if (nxt_controller_listening == 0) { + rt = task->thread->runtime; - nxt_controller_listening = 1; + if (nxt_slow_path(nxt_listen_event(task, rt->controller_socket) == NULL)) { + nxt_abort(); } - nxt_controller_flush_requests(task); -} + nxt_controller_listening = 1; + } + nxt_controller_flush_requests(task); +} -static void -nxt_controller_flush_requests(nxt_task_t *task) -{ - nxt_queue_t queue; - nxt_controller_request_t *req; +static void nxt_controller_flush_requests(nxt_task_t *task) { + nxt_queue_t queue; + nxt_controller_request_t *req; - nxt_queue_init(&queue); - nxt_queue_add(&queue, &nxt_controller_waiting_requests); + nxt_queue_init(&queue); + nxt_queue_add(&queue, &nxt_controller_waiting_requests); - nxt_queue_init(&nxt_controller_waiting_requests); + nxt_queue_init(&nxt_controller_waiting_requests); - nxt_queue_each(req, &queue, nxt_controller_request_t, link) { - nxt_controller_process_request(task, req); - } nxt_queue_loop; + nxt_queue_each(req, &queue, nxt_controller_request_t, link) { + nxt_controller_process_request(task, req); + } + nxt_queue_loop; } +static nxt_int_t nxt_controller_conf_send(nxt_task_t *task, nxt_mp_t *mp, + nxt_conf_value_t *conf, + nxt_port_rpc_handler_t handler, + void *data) { + void *mem; + u_char *end; + size_t size; + uint32_t stream; + nxt_fd_t fd; + nxt_int_t rc; + nxt_buf_t *b; + nxt_port_t *router_port, *controller_port; + nxt_runtime_t *rt; -static nxt_int_t -nxt_controller_conf_send(nxt_task_t *task, nxt_mp_t *mp, nxt_conf_value_t *conf, - nxt_port_rpc_handler_t handler, void *data) -{ - void *mem; - u_char *end; - size_t size; - uint32_t stream; - nxt_fd_t fd; - nxt_int_t rc; - nxt_buf_t *b; - nxt_port_t *router_port, *controller_port; - nxt_runtime_t *rt; - - rt = task->thread->runtime; + rt = task->thread->runtime; - router_port = rt->port_by_type[NXT_PROCESS_ROUTER]; + router_port = rt->port_by_type[NXT_PROCESS_ROUTER]; - nxt_assert(router_port != NULL); - nxt_assert(nxt_controller_router_ready); + nxt_assert(router_port != NULL); + nxt_assert(nxt_controller_router_ready); - controller_port = rt->port_by_type[NXT_PROCESS_CONTROLLER]; + controller_port = rt->port_by_type[NXT_PROCESS_CONTROLLER]; - size = nxt_conf_json_length(conf, NULL); + size = nxt_conf_json_length(conf, NULL); - b = nxt_buf_mem_alloc(mp, sizeof(size_t), 0); - if (nxt_slow_path(b == NULL)) { - return NXT_ERROR; - } + b = nxt_buf_mem_alloc(mp, sizeof(size_t), 0); + if (nxt_slow_path(b == NULL)) { + return NXT_ERROR; + } - fd = nxt_shm_open(task, size); - if (nxt_slow_path(fd == -1)) { - return NXT_ERROR; - } + fd = nxt_shm_open(task, size); + if (nxt_slow_path(fd == -1)) { + return NXT_ERROR; + } - mem = nxt_mem_mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); - if (nxt_slow_path(mem == MAP_FAILED)) { - goto fail; - } + mem = nxt_mem_mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); + if (nxt_slow_path(mem == MAP_FAILED)) { + goto fail; + } - end = nxt_conf_json_print(mem, conf, NULL); + end = nxt_conf_json_print(mem, conf, NULL); - nxt_mem_munmap(mem, size); + nxt_mem_munmap(mem, size); - size = end - (u_char *) mem; + size = end - (u_char *)mem; - b->mem.free = nxt_cpymem(b->mem.pos, &size, sizeof(size_t)); + b->mem.free = nxt_cpymem(b->mem.pos, &size, sizeof(size_t)); - stream = nxt_port_rpc_register_handler(task, controller_port, - handler, handler, - router_port->pid, data); - if (nxt_slow_path(stream == 0)) { - goto fail; - } + stream = nxt_port_rpc_register_handler(task, controller_port, handler, + handler, router_port->pid, data); + if (nxt_slow_path(stream == 0)) { + goto fail; + } - rc = nxt_port_socket_write(task, router_port, - NXT_PORT_MSG_DATA_LAST | NXT_PORT_MSG_CLOSE_FD, - fd, stream, controller_port->id, b); + rc = nxt_port_socket_write(task, router_port, + NXT_PORT_MSG_DATA_LAST | NXT_PORT_MSG_CLOSE_FD, fd, + stream, controller_port->id, b); - if (nxt_slow_path(rc != NXT_OK)) { - nxt_port_rpc_cancel(task, controller_port, stream); + if (nxt_slow_path(rc != NXT_OK)) { + nxt_port_rpc_cancel(task, controller_port, stream); - goto fail; - } + goto fail; + } - return NXT_OK; + return NXT_OK; fail: - nxt_fd_close(fd); + nxt_fd_close(fd); - return NXT_ERROR; + return NXT_ERROR; } +nxt_int_t nxt_runtime_controller_socket(nxt_task_t *task, nxt_runtime_t *rt) { + nxt_listen_socket_t *ls; -nxt_int_t -nxt_runtime_controller_socket(nxt_task_t *task, nxt_runtime_t *rt) -{ - nxt_listen_socket_t *ls; - - ls = nxt_mp_alloc(rt->mem_pool, sizeof(nxt_listen_socket_t)); - if (ls == NULL) { - return NXT_ERROR; - } + ls = nxt_mp_alloc(rt->mem_pool, sizeof(nxt_listen_socket_t)); + if (ls == NULL) { + return NXT_ERROR; + } - ls->sockaddr = rt->controller_listen; + ls->sockaddr = rt->controller_listen; - nxt_listen_socket_remote_size(ls); + nxt_listen_socket_remote_size(ls); - ls->socket = -1; - ls->backlog = NXT_LISTEN_BACKLOG; - ls->read_after_accept = 1; - ls->flags = NXT_NONBLOCK; + ls->socket = -1; + ls->backlog = NXT_LISTEN_BACKLOG; + ls->read_after_accept = 1; + ls->flags = NXT_NONBLOCK; #if 0 /* STUB */ @@ -689,1995 +658,1894 @@ nxt_runtime_controller_socket(nxt_task_t *task, nxt_runtime_t *rt) ls->work_queue = wq; #endif - ls->handler = nxt_controller_conn_init; + ls->handler = nxt_controller_conn_init; #if (NXT_HAVE_UNIX_DOMAIN) - if (ls->sockaddr->u.sockaddr.sa_family == AF_UNIX) { - const char *path = ls->sockaddr->u.sockaddr_un.sun_path; + if (ls->sockaddr->u.sockaddr.sa_family == AF_UNIX) { + const char *path = ls->sockaddr->u.sockaddr_un.sun_path; - nxt_fs_mkdir_p_dirname((const u_char *) path, 0755); - } + nxt_fs_mkdir_p_dirname((const u_char *)path, 0755); + } #endif - if (nxt_listen_socket_create(task, rt->mem_pool, ls) != NXT_OK) { - return NXT_ERROR; - } + if (nxt_listen_socket_create(task, rt->mem_pool, ls) != NXT_OK) { + return NXT_ERROR; + } - rt->controller_socket = ls; + rt->controller_socket = ls; - return NXT_OK; + return NXT_OK; } +static void nxt_controller_conn_init(nxt_task_t *task, void *obj, void *data) { + nxt_buf_t *b; + nxt_conn_t *c; + nxt_event_engine_t *engine; + nxt_controller_request_t *r; -static void -nxt_controller_conn_init(nxt_task_t *task, void *obj, void *data) -{ - nxt_buf_t *b; - nxt_conn_t *c; - nxt_event_engine_t *engine; - nxt_controller_request_t *r; - - c = obj; + c = obj; - nxt_debug(task, "controller conn init fd:%d", c->socket.fd); + nxt_debug(task, "controller conn init fd:%d", c->socket.fd); - r = nxt_mp_zget(c->mem_pool, sizeof(nxt_controller_request_t)); - if (nxt_slow_path(r == NULL)) { - nxt_controller_conn_free(task, c, NULL); - return; - } + r = nxt_mp_zget(c->mem_pool, sizeof(nxt_controller_request_t)); + if (nxt_slow_path(r == NULL)) { + nxt_controller_conn_free(task, c, NULL); + return; + } - r->conn = c; + r->conn = c; - if (nxt_slow_path(nxt_http_parse_request_init(&r->parser, c->mem_pool) - != NXT_OK)) - { - nxt_controller_conn_free(task, c, NULL); - return; - } + if (nxt_slow_path(nxt_http_parse_request_init(&r->parser, c->mem_pool) != + NXT_OK)) { + nxt_controller_conn_free(task, c, NULL); + return; + } - r->parser.encoded_slashes = 1; + r->parser.encoded_slashes = 1; - b = nxt_buf_mem_alloc(c->mem_pool, 1024, 0); - if (nxt_slow_path(b == NULL)) { - nxt_controller_conn_free(task, c, NULL); - return; - } + b = nxt_buf_mem_alloc(c->mem_pool, 1024, 0); + if (nxt_slow_path(b == NULL)) { + nxt_controller_conn_free(task, c, NULL); + return; + } - c->read = b; - c->socket.data = r; - c->socket.read_ready = 1; - c->read_state = &nxt_controller_conn_read_state; + c->read = b; + c->socket.data = r; + c->socket.read_ready = 1; + c->read_state = &nxt_controller_conn_read_state; - engine = task->thread->engine; - c->read_work_queue = &engine->read_work_queue; - c->write_work_queue = &engine->write_work_queue; + engine = task->thread->engine; + c->read_work_queue = &engine->read_work_queue; + c->write_work_queue = &engine->write_work_queue; - nxt_conn_read(engine, c); + nxt_conn_read(engine, c); } +static const nxt_event_conn_state_t + nxt_controller_conn_read_state nxt_aligned(64) = { + .ready_handler = nxt_controller_conn_read, + .close_handler = nxt_controller_conn_close, + .error_handler = nxt_controller_conn_read_error, -static const nxt_event_conn_state_t nxt_controller_conn_read_state - nxt_aligned(64) = -{ - .ready_handler = nxt_controller_conn_read, - .close_handler = nxt_controller_conn_close, - .error_handler = nxt_controller_conn_read_error, - - .timer_handler = nxt_controller_conn_read_timeout, - .timer_value = nxt_controller_conn_timeout_value, - .timer_data = 300 * 1000, + .timer_handler = nxt_controller_conn_read_timeout, + .timer_value = nxt_controller_conn_timeout_value, + .timer_data = 300 * 1000, }; +static void nxt_controller_conn_read(nxt_task_t *task, void *obj, void *data) { + size_t preread; + nxt_buf_t *b; + nxt_int_t rc; + nxt_conn_t *c; + nxt_controller_request_t *r; -static void -nxt_controller_conn_read(nxt_task_t *task, void *obj, void *data) -{ - size_t preread; - nxt_buf_t *b; - nxt_int_t rc; - nxt_conn_t *c; - nxt_controller_request_t *r; - - c = obj; - r = data; - - nxt_debug(task, "controller conn read"); + c = obj; + r = data; - nxt_queue_remove(&c->link); - nxt_queue_self(&c->link); + nxt_debug(task, "controller conn read"); - b = c->read; + nxt_queue_remove(&c->link); + nxt_queue_self(&c->link); - rc = nxt_http_parse_request(&r->parser, &b->mem); + b = c->read; - if (nxt_slow_path(rc != NXT_DONE)) { + rc = nxt_http_parse_request(&r->parser, &b->mem); - if (rc == NXT_AGAIN) { - if (nxt_buf_mem_free_size(&b->mem) == 0) { - nxt_log(task, NXT_LOG_ERR, "too long request headers"); - nxt_controller_conn_close(task, c, r); - return; - } - - nxt_conn_read(task->thread->engine, c); - return; - } - - /* rc == NXT_ERROR */ - - nxt_log(task, NXT_LOG_ERR, "parsing error"); + if (nxt_slow_path(rc != NXT_DONE)) { + if (rc == NXT_AGAIN) { + if (nxt_buf_mem_free_size(&b->mem) == 0) { + nxt_log(task, NXT_LOG_ERR, "too long request headers"); nxt_controller_conn_close(task, c, r); return; + } + + nxt_conn_read(task->thread->engine, c); + return; } - rc = nxt_http_fields_process(r->parser.fields, &nxt_controller_fields_hash, - r); + /* rc == NXT_ERROR */ - if (nxt_slow_path(rc != NXT_OK)) { - nxt_controller_conn_close(task, c, r); - return; - } + nxt_log(task, NXT_LOG_ERR, "parsing error"); - preread = nxt_buf_mem_used_size(&b->mem); + nxt_controller_conn_close(task, c, r); + return; + } - nxt_debug(task, "controller request header parsing complete, " - "body length: %uz, preread: %uz", - r->length, preread); + rc = + nxt_http_fields_process(r->parser.fields, &nxt_controller_fields_hash, r); - if (preread >= r->length) { - nxt_controller_process_request(task, r); - return; - } + if (nxt_slow_path(rc != NXT_OK)) { + nxt_controller_conn_close(task, c, r); + return; + } - if (r->length - preread > (size_t) nxt_buf_mem_free_size(&b->mem)) { - b = nxt_buf_mem_alloc(c->mem_pool, r->length, 0); - if (nxt_slow_path(b == NULL)) { - nxt_controller_conn_free(task, c, NULL); - return; - } + preread = nxt_buf_mem_used_size(&b->mem); - b->mem.free = nxt_cpymem(b->mem.free, c->read->mem.pos, preread); + nxt_debug(task, + "controller request header parsing complete, " + "body length: %uz, preread: %uz", + r->length, preread); + + if (preread >= r->length) { + nxt_controller_process_request(task, r); + return; + } - c->read = b; + if (r->length - preread > (size_t)nxt_buf_mem_free_size(&b->mem)) { + b = nxt_buf_mem_alloc(c->mem_pool, r->length, 0); + if (nxt_slow_path(b == NULL)) { + nxt_controller_conn_free(task, c, NULL); + return; } - c->read_state = &nxt_controller_conn_body_read_state; + b->mem.free = nxt_cpymem(b->mem.free, c->read->mem.pos, preread); - nxt_conn_read(task->thread->engine, c); -} + c->read = b; + } + c->read_state = &nxt_controller_conn_body_read_state; -static nxt_msec_t -nxt_controller_conn_timeout_value(nxt_conn_t *c, uintptr_t data) -{ - return (nxt_msec_t) data; + nxt_conn_read(task->thread->engine, c); } +static nxt_msec_t nxt_controller_conn_timeout_value(nxt_conn_t *c, + uintptr_t data) { + return (nxt_msec_t)data; +} -static void -nxt_controller_conn_read_error(nxt_task_t *task, void *obj, void *data) -{ - nxt_conn_t *c; +static void nxt_controller_conn_read_error(nxt_task_t *task, void *obj, + void *data) { + nxt_conn_t *c; - c = obj; + c = obj; - nxt_debug(task, "controller conn read error"); + nxt_debug(task, "controller conn read error"); - nxt_controller_conn_close(task, c, data); + nxt_controller_conn_close(task, c, data); } +static void nxt_controller_conn_read_timeout(nxt_task_t *task, void *obj, + void *data) { + nxt_timer_t *timer; + nxt_conn_t *c; -static void -nxt_controller_conn_read_timeout(nxt_task_t *task, void *obj, void *data) -{ - nxt_timer_t *timer; - nxt_conn_t *c; - - timer = obj; + timer = obj; - c = nxt_read_timer_conn(timer); - c->socket.timedout = 1; - c->socket.closed = 1; + c = nxt_read_timer_conn(timer); + c->socket.timedout = 1; + c->socket.closed = 1; - nxt_debug(task, "controller conn read timeout"); + nxt_debug(task, "controller conn read timeout"); - nxt_controller_conn_close(task, c, data); + nxt_controller_conn_close(task, c, data); } +static const nxt_event_conn_state_t + nxt_controller_conn_body_read_state nxt_aligned(64) = { + .ready_handler = nxt_controller_conn_body_read, + .close_handler = nxt_controller_conn_close, + .error_handler = nxt_controller_conn_read_error, -static const nxt_event_conn_state_t nxt_controller_conn_body_read_state - nxt_aligned(64) = -{ - .ready_handler = nxt_controller_conn_body_read, - .close_handler = nxt_controller_conn_close, - .error_handler = nxt_controller_conn_read_error, - - .timer_handler = nxt_controller_conn_read_timeout, - .timer_value = nxt_controller_conn_timeout_value, - .timer_data = 60 * 1000, - .timer_autoreset = 1, + .timer_handler = nxt_controller_conn_read_timeout, + .timer_value = nxt_controller_conn_timeout_value, + .timer_data = 60 * 1000, + .timer_autoreset = 1, }; +static void nxt_controller_conn_body_read(nxt_task_t *task, void *obj, + void *data) { + size_t read; + nxt_buf_t *b; + nxt_conn_t *c; + nxt_controller_request_t *r; -static void -nxt_controller_conn_body_read(nxt_task_t *task, void *obj, void *data) -{ - size_t read; - nxt_buf_t *b; - nxt_conn_t *c; - nxt_controller_request_t *r; - - c = obj; - r = data; - b = c->read; + c = obj; + r = data; + b = c->read; - read = nxt_buf_mem_used_size(&b->mem); + read = nxt_buf_mem_used_size(&b->mem); - nxt_debug(task, "controller conn body read: %uz of %uz", - read, r->length); + nxt_debug(task, "controller conn body read: %uz of %uz", read, r->length); - if (read >= r->length) { - nxt_controller_process_request(task, r); - return; - } + if (read >= r->length) { + nxt_controller_process_request(task, r); + return; + } - nxt_conn_read(task->thread->engine, c); + nxt_conn_read(task->thread->engine, c); } +static const nxt_event_conn_state_t + nxt_controller_conn_write_state nxt_aligned(64) = { + .ready_handler = nxt_controller_conn_write, + .error_handler = nxt_controller_conn_write_error, -static const nxt_event_conn_state_t nxt_controller_conn_write_state - nxt_aligned(64) = -{ - .ready_handler = nxt_controller_conn_write, - .error_handler = nxt_controller_conn_write_error, - - .timer_handler = nxt_controller_conn_write_timeout, - .timer_value = nxt_controller_conn_timeout_value, - .timer_data = 60 * 1000, - .timer_autoreset = 1, + .timer_handler = nxt_controller_conn_write_timeout, + .timer_value = nxt_controller_conn_timeout_value, + .timer_data = 60 * 1000, + .timer_autoreset = 1, }; +static void nxt_controller_conn_write(nxt_task_t *task, void *obj, void *data) { + nxt_buf_t *b; + nxt_conn_t *c; -static void -nxt_controller_conn_write(nxt_task_t *task, void *obj, void *data) -{ - nxt_buf_t *b; - nxt_conn_t *c; - - c = obj; + c = obj; - nxt_debug(task, "controller conn write"); + nxt_debug(task, "controller conn write"); - b = c->write; + b = c->write; - if (b->mem.pos != b->mem.free) { - nxt_conn_write(task->thread->engine, c); - return; - } + if (b->mem.pos != b->mem.free) { + nxt_conn_write(task->thread->engine, c); + return; + } - nxt_debug(task, "controller conn write complete"); + nxt_debug(task, "controller conn write complete"); - nxt_controller_conn_close(task, c, data); + nxt_controller_conn_close(task, c, data); } +static void nxt_controller_conn_write_error(nxt_task_t *task, void *obj, + void *data) { + nxt_conn_t *c; -static void -nxt_controller_conn_write_error(nxt_task_t *task, void *obj, void *data) -{ - nxt_conn_t *c; - - c = obj; + c = obj; - nxt_debug(task, "controller conn write error"); + nxt_debug(task, "controller conn write error"); - nxt_controller_conn_close(task, c, data); + nxt_controller_conn_close(task, c, data); } +static void nxt_controller_conn_write_timeout(nxt_task_t *task, void *obj, + void *data) { + nxt_conn_t *c; + nxt_timer_t *timer; -static void -nxt_controller_conn_write_timeout(nxt_task_t *task, void *obj, void *data) -{ - nxt_conn_t *c; - nxt_timer_t *timer; - - timer = obj; + timer = obj; - c = nxt_write_timer_conn(timer); - c->socket.timedout = 1; - c->socket.closed = 1; + c = nxt_write_timer_conn(timer); + c->socket.timedout = 1; + c->socket.closed = 1; - nxt_debug(task, "controller conn write timeout"); + nxt_debug(task, "controller conn write timeout"); - nxt_controller_conn_close(task, c, data); + nxt_controller_conn_close(task, c, data); } - -static const nxt_event_conn_state_t nxt_controller_conn_close_state - nxt_aligned(64) = -{ - .ready_handler = nxt_controller_conn_free, +static const nxt_event_conn_state_t + nxt_controller_conn_close_state nxt_aligned(64) = { + .ready_handler = nxt_controller_conn_free, }; +static void nxt_controller_conn_close(nxt_task_t *task, void *obj, void *data) { + nxt_conn_t *c; -static void -nxt_controller_conn_close(nxt_task_t *task, void *obj, void *data) -{ - nxt_conn_t *c; - - c = obj; + c = obj; - nxt_debug(task, "controller conn close"); + nxt_debug(task, "controller conn close"); - nxt_queue_remove(&c->link); + nxt_queue_remove(&c->link); - c->write_state = &nxt_controller_conn_close_state; + c->write_state = &nxt_controller_conn_close_state; - nxt_conn_close(task->thread->engine, c); + nxt_conn_close(task->thread->engine, c); } +static void nxt_controller_conn_free(nxt_task_t *task, void *obj, void *data) { + nxt_conn_t *c; -static void -nxt_controller_conn_free(nxt_task_t *task, void *obj, void *data) -{ - nxt_conn_t *c; + c = obj; - c = obj; + nxt_debug(task, "controller conn free"); - nxt_debug(task, "controller conn free"); + nxt_sockaddr_cache_free(task->thread->engine, c); - nxt_sockaddr_cache_free(task->thread->engine, c); - - nxt_conn_free(task, c); + nxt_conn_free(task, c); } +static nxt_int_t nxt_controller_request_content_length(void *ctx, + nxt_http_field_t *field, + uintptr_t data) { + off_t length; + nxt_controller_request_t *r; -static nxt_int_t -nxt_controller_request_content_length(void *ctx, nxt_http_field_t *field, - uintptr_t data) -{ - off_t length; - nxt_controller_request_t *r; - - r = ctx; - - length = nxt_off_t_parse(field->value, field->value_length); + r = ctx; - if (nxt_fast_path(length >= 0)) { + length = nxt_off_t_parse(field->value, field->value_length); - if (nxt_slow_path(length > NXT_SIZE_T_MAX)) { - nxt_log_error(NXT_LOG_ERR, &r->conn->log, - "Content-Length is too big"); - return NXT_ERROR; - } + if (nxt_fast_path(length >= 0)) { - r->length = length; - return NXT_OK; + if (nxt_slow_path(length > NXT_SIZE_T_MAX)) { + nxt_log_error(NXT_LOG_ERR, &r->conn->log, "Content-Length is too big"); + return NXT_ERROR; } - nxt_log_error(NXT_LOG_ERR, &r->conn->log, "Content-Length is invalid"); + r->length = length; + return NXT_OK; + } + + nxt_log_error(NXT_LOG_ERR, &r->conn->log, "Content-Length is invalid"); - return NXT_ERROR; + return NXT_ERROR; } - -static void -nxt_controller_process_request(nxt_task_t *task, nxt_controller_request_t *req) -{ - uint32_t i, count; - nxt_str_t path; - nxt_conn_t *c; - nxt_conf_value_t *value; - nxt_controller_response_t resp; +static void nxt_controller_process_request(nxt_task_t *task, + nxt_controller_request_t *req) { + uint32_t i, count; + nxt_str_t path; + nxt_conn_t *c; + nxt_conf_value_t *value; + nxt_controller_response_t resp; #if (NXT_TLS) - nxt_conf_value_t *certs; + nxt_conf_value_t *certs; #endif #if (NXT_HAVE_NJS) - nxt_conf_value_t *scripts; + nxt_conf_value_t *scripts; #endif #if (NXT_TLS) - static nxt_str_t certificates = nxt_string("certificates"); + static nxt_str_t certificates = nxt_string("certificates"); #endif #if (NXT_HAVE_NJS) - static nxt_str_t scripts_str = nxt_string("js_modules"); + static nxt_str_t scripts_str = nxt_string("js_modules"); #endif - static nxt_str_t config = nxt_string("config"); - static nxt_str_t status = nxt_string("status"); + static nxt_str_t config = nxt_string("config"); + static nxt_str_t status = nxt_string("status"); - c = req->conn; - path = req->parser.path; + c = req->conn; + path = req->parser.path; - if (path.length > 1 && path.start[path.length - 1] == '/') { - path.length--; - } - - if (nxt_str_start(&path, "/config", 7) - && (path.length == 7 || path.start[7] == '/')) - { - if (path.length == 7) { - path.length = 1; + if (path.length > 1 && path.start[path.length - 1] == '/') { + path.length--; + } - } else { - path.length -= 7; - path.start += 7; - } + if (nxt_str_start(&path, "/config", 7) && + (path.length == 7 || path.start[7] == '/')) { + if (path.length == 7) { + path.length = 1; - nxt_controller_process_config(task, req, &path); - return; + } else { + path.length -= 7; + path.start += 7; } - nxt_memzero(&resp, sizeof(nxt_controller_response_t)); + nxt_controller_process_config(task, req, &path); + return; + } - if (nxt_str_start(&path, "/status", 7) - && (path.length == 7 || path.start[7] == '/')) - { - if (!nxt_str_eq(&req->parser.method, "GET", 3)) { - goto invalid_method; - } + nxt_memzero(&resp, sizeof(nxt_controller_response_t)); - if (nxt_controller_status == NULL) { - nxt_controller_process_status(task, req); - return; - } + if (nxt_str_start(&path, "/status", 7) && + (path.length == 7 || path.start[7] == '/')) { + if (!nxt_str_eq(&req->parser.method, "GET", 3)) { + goto invalid_method; + } - if (path.length == 7) { - path.length = 1; + if (nxt_controller_status == NULL) { + nxt_controller_process_status(task, req); + return; + } - } else { - path.length -= 7; - path.start += 7; - } + if (path.length == 7) { + path.length = 1; - nxt_controller_status_response(task, req, &path); - return; + } else { + path.length -= 7; + path.start += 7; } -#if (NXT_TLS) + nxt_controller_status_response(task, req, &path); + return; + } - if (nxt_str_start(&path, "/certificates", 13) - && (path.length == 13 || path.start[13] == '/')) - { - if (path.length == 13) { - path.length = 1; +#if (NXT_TLS) - } else { - path.length -= 13; - path.start += 13; - } + if (nxt_str_start(&path, "/certificates", 13) && + (path.length == 13 || path.start[13] == '/')) { + if (path.length == 13) { + path.length = 1; - nxt_controller_process_cert(task, req, &path); - return; + } else { + path.length -= 13; + path.start += 13; } + nxt_controller_process_cert(task, req, &path); + return; + } + #endif #if (NXT_HAVE_NJS) - if (nxt_str_start(&path, "/js_modules", 11) - && (path.length == 11 || path.start[11] == '/')) - { - if (path.length == 11) { - path.length = 1; - - } else { - path.length -= 11; - path.start += 11; - } + if (nxt_str_start(&path, "/js_modules", 11) && + (path.length == 11 || path.start[11] == '/')) { + if (path.length == 11) { + path.length = 1; - nxt_controller_process_script(task, req, &path); - return; + } else { + path.length -= 11; + path.start += 11; } + nxt_controller_process_script(task, req, &path); + return; + } + #endif - if (nxt_str_start(&path, "/control/", 9)) { - path.length -= 9; - path.start += 9; + if (nxt_str_start(&path, "/control/", 9)) { + path.length -= 9; + path.start += 9; - nxt_controller_process_control(task, req, &path); - return; - } + nxt_controller_process_control(task, req, &path); + return; + } - if (path.length == 1 && path.start[0] == '/') { + if (path.length == 1 && path.start[0] == '/') { - if (!nxt_str_eq(&req->parser.method, "GET", 3)) { - goto invalid_method; - } + if (!nxt_str_eq(&req->parser.method, "GET", 3)) { + goto invalid_method; + } - if (nxt_controller_status == NULL) { - nxt_controller_process_status(task, req); - return; - } + if (nxt_controller_status == NULL) { + nxt_controller_process_status(task, req); + return; + } - count = 2; + count = 2; #if (NXT_TLS) - count++; + count++; #endif #if (NXT_HAVE_NJS) - count++; + count++; #endif - value = nxt_conf_create_object(c->mem_pool, count); - if (nxt_slow_path(value == NULL)) { - goto alloc_fail; - } + value = nxt_conf_create_object(c->mem_pool, count); + if (nxt_slow_path(value == NULL)) { + goto alloc_fail; + } - i = 0; + i = 0; #if (NXT_TLS) - certs = nxt_cert_info_get_all(c->mem_pool); - if (nxt_slow_path(certs == NULL)) { - goto alloc_fail; - } + certs = nxt_cert_info_get_all(c->mem_pool); + if (nxt_slow_path(certs == NULL)) { + goto alloc_fail; + } - nxt_conf_set_member(value, &certificates, certs, i++); + nxt_conf_set_member(value, &certificates, certs, i++); #endif #if (NXT_HAVE_NJS) - scripts = nxt_script_info_get_all(c->mem_pool); - if (nxt_slow_path(scripts == NULL)) { - goto alloc_fail; - } + scripts = nxt_script_info_get_all(c->mem_pool); + if (nxt_slow_path(scripts == NULL)) { + goto alloc_fail; + } - nxt_conf_set_member(value, &scripts_str, scripts, i++); + nxt_conf_set_member(value, &scripts_str, scripts, i++); #endif - nxt_conf_set_member(value, &config, nxt_controller_conf.root, i++); - nxt_conf_set_member(value, &status, nxt_controller_status, i); + nxt_conf_set_member(value, &config, nxt_controller_conf.root, i++); + nxt_conf_set_member(value, &status, nxt_controller_status, i); - resp.status = 200; - resp.conf = value; - - nxt_controller_response(task, req, &resp); - return; - } - - resp.status = 404; - resp.title = (u_char *) "Value doesn't exist."; - resp.offset = -1; + resp.status = 200; + resp.conf = value; nxt_controller_response(task, req, &resp); return; + } + + resp.status = 404; + resp.title = (u_char *)"Value doesn't exist."; + resp.offset = -1; + + nxt_controller_response(task, req, &resp); + return; invalid_method: - resp.status = 405; - resp.title = (u_char *) "Invalid method."; - resp.offset = -1; + resp.status = 405; + resp.title = (u_char *)"Invalid method."; + resp.offset = -1; - nxt_controller_response(task, req, &resp); - return; + nxt_controller_response(task, req, &resp); + return; alloc_fail: - resp.status = 500; - resp.title = (u_char *) "Memory allocation failed."; - resp.offset = -1; + resp.status = 500; + resp.title = (u_char *)"Memory allocation failed."; + resp.offset = -1; - nxt_controller_response(task, req, &resp); - return; + nxt_controller_response(task, req, &resp); + return; } +static void nxt_controller_process_config(nxt_task_t *task, + nxt_controller_request_t *req, + nxt_str_t *path) { + nxt_mp_t *mp; + nxt_int_t rc; + nxt_conn_t *c; + nxt_bool_t post; + nxt_buf_mem_t *mbuf; + nxt_conf_op_t *ops; + nxt_conf_value_t *value; + nxt_conf_validation_t vldt; + nxt_conf_json_error_t error; + nxt_controller_response_t resp; -static void -nxt_controller_process_config(nxt_task_t *task, nxt_controller_request_t *req, - nxt_str_t *path) -{ - nxt_mp_t *mp; - nxt_int_t rc; - nxt_conn_t *c; - nxt_bool_t post; - nxt_buf_mem_t *mbuf; - nxt_conf_op_t *ops; - nxt_conf_value_t *value; - nxt_conf_validation_t vldt; - nxt_conf_json_error_t error; - nxt_controller_response_t resp; + static const nxt_str_t empty_obj = nxt_string("{}"); - static const nxt_str_t empty_obj = nxt_string("{}"); + nxt_memzero(&resp, sizeof(nxt_controller_response_t)); - nxt_memzero(&resp, sizeof(nxt_controller_response_t)); + c = req->conn; - c = req->conn; + if (nxt_str_eq(&req->parser.method, "GET", 3)) { - if (nxt_str_eq(&req->parser.method, "GET", 3)) { + value = nxt_conf_get_path(nxt_controller_conf.root, path); - value = nxt_conf_get_path(nxt_controller_conf.root, path); - - if (value == NULL) { - goto not_found; - } - - resp.status = 200; - resp.conf = value; - - nxt_controller_response(task, req, &resp); - return; + if (value == NULL) { + goto not_found; } - if (nxt_str_eq(&req->parser.method, "POST", 4)) { - if (path->length == 1) { - goto not_allowed; - } + resp.status = 200; + resp.conf = value; - post = 1; + nxt_controller_response(task, req, &resp); + return; + } - } else { - post = 0; + if (nxt_str_eq(&req->parser.method, "POST", 4)) { + if (path->length == 1) { + goto not_allowed; } - if (post || nxt_str_eq(&req->parser.method, "PUT", 3)) { + post = 1; - if (nxt_controller_check_postpone_request(task)) { - nxt_queue_insert_tail(&nxt_controller_waiting_requests, &req->link); - return; - } + } else { + post = 0; + } - mp = nxt_mp_create(1024, 128, 256, 32); + if (post || nxt_str_eq(&req->parser.method, "PUT", 3)) { - if (nxt_slow_path(mp == NULL)) { - goto alloc_fail; - } + if (nxt_controller_check_postpone_request(task)) { + nxt_queue_insert_tail(&nxt_controller_waiting_requests, &req->link); + return; + } - mbuf = &c->read->mem; + mp = nxt_mp_create(1024, 128, 256, 32); - nxt_memzero(&error, sizeof(nxt_conf_json_error_t)); + if (nxt_slow_path(mp == NULL)) { + goto alloc_fail; + } - /* Skip UTF-8 BOM. */ - if (nxt_buf_mem_used_size(mbuf) >= 3 - && memcmp(mbuf->pos, "\xEF\xBB\xBF", 3) == 0) - { - mbuf->pos += 3; - } + mbuf = &c->read->mem; - value = nxt_conf_json_parse(mp, mbuf->pos, mbuf->free, &error); + nxt_memzero(&error, sizeof(nxt_conf_json_error_t)); - if (value == NULL) { - nxt_mp_destroy(mp); - - if (error.pos == NULL) { - goto alloc_fail; - } + /* Skip UTF-8 BOM. */ + if (nxt_buf_mem_used_size(mbuf) >= 3 && + memcmp(mbuf->pos, "\xEF\xBB\xBF", 3) == 0) { + mbuf->pos += 3; + } - resp.status = 400; - resp.title = (u_char *) "Invalid JSON."; - resp.detail.length = nxt_strlen(error.detail); - resp.detail.start = error.detail; - resp.offset = error.pos - mbuf->pos; + value = nxt_conf_json_parse(mp, mbuf->pos, mbuf->free, &error); - nxt_conf_json_position(mbuf->pos, error.pos, - &resp.line, &resp.column); + if (value == NULL) { + nxt_mp_destroy(mp); - nxt_controller_response(task, req, &resp); - return; - } + if (error.pos == NULL) { + goto alloc_fail; + } - if (path->length != 1) { - rc = nxt_conf_op_compile(c->mem_pool, &ops, - nxt_controller_conf.root, - path, value, post); + resp.status = 400; + resp.title = (u_char *)"Invalid JSON."; + resp.detail.length = nxt_strlen(error.detail); + resp.detail.start = error.detail; + resp.offset = error.pos - mbuf->pos; - if (rc != NXT_CONF_OP_OK) { - nxt_mp_destroy(mp); + nxt_conf_json_position(mbuf->pos, error.pos, &resp.line, &resp.column); - switch (rc) { - case NXT_CONF_OP_NOT_FOUND: - goto not_found; + nxt_controller_response(task, req, &resp); + return; + } - case NXT_CONF_OP_NOT_ALLOWED: - goto not_allowed; - } + if (path->length != 1) { + rc = nxt_conf_op_compile(c->mem_pool, &ops, nxt_controller_conf.root, + path, value, post); - /* rc == NXT_CONF_OP_ERROR */ - goto alloc_fail; - } + if (rc != NXT_CONF_OP_OK) { + nxt_mp_destroy(mp); - value = nxt_conf_clone(mp, ops, nxt_controller_conf.root); + switch (rc) { + case NXT_CONF_OP_NOT_FOUND: + goto not_found; - if (nxt_slow_path(value == NULL)) { - nxt_mp_destroy(mp); - goto alloc_fail; - } + case NXT_CONF_OP_NOT_ALLOWED: + goto not_allowed; } - nxt_memzero(&vldt, sizeof(nxt_conf_validation_t)); + /* rc == NXT_CONF_OP_ERROR */ + goto alloc_fail; + } - vldt.conf = value; - vldt.pool = c->mem_pool; - vldt.conf_pool = mp; - vldt.ver = NXT_VERNUM; + value = nxt_conf_clone(mp, ops, nxt_controller_conf.root); - rc = nxt_conf_validate(&vldt); + if (nxt_slow_path(value == NULL)) { + nxt_mp_destroy(mp); + goto alloc_fail; + } + } - if (nxt_slow_path(rc != NXT_OK)) { - nxt_mp_destroy(mp); + nxt_memzero(&vldt, sizeof(nxt_conf_validation_t)); - if (rc == NXT_DECLINED) { - resp.detail = vldt.error; - goto invalid_conf; - } + vldt.conf = value; + vldt.pool = c->mem_pool; + vldt.conf_pool = mp; + vldt.ver = NXT_VERNUM; - /* rc == NXT_ERROR */ - goto alloc_fail; - } + rc = nxt_conf_validate(&vldt); - rc = nxt_controller_conf_send(task, mp, value, - nxt_controller_conf_handler, req); + if (nxt_slow_path(rc != NXT_OK)) { + nxt_mp_destroy(mp); - if (nxt_slow_path(rc != NXT_OK)) { - nxt_mp_destroy(mp); + if (rc == NXT_DECLINED) { + resp.detail = vldt.error; + goto invalid_conf; + } - /* rc == NXT_ERROR */ - goto alloc_fail; - } + /* rc == NXT_ERROR */ + goto alloc_fail; + } - req->conf.root = value; - req->conf.pool = mp; + rc = nxt_controller_conf_send(task, mp, value, nxt_controller_conf_handler, + req); - nxt_queue_insert_head(&nxt_controller_waiting_requests, &req->link); + if (nxt_slow_path(rc != NXT_OK)) { + nxt_mp_destroy(mp); - return; + /* rc == NXT_ERROR */ + goto alloc_fail; } - if (nxt_str_eq(&req->parser.method, "DELETE", 6)) { + req->conf.root = value; + req->conf.pool = mp; - if (nxt_controller_check_postpone_request(task)) { - nxt_queue_insert_tail(&nxt_controller_waiting_requests, &req->link); - return; - } - - if (path->length == 1) { - mp = nxt_mp_create(1024, 128, 256, 32); + nxt_queue_insert_head(&nxt_controller_waiting_requests, &req->link); - if (nxt_slow_path(mp == NULL)) { - goto alloc_fail; - } + return; + } - value = nxt_conf_json_parse_str(mp, &empty_obj); + if (nxt_str_eq(&req->parser.method, "DELETE", 6)) { - } else { - rc = nxt_conf_op_compile(c->mem_pool, &ops, - nxt_controller_conf.root, - path, NULL, 0); + if (nxt_controller_check_postpone_request(task)) { + nxt_queue_insert_tail(&nxt_controller_waiting_requests, &req->link); + return; + } - if (rc != NXT_OK) { - if (rc == NXT_CONF_OP_NOT_FOUND) { - goto not_found; - } + if (path->length == 1) { + mp = nxt_mp_create(1024, 128, 256, 32); - /* rc == NXT_CONF_OP_ERROR */ - goto alloc_fail; - } + if (nxt_slow_path(mp == NULL)) { + goto alloc_fail; + } - mp = nxt_mp_create(1024, 128, 256, 32); + value = nxt_conf_json_parse_str(mp, &empty_obj); - if (nxt_slow_path(mp == NULL)) { - goto alloc_fail; - } + } else { + rc = nxt_conf_op_compile(c->mem_pool, &ops, nxt_controller_conf.root, + path, NULL, 0); - value = nxt_conf_clone(mp, ops, nxt_controller_conf.root); + if (rc != NXT_OK) { + if (rc == NXT_CONF_OP_NOT_FOUND) { + goto not_found; } - if (nxt_slow_path(value == NULL)) { - nxt_mp_destroy(mp); - goto alloc_fail; - } + /* rc == NXT_CONF_OP_ERROR */ + goto alloc_fail; + } - nxt_memzero(&vldt, sizeof(nxt_conf_validation_t)); + mp = nxt_mp_create(1024, 128, 256, 32); - vldt.conf = value; - vldt.pool = c->mem_pool; - vldt.conf_pool = mp; - vldt.ver = NXT_VERNUM; + if (nxt_slow_path(mp == NULL)) { + goto alloc_fail; + } - rc = nxt_conf_validate(&vldt); + value = nxt_conf_clone(mp, ops, nxt_controller_conf.root); + } - if (nxt_slow_path(rc != NXT_OK)) { - nxt_mp_destroy(mp); + if (nxt_slow_path(value == NULL)) { + nxt_mp_destroy(mp); + goto alloc_fail; + } - if (rc == NXT_DECLINED) { - resp.detail = vldt.error; - goto invalid_conf; - } + nxt_memzero(&vldt, sizeof(nxt_conf_validation_t)); - /* rc == NXT_ERROR */ - goto alloc_fail; - } + vldt.conf = value; + vldt.pool = c->mem_pool; + vldt.conf_pool = mp; + vldt.ver = NXT_VERNUM; - rc = nxt_controller_conf_send(task, mp, value, - nxt_controller_conf_handler, req); + rc = nxt_conf_validate(&vldt); - if (nxt_slow_path(rc != NXT_OK)) { - nxt_mp_destroy(mp); + if (nxt_slow_path(rc != NXT_OK)) { + nxt_mp_destroy(mp); - /* rc == NXT_ERROR */ - goto alloc_fail; - } + if (rc == NXT_DECLINED) { + resp.detail = vldt.error; + goto invalid_conf; + } - req->conf.root = value; - req->conf.pool = mp; + /* rc == NXT_ERROR */ + goto alloc_fail; + } - nxt_queue_insert_head(&nxt_controller_waiting_requests, &req->link); + rc = nxt_controller_conf_send(task, mp, value, nxt_controller_conf_handler, + req); - return; + if (nxt_slow_path(rc != NXT_OK)) { + nxt_mp_destroy(mp); + + /* rc == NXT_ERROR */ + goto alloc_fail; } -not_allowed: + req->conf.root = value; + req->conf.pool = mp; - resp.status = 405; - resp.title = (u_char *) "Method isn't allowed."; - resp.offset = -1; + nxt_queue_insert_head(&nxt_controller_waiting_requests, &req->link); - nxt_controller_response(task, req, &resp); return; + } + +not_allowed: + + resp.status = 405; + resp.title = (u_char *)"Method isn't allowed."; + resp.offset = -1; + + nxt_controller_response(task, req, &resp); + return; not_found: - resp.status = 404; - resp.title = (u_char *) "Value doesn't exist."; - resp.offset = -1; + resp.status = 404; + resp.title = (u_char *)"Value doesn't exist."; + resp.offset = -1; - nxt_controller_response(task, req, &resp); - return; + nxt_controller_response(task, req, &resp); + return; invalid_conf: - resp.status = 400; - resp.title = (u_char *) "Invalid configuration."; - resp.offset = -1; + resp.status = 400; + resp.title = (u_char *)"Invalid configuration."; + resp.offset = -1; - nxt_controller_response(task, req, &resp); - return; + nxt_controller_response(task, req, &resp); + return; alloc_fail: - resp.status = 500; - resp.title = (u_char *) "Memory allocation failed."; - resp.offset = -1; + resp.status = 500; + resp.title = (u_char *)"Memory allocation failed."; + resp.offset = -1; - nxt_controller_response(task, req, &resp); + nxt_controller_response(task, req, &resp); } +static nxt_bool_t nxt_controller_check_postpone_request(nxt_task_t *task) { + nxt_port_t *router_port; + nxt_runtime_t *rt; -static nxt_bool_t -nxt_controller_check_postpone_request(nxt_task_t *task) -{ - nxt_port_t *router_port; - nxt_runtime_t *rt; - - if (!nxt_queue_is_empty(&nxt_controller_waiting_requests) - || nxt_controller_waiting_init_conf - || !nxt_controller_router_ready) - { - return 1; - } + if (!nxt_queue_is_empty(&nxt_controller_waiting_requests) || + nxt_controller_waiting_init_conf || !nxt_controller_router_ready) { + return 1; + } - rt = task->thread->runtime; + rt = task->thread->runtime; - router_port = rt->port_by_type[NXT_PROCESS_ROUTER]; + router_port = rt->port_by_type[NXT_PROCESS_ROUTER]; - return (router_port == NULL); + return (router_port == NULL); } +static void nxt_controller_process_status(nxt_task_t *task, + nxt_controller_request_t *req) { + uint32_t stream; + nxt_int_t rc; + nxt_port_t *router_port, *controller_port; + nxt_runtime_t *rt; + nxt_controller_response_t resp; + + if (nxt_controller_check_postpone_request(task)) { + nxt_queue_insert_tail(&nxt_controller_waiting_requests, &req->link); + return; + } -static void -nxt_controller_process_status(nxt_task_t *task, nxt_controller_request_t *req) -{ - uint32_t stream; - nxt_int_t rc; - nxt_port_t *router_port, *controller_port; - nxt_runtime_t *rt; - nxt_controller_response_t resp; + rt = task->thread->runtime; - if (nxt_controller_check_postpone_request(task)) { - nxt_queue_insert_tail(&nxt_controller_waiting_requests, &req->link); - return; - } + router_port = rt->port_by_type[NXT_PROCESS_ROUTER]; - rt = task->thread->runtime; + nxt_assert(router_port != NULL); + nxt_assert(nxt_controller_router_ready); - router_port = rt->port_by_type[NXT_PROCESS_ROUTER]; + controller_port = rt->port_by_type[NXT_PROCESS_CONTROLLER]; - nxt_assert(router_port != NULL); - nxt_assert(nxt_controller_router_ready); + stream = nxt_port_rpc_register_handler( + task, controller_port, nxt_controller_status_handler, + nxt_controller_status_handler, router_port->pid, req); + if (nxt_slow_path(stream == 0)) { + goto fail; + } - controller_port = rt->port_by_type[NXT_PROCESS_CONTROLLER]; + rc = nxt_port_socket_write(task, router_port, NXT_PORT_MSG_STATUS, -1, stream, + controller_port->id, NULL); - stream = nxt_port_rpc_register_handler(task, controller_port, - nxt_controller_status_handler, - nxt_controller_status_handler, - router_port->pid, req); - if (nxt_slow_path(stream == 0)) { - goto fail; - } - - rc = nxt_port_socket_write(task, router_port, NXT_PORT_MSG_STATUS, - -1, stream, controller_port->id, NULL); - - if (nxt_slow_path(rc != NXT_OK)) { - nxt_port_rpc_cancel(task, controller_port, stream); + if (nxt_slow_path(rc != NXT_OK)) { + nxt_port_rpc_cancel(task, controller_port, stream); - goto fail; - } + goto fail; + } - nxt_queue_insert_head(&nxt_controller_waiting_requests, &req->link); - return; + nxt_queue_insert_head(&nxt_controller_waiting_requests, &req->link); + return; fail: - nxt_memzero(&resp, sizeof(nxt_controller_response_t)); + nxt_memzero(&resp, sizeof(nxt_controller_response_t)); - resp.status = 500; - resp.title = (u_char *) "Failed to get status."; - resp.offset = -1; + resp.status = 500; + resp.title = (u_char *)"Failed to get status."; + resp.offset = -1; - nxt_controller_response(task, req, &resp); - return; + nxt_controller_response(task, req, &resp); + return; } +static void nxt_controller_status_handler(nxt_task_t *task, + nxt_port_recv_msg_t *msg, + void *data) { + nxt_conf_value_t *status; + nxt_controller_request_t *req; + nxt_controller_response_t resp; -static void -nxt_controller_status_handler(nxt_task_t *task, nxt_port_recv_msg_t *msg, - void *data) -{ - nxt_conf_value_t *status; - nxt_controller_request_t *req; - nxt_controller_response_t resp; - - nxt_debug(task, "controller status handler"); + nxt_debug(task, "controller status handler"); - req = data; + req = data; - if (msg->port_msg.type == NXT_PORT_MSG_RPC_READY) { - status = nxt_status_get((nxt_status_report_t *) msg->buf->mem.pos, - req->conn->mem_pool); - } else { - status = NULL; - } + if (msg->port_msg.type == NXT_PORT_MSG_RPC_READY) { + status = nxt_status_get((nxt_status_report_t *)msg->buf->mem.pos, + req->conn->mem_pool); + } else { + status = NULL; + } - if (status == NULL) { - nxt_queue_remove(&req->link); + if (status == NULL) { + nxt_queue_remove(&req->link); - nxt_memzero(&resp, sizeof(nxt_controller_response_t)); + nxt_memzero(&resp, sizeof(nxt_controller_response_t)); - resp.status = 500; - resp.title = (u_char *) "Failed to get status."; - resp.offset = -1; + resp.status = 500; + resp.title = (u_char *)"Failed to get status."; + resp.offset = -1; - nxt_controller_response(task, req, &resp); - } + nxt_controller_response(task, req, &resp); + } - nxt_controller_status = status; + nxt_controller_status = status; - nxt_controller_flush_requests(task); + nxt_controller_flush_requests(task); - nxt_controller_status = NULL; + nxt_controller_status = NULL; } +static void nxt_controller_status_response(nxt_task_t *task, + nxt_controller_request_t *req, + nxt_str_t *path) { + nxt_conf_value_t *status; + nxt_controller_response_t resp; -static void -nxt_controller_status_response(nxt_task_t *task, nxt_controller_request_t *req, - nxt_str_t *path) -{ - nxt_conf_value_t *status; - nxt_controller_response_t resp; + status = nxt_conf_get_path(nxt_controller_status, path); - status = nxt_conf_get_path(nxt_controller_status, path); + nxt_memzero(&resp, sizeof(nxt_controller_response_t)); - nxt_memzero(&resp, sizeof(nxt_controller_response_t)); + if (status == NULL) { + resp.status = 404; + resp.title = (u_char *)"Invalid path."; + resp.offset = -1; - if (status == NULL) { - resp.status = 404; - resp.title = (u_char *) "Invalid path."; - resp.offset = -1; + nxt_controller_response(task, req, &resp); + return; + } - nxt_controller_response(task, req, &resp); - return; - } + resp.status = 200; + resp.conf = status; - resp.status = 200; - resp.conf = status; - - nxt_controller_response(task, req, &resp); + nxt_controller_response(task, req, &resp); } - #if (NXT_TLS) -static void -nxt_controller_process_cert(nxt_task_t *task, - nxt_controller_request_t *req, nxt_str_t *path) -{ - u_char *p; - nxt_str_t name; - nxt_int_t ret; - nxt_conn_t *c; - nxt_cert_t *cert; - nxt_conf_value_t *value; - nxt_controller_response_t resp; - - name.length = path->length - 1; - name.start = path->start + 1; +static void nxt_controller_process_cert(nxt_task_t *task, + nxt_controller_request_t *req, + nxt_str_t *path) { + u_char *p; + nxt_str_t name; + nxt_int_t ret; + nxt_conn_t *c; + nxt_cert_t *cert; + nxt_conf_value_t *value; + nxt_controller_response_t resp; - p = memchr(name.start, '/', name.length); + name.length = path->length - 1; + name.start = path->start + 1; - if (p != NULL) { - name.length = p - name.start; + p = memchr(name.start, '/', name.length); - path->length -= p - path->start; - path->start = p; + if (p != NULL) { + name.length = p - name.start; - } else { - path = NULL; - } + path->length -= p - path->start; + path->start = p; - nxt_memzero(&resp, sizeof(nxt_controller_response_t)); + } else { + path = NULL; + } - c = req->conn; + nxt_memzero(&resp, sizeof(nxt_controller_response_t)); - if (nxt_str_eq(&req->parser.method, "GET", 3)) { + c = req->conn; - if (name.length != 0) { - value = nxt_cert_info_get(&name); - if (value == NULL) { - goto cert_not_found; - } + if (nxt_str_eq(&req->parser.method, "GET", 3)) { - if (path != NULL) { - value = nxt_conf_get_path(value, path); - if (value == NULL) { - goto not_found; - } - } + if (name.length != 0) { + value = nxt_cert_info_get(&name); + if (value == NULL) { + goto cert_not_found; + } - } else { - value = nxt_cert_info_get_all(c->mem_pool); - if (value == NULL) { - goto alloc_fail; - } + if (path != NULL) { + value = nxt_conf_get_path(value, path); + if (value == NULL) { + goto not_found; } + } - resp.status = 200; - resp.conf = value; - - nxt_controller_response(task, req, &resp); - return; - } - - if (name.length == 0 || path != NULL) { - goto invalid_name; + } else { + value = nxt_cert_info_get_all(c->mem_pool); + if (value == NULL) { + goto alloc_fail; + } } - if (nxt_str_eq(&req->parser.method, "PUT", 3)) { - value = nxt_cert_info_get(&name); - if (value != NULL) { - goto exists_cert; - } - - cert = nxt_cert_mem(task, &c->read->mem); - if (cert == NULL) { - goto invalid_cert; - } + resp.status = 200; + resp.conf = value; - ret = nxt_cert_info_save(&name, cert); + nxt_controller_response(task, req, &resp); + return; + } - nxt_cert_destroy(cert); + if (name.length == 0 || path != NULL) { + goto invalid_name; + } - if (nxt_slow_path(ret != NXT_OK)) { - goto alloc_fail; - } + if (nxt_str_eq(&req->parser.method, "PUT", 3)) { + value = nxt_cert_info_get(&name); + if (value != NULL) { + goto exists_cert; + } - nxt_cert_store_get(task, &name, c->mem_pool, - nxt_controller_process_cert_save, req); - return; + cert = nxt_cert_mem(task, &c->read->mem); + if (cert == NULL) { + goto invalid_cert; } - if (nxt_str_eq(&req->parser.method, "DELETE", 6)) { + ret = nxt_cert_info_save(&name, cert); - if (nxt_controller_cert_in_use(&name)) { - goto cert_in_use; - } + nxt_cert_destroy(cert); - if (nxt_cert_info_delete(&name) != NXT_OK) { - goto cert_not_found; - } + if (nxt_slow_path(ret != NXT_OK)) { + goto alloc_fail; + } - nxt_cert_store_delete(task, &name, c->mem_pool); + nxt_cert_store_get(task, &name, c->mem_pool, + nxt_controller_process_cert_save, req); + return; + } - resp.status = 200; - resp.title = (u_char *) "Certificate deleted."; + if (nxt_str_eq(&req->parser.method, "DELETE", 6)) { - nxt_controller_response(task, req, &resp); - return; + if (nxt_controller_cert_in_use(&name)) { + goto cert_in_use; } - resp.status = 405; - resp.title = (u_char *) "Invalid method."; - resp.offset = -1; + if (nxt_cert_info_delete(&name) != NXT_OK) { + goto cert_not_found; + } + + nxt_cert_store_delete(task, &name, c->mem_pool); + + resp.status = 200; + resp.title = (u_char *)"Certificate deleted."; nxt_controller_response(task, req, &resp); return; + } + + resp.status = 405; + resp.title = (u_char *)"Invalid method."; + resp.offset = -1; + + nxt_controller_response(task, req, &resp); + return; invalid_name: - resp.status = 400; - resp.title = (u_char *) "Invalid certificate name."; - resp.offset = -1; + resp.status = 400; + resp.title = (u_char *)"Invalid certificate name."; + resp.offset = -1; - nxt_controller_response(task, req, &resp); - return; + nxt_controller_response(task, req, &resp); + return; invalid_cert: - resp.status = 400; - resp.title = (u_char *) "Invalid certificate."; - resp.offset = -1; + resp.status = 400; + resp.title = (u_char *)"Invalid certificate."; + resp.offset = -1; - nxt_controller_response(task, req, &resp); - return; + nxt_controller_response(task, req, &resp); + return; exists_cert: - resp.status = 400; - resp.title = (u_char *) "Certificate already exists."; - resp.offset = -1; + resp.status = 400; + resp.title = (u_char *)"Certificate already exists."; + resp.offset = -1; - nxt_controller_response(task, req, &resp); - return; + nxt_controller_response(task, req, &resp); + return; cert_in_use: - resp.status = 400; - resp.title = (u_char *) "Certificate is used in the configuration."; - resp.offset = -1; + resp.status = 400; + resp.title = (u_char *)"Certificate is used in the configuration."; + resp.offset = -1; - nxt_controller_response(task, req, &resp); - return; + nxt_controller_response(task, req, &resp); + return; cert_not_found: - resp.status = 404; - resp.title = (u_char *) "Certificate doesn't exist."; - resp.offset = -1; + resp.status = 404; + resp.title = (u_char *)"Certificate doesn't exist."; + resp.offset = -1; - nxt_controller_response(task, req, &resp); - return; + nxt_controller_response(task, req, &resp); + return; not_found: - resp.status = 404; - resp.title = (u_char *) "Invalid path."; - resp.offset = -1; + resp.status = 404; + resp.title = (u_char *)"Invalid path."; + resp.offset = -1; - nxt_controller_response(task, req, &resp); - return; + nxt_controller_response(task, req, &resp); + return; alloc_fail: - resp.status = 500; - resp.title = (u_char *) "Memory allocation failed."; - resp.offset = -1; + resp.status = 500; + resp.title = (u_char *)"Memory allocation failed."; + resp.offset = -1; - nxt_controller_response(task, req, &resp); - return; + nxt_controller_response(task, req, &resp); + return; } +static void nxt_controller_process_cert_save(nxt_task_t *task, + nxt_port_recv_msg_t *msg, + void *data) { + nxt_conn_t *c; + nxt_buf_mem_t *mbuf; + nxt_controller_request_t *req; + nxt_controller_response_t resp; -static void -nxt_controller_process_cert_save(nxt_task_t *task, nxt_port_recv_msg_t *msg, - void *data) -{ - nxt_conn_t *c; - nxt_buf_mem_t *mbuf; - nxt_controller_request_t *req; - nxt_controller_response_t resp; - - req = data; + req = data; - nxt_memzero(&resp, sizeof(nxt_controller_response_t)); + nxt_memzero(&resp, sizeof(nxt_controller_response_t)); - if (msg == NULL || msg->port_msg.type == _NXT_PORT_MSG_RPC_ERROR) { - resp.status = 500; - resp.title = (u_char *) "Failed to store certificate."; + if (msg == NULL || msg->port_msg.type == _NXT_PORT_MSG_RPC_ERROR) { + resp.status = 500; + resp.title = (u_char *)"Failed to store certificate."; - nxt_controller_response(task, req, &resp); - return; - } + nxt_controller_response(task, req, &resp); + return; + } - c = req->conn; + c = req->conn; - mbuf = &c->read->mem; + mbuf = &c->read->mem; - nxt_fd_write(msg->fd[0], mbuf->pos, nxt_buf_mem_used_size(mbuf)); + nxt_fd_write(msg->fd[0], mbuf->pos, nxt_buf_mem_used_size(mbuf)); - nxt_fd_close(msg->fd[0]); + nxt_fd_close(msg->fd[0]); - nxt_memzero(&resp, sizeof(nxt_controller_response_t)); + nxt_memzero(&resp, sizeof(nxt_controller_response_t)); - resp.status = 200; - resp.title = (u_char *) "Certificate chain uploaded."; + resp.status = 200; + resp.title = (u_char *)"Certificate chain uploaded."; - nxt_controller_response(task, req, &resp); + nxt_controller_response(task, req, &resp); } +static nxt_bool_t nxt_controller_cert_in_use(nxt_str_t *name) { + uint32_t i, n, next; + nxt_str_t str; + nxt_conf_value_t *listeners, *listener, *value, *element; -static nxt_bool_t -nxt_controller_cert_in_use(nxt_str_t *name) -{ - uint32_t i, n, next; - nxt_str_t str; - nxt_conf_value_t *listeners, *listener, *value, *element; + static const nxt_str_t listeners_path = nxt_string("/listeners"); + static const nxt_str_t certificate_path = nxt_string("/tls/certificate"); - static const nxt_str_t listeners_path = nxt_string("/listeners"); - static const nxt_str_t certificate_path = nxt_string("/tls/certificate"); + listeners = nxt_conf_get_path(nxt_controller_conf.root, &listeners_path); - listeners = nxt_conf_get_path(nxt_controller_conf.root, &listeners_path); + if (listeners != NULL) { + next = 0; - if (listeners != NULL) { - next = 0; - - for ( ;; ) { - listener = nxt_conf_next_object_member(listeners, &str, &next); - if (listener == NULL) { - break; - } + for (;;) { + listener = nxt_conf_next_object_member(listeners, &str, &next); + if (listener == NULL) { + break; + } - value = nxt_conf_get_path(listener, &certificate_path); - if (value == NULL) { - continue; - } + value = nxt_conf_get_path(listener, &certificate_path); + if (value == NULL) { + continue; + } - if (nxt_conf_type(value) == NXT_CONF_ARRAY) { - n = nxt_conf_array_elements_count(value); + if (nxt_conf_type(value) == NXT_CONF_ARRAY) { + n = nxt_conf_array_elements_count(value); - for (i = 0; i < n; i++) { - element = nxt_conf_get_array_element(value, i); + for (i = 0; i < n; i++) { + element = nxt_conf_get_array_element(value, i); - nxt_conf_get_string(element, &str); + nxt_conf_get_string(element, &str); - if (nxt_strstr_eq(&str, name)) { - return 1; - } - } + if (nxt_strstr_eq(&str, name)) { + return 1; + } + } - } else { - /* NXT_CONF_STRING */ + } else { + /* NXT_CONF_STRING */ - nxt_conf_get_string(value, &str); + nxt_conf_get_string(value, &str); - if (nxt_strstr_eq(&str, name)) { - return 1; - } - } + if (nxt_strstr_eq(&str, name)) { + return 1; } + } } + } - return 0; + return 0; } #endif - #if (NXT_HAVE_NJS) -static void -nxt_controller_process_script(nxt_task_t *task, - nxt_controller_request_t *req, nxt_str_t *path) -{ - u_char *p; - nxt_int_t ret; - nxt_str_t name; - nxt_conn_t *c; - nxt_script_t *script; - nxt_buf_mem_t *bm; - nxt_conf_value_t *value; - nxt_controller_response_t resp; - u_char error[NXT_MAX_ERROR_STR]; +static void nxt_controller_process_script(nxt_task_t *task, + nxt_controller_request_t *req, + nxt_str_t *path) { + u_char *p; + nxt_int_t ret; + nxt_str_t name; + nxt_conn_t *c; + nxt_script_t *script; + nxt_buf_mem_t *bm; + nxt_conf_value_t *value; + nxt_controller_response_t resp; + u_char error[NXT_MAX_ERROR_STR]; - name.length = path->length - 1; - name.start = path->start + 1; + name.length = path->length - 1; + name.start = path->start + 1; - p = memchr(name.start, '/', name.length); + p = memchr(name.start, '/', name.length); - if (p != NULL) { - name.length = p - name.start; + if (p != NULL) { + name.length = p - name.start; - path->length -= p - path->start; - path->start = p; + path->length -= p - path->start; + path->start = p; - } else { - path = NULL; - } + } else { + path = NULL; + } - nxt_memzero(&resp, sizeof(nxt_controller_response_t)); - - c = req->conn; + nxt_memzero(&resp, sizeof(nxt_controller_response_t)); - if (nxt_str_eq(&req->parser.method, "GET", 3)) { + c = req->conn; - if (name.length != 0) { - value = nxt_script_info_get(&name); - if (value == NULL) { - goto script_not_found; - } + if (nxt_str_eq(&req->parser.method, "GET", 3)) { - if (path != NULL) { - value = nxt_conf_get_path(value, path); - if (value == NULL) { - goto not_found; - } - } + if (name.length != 0) { + value = nxt_script_info_get(&name); + if (value == NULL) { + goto script_not_found; + } - } else { - value = nxt_script_info_get_all(c->mem_pool); - if (value == NULL) { - goto alloc_fail; - } + if (path != NULL) { + value = nxt_conf_get_path(value, path); + if (value == NULL) { + goto not_found; } + } - resp.status = 200; - resp.conf = value; - - nxt_controller_response(task, req, &resp); - return; - } - - if (name.length == 0 || path != NULL) { - goto invalid_name; + } else { + value = nxt_script_info_get_all(c->mem_pool); + if (value == NULL) { + goto alloc_fail; + } } - if (nxt_str_eq(&req->parser.method, "PUT", 3)) { - value = nxt_script_info_get(&name); - if (value != NULL) { - goto exists_script; - } + resp.status = 200; + resp.conf = value; - bm = &c->read->mem; + nxt_controller_response(task, req, &resp); + return; + } - script = nxt_script_new(task, &name, bm->pos, - nxt_buf_mem_used_size(bm), error); - if (script == NULL) { - goto invalid_script; - } + if (name.length == 0 || path != NULL) { + goto invalid_name; + } - ret = nxt_script_info_save(&name, script); + if (nxt_str_eq(&req->parser.method, "PUT", 3)) { + value = nxt_script_info_get(&name); + if (value != NULL) { + goto exists_script; + } - nxt_script_destroy(script); + bm = &c->read->mem; - if (nxt_slow_path(ret != NXT_OK)) { - goto alloc_fail; - } - - nxt_script_store_get(task, &name, c->mem_pool, - nxt_controller_process_script_save, req); - return; + script = + nxt_script_new(task, &name, bm->pos, nxt_buf_mem_used_size(bm), error); + if (script == NULL) { + goto invalid_script; } - if (nxt_str_eq(&req->parser.method, "DELETE", 6)) { + ret = nxt_script_info_save(&name, script); - if (nxt_controller_script_in_use(&name)) { - goto script_in_use; - } + nxt_script_destroy(script); - if (nxt_script_info_delete(&name) != NXT_OK) { - goto script_not_found; - } + if (nxt_slow_path(ret != NXT_OK)) { + goto alloc_fail; + } - nxt_script_store_delete(task, &name, c->mem_pool); + nxt_script_store_get(task, &name, c->mem_pool, + nxt_controller_process_script_save, req); + return; + } - resp.status = 200; - resp.title = (u_char *) "JS module deleted."; + if (nxt_str_eq(&req->parser.method, "DELETE", 6)) { - nxt_controller_response(task, req, &resp); - return; + if (nxt_controller_script_in_use(&name)) { + goto script_in_use; } - resp.status = 405; - resp.title = (u_char *) "Invalid method."; - resp.offset = -1; + if (nxt_script_info_delete(&name) != NXT_OK) { + goto script_not_found; + } + + nxt_script_store_delete(task, &name, c->mem_pool); + + resp.status = 200; + resp.title = (u_char *)"JS module deleted."; nxt_controller_response(task, req, &resp); return; + } + + resp.status = 405; + resp.title = (u_char *)"Invalid method."; + resp.offset = -1; + + nxt_controller_response(task, req, &resp); + return; invalid_name: - resp.status = 400; - resp.title = (u_char *) "Invalid JS module name."; - resp.offset = -1; + resp.status = 400; + resp.title = (u_char *)"Invalid JS module name."; + resp.offset = -1; - nxt_controller_response(task, req, &resp); - return; + nxt_controller_response(task, req, &resp); + return; invalid_script: - resp.status = 400; - resp.title = (u_char *) "Invalid JS module."; - resp.offset = -1; + resp.status = 400; + resp.title = (u_char *)"Invalid JS module."; + resp.offset = -1; - resp.detail.start = error; - resp.detail.length = nxt_strlen(error); + resp.detail.start = error; + resp.detail.length = nxt_strlen(error); - nxt_controller_response(task, req, &resp); - return; + nxt_controller_response(task, req, &resp); + return; exists_script: - resp.status = 400; - resp.title = (u_char *) "JS module already exists."; - resp.offset = -1; + resp.status = 400; + resp.title = (u_char *)"JS module already exists."; + resp.offset = -1; - nxt_controller_response(task, req, &resp); - return; + nxt_controller_response(task, req, &resp); + return; script_in_use: - resp.status = 400; - resp.title = (u_char *) "JS module is used in the configuration."; - resp.offset = -1; + resp.status = 400; + resp.title = (u_char *)"JS module is used in the configuration."; + resp.offset = -1; - nxt_controller_response(task, req, &resp); - return; + nxt_controller_response(task, req, &resp); + return; script_not_found: - resp.status = 404; - resp.title = (u_char *) "JS module doesn't exist."; - resp.offset = -1; + resp.status = 404; + resp.title = (u_char *)"JS module doesn't exist."; + resp.offset = -1; - nxt_controller_response(task, req, &resp); - return; + nxt_controller_response(task, req, &resp); + return; not_found: - resp.status = 404; - resp.title = (u_char *) "Invalid path."; - resp.offset = -1; + resp.status = 404; + resp.title = (u_char *)"Invalid path."; + resp.offset = -1; - nxt_controller_response(task, req, &resp); - return; + nxt_controller_response(task, req, &resp); + return; alloc_fail: - resp.status = 500; - resp.title = (u_char *) "Memory allocation failed."; - resp.offset = -1; + resp.status = 500; + resp.title = (u_char *)"Memory allocation failed."; + resp.offset = -1; - nxt_controller_response(task, req, &resp); + nxt_controller_response(task, req, &resp); } +static void nxt_controller_process_script_save(nxt_task_t *task, + nxt_port_recv_msg_t *msg, + void *data) { + nxt_conn_t *c; + nxt_buf_mem_t *mbuf; + nxt_controller_request_t *req; + nxt_controller_response_t resp; -static void -nxt_controller_process_script_save(nxt_task_t *task, nxt_port_recv_msg_t *msg, - void *data) -{ - nxt_conn_t *c; - nxt_buf_mem_t *mbuf; - nxt_controller_request_t *req; - nxt_controller_response_t resp; - - req = data; + req = data; - nxt_memzero(&resp, sizeof(nxt_controller_response_t)); + nxt_memzero(&resp, sizeof(nxt_controller_response_t)); - if (msg == NULL || msg->port_msg.type == _NXT_PORT_MSG_RPC_ERROR) { - resp.status = 500; - resp.title = (u_char *) "Failed to store script."; + if (msg == NULL || msg->port_msg.type == _NXT_PORT_MSG_RPC_ERROR) { + resp.status = 500; + resp.title = (u_char *)"Failed to store script."; - nxt_controller_response(task, req, &resp); - return; - } + nxt_controller_response(task, req, &resp); + return; + } - c = req->conn; + c = req->conn; - mbuf = &c->read->mem; + mbuf = &c->read->mem; - nxt_fd_write(msg->fd[0], mbuf->pos, nxt_buf_mem_used_size(mbuf)); + nxt_fd_write(msg->fd[0], mbuf->pos, nxt_buf_mem_used_size(mbuf)); - nxt_fd_close(msg->fd[0]); + nxt_fd_close(msg->fd[0]); - nxt_memzero(&resp, sizeof(nxt_controller_response_t)); + nxt_memzero(&resp, sizeof(nxt_controller_response_t)); - resp.status = 200; - resp.title = (u_char *) "JS module uploaded."; + resp.status = 200; + resp.title = (u_char *)"JS module uploaded."; - nxt_controller_response(task, req, &resp); + nxt_controller_response(task, req, &resp); } +static nxt_bool_t nxt_controller_script_in_use(nxt_str_t *name) { + uint32_t i, n; + nxt_str_t str; + nxt_conf_value_t *js_module, *element; -static nxt_bool_t -nxt_controller_script_in_use(nxt_str_t *name) -{ - uint32_t i, n; - nxt_str_t str; - nxt_conf_value_t *js_module, *element; - - static const nxt_str_t js_module_path = nxt_string("/settings/js_module"); + static const nxt_str_t js_module_path = nxt_string("/settings/js_module"); - js_module = nxt_conf_get_path(nxt_controller_conf.root, - &js_module_path); + js_module = nxt_conf_get_path(nxt_controller_conf.root, &js_module_path); - if (js_module != NULL) { + if (js_module != NULL) { - if (nxt_conf_type(js_module) == NXT_CONF_ARRAY) { - n = nxt_conf_array_elements_count(js_module); + if (nxt_conf_type(js_module) == NXT_CONF_ARRAY) { + n = nxt_conf_array_elements_count(js_module); - for (i = 0; i < n; i++) { - element = nxt_conf_get_array_element(js_module, i); + for (i = 0; i < n; i++) { + element = nxt_conf_get_array_element(js_module, i); - nxt_conf_get_string(element, &str); + nxt_conf_get_string(element, &str); - if (nxt_strstr_eq(&str, name)) { - return 1; - } - } + if (nxt_strstr_eq(&str, name)) { + return 1; + } + } - } else { - /* NXT_CONF_STRING */ + } else { + /* NXT_CONF_STRING */ - nxt_conf_get_string(js_module, &str); + nxt_conf_get_string(js_module, &str); - if (nxt_strstr_eq(&str, name)) { - return 1; - } - } + if (nxt_strstr_eq(&str, name)) { + return 1; + } } + } - return 0; + return 0; } +static void nxt_controller_script_cleanup(nxt_task_t *task, void *obj, + void *data) { + pid_t main_pid; + nxt_array_t *scripts; + nxt_runtime_t *rt; -static void -nxt_controller_script_cleanup(nxt_task_t *task, void *obj, void *data) -{ - pid_t main_pid; - nxt_array_t *scripts; - nxt_runtime_t *rt; - - scripts = obj; - rt = data; + scripts = obj; + rt = data; - main_pid = rt->port_by_type[NXT_PROCESS_MAIN]->pid; + main_pid = rt->port_by_type[NXT_PROCESS_MAIN]->pid; - if (nxt_pid == main_pid && scripts != NULL) { - nxt_script_store_release(scripts); - } + if (nxt_pid == main_pid && scripts != NULL) { + nxt_script_store_release(scripts); + } } #endif +static void nxt_controller_conf_handler(nxt_task_t *task, + nxt_port_recv_msg_t *msg, void *data) { + nxt_controller_request_t *req; + nxt_controller_response_t resp; -static void -nxt_controller_conf_handler(nxt_task_t *task, nxt_port_recv_msg_t *msg, - void *data) -{ - nxt_controller_request_t *req; - nxt_controller_response_t resp; - - req = data; + req = data; - nxt_debug(task, "controller conf ready: %*s", - nxt_buf_mem_used_size(&msg->buf->mem), msg->buf->mem.pos); + nxt_debug(task, "controller conf ready: %*s", + nxt_buf_mem_used_size(&msg->buf->mem), msg->buf->mem.pos); - nxt_queue_remove(&req->link); + nxt_queue_remove(&req->link); - nxt_memzero(&resp, sizeof(nxt_controller_response_t)); + nxt_memzero(&resp, sizeof(nxt_controller_response_t)); - if (msg->port_msg.type == NXT_PORT_MSG_RPC_READY) { - nxt_mp_destroy(nxt_controller_conf.pool); + if (msg->port_msg.type == NXT_PORT_MSG_RPC_READY) { + nxt_mp_destroy(nxt_controller_conf.pool); - nxt_controller_conf = req->conf; + nxt_controller_conf = req->conf; - nxt_controller_conf_store(task, req->conf.root); + nxt_controller_conf_store(task, req->conf.root); - resp.status = 200; - resp.title = (u_char *) "Reconfiguration done."; + resp.status = 200; + resp.title = (u_char *)"Reconfiguration done."; - } else { - nxt_mp_destroy(req->conf.pool); + } else { + nxt_mp_destroy(req->conf.pool); - resp.status = 500; - resp.title = (u_char *) "Failed to apply new configuration."; - resp.offset = -1; - } + resp.status = 500; + resp.title = (u_char *)"Failed to apply new configuration."; + resp.offset = -1; + } - nxt_controller_response(task, req, &resp); + nxt_controller_response(task, req, &resp); - nxt_controller_flush_requests(task); + nxt_controller_flush_requests(task); } +static void nxt_controller_process_control(nxt_task_t *task, + nxt_controller_request_t *req, + nxt_str_t *path) { + uint32_t stream; + nxt_buf_t *b; + nxt_int_t rc; + nxt_port_t *router_port, *controller_port; + nxt_runtime_t *rt; + nxt_conf_value_t *value; + nxt_controller_response_t resp; + + static nxt_str_t applications = nxt_string("applications"); + + nxt_memzero(&resp, sizeof(nxt_controller_response_t)); + + if (!nxt_str_eq(&req->parser.method, "GET", 3)) { + goto not_allowed; + } + + if (!nxt_str_start(path, "applications/", 13) || + memcmp(path->start + path->length - 8, "/restart", 8) != 0) { + goto not_found; + } + + path->start += 13; + path->length -= 13 + 8; + + if (nxt_controller_check_postpone_request(task)) { + nxt_queue_insert_tail(&nxt_controller_waiting_requests, &req->link); + return; + } -static void -nxt_controller_process_control(nxt_task_t *task, - nxt_controller_request_t *req, nxt_str_t *path) -{ - uint32_t stream; - nxt_buf_t *b; - nxt_int_t rc; - nxt_port_t *router_port, *controller_port; - nxt_runtime_t *rt; - nxt_conf_value_t *value; - nxt_controller_response_t resp; - - static nxt_str_t applications = nxt_string("applications"); - - nxt_memzero(&resp, sizeof(nxt_controller_response_t)); - - if (!nxt_str_eq(&req->parser.method, "GET", 3)) { - goto not_allowed; - } - - if (!nxt_str_start(path, "applications/", 13) - || memcmp(path->start + path->length - 8, "/restart", 8) != 0) - { - goto not_found; - } + value = nxt_controller_conf.root; + if (value == NULL) { + goto not_found; + } - path->start += 13; - path->length -= 13 + 8; + value = nxt_conf_get_object_member(value, &applications, NULL); + if (value == NULL) { + goto not_found; + } - if (nxt_controller_check_postpone_request(task)) { - nxt_queue_insert_tail(&nxt_controller_waiting_requests, &req->link); - return; - } + value = nxt_conf_get_object_member(value, path, NULL); + if (value == NULL) { + goto not_found; + } - value = nxt_controller_conf.root; - if (value == NULL) { - goto not_found; - } + b = nxt_buf_mem_alloc(req->conn->mem_pool, path->length, 0); + if (nxt_slow_path(b == NULL)) { + goto alloc_fail; + } - value = nxt_conf_get_object_member(value, &applications, NULL); - if (value == NULL) { - goto not_found; - } + b->mem.free = nxt_cpymem(b->mem.pos, path->start, path->length); - value = nxt_conf_get_object_member(value, path, NULL); - if (value == NULL) { - goto not_found; - } + rt = task->thread->runtime; - b = nxt_buf_mem_alloc(req->conn->mem_pool, path->length, 0); - if (nxt_slow_path(b == NULL)) { - goto alloc_fail; - } + controller_port = rt->port_by_type[NXT_PROCESS_CONTROLLER]; + router_port = rt->port_by_type[NXT_PROCESS_ROUTER]; - b->mem.free = nxt_cpymem(b->mem.pos, path->start, path->length); + stream = nxt_port_rpc_register_handler( + task, controller_port, nxt_controller_app_restart_handler, + nxt_controller_app_restart_handler, router_port->pid, req); + if (nxt_slow_path(stream == 0)) { + goto alloc_fail; + } - rt = task->thread->runtime; + rc = nxt_port_socket_write(task, router_port, NXT_PORT_MSG_APP_RESTART, -1, + stream, 0, b); + if (nxt_slow_path(rc != NXT_OK)) { + nxt_port_rpc_cancel(task, controller_port, stream); - controller_port = rt->port_by_type[NXT_PROCESS_CONTROLLER]; - router_port = rt->port_by_type[NXT_PROCESS_ROUTER]; + goto fail; + } - stream = nxt_port_rpc_register_handler(task, controller_port, - nxt_controller_app_restart_handler, - nxt_controller_app_restart_handler, - router_port->pid, req); - if (nxt_slow_path(stream == 0)) { - goto alloc_fail; - } + nxt_queue_insert_head(&nxt_controller_waiting_requests, &req->link); - rc = nxt_port_socket_write(task, router_port, NXT_PORT_MSG_APP_RESTART, - -1, stream, 0, b); - if (nxt_slow_path(rc != NXT_OK)) { - nxt_port_rpc_cancel(task, controller_port, stream); - - goto fail; - } - - nxt_queue_insert_head(&nxt_controller_waiting_requests, &req->link); - - return; + return; not_allowed: - resp.status = 405; - resp.title = (u_char *) "Method isn't allowed."; - resp.offset = -1; + resp.status = 405; + resp.title = (u_char *)"Method isn't allowed."; + resp.offset = -1; - nxt_controller_response(task, req, &resp); - return; + nxt_controller_response(task, req, &resp); + return; not_found: - resp.status = 404; - resp.title = (u_char *) "Value doesn't exist."; - resp.offset = -1; + resp.status = 404; + resp.title = (u_char *)"Value doesn't exist."; + resp.offset = -1; - nxt_controller_response(task, req, &resp); - return; + nxt_controller_response(task, req, &resp); + return; alloc_fail: - resp.status = 500; - resp.title = (u_char *) "Memory allocation failed."; - resp.offset = -1; + resp.status = 500; + resp.title = (u_char *)"Memory allocation failed."; + resp.offset = -1; - nxt_controller_response(task, req, &resp); - return; + nxt_controller_response(task, req, &resp); + return; fail: - resp.status = 500; - resp.title = (u_char *) "Send restart failed."; - resp.offset = -1; + resp.status = 500; + resp.title = (u_char *)"Send restart failed."; + resp.offset = -1; - nxt_controller_response(task, req, &resp); + nxt_controller_response(task, req, &resp); } +static void nxt_controller_app_restart_handler(nxt_task_t *task, + nxt_port_recv_msg_t *msg, + void *data) { + nxt_controller_request_t *req; + nxt_controller_response_t resp; -static void -nxt_controller_app_restart_handler(nxt_task_t *task, nxt_port_recv_msg_t *msg, - void *data) -{ - nxt_controller_request_t *req; - nxt_controller_response_t resp; - - req = data; + req = data; - nxt_debug(task, "controller app restart handler"); + nxt_debug(task, "controller app restart handler"); - nxt_queue_remove(&req->link); + nxt_queue_remove(&req->link); - nxt_memzero(&resp, sizeof(nxt_controller_response_t)); + nxt_memzero(&resp, sizeof(nxt_controller_response_t)); - if (msg->port_msg.type == NXT_PORT_MSG_RPC_READY) { - resp.status = 200; - resp.title = (u_char *) "Ok"; + if (msg->port_msg.type == NXT_PORT_MSG_RPC_READY) { + resp.status = 200; + resp.title = (u_char *)"Ok"; - } else { - resp.status = 500; - resp.title = (u_char *) "Failed to restart app."; - resp.offset = -1; - } + } else { + resp.status = 500; + resp.title = (u_char *)"Failed to restart app."; + resp.offset = -1; + } - nxt_controller_response(task, req, &resp); + nxt_controller_response(task, req, &resp); - nxt_controller_flush_requests(task); + nxt_controller_flush_requests(task); } +static void nxt_controller_conf_store(nxt_task_t *task, + nxt_conf_value_t *conf) { + void *mem; + u_char *end; + size_t size; + nxt_fd_t fd; + nxt_buf_t *b; + nxt_port_t *main_port; + nxt_runtime_t *rt; -static void -nxt_controller_conf_store(nxt_task_t *task, nxt_conf_value_t *conf) -{ - void *mem; - u_char *end; - size_t size; - nxt_fd_t fd; - nxt_buf_t *b; - nxt_port_t *main_port; - nxt_runtime_t *rt; + rt = task->thread->runtime; - rt = task->thread->runtime; + main_port = rt->port_by_type[NXT_PROCESS_MAIN]; - main_port = rt->port_by_type[NXT_PROCESS_MAIN]; + size = nxt_conf_json_length(conf, NULL); - size = nxt_conf_json_length(conf, NULL); - - fd = nxt_shm_open(task, size); - if (nxt_slow_path(fd == -1)) { - return; - } + fd = nxt_shm_open(task, size); + if (nxt_slow_path(fd == -1)) { + return; + } - mem = nxt_mem_mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); - if (nxt_slow_path(mem == MAP_FAILED)) { - goto fail; - } + mem = nxt_mem_mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); + if (nxt_slow_path(mem == MAP_FAILED)) { + goto fail; + } - end = nxt_conf_json_print(mem, conf, NULL); + end = nxt_conf_json_print(mem, conf, NULL); - nxt_mem_munmap(mem, size); + nxt_mem_munmap(mem, size); - size = end - (u_char *) mem; + size = end - (u_char *)mem; - b = nxt_buf_mem_alloc(task->thread->engine->mem_pool, sizeof(size_t), 0); - if (nxt_slow_path(b == NULL)) { - goto fail; - } + b = nxt_buf_mem_alloc(task->thread->engine->mem_pool, sizeof(size_t), 0); + if (nxt_slow_path(b == NULL)) { + goto fail; + } - b->mem.free = nxt_cpymem(b->mem.pos, &size, sizeof(size_t)); + b->mem.free = nxt_cpymem(b->mem.pos, &size, sizeof(size_t)); - (void) nxt_port_socket_write(task, main_port, - NXT_PORT_MSG_CONF_STORE | NXT_PORT_MSG_CLOSE_FD, - fd, 0, -1, b); + (void)nxt_port_socket_write(task, main_port, + NXT_PORT_MSG_CONF_STORE | NXT_PORT_MSG_CLOSE_FD, + fd, 0, -1, b); - return; + return; fail: - nxt_fd_close(fd); + nxt_fd_close(fd); } +static void nxt_controller_response(nxt_task_t *task, + nxt_controller_request_t *req, + nxt_controller_response_t *resp) { + size_t size; + nxt_str_t status_line, str; + nxt_buf_t *b, *body; + nxt_conn_t *c; + nxt_uint_t n; + nxt_conf_value_t *value, *location; + nxt_conf_json_pretty_t pretty; + + static const nxt_str_t success_str = nxt_string("success"); + static const nxt_str_t error_str = nxt_string("error"); + static const nxt_str_t detail_str = nxt_string("detail"); + static const nxt_str_t location_str = nxt_string("location"); + static const nxt_str_t offset_str = nxt_string("offset"); + static const nxt_str_t line_str = nxt_string("line"); + static const nxt_str_t column_str = nxt_string("column"); + + static nxt_time_string_t date_cache = { + (nxt_atomic_uint_t)-1, + nxt_controller_date, + "%s, %02d %s %4d %02d:%02d:%02d GMT", + nxt_length("Wed, 31 Dec 1986 16:40:00 GMT"), + NXT_THREAD_TIME_GMT, + NXT_THREAD_TIME_SEC, + }; + + switch (resp->status) { + + case 200: + nxt_str_set(&status_line, "200 OK"); + break; + + case 400: + nxt_str_set(&status_line, "400 Bad Request"); + break; + + case 404: + nxt_str_set(&status_line, "404 Not Found"); + break; + + case 405: + nxt_str_set(&status_line, "405 Method Not Allowed"); + break; + + default: + nxt_str_set(&status_line, "500 Internal Server Error"); + break; + } + + c = req->conn; + value = resp->conf; + + if (value == NULL) { + n = 1 + (resp->detail.length != 0) + + (resp->status >= 400 && resp->offset != -1); + + value = nxt_conf_create_object(c->mem_pool, n); + + if (nxt_slow_path(value == NULL)) { + nxt_controller_conn_close(task, c, req); + return; + } + + str.length = nxt_strlen(resp->title); + str.start = resp->title; + + if (resp->status < 400) { + nxt_conf_set_member_string(value, &success_str, &str, 0); -static void -nxt_controller_response(nxt_task_t *task, nxt_controller_request_t *req, - nxt_controller_response_t *resp) -{ - size_t size; - nxt_str_t status_line, str; - nxt_buf_t *b, *body; - nxt_conn_t *c; - nxt_uint_t n; - nxt_conf_value_t *value, *location; - nxt_conf_json_pretty_t pretty; - - static const nxt_str_t success_str = nxt_string("success"); - static const nxt_str_t error_str = nxt_string("error"); - static const nxt_str_t detail_str = nxt_string("detail"); - static const nxt_str_t location_str = nxt_string("location"); - static const nxt_str_t offset_str = nxt_string("offset"); - static const nxt_str_t line_str = nxt_string("line"); - static const nxt_str_t column_str = nxt_string("column"); - - static nxt_time_string_t date_cache = { - (nxt_atomic_uint_t) -1, - nxt_controller_date, - "%s, %02d %s %4d %02d:%02d:%02d GMT", - nxt_length("Wed, 31 Dec 1986 16:40:00 GMT"), - NXT_THREAD_TIME_GMT, - NXT_THREAD_TIME_SEC, - }; - - switch (resp->status) { - - case 200: - nxt_str_set(&status_line, "200 OK"); - break; - - case 400: - nxt_str_set(&status_line, "400 Bad Request"); - break; - - case 404: - nxt_str_set(&status_line, "404 Not Found"); - break; - - case 405: - nxt_str_set(&status_line, "405 Method Not Allowed"); - break; - - default: - nxt_str_set(&status_line, "500 Internal Server Error"); - break; + } else { + nxt_conf_set_member_string(value, &error_str, &str, 0); } - c = req->conn; - value = resp->conf; - - if (value == NULL) { - n = 1 - + (resp->detail.length != 0) - + (resp->status >= 400 && resp->offset != -1); - - value = nxt_conf_create_object(c->mem_pool, n); - - if (nxt_slow_path(value == NULL)) { - nxt_controller_conn_close(task, c, req); - return; - } + n = 0; - str.length = nxt_strlen(resp->title); - str.start = resp->title; + if (resp->detail.length != 0) { + n++; - if (resp->status < 400) { - nxt_conf_set_member_string(value, &success_str, &str, 0); - - } else { - nxt_conf_set_member_string(value, &error_str, &str, 0); - } - - n = 0; - - if (resp->detail.length != 0) { - n++; - - nxt_conf_set_member_string(value, &detail_str, &resp->detail, n); - } + nxt_conf_set_member_string(value, &detail_str, &resp->detail, n); + } - if (resp->status >= 400 && resp->offset != -1) { - n++; + if (resp->status >= 400 && resp->offset != -1) { + n++; - location = nxt_conf_create_object(c->mem_pool, - resp->line != 0 ? 3 : 1); + location = nxt_conf_create_object(c->mem_pool, resp->line != 0 ? 3 : 1); - nxt_conf_set_member(value, &location_str, location, n); + nxt_conf_set_member(value, &location_str, location, n); - nxt_conf_set_member_integer(location, &offset_str, resp->offset, 0); + nxt_conf_set_member_integer(location, &offset_str, resp->offset, 0); - if (resp->line != 0) { - nxt_conf_set_member_integer(location, &line_str, - resp->line, 1); + if (resp->line != 0) { + nxt_conf_set_member_integer(location, &line_str, resp->line, 1); - nxt_conf_set_member_integer(location, &column_str, - resp->column, 2); - } - } + nxt_conf_set_member_integer(location, &column_str, resp->column, 2); + } } + } - nxt_memzero(&pretty, sizeof(nxt_conf_json_pretty_t)); + nxt_memzero(&pretty, sizeof(nxt_conf_json_pretty_t)); - size = nxt_conf_json_length(value, &pretty) + 2; + size = nxt_conf_json_length(value, &pretty) + 2; - body = nxt_buf_mem_alloc(c->mem_pool, size, 0); - if (nxt_slow_path(body == NULL)) { - nxt_controller_conn_close(task, c, req); - return; - } + body = nxt_buf_mem_alloc(c->mem_pool, size, 0); + if (nxt_slow_path(body == NULL)) { + nxt_controller_conn_close(task, c, req); + return; + } - nxt_memzero(&pretty, sizeof(nxt_conf_json_pretty_t)); + nxt_memzero(&pretty, sizeof(nxt_conf_json_pretty_t)); - body->mem.free = nxt_conf_json_print(body->mem.free, value, &pretty); + body->mem.free = nxt_conf_json_print(body->mem.free, value, &pretty); - body->mem.free = nxt_cpymem(body->mem.free, "\r\n", 2); + body->mem.free = nxt_cpymem(body->mem.free, "\r\n", 2); - size = nxt_length("HTTP/1.1 " "\r\n") + status_line.length - + nxt_length("Server: " NXT_SERVER "\r\n") - + nxt_length("Date: Wed, 31 Dec 1986 16:40:00 GMT\r\n") - + nxt_length("Content-Type: application/json\r\n") - + nxt_length("Content-Length: " "\r\n") + NXT_SIZE_T_LEN - + nxt_length("Connection: close\r\n") - + nxt_length("\r\n"); + size = nxt_length("HTTP/1.1 " + "\r\n") + + status_line.length + nxt_length("Server: " NXT_SERVER "\r\n") + + nxt_length("Date: Wed, 31 Dec 1986 16:40:00 GMT\r\n") + + nxt_length("Content-Type: application/json\r\n") + + nxt_length("Content-Length: " + "\r\n") + + NXT_SIZE_T_LEN + nxt_length("Connection: close\r\n") + + nxt_length("\r\n"); - b = nxt_buf_mem_alloc(c->mem_pool, size, 0); - if (nxt_slow_path(b == NULL)) { - nxt_controller_conn_close(task, c, req); - return; - } + b = nxt_buf_mem_alloc(c->mem_pool, size, 0); + if (nxt_slow_path(b == NULL)) { + nxt_controller_conn_close(task, c, req); + return; + } - b->next = body; + b->next = body; - nxt_str_set(&str, "HTTP/1.1 "); + nxt_str_set(&str, "HTTP/1.1 "); - b->mem.free = nxt_cpymem(b->mem.free, str.start, str.length); - b->mem.free = nxt_cpymem(b->mem.free, status_line.start, - status_line.length); + b->mem.free = nxt_cpymem(b->mem.free, str.start, str.length); + b->mem.free = nxt_cpymem(b->mem.free, status_line.start, status_line.length); - nxt_str_set(&str, "\r\n" - "Server: " NXT_SERVER "\r\n" - "Date: "); + nxt_str_set(&str, "\r\n" + "Server: " NXT_SERVER "\r\n" + "Date: "); - b->mem.free = nxt_cpymem(b->mem.free, str.start, str.length); + b->mem.free = nxt_cpymem(b->mem.free, str.start, str.length); - b->mem.free = nxt_thread_time_string(task->thread, &date_cache, - b->mem.free); + b->mem.free = nxt_thread_time_string(task->thread, &date_cache, b->mem.free); - nxt_str_set(&str, "\r\n" - "Content-Type: application/json\r\n" - "Content-Length: "); + nxt_str_set(&str, "\r\n" + "Content-Type: application/json\r\n" + "Content-Length: "); - b->mem.free = nxt_cpymem(b->mem.free, str.start, str.length); + b->mem.free = nxt_cpymem(b->mem.free, str.start, str.length); - b->mem.free = nxt_sprintf(b->mem.free, b->mem.end, "%uz", - nxt_buf_mem_used_size(&body->mem)); + b->mem.free = nxt_sprintf(b->mem.free, b->mem.end, "%uz", + nxt_buf_mem_used_size(&body->mem)); - nxt_str_set(&str, "\r\n" - "Connection: close\r\n" - "\r\n"); + nxt_str_set(&str, "\r\n" + "Connection: close\r\n" + "\r\n"); - b->mem.free = nxt_cpymem(b->mem.free, str.start, str.length); + b->mem.free = nxt_cpymem(b->mem.free, str.start, str.length); - c->write = b; - c->write_state = &nxt_controller_conn_write_state; + c->write = b; + c->write_state = &nxt_controller_conn_write_state; - nxt_conn_write(task->thread->engine, c); + nxt_conn_write(task->thread->engine, c); } +static u_char *nxt_controller_date(u_char *buf, nxt_realtime_t *now, + struct tm *tm, size_t size, + const char *format) { + static const char *const week[] = {"Sun", "Mon", "Tue", "Wed", + "Thu", "Fri", "Sat"}; -static u_char * -nxt_controller_date(u_char *buf, nxt_realtime_t *now, struct tm *tm, - size_t size, const char *format) -{ - static const char * const week[] = { "Sun", "Mon", "Tue", "Wed", "Thu", - "Fri", "Sat" }; - - static const char * const month[] = { "Jan", "Feb", "Mar", "Apr", "May", - "Jun", "Jul", "Aug", "Sep", "Oct", - "Nov", "Dec" }; + static const char *const month[] = {"Jan", "Feb", "Mar", "Apr", "May", "Jun", + "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"}; - return nxt_sprintf(buf, buf + size, format, - week[tm->tm_wday], tm->tm_mday, - month[tm->tm_mon], tm->tm_year + 1900, - tm->tm_hour, tm->tm_min, tm->tm_sec); + return nxt_sprintf(buf, buf + size, format, week[tm->tm_wday], tm->tm_mday, + month[tm->tm_mon], tm->tm_year + 1900, tm->tm_hour, + tm->tm_min, tm->tm_sec); } diff --git a/src/nxt_credential.c b/src/nxt_credential.c index 1c9fa9a7a..e75ebc6bb 100644 --- a/src/nxt_credential.c +++ b/src/nxt_credential.c @@ -5,149 +5,139 @@ #include - static nxt_int_t nxt_credential_groups_get(nxt_task_t *task, nxt_mp_t *mp, - nxt_credential_t *uc); - + nxt_credential_t *uc); -nxt_int_t -nxt_credential_get(nxt_task_t *task, nxt_mp_t *mp, nxt_credential_t *uc, - const char *group) -{ - struct group *grp; - struct passwd *pwd; - - nxt_errno = 0; +nxt_int_t nxt_credential_get(nxt_task_t *task, nxt_mp_t *mp, + nxt_credential_t *uc, const char *group) { + struct group *grp; + struct passwd *pwd; - pwd = getpwnam(uc->user); + nxt_errno = 0; - if (nxt_slow_path(pwd == NULL)) { + pwd = getpwnam(uc->user); - if (nxt_errno == 0) { - nxt_alert(task, "getpwnam(\"%s\") failed, user \"%s\" not found", - uc->user, uc->user); - } else { - nxt_alert(task, "getpwnam(\"%s\") failed %E", uc->user, nxt_errno); - } + if (nxt_slow_path(pwd == NULL)) { - return NXT_ERROR; + if (nxt_errno == 0) { + nxt_alert(task, "getpwnam(\"%s\") failed, user \"%s\" not found", + uc->user, uc->user); + } else { + nxt_alert(task, "getpwnam(\"%s\") failed %E", uc->user, nxt_errno); } - uc->uid = pwd->pw_uid; - uc->base_gid = pwd->pw_gid; + return NXT_ERROR; + } - if (group != NULL && group[0] != '\0') { - nxt_errno = 0; + uc->uid = pwd->pw_uid; + uc->base_gid = pwd->pw_gid; - grp = getgrnam(group); + if (group != NULL && group[0] != '\0') { + nxt_errno = 0; - if (nxt_slow_path(grp == NULL)) { + grp = getgrnam(group); - if (nxt_errno == 0) { - nxt_alert(task, - "getgrnam(\"%s\") failed, group \"%s\" not found", - group, group); - } else { - nxt_alert(task, "getgrnam(\"%s\") failed %E", group, nxt_errno); - } + if (nxt_slow_path(grp == NULL)) { - return NXT_ERROR; - } + if (nxt_errno == 0) { + nxt_alert(task, "getgrnam(\"%s\") failed, group \"%s\" not found", + group, group); + } else { + nxt_alert(task, "getgrnam(\"%s\") failed %E", group, nxt_errno); + } - uc->base_gid = grp->gr_gid; + return NXT_ERROR; } - nxt_debug(task, "about to get \"%s\" groups (uid:%d, base gid:%d)", - uc->user, uc->uid, uc->base_gid); + uc->base_gid = grp->gr_gid; + } - if (nxt_credential_groups_get(task, mp, uc) != NXT_OK) { - return NXT_ERROR; - } + nxt_debug(task, "about to get \"%s\" groups (uid:%d, base gid:%d)", uc->user, + uc->uid, uc->base_gid); -#if (NXT_DEBUG) - { - u_char *p, *end; - nxt_uint_t i; - u_char msg[NXT_MAX_ERROR_STR]; + if (nxt_credential_groups_get(task, mp, uc) != NXT_OK) { + return NXT_ERROR; + } - p = msg; - end = msg + NXT_MAX_ERROR_STR; +#if (NXT_DEBUG) + { + u_char *p, *end; + nxt_uint_t i; + u_char msg[NXT_MAX_ERROR_STR]; - for (i = 0; i < uc->ngroups; i++) { - p = nxt_sprintf(p, end, "%d,", uc->gids[i]); - } + p = msg; + end = msg + NXT_MAX_ERROR_STR; - if (uc->ngroups > 0) { - p--; - } + for (i = 0; i < uc->ngroups; i++) { + p = nxt_sprintf(p, end, "%d,", uc->gids[i]); + } - nxt_debug(task, "user \"%s\" has gids:%*s", uc->user, p - msg, msg); + if (uc->ngroups > 0) { + p--; } + + nxt_debug(task, "user \"%s\" has gids:%*s", uc->user, p - msg, msg); + } #endif - return NXT_OK; + return NXT_OK; } - #if (NXT_HAVE_GETGROUPLIST && !NXT_MACOSX) #define NXT_NGROUPS nxt_min(256, NGROUPS_MAX) +static nxt_int_t nxt_credential_groups_get(nxt_task_t *task, nxt_mp_t *mp, + nxt_credential_t *uc) { + int ngroups; + gid_t groups[NXT_NGROUPS]; -static nxt_int_t -nxt_credential_groups_get(nxt_task_t *task, nxt_mp_t *mp, - nxt_credential_t *uc) -{ - int ngroups; - gid_t groups[NXT_NGROUPS]; - - ngroups = NXT_NGROUPS; + ngroups = NXT_NGROUPS; - if (getgrouplist(uc->user, uc->base_gid, groups, &ngroups) < 0) { - if (nxt_slow_path(ngroups <= NXT_NGROUPS)) { - nxt_alert(task, "getgrouplist(\"%s\", %d, ...) failed %E", uc->user, - uc->base_gid, nxt_errno); + if (getgrouplist(uc->user, uc->base_gid, groups, &ngroups) < 0) { + if (nxt_slow_path(ngroups <= NXT_NGROUPS)) { + nxt_alert(task, "getgrouplist(\"%s\", %d, ...) failed %E", uc->user, + uc->base_gid, nxt_errno); - return NXT_ERROR; - } + return NXT_ERROR; } + } - if (ngroups > NXT_NGROUPS) { - if (ngroups > NGROUPS_MAX) { - ngroups = NGROUPS_MAX; - } - - uc->ngroups = ngroups; - - uc->gids = nxt_mp_alloc(mp, ngroups * sizeof(gid_t)); - if (nxt_slow_path(uc->gids == NULL)) { - return NXT_ERROR; - } - - if (nxt_slow_path(getgrouplist(uc->user, uc->base_gid, uc->gids, - &ngroups) < 0)) { - - nxt_alert(task, "getgrouplist(\"%s\", %d) failed %E", uc->user, - uc->base_gid, nxt_errno); - - return NXT_ERROR; - } - - return NXT_OK; + if (ngroups > NXT_NGROUPS) { + if (ngroups > NGROUPS_MAX) { + ngroups = NGROUPS_MAX; } uc->ngroups = ngroups; uc->gids = nxt_mp_alloc(mp, ngroups * sizeof(gid_t)); if (nxt_slow_path(uc->gids == NULL)) { - return NXT_ERROR; + return NXT_ERROR; } - nxt_memcpy(uc->gids, groups, ngroups * sizeof(gid_t)); + if (nxt_slow_path(getgrouplist(uc->user, uc->base_gid, uc->gids, &ngroups) < + 0)) { + + nxt_alert(task, "getgrouplist(\"%s\", %d) failed %E", uc->user, + uc->base_gid, nxt_errno); + + return NXT_ERROR; + } return NXT_OK; -} + } + + uc->ngroups = ngroups; + uc->gids = nxt_mp_alloc(mp, ngroups * sizeof(gid_t)); + if (nxt_slow_path(uc->gids == NULL)) { + return NXT_ERROR; + } + + nxt_memcpy(uc->gids, groups, ngroups * sizeof(gid_t)); + + return NXT_OK; +} #else @@ -179,175 +169,171 @@ nxt_credential_groups_get(nxt_task_t *task, nxt_mp_t *mp, * For such cases initgroups() is used in worker process as fallback. */ -static nxt_int_t -nxt_credential_groups_get(nxt_task_t *task, nxt_mp_t *mp, nxt_credential_t *uc) -{ - int nsaved, ngroups; - nxt_int_t ret; - nxt_gid_t *saved; +static nxt_int_t nxt_credential_groups_get(nxt_task_t *task, nxt_mp_t *mp, + nxt_credential_t *uc) { + int nsaved, ngroups; + nxt_int_t ret; + nxt_gid_t *saved; - nsaved = getgroups(0, NULL); + nsaved = getgroups(0, NULL); - if (nxt_slow_path(nsaved == -1)) { - nxt_alert(task, "getgroups(0, NULL) failed %E", nxt_errno); - return NXT_ERROR; - } + if (nxt_slow_path(nsaved == -1)) { + nxt_alert(task, "getgroups(0, NULL) failed %E", nxt_errno); + return NXT_ERROR; + } - nxt_debug(task, "getgroups(0, NULL): %d", nsaved); + nxt_debug(task, "getgroups(0, NULL): %d", nsaved); - if (nsaved > NGROUPS_MAX) { - /* MacOSX case. */ + if (nsaved > NGROUPS_MAX) { + /* MacOSX case. */ - uc->gids = NULL; - uc->ngroups = 0; + uc->gids = NULL; + uc->ngroups = 0; - return NXT_OK; - } + return NXT_OK; + } - saved = nxt_mp_alloc(mp, nsaved * sizeof(nxt_gid_t)); + saved = nxt_mp_alloc(mp, nsaved * sizeof(nxt_gid_t)); - if (nxt_slow_path(saved == NULL)) { - return NXT_ERROR; - } + if (nxt_slow_path(saved == NULL)) { + return NXT_ERROR; + } - ret = NXT_ERROR; + ret = NXT_ERROR; - nsaved = getgroups(nsaved, saved); + nsaved = getgroups(nsaved, saved); - if (nxt_slow_path(nsaved == -1)) { - nxt_alert(task, "getgroups(%d) failed %E", nsaved, nxt_errno); - goto free; - } + if (nxt_slow_path(nsaved == -1)) { + nxt_alert(task, "getgroups(%d) failed %E", nsaved, nxt_errno); + goto free; + } - nxt_debug(task, "getgroups(): %d", nsaved); + nxt_debug(task, "getgroups(): %d", nsaved); - if (initgroups(uc->user, uc->base_gid) != 0) { - if (nxt_errno == NXT_EPERM) { - nxt_log(task, NXT_LOG_NOTICE, - "initgroups(%s, %d) failed %E, ignored", - uc->user, uc->base_gid, nxt_errno); + if (initgroups(uc->user, uc->base_gid) != 0) { + if (nxt_errno == NXT_EPERM) { + nxt_log(task, NXT_LOG_NOTICE, "initgroups(%s, %d) failed %E, ignored", + uc->user, uc->base_gid, nxt_errno); - ret = NXT_OK; + ret = NXT_OK; - goto free; + goto free; - } else { - nxt_alert(task, "initgroups(%s, %d) failed %E", - uc->user, uc->base_gid, nxt_errno); - goto restore; - } + } else { + nxt_alert(task, "initgroups(%s, %d) failed %E", uc->user, uc->base_gid, + nxt_errno); + goto restore; } + } - ngroups = getgroups(0, NULL); + ngroups = getgroups(0, NULL); - if (nxt_slow_path(ngroups == -1)) { - nxt_alert(task, "getgroups(0, NULL) failed %E", nxt_errno); - goto restore; - } + if (nxt_slow_path(ngroups == -1)) { + nxt_alert(task, "getgroups(0, NULL) failed %E", nxt_errno); + goto restore; + } - nxt_debug(task, "getgroups(0, NULL): %d", ngroups); + nxt_debug(task, "getgroups(0, NULL): %d", ngroups); - uc->gids = nxt_mp_alloc(mp, ngroups * sizeof(nxt_gid_t)); + uc->gids = nxt_mp_alloc(mp, ngroups * sizeof(nxt_gid_t)); - if (nxt_slow_path(uc->gids == NULL)) { - goto restore; - } + if (nxt_slow_path(uc->gids == NULL)) { + goto restore; + } - ngroups = getgroups(ngroups, uc->gids); + ngroups = getgroups(ngroups, uc->gids); - if (nxt_slow_path(ngroups == -1)) { - nxt_alert(task, "getgroups(%d) failed %E", ngroups, nxt_errno); - goto restore; - } + if (nxt_slow_path(ngroups == -1)) { + nxt_alert(task, "getgroups(%d) failed %E", ngroups, nxt_errno); + goto restore; + } - uc->ngroups = ngroups; + uc->ngroups = ngroups; - ret = NXT_OK; + ret = NXT_OK; restore: - if (nxt_slow_path(setgroups(nsaved, saved) != 0)) { - nxt_alert(task, "setgroups(%d) failed %E", nsaved, nxt_errno); - ret = NXT_ERROR; - } + if (nxt_slow_path(setgroups(nsaved, saved) != 0)) { + nxt_alert(task, "setgroups(%d) failed %E", nsaved, nxt_errno); + ret = NXT_ERROR; + } free: - nxt_mp_free(mp, saved); + nxt_mp_free(mp, saved); - return ret; + return ret; } - #endif +nxt_int_t nxt_credential_setuid(nxt_task_t *task, nxt_credential_t *uc) { + nxt_debug(task, "user cred set: \"%s\" uid:%d", uc->user, uc->uid); -nxt_int_t -nxt_credential_setuid(nxt_task_t *task, nxt_credential_t *uc) -{ - nxt_debug(task, "user cred set: \"%s\" uid:%d", uc->user, uc->uid); - - if (setuid(uc->uid) != 0) { + if (setuid(uc->uid) != 0) { #if (NXT_HAVE_LINUX_NS) - if (nxt_errno == EINVAL) { - nxt_log(task, NXT_LOG_ERR, "The uid %d (user \"%s\") isn't " - "valid in the application namespace.", uc->uid, uc->user); - return NXT_ERROR; - } + if (nxt_errno == EINVAL) { + nxt_log(task, NXT_LOG_ERR, + "The uid %d (user \"%s\") isn't " + "valid in the application namespace.", + uc->uid, uc->user); + return NXT_ERROR; + } #endif - nxt_alert(task, "setuid(%d) failed %E", uc->uid, nxt_errno); - return NXT_ERROR; - } + nxt_alert(task, "setuid(%d) failed %E", uc->uid, nxt_errno); + return NXT_ERROR; + } - return NXT_OK; + return NXT_OK; } +nxt_int_t nxt_credential_setgids(nxt_task_t *task, nxt_credential_t *uc) { + nxt_runtime_t *rt; -nxt_int_t -nxt_credential_setgids(nxt_task_t *task, nxt_credential_t *uc) -{ - nxt_runtime_t *rt; - - nxt_debug(task, "user cred set gids: base gid:%d, ngroups: %d", - uc->base_gid, uc->ngroups); + nxt_debug(task, "user cred set gids: base gid:%d, ngroups: %d", uc->base_gid, + uc->ngroups); - rt = task->thread->runtime; + rt = task->thread->runtime; - if (setgid(uc->base_gid) != 0) { + if (setgid(uc->base_gid) != 0) { #if (NXT_HAVE_LINUX_NS) - if (nxt_errno == EINVAL) { - nxt_log(task, NXT_LOG_ERR, "The gid %d isn't valid in the " - "application namespace.", uc->base_gid); - return NXT_ERROR; - } + if (nxt_errno == EINVAL) { + nxt_log(task, NXT_LOG_ERR, + "The gid %d isn't valid in the " + "application namespace.", + uc->base_gid); + return NXT_ERROR; + } #endif - nxt_alert(task, "setgid(%d) failed %E", uc->base_gid, nxt_errno); - return NXT_ERROR; - } + nxt_alert(task, "setgid(%d) failed %E", uc->base_gid, nxt_errno); + return NXT_ERROR; + } - if (!rt->capabilities.setid) { - return NXT_OK; - } + if (!rt->capabilities.setid) { + return NXT_OK; + } - if (nxt_slow_path(uc->ngroups > 0 - && setgroups(uc->ngroups, uc->gids) != 0)) { + if (nxt_slow_path(uc->ngroups > 0 && setgroups(uc->ngroups, uc->gids) != 0)) { #if (NXT_HAVE_LINUX_NS) - if (nxt_errno == EINVAL) { - nxt_log(task, NXT_LOG_ERR, "The user \"%s\" (uid: %d) has " - "supplementary group ids not valid in the application " - "namespace.", uc->user, uc->uid); - return NXT_ERROR; - } + if (nxt_errno == EINVAL) { + nxt_log(task, NXT_LOG_ERR, + "The user \"%s\" (uid: %d) has " + "supplementary group ids not valid in the application " + "namespace.", + uc->user, uc->uid); + return NXT_ERROR; + } #endif - nxt_alert(task, "setgroups(%i) failed %E", uc->ngroups, nxt_errno); - return NXT_ERROR; - } + nxt_alert(task, "setgroups(%i) failed %E", uc->ngroups, nxt_errno); + return NXT_ERROR; + } - return NXT_OK; + return NXT_OK; } diff --git a/src/nxt_credential.h b/src/nxt_credential.h index 243eba83e..e75f52163 100644 --- a/src/nxt_credential.h +++ b/src/nxt_credential.h @@ -6,25 +6,23 @@ #ifndef _NXT_CREDENTIAL_H_INCLUDED_ #define _NXT_CREDENTIAL_H_INCLUDED_ - -typedef uid_t nxt_uid_t; -typedef gid_t nxt_gid_t; +typedef uid_t nxt_uid_t; +typedef gid_t nxt_gid_t; typedef struct { - const char *user; - nxt_uid_t uid; - nxt_gid_t base_gid; - nxt_uint_t ngroups; - nxt_gid_t *gids; + const char *user; + nxt_uid_t uid; + nxt_gid_t base_gid; + nxt_uint_t ngroups; + nxt_gid_t *gids; } nxt_credential_t; - NXT_EXPORT nxt_int_t nxt_credential_get(nxt_task_t *task, nxt_mp_t *mp, - nxt_credential_t *uc, const char *group); + nxt_credential_t *uc, + const char *group); NXT_EXPORT nxt_int_t nxt_credential_setuid(nxt_task_t *task, - nxt_credential_t *uc); + nxt_credential_t *uc); NXT_EXPORT nxt_int_t nxt_credential_setgids(nxt_task_t *task, - nxt_credential_t *uc); - + nxt_credential_t *uc); #endif /* _NXT_CREDENTIAL_H_INCLUDED_ */ diff --git a/src/nxt_cyassl.c b/src/nxt_cyassl.c index 91039e0c5..46a7935ac 100644 --- a/src/nxt_cyassl.c +++ b/src/nxt_cyassl.c @@ -8,49 +8,47 @@ #include #include - typedef struct { - CYASSL *session; + CYASSL *session; - int ssl_error; - uint8_t times; /* 2 bits */ + int ssl_error; + uint8_t times; /* 2 bits */ - nxt_buf_mem_t buffer; + nxt_buf_mem_t buffer; } nxt_cyassl_conn_t; - static nxt_int_t nxt_cyassl_server_init(nxt_ssltls_conf_t *conf); static void nxt_cyassl_conn_init(nxt_thread_t *thr, nxt_ssltls_conf_t *conf, - nxt_event_conn_t *c); + nxt_event_conn_t *c); static void nxt_cyassl_session_cleanup(void *data); static int nxt_cyassl_io_recv(CYASSL *ssl, char *buf, int size, void *data); static int nxt_cyassl_io_send(CYASSL *ssl, char *buf, int size, void *data); static void nxt_cyassl_conn_handshake(nxt_thread_t *thr, void *obj, void *data); static void nxt_cyassl_conn_io_read(nxt_thread_t *thr, void *obj, void *data); static void nxt_cyassl_conn_io_shutdown(nxt_thread_t *thr, void *obj, - void *data); + void *data); static ssize_t nxt_cyassl_conn_io_write_chunk(nxt_thread_t *thr, - nxt_event_conn_t *c, nxt_buf_t *b, size_t limit); + nxt_event_conn_t *c, nxt_buf_t *b, + size_t limit); static ssize_t nxt_cyassl_conn_io_send(nxt_event_conn_t *c, void *buf, - size_t size); + size_t size); static nxt_int_t nxt_cyassl_conn_test_error(nxt_thread_t *thr, - nxt_event_conn_t *c, int err, nxt_work_handler_t handler); + nxt_event_conn_t *c, int err, + nxt_work_handler_t handler); static void nxt_cdecl nxt_cyassl_conn_error(nxt_event_conn_t *c, nxt_err_t err, - const char *fmt, ...); + const char *fmt, ...); static nxt_uint_t nxt_cyassl_log_error_level(nxt_event_conn_t *c, nxt_err_t err, - int ssl_error); + int ssl_error); static void nxt_cdecl nxt_cyassl_log_error(nxt_uint_t level, nxt_log_t *log, - int ret, const char *fmt, ...); + int ret, const char *fmt, ...); static u_char *nxt_cyassl_copy_error(int err, u_char *p, u_char *end); - -const nxt_ssltls_lib_t nxt_cyassl_lib = { +const nxt_ssltls_lib_t nxt_cyassl_lib = { nxt_cyassl_server_init, NULL, }; - -static nxt_event_conn_io_t nxt_cyassl_event_conn_io = { +static nxt_event_conn_io_t nxt_cyassl_event_conn_io = { NULL, NULL, @@ -67,555 +65,507 @@ static nxt_event_conn_io_t nxt_cyassl_event_conn_io = { nxt_cyassl_conn_io_shutdown, }; +static nxt_int_t nxt_cyassl_start(void) { + int err; + nxt_thread_t *thr; + static nxt_bool_t started; -static nxt_int_t -nxt_cyassl_start(void) -{ - int err; - nxt_thread_t *thr; - static nxt_bool_t started; - - if (nxt_fast_path(started)) { - return NXT_OK; - } + if (nxt_fast_path(started)) { + return NXT_OK; + } - started = 1; + started = 1; - thr = nxt_thread(); + thr = nxt_thread(); - /* TODO: CyaSSL_Cleanup() */ + /* TODO: CyaSSL_Cleanup() */ - err = CyaSSL_Init(); - if (err != SSL_SUCCESS) { - nxt_cyassl_log_error(NXT_LOG_ALERT, thr->log, err, - "CyaSSL_Init() failed"); - return NXT_ERROR; - } + err = CyaSSL_Init(); + if (err != SSL_SUCCESS) { + nxt_cyassl_log_error(NXT_LOG_ALERT, thr->log, err, "CyaSSL_Init() failed"); + return NXT_ERROR; + } - nxt_thread_log_error(NXT_LOG_INFO, "CyaSSL version: %s", - LIBCYASSL_VERSION_STRING); + nxt_thread_log_error(NXT_LOG_INFO, "CyaSSL version: %s", + LIBCYASSL_VERSION_STRING); - /* CyaSSL_SetLoggingCb */ - /* CyaSSL_SetAllocators */ + /* CyaSSL_SetLoggingCb */ + /* CyaSSL_SetAllocators */ - return NXT_OK; + return NXT_OK; } +static nxt_int_t nxt_cyassl_server_init(nxt_ssltls_conf_t *conf) { + int err; + char *certificate, *key; + CYASSL_CTX *ctx; + nxt_thread_t *thr; -static nxt_int_t -nxt_cyassl_server_init(nxt_ssltls_conf_t *conf) -{ - int err; - char *certificate, *key; - CYASSL_CTX *ctx; - nxt_thread_t *thr; + thr = nxt_thread(); - thr = nxt_thread(); + if (nxt_slow_path(nxt_cyassl_start() != NXT_OK)) { + return NXT_ERROR; + } - if (nxt_slow_path(nxt_cyassl_start() != NXT_OK)) { - return NXT_ERROR; - } + ctx = CyaSSL_CTX_new(CyaSSLv23_server_method()); + if (ctx == NULL) { + nxt_cyassl_log_error(NXT_LOG_ALERT, thr->log, 0, "CyaSSL_CTX_new() failed"); + return NXT_ERROR; + } - ctx = CyaSSL_CTX_new(CyaSSLv23_server_method()); - if (ctx == NULL) { - nxt_cyassl_log_error(NXT_LOG_ALERT, thr->log, 0, - "CyaSSL_CTX_new() failed"); - return NXT_ERROR; - } + conf->ctx = ctx; + conf->conn_init = nxt_cyassl_conn_init; - conf->ctx = ctx; - conf->conn_init = nxt_cyassl_conn_init; + certificate = conf->certificate; - certificate = conf->certificate; + err = CyaSSL_CTX_use_certificate_file(ctx, certificate, SSL_FILETYPE_PEM); + if (err != SSL_SUCCESS) { + nxt_cyassl_log_error(NXT_LOG_ALERT, thr->log, err, + "CyaSSL_CTX_use_certificate_file(\"%s\") failed", + certificate); + goto fail; + } - err = CyaSSL_CTX_use_certificate_file(ctx, certificate, SSL_FILETYPE_PEM); - if (err != SSL_SUCCESS) { - nxt_cyassl_log_error(NXT_LOG_ALERT, thr->log, err, - "CyaSSL_CTX_use_certificate_file(\"%s\") failed", - certificate); - goto fail; - } + key = conf->certificate_key; - key = conf->certificate_key; + err = CyaSSL_CTX_use_PrivateKey_file(ctx, key, SSL_FILETYPE_PEM); + if (err != SSL_SUCCESS) { + nxt_cyassl_log_error(NXT_LOG_ALERT, thr->log, err, + "CyaSSL_CTX_use_PrivateKey_file(\"%s\") failed", key); + goto fail; + } - err = CyaSSL_CTX_use_PrivateKey_file(ctx, key, SSL_FILETYPE_PEM); + if (conf->ciphers != NULL) { + err = CyaSSL_CTX_set_cipher_list(ctx, conf->ciphers); if (err != SSL_SUCCESS) { - nxt_cyassl_log_error(NXT_LOG_ALERT, thr->log, err, - "CyaSSL_CTX_use_PrivateKey_file(\"%s\") failed", - key); - goto fail; + nxt_cyassl_log_error(NXT_LOG_ALERT, thr->log, err, + "CyaSSL_CTX_set_cipher_list(\"%s\") failed", + conf->ciphers); + goto fail; } + } - if (conf->ciphers != NULL) { - err = CyaSSL_CTX_set_cipher_list(ctx, conf->ciphers); - if (err != SSL_SUCCESS) { - nxt_cyassl_log_error(NXT_LOG_ALERT, thr->log, err, - "CyaSSL_CTX_set_cipher_list(\"%s\") failed", - conf->ciphers); - goto fail; - } - } - - /* TODO: ca_certificate */ + /* TODO: ca_certificate */ - CyaSSL_SetIORecv(ctx, nxt_cyassl_io_recv); - CyaSSL_SetIOSend(ctx, nxt_cyassl_io_send); + CyaSSL_SetIORecv(ctx, nxt_cyassl_io_recv); + CyaSSL_SetIOSend(ctx, nxt_cyassl_io_send); - return NXT_OK; + return NXT_OK; fail: - CyaSSL_CTX_free(ctx); + CyaSSL_CTX_free(ctx); - return NXT_ERROR; + return NXT_ERROR; } +static void nxt_cyassl_conn_init(nxt_thread_t *thr, nxt_ssltls_conf_t *conf, + nxt_event_conn_t *c) { + CYASSL *s; + CYASSL_CTX *ctx; + nxt_cyassl_conn_t *ssltls; + nxt_mem_pool_cleanup_t *mpcl; -static void -nxt_cyassl_conn_init(nxt_thread_t *thr, nxt_ssltls_conf_t *conf, - nxt_event_conn_t *c) -{ - CYASSL *s; - CYASSL_CTX *ctx; - nxt_cyassl_conn_t *ssltls; - nxt_mem_pool_cleanup_t *mpcl; - - nxt_log_debug(c->socket.log, "cyassl conn init"); + nxt_log_debug(c->socket.log, "cyassl conn init"); - ssltls = nxt_mp_zget(c->mem_pool, sizeof(nxt_cyassl_conn_t)); - if (ssltls == NULL) { - goto fail; - } + ssltls = nxt_mp_zget(c->mem_pool, sizeof(nxt_cyassl_conn_t)); + if (ssltls == NULL) { + goto fail; + } - c->u.ssltls = ssltls; - nxt_buf_mem_set_size(&ssltls->buffer, conf->buffer_size); + c->u.ssltls = ssltls; + nxt_buf_mem_set_size(&ssltls->buffer, conf->buffer_size); - mpcl = nxt_mem_pool_cleanup(c->mem_pool, 0); - if (mpcl == NULL) { - goto fail; - } + mpcl = nxt_mem_pool_cleanup(c->mem_pool, 0); + if (mpcl == NULL) { + goto fail; + } - ctx = conf->ctx; + ctx = conf->ctx; - s = CyaSSL_new(ctx); - if (s == NULL) { - nxt_cyassl_log_error(NXT_LOG_ALERT, c->socket.log, 0, - "CyaSSL_new() failed"); - goto fail; - } + s = CyaSSL_new(ctx); + if (s == NULL) { + nxt_cyassl_log_error(NXT_LOG_ALERT, c->socket.log, 0, + "CyaSSL_new() failed"); + goto fail; + } - ssltls->session = s; - mpcl->handler = nxt_cyassl_session_cleanup; - mpcl->data = ssltls; + ssltls->session = s; + mpcl->handler = nxt_cyassl_session_cleanup; + mpcl->data = ssltls; - CyaSSL_SetIOReadCtx(s, c); - CyaSSL_SetIOWriteCtx(s, c); + CyaSSL_SetIOReadCtx(s, c); + CyaSSL_SetIOWriteCtx(s, c); - c->io = &nxt_cyassl_event_conn_io; - c->sendfile = NXT_CONN_SENDFILE_OFF; + c->io = &nxt_cyassl_event_conn_io; + c->sendfile = NXT_CONN_SENDFILE_OFF; - nxt_cyassl_conn_handshake(thr, c, c->socket.data); - return; + nxt_cyassl_conn_handshake(thr, c, c->socket.data); + return; fail: - nxt_event_conn_io_handle(thr, c->read_work_queue, - c->read_state->error_handler, c, c->socket.data); + nxt_event_conn_io_handle(thr, c->read_work_queue, + c->read_state->error_handler, c, c->socket.data); } +static void nxt_cyassl_session_cleanup(void *data) { + nxt_cyassl_conn_t *ssltls; -static void -nxt_cyassl_session_cleanup(void *data) -{ - nxt_cyassl_conn_t *ssltls; + ssltls = data; - ssltls = data; + nxt_thread_log_debug("cyassl session cleanup"); - nxt_thread_log_debug("cyassl session cleanup"); + nxt_free(ssltls->buffer.start); - nxt_free(ssltls->buffer.start); - - CyaSSL_free(ssltls->session); + CyaSSL_free(ssltls->session); } +static int nxt_cyassl_io_recv(CYASSL *ssl, char *buf, int size, void *data) { + ssize_t n; + nxt_thread_t *thr; + nxt_event_conn_t *c; -static int -nxt_cyassl_io_recv(CYASSL *ssl, char *buf, int size, void *data) -{ - ssize_t n; - nxt_thread_t *thr; - nxt_event_conn_t *c; - - c = data; - thr = nxt_thread(); + c = data; + thr = nxt_thread(); - n = thr->engine->event->io->recv(c, (u_char *) buf, size, 0); + n = thr->engine->event->io->recv(c, (u_char *)buf, size, 0); - if (n > 0) { - return n; - } + if (n > 0) { + return n; + } - if (n == 0) { - return CYASSL_CBIO_ERR_CONN_CLOSE; - } + if (n == 0) { + return CYASSL_CBIO_ERR_CONN_CLOSE; + } - if (n == NXT_AGAIN) { - return CYASSL_CBIO_ERR_WANT_READ; - } + if (n == NXT_AGAIN) { + return CYASSL_CBIO_ERR_WANT_READ; + } - return CYASSL_CBIO_ERR_GENERAL; + return CYASSL_CBIO_ERR_GENERAL; } +static int nxt_cyassl_io_send(CYASSL *ssl, char *buf, int size, void *data) { + ssize_t n; + nxt_thread_t *thr; + nxt_event_conn_t *c; -static int -nxt_cyassl_io_send(CYASSL *ssl, char *buf, int size, void *data) -{ - ssize_t n; - nxt_thread_t *thr; - nxt_event_conn_t *c; - - c = data; - thr = nxt_thread(); + c = data; + thr = nxt_thread(); - n = thr->engine->event->io->send(c, (u_char *) buf, size); + n = thr->engine->event->io->send(c, (u_char *)buf, size); - if (n > 0) { - return n; - } + if (n > 0) { + return n; + } - if (n == NXT_AGAIN) { - return CYASSL_CBIO_ERR_WANT_WRITE; - } + if (n == NXT_AGAIN) { + return CYASSL_CBIO_ERR_WANT_WRITE; + } - return CYASSL_CBIO_ERR_GENERAL; + return CYASSL_CBIO_ERR_GENERAL; } +static void nxt_cyassl_conn_handshake(nxt_thread_t *thr, void *obj, + void *data) { + int ret; + nxt_int_t n; + nxt_err_t err; + nxt_event_conn_t *c; + nxt_cyassl_conn_t *ssltls; -static void -nxt_cyassl_conn_handshake(nxt_thread_t *thr, void *obj, void *data) -{ - int ret; - nxt_int_t n; - nxt_err_t err; - nxt_event_conn_t *c; - nxt_cyassl_conn_t *ssltls; + c = obj; + ssltls = c->u.ssltls; - c = obj; - ssltls = c->u.ssltls; + nxt_log_debug(thr->log, "cyassl conn handshake: %d", ssltls->times); - nxt_log_debug(thr->log, "cyassl conn handshake: %d", ssltls->times); + /* "ssltls->times == 1" is suitable to run CyaSSL_negotiate() in job. */ - /* "ssltls->times == 1" is suitable to run CyaSSL_negotiate() in job. */ + ret = CyaSSL_negotiate(ssltls->session); - ret = CyaSSL_negotiate(ssltls->session); + err = (ret != 0) ? nxt_socket_errno : 0; - err = (ret != 0) ? nxt_socket_errno : 0; + nxt_thread_time_debug_update(thr); - nxt_thread_time_debug_update(thr); + nxt_log_debug(thr->log, "CyaSSL_negotiate(%d): %d", c->socket.fd, ret); - nxt_log_debug(thr->log, "CyaSSL_negotiate(%d): %d", c->socket.fd, ret); - - if (ret == 0) { - nxt_cyassl_conn_io_read(thr, c, data); - return; - } + if (ret == 0) { + nxt_cyassl_conn_io_read(thr, c, data); + return; + } - n = nxt_cyassl_conn_test_error(thr, c, ret, nxt_cyassl_conn_handshake); + n = nxt_cyassl_conn_test_error(thr, c, ret, nxt_cyassl_conn_handshake); - if (n == NXT_ERROR) { - nxt_cyassl_conn_error(c, err, "CyaSSL_negotiate(%d) failed", - c->socket.fd); + if (n == NXT_ERROR) { + nxt_cyassl_conn_error(c, err, "CyaSSL_negotiate(%d) failed", c->socket.fd); - nxt_event_conn_io_handle(thr, c->read_work_queue, - c->read_state->error_handler, c, data); + nxt_event_conn_io_handle(thr, c->read_work_queue, + c->read_state->error_handler, c, data); - } else if (ssltls->ssl_error == SSL_ERROR_WANT_READ && ssltls->times < 2) { - ssltls->times++; - } + } else if (ssltls->ssl_error == SSL_ERROR_WANT_READ && ssltls->times < 2) { + ssltls->times++; + } } +static void nxt_cyassl_conn_io_read(nxt_thread_t *thr, void *obj, void *data) { + int ret; + nxt_buf_t *b; + nxt_err_t err; + nxt_int_t n; + nxt_event_conn_t *c; + nxt_cyassl_conn_t *ssltls; + nxt_work_handler_t handler; -static void -nxt_cyassl_conn_io_read(nxt_thread_t *thr, void *obj, void *data) -{ - int ret; - nxt_buf_t *b; - nxt_err_t err; - nxt_int_t n; - nxt_event_conn_t *c; - nxt_cyassl_conn_t *ssltls; - nxt_work_handler_t handler; - - c = obj; + c = obj; - nxt_log_debug(thr->log, "cyassl conn read"); + nxt_log_debug(thr->log, "cyassl conn read"); - handler = c->read_state->ready_handler; - b = c->read; + handler = c->read_state->ready_handler; + b = c->read; - /* b == NULL is used to test descriptor readiness. */ + /* b == NULL is used to test descriptor readiness. */ - if (b != NULL) { - ssltls = c->u.ssltls; + if (b != NULL) { + ssltls = c->u.ssltls; - ret = CyaSSL_read(ssltls->session, b->mem.free, - b->mem.end - b->mem.free); + ret = CyaSSL_read(ssltls->session, b->mem.free, b->mem.end - b->mem.free); - err = (ret <= 0) ? nxt_socket_errno : 0; + err = (ret <= 0) ? nxt_socket_errno : 0; - nxt_log_debug(thr->log, "CyaSSL_read(%d, %p, %uz): %d", - c->socket.fd, b->mem.free, b->mem.end - b->mem.free, ret); + nxt_log_debug(thr->log, "CyaSSL_read(%d, %p, %uz): %d", c->socket.fd, + b->mem.free, b->mem.end - b->mem.free, ret); - if (ret > 0) { - /* c->socket.read_ready is kept. */ - b->mem.free += ret; - handler = c->read_state->ready_handler; + if (ret > 0) { + /* c->socket.read_ready is kept. */ + b->mem.free += ret; + handler = c->read_state->ready_handler; - } else { - n = nxt_cyassl_conn_test_error(thr, c, ret, - nxt_cyassl_conn_io_read); + } else { + n = nxt_cyassl_conn_test_error(thr, c, ret, nxt_cyassl_conn_io_read); - if (nxt_fast_path(n != NXT_ERROR)) { - return; - } + if (nxt_fast_path(n != NXT_ERROR)) { + return; + } - nxt_cyassl_conn_error(c, err, "CyaSSL_read(%d, %p, %uz) failed", - c->socket.fd, b->mem.free, - b->mem.end - b->mem.free); + nxt_cyassl_conn_error(c, err, "CyaSSL_read(%d, %p, %uz) failed", + c->socket.fd, b->mem.free, + b->mem.end - b->mem.free); - handler = c->read_state->error_handler; - } + handler = c->read_state->error_handler; } + } - nxt_event_conn_io_handle(thr, c->read_work_queue, handler, c, data); + nxt_event_conn_io_handle(thr, c->read_work_queue, handler, c, data); } +static ssize_t nxt_cyassl_conn_io_write_chunk(nxt_thread_t *thr, + nxt_event_conn_t *c, nxt_buf_t *b, + size_t limit) { + nxt_cyassl_conn_t *ssltls; -static ssize_t -nxt_cyassl_conn_io_write_chunk(nxt_thread_t *thr, nxt_event_conn_t *c, - nxt_buf_t *b, size_t limit) -{ - nxt_cyassl_conn_t *ssltls; - - nxt_log_debug(thr->log, "cyassl conn write chunk"); + nxt_log_debug(thr->log, "cyassl conn write chunk"); - ssltls = c->u.ssltls; + ssltls = c->u.ssltls; - return nxt_sendbuf_copy_coalesce(c, &ssltls->buffer, b, limit); + return nxt_sendbuf_copy_coalesce(c, &ssltls->buffer, b, limit); } +static ssize_t nxt_cyassl_conn_io_send(nxt_event_conn_t *c, void *buf, + size_t size) { + int ret; + nxt_err_t err; + nxt_int_t n; + nxt_cyassl_conn_t *ssltls; -static ssize_t -nxt_cyassl_conn_io_send(nxt_event_conn_t *c, void *buf, size_t size) -{ - int ret; - nxt_err_t err; - nxt_int_t n; - nxt_cyassl_conn_t *ssltls; - - nxt_log_debug(c->socket.log, "cyassl send"); + nxt_log_debug(c->socket.log, "cyassl send"); - ssltls = c->u.ssltls; + ssltls = c->u.ssltls; - ret = CyaSSL_write(ssltls->session, buf, size); + ret = CyaSSL_write(ssltls->session, buf, size); - if (ret <= 0) { - err = nxt_socket_errno; - c->socket.error = err; + if (ret <= 0) { + err = nxt_socket_errno; + c->socket.error = err; - } else { - err = 0; - } + } else { + err = 0; + } - nxt_log_debug(c->socket.log, "CyaSSL_write(%d, %p, %uz): %d", - c->socket.fd, buf, size, ret); + nxt_log_debug(c->socket.log, "CyaSSL_write(%d, %p, %uz): %d", c->socket.fd, + buf, size, ret); - if (ret > 0) { - return ret; - } + if (ret > 0) { + return ret; + } - n = nxt_cyassl_conn_test_error(nxt_thread(), c, ret, - nxt_event_conn_io_write); + n = nxt_cyassl_conn_test_error(nxt_thread(), c, ret, nxt_event_conn_io_write); - if (nxt_slow_path(n == NXT_ERROR)) { - nxt_cyassl_conn_error(c, err, "CyaSSL_write(%d, %p, %uz) failed", - c->socket.fd, buf, size); - } + if (nxt_slow_path(n == NXT_ERROR)) { + nxt_cyassl_conn_error(c, err, "CyaSSL_write(%d, %p, %uz) failed", + c->socket.fd, buf, size); + } - return n; + return n; } +static void nxt_cyassl_conn_io_shutdown(nxt_thread_t *thr, void *obj, + void *data) { + int ret; + nxt_event_conn_t *c; + nxt_cyassl_conn_t *ssltls; -static void -nxt_cyassl_conn_io_shutdown(nxt_thread_t *thr, void *obj, void *data) -{ - int ret; - nxt_event_conn_t *c; - nxt_cyassl_conn_t *ssltls; + c = obj; - c = obj; + nxt_log_debug(thr->log, "cyassl conn shutdown"); - nxt_log_debug(thr->log, "cyassl conn shutdown"); + ssltls = c->u.ssltls; - ssltls = c->u.ssltls; + ret = CyaSSL_shutdown(ssltls->session); - ret = CyaSSL_shutdown(ssltls->session); + nxt_log_debug(thr->log, "CyaSSL_shutdown(%d): %d", c->socket.fd, ret); - nxt_log_debug(thr->log, "CyaSSL_shutdown(%d): %d", c->socket.fd, ret); - - if (nxt_slow_path(ret != SSL_SUCCESS)) { - nxt_cyassl_conn_error(c, 0, "CyaSSL_shutdown(%d) failed", c->socket.fd); - } + if (nxt_slow_path(ret != SSL_SUCCESS)) { + nxt_cyassl_conn_error(c, 0, "CyaSSL_shutdown(%d) failed", c->socket.fd); + } - nxt_event_conn_io_handle(thr, c->write_work_queue, - c->write_state->close_handler, c, data); + nxt_event_conn_io_handle(thr, c->write_work_queue, + c->write_state->close_handler, c, data); } +static nxt_int_t nxt_cyassl_conn_test_error(nxt_thread_t *thr, + nxt_event_conn_t *c, int ret, + nxt_work_handler_t handler) { + nxt_work_queue_t *wq; + nxt_cyassl_conn_t *ssltls; -static nxt_int_t -nxt_cyassl_conn_test_error(nxt_thread_t *thr, nxt_event_conn_t *c, int ret, - nxt_work_handler_t handler) -{ - nxt_work_queue_t *wq; - nxt_cyassl_conn_t *ssltls; - - ssltls = c->u.ssltls; - ssltls->ssl_error = CyaSSL_get_error(ssltls->session, ret); + ssltls = c->u.ssltls; + ssltls->ssl_error = CyaSSL_get_error(ssltls->session, ret); - nxt_log_debug(thr->log, "CyaSSL_get_error(): %d", ssltls->ssl_error); + nxt_log_debug(thr->log, "CyaSSL_get_error(): %d", ssltls->ssl_error); - switch (ssltls->ssl_error) { + switch (ssltls->ssl_error) { - case SSL_ERROR_WANT_READ: - nxt_event_fd_block_write(thr->engine, &c->socket); + case SSL_ERROR_WANT_READ: + nxt_event_fd_block_write(thr->engine, &c->socket); - c->socket.read_ready = 0; - c->socket.read_handler = handler; + c->socket.read_ready = 0; + c->socket.read_handler = handler; - if (nxt_event_fd_is_disabled(c->socket.read)) { - nxt_event_fd_enable_read(thr->engine, &c->socket); - } + if (nxt_event_fd_is_disabled(c->socket.read)) { + nxt_event_fd_enable_read(thr->engine, &c->socket); + } - return NXT_AGAIN; + return NXT_AGAIN; - case SSL_ERROR_WANT_WRITE: - nxt_event_fd_block_read(thr->engine, &c->socket); + case SSL_ERROR_WANT_WRITE: + nxt_event_fd_block_read(thr->engine, &c->socket); - c->socket.write_ready = 0; - c->socket.write_handler = handler; + c->socket.write_ready = 0; + c->socket.write_handler = handler; - if (nxt_event_fd_is_disabled(c->socket.write)) { - nxt_event_fd_enable_write(thr->engine, &c->socket); - } + if (nxt_event_fd_is_disabled(c->socket.write)) { + nxt_event_fd_enable_write(thr->engine, &c->socket); + } - return NXT_AGAIN; + return NXT_AGAIN; - case SSL_ERROR_ZERO_RETURN: - /* A "close notify" alert */ + case SSL_ERROR_ZERO_RETURN: + /* A "close notify" alert */ - if (c->read_state != NULL) { - wq = c->read_work_queue; - handler = c->read_state->close_handler; + if (c->read_state != NULL) { + wq = c->read_work_queue; + handler = c->read_state->close_handler; - } else { - wq = c->write_work_queue; - handler = c->write_state->close_handler; - } + } else { + wq = c->write_work_queue; + handler = c->write_state->close_handler; + } - nxt_event_conn_io_handle(thr, wq, handler, c, c->socket.data); + nxt_event_conn_io_handle(thr, wq, handler, c, c->socket.data); - return 0; + return 0; - default: - return NXT_ERROR; - } + default: + return NXT_ERROR; + } } +static void nxt_cdecl nxt_cyassl_conn_error(nxt_event_conn_t *c, nxt_err_t err, + const char *fmt, ...) { + u_char *p, *end; + va_list args; + nxt_uint_t level; + nxt_cyassl_conn_t *ssltls; + u_char msg[NXT_MAX_ERROR_STR]; -static void nxt_cdecl -nxt_cyassl_conn_error(nxt_event_conn_t *c, nxt_err_t err, const char *fmt, ...) -{ - u_char *p, *end; - va_list args; - nxt_uint_t level; - nxt_cyassl_conn_t *ssltls; - u_char msg[NXT_MAX_ERROR_STR]; - - ssltls = c->u.ssltls; + ssltls = c->u.ssltls; - level = nxt_cyassl_log_error_level(c, err, ssltls->ssl_error); + level = nxt_cyassl_log_error_level(c, err, ssltls->ssl_error); - if (nxt_log_level_enough(c->socket.log, level)) { + if (nxt_log_level_enough(c->socket.log, level)) { - end = msg + sizeof(msg); + end = msg + sizeof(msg); - va_start(args, fmt); - p = nxt_vsprintf(msg, end, fmt, args); - va_end(args); + va_start(args, fmt); + p = nxt_vsprintf(msg, end, fmt, args); + va_end(args); - if (err != 0) { - p = nxt_sprintf(p, end, " %E", err); - } + if (err != 0) { + p = nxt_sprintf(p, end, " %E", err); + } - p = nxt_cyassl_copy_error(ssltls->ssl_error, p, end); + p = nxt_cyassl_copy_error(ssltls->ssl_error, p, end); - nxt_log_error(level, c->socket.log, "%*s", p - msg, msg); - } + nxt_log_error(level, c->socket.log, "%*s", p - msg, msg); + } } +static nxt_uint_t nxt_cyassl_log_error_level(nxt_event_conn_t *c, nxt_err_t err, + int ssl_error) { + switch (ssl_error) { -static nxt_uint_t -nxt_cyassl_log_error_level(nxt_event_conn_t *c, nxt_err_t err, int ssl_error) -{ - switch (ssl_error) { - - case SOCKET_ERROR_E: /* -208 */ - case MATCH_SUITE_ERROR: /* -261 */ - break; + case SOCKET_ERROR_E: /* -208 */ + case MATCH_SUITE_ERROR: /* -261 */ + break; - default: - return NXT_LOG_ALERT; - } + default: + return NXT_LOG_ALERT; + } - return NXT_LOG_INFO; + return NXT_LOG_INFO; } +static void nxt_cdecl nxt_cyassl_log_error(nxt_uint_t level, nxt_log_t *log, + int err, const char *fmt, ...) { + u_char *p, *end; + va_list args; + u_char msg[NXT_MAX_ERROR_STR]; -static void nxt_cdecl -nxt_cyassl_log_error(nxt_uint_t level, nxt_log_t *log, int err, - const char *fmt, ...) -{ - u_char *p, *end; - va_list args; - u_char msg[NXT_MAX_ERROR_STR]; - - if (nxt_log_level_enough(log, level)) { + if (nxt_log_level_enough(log, level)) { - end = msg + sizeof(msg); + end = msg + sizeof(msg); - va_start(args, fmt); - p = nxt_vsprintf(msg, end, fmt, args); - va_end(args); + va_start(args, fmt); + p = nxt_vsprintf(msg, end, fmt, args); + va_end(args); - p = nxt_cyassl_copy_error(err, p, end); + p = nxt_cyassl_copy_error(err, p, end); - nxt_log_error(level, log, "%*s", p - msg, msg); - } + nxt_log_error(level, log, "%*s", p - msg, msg); + } } +static u_char *nxt_cyassl_copy_error(int err, u_char *p, u_char *end) { + p = nxt_sprintf(p, end, " (SSL:%d ", err); -static u_char * -nxt_cyassl_copy_error(int err, u_char *p, u_char *end) -{ - p = nxt_sprintf(p, end, " (SSL:%d ", err); + CyaSSL_ERR_error_string_n(err, (char *)p, end - p); - CyaSSL_ERR_error_string_n(err, (char *) p, end - p); + p += nxt_strlen(p); - p += nxt_strlen(p); - - if (p < end) { - *p++ = ')'; - } + if (p < end) { + *p++ = ')'; + } - return p; + return p; } diff --git a/src/nxt_devpoll_engine.c b/src/nxt_devpoll_engine.c index 71ab11a38..d864538c6 100644 --- a/src/nxt_devpoll_engine.c +++ b/src/nxt_devpoll_engine.c @@ -6,7 +6,6 @@ #include - /* * "/dev/poll" has been introduced in Solaris 7 (11/99), HP-UX 11.22 (named * "eventport pseudo driver" internally, not to be confused with Solaris 10 @@ -20,49 +19,45 @@ * in the revents field of pollfd structure. */ - -#define NXT_DEVPOLL_ADD 0 -#define NXT_DEVPOLL_UPDATE 1 -#define NXT_DEVPOLL_CHANGE 2 -#define NXT_DEVPOLL_DELETE 3 - +#define NXT_DEVPOLL_ADD 0 +#define NXT_DEVPOLL_UPDATE 1 +#define NXT_DEVPOLL_CHANGE 2 +#define NXT_DEVPOLL_DELETE 3 static nxt_int_t nxt_devpoll_create(nxt_event_engine_t *engine, - nxt_uint_t mchanges, nxt_uint_t mevents); + nxt_uint_t mchanges, nxt_uint_t mevents); static void nxt_devpoll_free(nxt_event_engine_t *engine); static void nxt_devpoll_enable(nxt_event_engine_t *engine, nxt_fd_event_t *ev); static void nxt_devpoll_disable(nxt_event_engine_t *engine, nxt_fd_event_t *ev); static nxt_bool_t nxt_devpoll_close(nxt_event_engine_t *engine, - nxt_fd_event_t *ev); + nxt_fd_event_t *ev); static void nxt_devpoll_enable_read(nxt_event_engine_t *engine, - nxt_fd_event_t *ev); + nxt_fd_event_t *ev); static void nxt_devpoll_enable_write(nxt_event_engine_t *engine, - nxt_fd_event_t *ev); + nxt_fd_event_t *ev); static void nxt_devpoll_disable_read(nxt_event_engine_t *engine, - nxt_fd_event_t *ev); + nxt_fd_event_t *ev); static void nxt_devpoll_disable_write(nxt_event_engine_t *engine, - nxt_fd_event_t *ev); + nxt_fd_event_t *ev); static void nxt_devpoll_block_read(nxt_event_engine_t *engine, - nxt_fd_event_t *ev); + nxt_fd_event_t *ev); static void nxt_devpoll_block_write(nxt_event_engine_t *engine, - nxt_fd_event_t *ev); + nxt_fd_event_t *ev); static void nxt_devpoll_oneshot_read(nxt_event_engine_t *engine, - nxt_fd_event_t *ev); + nxt_fd_event_t *ev); static void nxt_devpoll_oneshot_write(nxt_event_engine_t *engine, - nxt_fd_event_t *ev); + nxt_fd_event_t *ev); static void nxt_devpoll_change(nxt_event_engine_t *engine, nxt_fd_event_t *ev, - nxt_uint_t op, nxt_uint_t events); + nxt_uint_t op, nxt_uint_t events); static nxt_int_t nxt_devpoll_commit_changes(nxt_event_engine_t *engine); static void nxt_devpoll_change_error(nxt_event_engine_t *engine, - nxt_fd_event_t *ev); + nxt_fd_event_t *ev); static void nxt_devpoll_remove(nxt_event_engine_t *engine, nxt_fd_t fd); static nxt_int_t nxt_devpoll_write(nxt_event_engine_t *engine, - struct pollfd *pfd, size_t n); -static void nxt_devpoll_poll(nxt_event_engine_t *engine, - nxt_msec_t timeout); + struct pollfd *pfd, size_t n); +static void nxt_devpoll_poll(nxt_event_engine_t *engine, nxt_msec_t timeout); - -const nxt_event_interface_t nxt_devpoll_engine = { +const nxt_event_interface_t nxt_devpoll_engine = { "devpoll", nxt_devpoll_create, nxt_devpoll_free, @@ -91,104 +86,92 @@ const nxt_event_interface_t nxt_devpoll_engine = { NXT_NO_SIGNAL_EVENTS, }; +static nxt_int_t nxt_devpoll_create(nxt_event_engine_t *engine, + nxt_uint_t mchanges, nxt_uint_t mevents) { + void *changes; -static nxt_int_t -nxt_devpoll_create(nxt_event_engine_t *engine, nxt_uint_t mchanges, - nxt_uint_t mevents) -{ - void *changes; - - engine->u.devpoll.fd = -1; - engine->u.devpoll.mchanges = mchanges; - engine->u.devpoll.mevents = mevents; + engine->u.devpoll.fd = -1; + engine->u.devpoll.mchanges = mchanges; + engine->u.devpoll.mevents = mevents; - changes = nxt_malloc(sizeof(nxt_devpoll_change_t) * mchanges); - if (changes == NULL) { - goto fail; - } + changes = nxt_malloc(sizeof(nxt_devpoll_change_t) * mchanges); + if (changes == NULL) { + goto fail; + } - engine->u.devpoll.changes = changes; + engine->u.devpoll.changes = changes; - /* - * NXT_DEVPOLL_CHANGE requires two struct pollfd's: - * for POLLREMOVE and subsequent POLLIN or POLLOUT. - */ - changes = nxt_malloc(2 * sizeof(struct pollfd) * mchanges); - if (changes == NULL) { - goto fail; - } + /* + * NXT_DEVPOLL_CHANGE requires two struct pollfd's: + * for POLLREMOVE and subsequent POLLIN or POLLOUT. + */ + changes = nxt_malloc(2 * sizeof(struct pollfd) * mchanges); + if (changes == NULL) { + goto fail; + } - engine->u.devpoll.write_changes = changes; + engine->u.devpoll.write_changes = changes; - engine->u.devpoll.events = nxt_malloc(sizeof(struct pollfd) * mevents); - if (engine->u.devpoll.events == NULL) { - goto fail; - } + engine->u.devpoll.events = nxt_malloc(sizeof(struct pollfd) * mevents); + if (engine->u.devpoll.events == NULL) { + goto fail; + } - engine->u.devpoll.fd = open("/dev/poll", O_RDWR); + engine->u.devpoll.fd = open("/dev/poll", O_RDWR); - if (engine->u.devpoll.fd == -1) { - nxt_alert(&engine->task, "open(\"/dev/poll\") failed %E", nxt_errno); - goto fail; - } + if (engine->u.devpoll.fd == -1) { + nxt_alert(&engine->task, "open(\"/dev/poll\") failed %E", nxt_errno); + goto fail; + } - nxt_debug(&engine->task, "open(\"/dev/poll\"): %d", engine->u.devpoll.fd); + nxt_debug(&engine->task, "open(\"/dev/poll\"): %d", engine->u.devpoll.fd); - return NXT_OK; + return NXT_OK; fail: - nxt_devpoll_free(engine); + nxt_devpoll_free(engine); - return NXT_ERROR; + return NXT_ERROR; } +static void nxt_devpoll_free(nxt_event_engine_t *engine) { + nxt_fd_t fd; -static void -nxt_devpoll_free(nxt_event_engine_t *engine) -{ - nxt_fd_t fd; + fd = engine->u.devpoll.fd; - fd = engine->u.devpoll.fd; + nxt_debug(&engine->task, "devpoll %d free", fd); - nxt_debug(&engine->task, "devpoll %d free", fd); + if (fd != -1 && close(fd) != 0) { + nxt_alert(&engine->task, "devpoll close(%d) failed %E", fd, nxt_errno); + } - if (fd != -1 && close(fd) != 0) { - nxt_alert(&engine->task, "devpoll close(%d) failed %E", fd, nxt_errno); - } - - nxt_free(engine->u.devpoll.events); - nxt_free(engine->u.devpoll.write_changes); - nxt_free(engine->u.devpoll.changes); - nxt_fd_event_hash_destroy(&engine->u.devpoll.fd_hash); + nxt_free(engine->u.devpoll.events); + nxt_free(engine->u.devpoll.write_changes); + nxt_free(engine->u.devpoll.changes); + nxt_fd_event_hash_destroy(&engine->u.devpoll.fd_hash); - nxt_memzero(&engine->u.devpoll, sizeof(nxt_devpoll_engine_t)); + nxt_memzero(&engine->u.devpoll, sizeof(nxt_devpoll_engine_t)); } +static void nxt_devpoll_enable(nxt_event_engine_t *engine, nxt_fd_event_t *ev) { + ev->read = NXT_EVENT_ACTIVE; + ev->write = NXT_EVENT_ACTIVE; -static void -nxt_devpoll_enable(nxt_event_engine_t *engine, nxt_fd_event_t *ev) -{ - ev->read = NXT_EVENT_ACTIVE; - ev->write = NXT_EVENT_ACTIVE; - - nxt_devpoll_change(engine, ev, NXT_DEVPOLL_ADD, POLLIN | POLLOUT); + nxt_devpoll_change(engine, ev, NXT_DEVPOLL_ADD, POLLIN | POLLOUT); } +static void nxt_devpoll_disable(nxt_event_engine_t *engine, + nxt_fd_event_t *ev) { + if (ev->read != NXT_EVENT_INACTIVE || ev->write != NXT_EVENT_INACTIVE) { -static void -nxt_devpoll_disable(nxt_event_engine_t *engine, nxt_fd_event_t *ev) -{ - if (ev->read != NXT_EVENT_INACTIVE || ev->write != NXT_EVENT_INACTIVE) { - - ev->read = NXT_EVENT_INACTIVE; - ev->write = NXT_EVENT_INACTIVE; + ev->read = NXT_EVENT_INACTIVE; + ev->write = NXT_EVENT_INACTIVE; - nxt_devpoll_change(engine, ev, NXT_DEVPOLL_DELETE, POLLREMOVE); - } + nxt_devpoll_change(engine, ev, NXT_DEVPOLL_DELETE, POLLREMOVE); + } } - /* * Solaris does not automatically remove a closed file descriptor from * a "/dev/poll" set: ioctl(DP_ISPOLLED) for the descriptor returns 1, @@ -214,15 +197,13 @@ nxt_devpoll_disable(nxt_event_engine_t *engine, nxt_fd_event_t *ev) * deregistered. */ -static nxt_bool_t -nxt_devpoll_close(nxt_event_engine_t *engine, nxt_fd_event_t *ev) -{ - nxt_devpoll_disable(engine, ev); +static nxt_bool_t nxt_devpoll_close(nxt_event_engine_t *engine, + nxt_fd_event_t *ev) { + nxt_devpoll_disable(engine, ev); - return ev->changing; + return ev->changing; } - /* * Solaris poll(7d): * @@ -234,428 +215,390 @@ nxt_devpoll_close(nxt_event_engine_t *engine, nxt_fd_event_t *ev) * the monitored set. The revents field is not used. */ -static void -nxt_devpoll_enable_read(nxt_event_engine_t *engine, nxt_fd_event_t *ev) -{ - nxt_uint_t op, events; - - if (ev->read != NXT_EVENT_BLOCKED) { +static void nxt_devpoll_enable_read(nxt_event_engine_t *engine, + nxt_fd_event_t *ev) { + nxt_uint_t op, events; - events = POLLIN; + if (ev->read != NXT_EVENT_BLOCKED) { - if (ev->write == NXT_EVENT_INACTIVE) { - op = NXT_DEVPOLL_ADD; + events = POLLIN; - } else if (ev->write == NXT_EVENT_BLOCKED) { - ev->write = NXT_EVENT_INACTIVE; - op = NXT_DEVPOLL_CHANGE; + if (ev->write == NXT_EVENT_INACTIVE) { + op = NXT_DEVPOLL_ADD; - } else { - op = NXT_DEVPOLL_UPDATE; - events = POLLIN | POLLOUT; - } + } else if (ev->write == NXT_EVENT_BLOCKED) { + ev->write = NXT_EVENT_INACTIVE; + op = NXT_DEVPOLL_CHANGE; - nxt_devpoll_change(engine, ev, op, events); + } else { + op = NXT_DEVPOLL_UPDATE; + events = POLLIN | POLLOUT; } - ev->read = NXT_EVENT_ACTIVE; -} - + nxt_devpoll_change(engine, ev, op, events); + } -static void -nxt_devpoll_enable_write(nxt_event_engine_t *engine, nxt_fd_event_t *ev) -{ - nxt_uint_t op, events; + ev->read = NXT_EVENT_ACTIVE; +} - if (ev->write != NXT_EVENT_BLOCKED) { +static void nxt_devpoll_enable_write(nxt_event_engine_t *engine, + nxt_fd_event_t *ev) { + nxt_uint_t op, events; - events = POLLOUT; + if (ev->write != NXT_EVENT_BLOCKED) { - if (ev->read == NXT_EVENT_INACTIVE) { - op = NXT_DEVPOLL_ADD; + events = POLLOUT; - } else if (ev->read == NXT_EVENT_BLOCKED) { - ev->read = NXT_EVENT_INACTIVE; - op = NXT_DEVPOLL_CHANGE; + if (ev->read == NXT_EVENT_INACTIVE) { + op = NXT_DEVPOLL_ADD; - } else { - op = NXT_DEVPOLL_UPDATE; - events = POLLIN | POLLOUT; - } + } else if (ev->read == NXT_EVENT_BLOCKED) { + ev->read = NXT_EVENT_INACTIVE; + op = NXT_DEVPOLL_CHANGE; - nxt_devpoll_change(engine, ev, op, events); + } else { + op = NXT_DEVPOLL_UPDATE; + events = POLLIN | POLLOUT; } - ev->write = NXT_EVENT_ACTIVE; -} + nxt_devpoll_change(engine, ev, op, events); + } + ev->write = NXT_EVENT_ACTIVE; +} -static void -nxt_devpoll_disable_read(nxt_event_engine_t *engine, nxt_fd_event_t *ev) -{ - nxt_uint_t op, events; +static void nxt_devpoll_disable_read(nxt_event_engine_t *engine, + nxt_fd_event_t *ev) { + nxt_uint_t op, events; - ev->read = NXT_EVENT_INACTIVE; + ev->read = NXT_EVENT_INACTIVE; - if (ev->write <= NXT_EVENT_BLOCKED) { - ev->write = NXT_EVENT_INACTIVE; - op = NXT_DEVPOLL_DELETE; - events = POLLREMOVE; + if (ev->write <= NXT_EVENT_BLOCKED) { + ev->write = NXT_EVENT_INACTIVE; + op = NXT_DEVPOLL_DELETE; + events = POLLREMOVE; - } else { - op = NXT_DEVPOLL_CHANGE; - events = POLLOUT; - } + } else { + op = NXT_DEVPOLL_CHANGE; + events = POLLOUT; + } - nxt_devpoll_change(engine, ev, op, events); + nxt_devpoll_change(engine, ev, op, events); } +static void nxt_devpoll_disable_write(nxt_event_engine_t *engine, + nxt_fd_event_t *ev) { + nxt_uint_t op, events; -static void -nxt_devpoll_disable_write(nxt_event_engine_t *engine, nxt_fd_event_t *ev) -{ - nxt_uint_t op, events; - - ev->write = NXT_EVENT_INACTIVE; + ev->write = NXT_EVENT_INACTIVE; - if (ev->read <= NXT_EVENT_BLOCKED) { - ev->read = NXT_EVENT_INACTIVE; - op = NXT_DEVPOLL_DELETE; - events = POLLREMOVE; + if (ev->read <= NXT_EVENT_BLOCKED) { + ev->read = NXT_EVENT_INACTIVE; + op = NXT_DEVPOLL_DELETE; + events = POLLREMOVE; - } else { - op = NXT_DEVPOLL_CHANGE; - events = POLLIN; - } + } else { + op = NXT_DEVPOLL_CHANGE; + events = POLLIN; + } - nxt_devpoll_change(engine, ev, op, events); + nxt_devpoll_change(engine, ev, op, events); } +static void nxt_devpoll_block_read(nxt_event_engine_t *engine, + nxt_fd_event_t *ev) { + if (ev->read != NXT_EVENT_INACTIVE) { + ev->read = NXT_EVENT_BLOCKED; + } +} -static void -nxt_devpoll_block_read(nxt_event_engine_t *engine, nxt_fd_event_t *ev) -{ - if (ev->read != NXT_EVENT_INACTIVE) { - ev->read = NXT_EVENT_BLOCKED; - } +static void nxt_devpoll_block_write(nxt_event_engine_t *engine, + nxt_fd_event_t *ev) { + if (ev->write != NXT_EVENT_INACTIVE) { + ev->write = NXT_EVENT_BLOCKED; + } } +static void nxt_devpoll_oneshot_read(nxt_event_engine_t *engine, + nxt_fd_event_t *ev) { + nxt_devpoll_enable_read(engine, ev); -static void -nxt_devpoll_block_write(nxt_event_engine_t *engine, nxt_fd_event_t *ev) -{ - if (ev->write != NXT_EVENT_INACTIVE) { - ev->write = NXT_EVENT_BLOCKED; - } + ev->read = NXT_EVENT_ONESHOT; } +static void nxt_devpoll_oneshot_write(nxt_event_engine_t *engine, + nxt_fd_event_t *ev) { + nxt_devpoll_enable_write(engine, ev); -static void -nxt_devpoll_oneshot_read(nxt_event_engine_t *engine, nxt_fd_event_t *ev) -{ - nxt_devpoll_enable_read(engine, ev); - - ev->read = NXT_EVENT_ONESHOT; + ev->write = NXT_EVENT_ONESHOT; } +static void nxt_devpoll_change(nxt_event_engine_t *engine, nxt_fd_event_t *ev, + nxt_uint_t op, nxt_uint_t events) { + nxt_devpoll_change_t *change; -static void -nxt_devpoll_oneshot_write(nxt_event_engine_t *engine, nxt_fd_event_t *ev) -{ - nxt_devpoll_enable_write(engine, ev); + nxt_debug(ev->task, "devpoll %d change fd:%d op:%ui ev:%04Xi", + engine->u.devpoll.fd, ev->fd, op, events); - ev->write = NXT_EVENT_ONESHOT; -} + if (engine->u.devpoll.nchanges >= engine->u.devpoll.mchanges) { + (void)nxt_devpoll_commit_changes(engine); + } + ev->changing = 1; -static void -nxt_devpoll_change(nxt_event_engine_t *engine, nxt_fd_event_t *ev, - nxt_uint_t op, nxt_uint_t events) -{ - nxt_devpoll_change_t *change; - - nxt_debug(ev->task, "devpoll %d change fd:%d op:%ui ev:%04Xi", - engine->u.devpoll.fd, ev->fd, op, events); + change = &engine->u.devpoll.changes[engine->u.devpoll.nchanges++]; + change->op = op; + change->events = events; + change->event = ev; +} - if (engine->u.devpoll.nchanges >= engine->u.devpoll.mchanges) { - (void) nxt_devpoll_commit_changes(engine); +static nxt_int_t nxt_devpoll_commit_changes(nxt_event_engine_t *engine) { + size_t n; + nxt_int_t ret, retval; + struct pollfd *pfd, *write_changes; + nxt_fd_event_t *ev; + nxt_devpoll_change_t *change, *end; + + nxt_debug(&engine->task, "devpoll %d changes:%ui", engine->u.devpoll.fd, + engine->u.devpoll.nchanges); + + retval = NXT_OK; + n = 0; + write_changes = engine->u.devpoll.write_changes; + change = engine->u.devpoll.changes; + end = change + engine->u.devpoll.nchanges; + + do { + ev = change->event; + + nxt_debug(&engine->task, "devpoll fd:%d op:%d ev:%04Xd", ev->fd, change->op, + change->events); + + if (change->op == NXT_DEVPOLL_CHANGE) { + pfd = &write_changes[n++]; + pfd->fd = ev->fd; + pfd->events = POLLREMOVE; + pfd->revents = 0; } - ev->changing = 1; + pfd = &write_changes[n++]; + pfd->fd = ev->fd; + pfd->events = change->events; + pfd->revents = 0; - change = &engine->u.devpoll.changes[engine->u.devpoll.nchanges++]; - change->op = op; - change->events = events; - change->event = ev; -} + ev->changing = 0; + change++; -static nxt_int_t -nxt_devpoll_commit_changes(nxt_event_engine_t *engine) -{ - size_t n; - nxt_int_t ret, retval; - struct pollfd *pfd, *write_changes; - nxt_fd_event_t *ev; - nxt_devpoll_change_t *change, *end; + } while (change < end); - nxt_debug(&engine->task, "devpoll %d changes:%ui", - engine->u.devpoll.fd, engine->u.devpoll.nchanges); + change = engine->u.devpoll.changes; + end = change + engine->u.devpoll.nchanges; - retval = NXT_OK; - n = 0; - write_changes = engine->u.devpoll.write_changes; - change = engine->u.devpoll.changes; - end = change + engine->u.devpoll.nchanges; + ret = nxt_devpoll_write(engine, write_changes, n); - do { - ev = change->event; + if (nxt_slow_path(ret != NXT_OK)) { - nxt_debug(&engine->task, "devpoll fd:%d op:%d ev:%04Xd", - ev->fd, change->op, change->events); + do { + nxt_devpoll_change_error(engine, change->event); + change++; + } while (change < end); - if (change->op == NXT_DEVPOLL_CHANGE) { - pfd = &write_changes[n++]; - pfd->fd = ev->fd; - pfd->events = POLLREMOVE; - pfd->revents = 0; - } + engine->u.devpoll.nchanges = 0; - pfd = &write_changes[n++]; - pfd->fd = ev->fd; - pfd->events = change->events; - pfd->revents = 0; + return NXT_ERROR; + } - ev->changing = 0; + do { + ev = change->event; - change++; + if (change->op == NXT_DEVPOLL_ADD) { + ret = nxt_fd_event_hash_add(&engine->u.devpoll.fd_hash, ev->fd, ev); - } while (change < end); + if (nxt_slow_path(ret != NXT_OK)) { + nxt_devpoll_change_error(engine, ev); + retval = NXT_ERROR; + } - change = engine->u.devpoll.changes; - end = change + engine->u.devpoll.nchanges; + } else if (change->op == NXT_DEVPOLL_DELETE) { + nxt_fd_event_hash_delete(&engine->task, &engine->u.devpoll.fd_hash, + ev->fd, 0); + } - ret = nxt_devpoll_write(engine, write_changes, n); + /* Nothing tp do for NXT_DEVPOLL_UPDATE and NXT_DEVPOLL_CHANGE. */ - if (nxt_slow_path(ret != NXT_OK)) { + change++; - do { - nxt_devpoll_change_error(engine, change->event); - change++; - } while (change < end); + } while (change < end); - engine->u.devpoll.nchanges = 0; + engine->u.devpoll.nchanges = 0; - return NXT_ERROR; - } + return retval; +} - do { - ev = change->event; +static void nxt_devpoll_change_error(nxt_event_engine_t *engine, + nxt_fd_event_t *ev) { + ev->read = NXT_EVENT_INACTIVE; + ev->write = NXT_EVENT_INACTIVE; - if (change->op == NXT_DEVPOLL_ADD) { - ret = nxt_fd_event_hash_add(&engine->u.devpoll.fd_hash, ev->fd, ev); + nxt_work_queue_add(&engine->fast_work_queue, ev->error_handler, ev->task, ev, + ev->data); - if (nxt_slow_path(ret != NXT_OK)) { - nxt_devpoll_change_error(engine, ev); - retval = NXT_ERROR; - } + nxt_fd_event_hash_delete(ev->task, &engine->u.devpoll.fd_hash, ev->fd, 1); - } else if (change->op == NXT_DEVPOLL_DELETE) { - nxt_fd_event_hash_delete(&engine->task, &engine->u.devpoll.fd_hash, - ev->fd, 0); - } + nxt_devpoll_remove(engine, ev->fd); +} - /* Nothing tp do for NXT_DEVPOLL_UPDATE and NXT_DEVPOLL_CHANGE. */ +static void nxt_devpoll_remove(nxt_event_engine_t *engine, nxt_fd_t fd) { + int n; + struct pollfd pfd; - change++; + pfd.fd = fd; + pfd.events = 0; + pfd.revents = 0; - } while (change < end); + n = ioctl(engine->u.devpoll.fd, DP_ISPOLLED, &pfd); - engine->u.devpoll.nchanges = 0; + nxt_debug(&engine->task, "ioctl(%d, DP_ISPOLLED, %d): %d", + engine->u.devpoll.fd, fd, n); - return retval; -} + if (n == 0) { + /* The file descriptor is not in the set. */ + return; + } + if (n == -1) { + nxt_alert(&engine->task, "ioctl(%d, DP_ISPOLLED, %d) failed %E", + engine->u.devpoll.fd, fd, nxt_errno); + /* Fall through. */ + } -static void -nxt_devpoll_change_error(nxt_event_engine_t *engine, nxt_fd_event_t *ev) -{ - ev->read = NXT_EVENT_INACTIVE; - ev->write = NXT_EVENT_INACTIVE; + /* n == 1: the file descriptor is in the set. */ - nxt_work_queue_add(&engine->fast_work_queue, ev->error_handler, - ev->task, ev, ev->data); + nxt_debug(&engine->task, "devpoll %d remove fd:%d", engine->u.devpoll.fd, fd); - nxt_fd_event_hash_delete(ev->task, &engine->u.devpoll.fd_hash, ev->fd, 1); + pfd.fd = fd; + pfd.events = POLLREMOVE; + pfd.revents = 0; - nxt_devpoll_remove(engine, ev->fd); + nxt_devpoll_write(engine, &pfd, 1); } +static nxt_int_t nxt_devpoll_write(nxt_event_engine_t *engine, + struct pollfd *pfd, size_t n) { + int fd; + + fd = engine->u.devpoll.fd; -static void -nxt_devpoll_remove(nxt_event_engine_t *engine, nxt_fd_t fd) -{ - int n; - struct pollfd pfd; + nxt_debug(&engine->task, "devpoll write(%d) changes:%uz", fd, n); - pfd.fd = fd; - pfd.events = 0; - pfd.revents = 0; + n *= sizeof(struct pollfd); - n = ioctl(engine->u.devpoll.fd, DP_ISPOLLED, &pfd); + if (nxt_slow_path(write(fd, pfd, n) == (ssize_t)n)) { + return NXT_OK; + } - nxt_debug(&engine->task, "ioctl(%d, DP_ISPOLLED, %d): %d", - engine->u.devpoll.fd, fd, n); + nxt_alert(&engine->task, "devpoll write(%d) failed %E", fd, nxt_errno); - if (n == 0) { - /* The file descriptor is not in the set. */ - return; - } + return NXT_ERROR; +} - if (n == -1) { - nxt_alert(&engine->task, "ioctl(%d, DP_ISPOLLED, %d) failed %E", - engine->u.devpoll.fd, fd, nxt_errno); - /* Fall through. */ +static void nxt_devpoll_poll(nxt_event_engine_t *engine, nxt_msec_t timeout) { + int nevents; + nxt_fd_t fd; + nxt_int_t i; + nxt_err_t err; + nxt_uint_t events, level; + struct dvpoll dvp; + struct pollfd *pfd; + nxt_fd_event_t *ev; + + if (engine->u.devpoll.nchanges != 0) { + if (nxt_devpoll_commit_changes(engine) != NXT_OK) { + /* Error handlers have been enqueued on failure. */ + timeout = 0; } + } - /* n == 1: the file descriptor is in the set. */ + nxt_debug(&engine->task, "ioctl(%d, DP_POLL) timeout:%M", + engine->u.devpoll.fd, timeout); - nxt_debug(&engine->task, "devpoll %d remove fd:%d", - engine->u.devpoll.fd, fd); + dvp.dp_fds = engine->u.devpoll.events; + dvp.dp_nfds = engine->u.devpoll.mevents; + dvp.dp_timeout = timeout; - pfd.fd = fd; - pfd.events = POLLREMOVE; - pfd.revents = 0; + nevents = ioctl(engine->u.devpoll.fd, DP_POLL, &dvp); - nxt_devpoll_write(engine, &pfd, 1); -} + err = (nevents == -1) ? nxt_errno : 0; + nxt_thread_time_update(engine->task.thread); -static nxt_int_t -nxt_devpoll_write(nxt_event_engine_t *engine, struct pollfd *pfd, size_t n) -{ - int fd; + nxt_debug(&engine->task, "ioctl(%d, DP_POLL): %d", engine->u.devpoll.fd, + nevents); - fd = engine->u.devpoll.fd; + if (nevents == -1) { + level = (err == NXT_EINTR) ? NXT_LOG_INFO : NXT_LOG_ALERT; - nxt_debug(&engine->task, "devpoll write(%d) changes:%uz", fd, n); + nxt_log(&engine->task, level, "ioctl(%d, DP_POLL) failed %E", + engine->u.devpoll.fd, err); - n *= sizeof(struct pollfd); + return; + } - if (nxt_slow_path(write(fd, pfd, n) == (ssize_t) n)) { - return NXT_OK; - } + for (i = 0; i < nevents; i++) { - nxt_alert(&engine->task, "devpoll write(%d) failed %E", fd, nxt_errno); + pfd = &engine->u.devpoll.events[i]; + fd = pfd->fd; + events = pfd->revents; - return NXT_ERROR; -} + ev = nxt_fd_event_hash_get(&engine->task, &engine->u.devpoll.fd_hash, fd); + if (nxt_slow_path(ev == NULL)) { + nxt_alert(&engine->task, + "ioctl(%d, DP_POLL) returned invalid " + "fd:%d ev:%04Xd rev:%04uXi", + engine->u.devpoll.fd, fd, pfd->events, events); -static void -nxt_devpoll_poll(nxt_event_engine_t *engine, nxt_msec_t timeout) -{ - int nevents; - nxt_fd_t fd; - nxt_int_t i; - nxt_err_t err; - nxt_uint_t events, level; - struct dvpoll dvp; - struct pollfd *pfd; - nxt_fd_event_t *ev; - - if (engine->u.devpoll.nchanges != 0) { - if (nxt_devpoll_commit_changes(engine) != NXT_OK) { - /* Error handlers have been enqueued on failure. */ - timeout = 0; - } + nxt_devpoll_remove(engine, fd); + continue; } - nxt_debug(&engine->task, "ioctl(%d, DP_POLL) timeout:%M", - engine->u.devpoll.fd, timeout); - - dvp.dp_fds = engine->u.devpoll.events; - dvp.dp_nfds = engine->u.devpoll.mevents; - dvp.dp_timeout = timeout; + nxt_debug(ev->task, "devpoll: fd:%d ev:%04uXi rd:%d wr:%d", fd, events, + ev->read, ev->write); - nevents = ioctl(engine->u.devpoll.fd, DP_POLL, &dvp); + if (nxt_slow_path(events & (POLLERR | POLLHUP | POLLNVAL)) != 0) { + nxt_alert(ev->task, "ioctl(%d, DP_POLL) error fd:%d ev:%04Xd rev:%04uXi", + engine->u.devpoll.fd, fd, pfd->events, events); - err = (nevents == -1) ? nxt_errno : 0; + nxt_work_queue_add(&engine->fast_work_queue, ev->error_handler, ev->task, + ev, ev->data); + continue; + } - nxt_thread_time_update(engine->task.thread); + if (events & POLLIN) { + ev->read_ready = 1; - nxt_debug(&engine->task, "ioctl(%d, DP_POLL): %d", - engine->u.devpoll.fd, nevents); + if (ev->read != NXT_EVENT_BLOCKED) { + nxt_work_queue_add(ev->read_work_queue, ev->read_handler, ev->task, ev, + ev->data); + } - if (nevents == -1) { - level = (err == NXT_EINTR) ? NXT_LOG_INFO : NXT_LOG_ALERT; + if (ev->read == NXT_EVENT_BLOCKED || ev->read == NXT_EVENT_ONESHOT) { + nxt_devpoll_disable_read(engine, ev); + } + } - nxt_log(&engine->task, level, "ioctl(%d, DP_POLL) failed %E", - engine->u.devpoll.fd, err); + if (events & POLLOUT) { + ev->write_ready = 1; - return; - } + if (ev->write != NXT_EVENT_BLOCKED) { + nxt_work_queue_add(ev->write_work_queue, ev->write_handler, ev->task, + ev, ev->data); + } - for (i = 0; i < nevents; i++) { - - pfd = &engine->u.devpoll.events[i]; - fd = pfd->fd; - events = pfd->revents; - - ev = nxt_fd_event_hash_get(&engine->task, &engine->u.devpoll.fd_hash, - fd); - - if (nxt_slow_path(ev == NULL)) { - nxt_alert(&engine->task, - "ioctl(%d, DP_POLL) returned invalid " - "fd:%d ev:%04Xd rev:%04uXi", - engine->u.devpoll.fd, fd, pfd->events, events); - - nxt_devpoll_remove(engine, fd); - continue; - } - - nxt_debug(ev->task, "devpoll: fd:%d ev:%04uXi rd:%d wr:%d", - fd, events, ev->read, ev->write); - - if (nxt_slow_path(events & (POLLERR | POLLHUP | POLLNVAL)) != 0) { - nxt_alert(ev->task, - "ioctl(%d, DP_POLL) error fd:%d ev:%04Xd rev:%04uXi", - engine->u.devpoll.fd, fd, pfd->events, events); - - nxt_work_queue_add(&engine->fast_work_queue, ev->error_handler, - ev->task, ev, ev->data); - continue; - } - - if (events & POLLIN) { - ev->read_ready = 1; - - if (ev->read != NXT_EVENT_BLOCKED) { - nxt_work_queue_add(ev->read_work_queue, ev->read_handler, - ev->task, ev, ev->data); - } - - if (ev->read == NXT_EVENT_BLOCKED - || ev->read == NXT_EVENT_ONESHOT) - { - nxt_devpoll_disable_read(engine, ev); - } - } - - if (events & POLLOUT) { - ev->write_ready = 1; - - if (ev->write != NXT_EVENT_BLOCKED) { - nxt_work_queue_add(ev->write_work_queue, ev->write_handler, - ev->task, ev, ev->data); - } - - if (ev->write == NXT_EVENT_BLOCKED - || ev->write == NXT_EVENT_ONESHOT) - { - nxt_devpoll_disable_write(engine, ev); - } - } + if (ev->write == NXT_EVENT_BLOCKED || ev->write == NXT_EVENT_ONESHOT) { + nxt_devpoll_disable_write(engine, ev); + } } + } } diff --git a/src/nxt_djb_hash.c b/src/nxt_djb_hash.c index cd3158693..3a520c3ed 100644 --- a/src/nxt_djb_hash.c +++ b/src/nxt_djb_hash.c @@ -6,40 +6,34 @@ #include +uint32_t nxt_djb_hash(const void *data, size_t len) { + uint32_t hash; + const u_char *p; -uint32_t -nxt_djb_hash(const void *data, size_t len) -{ - uint32_t hash; - const u_char *p; + p = data; + hash = NXT_DJB_HASH_INIT; - p = data; - hash = NXT_DJB_HASH_INIT; + while (len != 0) { + hash = nxt_djb_hash_add(hash, *p++); + len--; + } - while (len != 0) { - hash = nxt_djb_hash_add(hash, *p++); - len--; - } - - return hash; + return hash; } +uint32_t nxt_djb_hash_lowcase(const void *data, size_t len) { + u_char c; + uint32_t hash; + const u_char *p; -uint32_t -nxt_djb_hash_lowcase(const void *data, size_t len) -{ - u_char c; - uint32_t hash; - const u_char *p; - - p = data; - hash = NXT_DJB_HASH_INIT; + p = data; + hash = NXT_DJB_HASH_INIT; - while (len != 0) { - c = *p++; - hash = nxt_djb_hash_add(hash, nxt_lowcase(c)); - len--; - } + while (len != 0) { + c = *p++; + hash = nxt_djb_hash_add(hash, nxt_lowcase(c)); + len--; + } - return hash; + return hash; } diff --git a/src/nxt_djb_hash.h b/src/nxt_djb_hash.h index 43395e6ae..b5fb519f7 100644 --- a/src/nxt_djb_hash.h +++ b/src/nxt_djb_hash.h @@ -7,19 +7,14 @@ #ifndef _NXT_DJB_HASH_H_INCLUDED_ #define _NXT_DJB_HASH_H_INCLUDED_ - /* A fast and simple hash function by Daniel J. Bernstein. */ - NXT_EXPORT uint32_t nxt_djb_hash(const void *data, size_t len); NXT_EXPORT uint32_t nxt_djb_hash_lowcase(const void *data, size_t len); +#define NXT_DJB_HASH_INIT 5381 -#define NXT_DJB_HASH_INIT 5381 - - -#define nxt_djb_hash_add(hash, val) \ - ((uint32_t) ((((hash) << 5) + (hash)) ^ (uint32_t) (val))) - +#define nxt_djb_hash_add(hash, val) \ + ((uint32_t)((((hash) << 5) + (hash)) ^ (uint32_t)(val))) #endif /* _NXT_DJB_HASH_H_INCLUDED_ */ diff --git a/src/nxt_dyld.c b/src/nxt_dyld.c index 63e6be145..378ca8f59 100644 --- a/src/nxt_dyld.c +++ b/src/nxt_dyld.c @@ -6,81 +6,72 @@ #include +nxt_int_t nxt_dyld_load(nxt_dyld_t *dyld) { + const char *err; -nxt_int_t -nxt_dyld_load(nxt_dyld_t *dyld) -{ - const char *err; + dyld->handle = dlopen(dyld->name, RTLD_NOW | RTLD_GLOBAL); - dyld->handle = dlopen(dyld->name, RTLD_NOW | RTLD_GLOBAL); + if (dyld->handle != NULL) { + nxt_thread_log_debug("dlopen(\"%s\")", dyld->name); + return NXT_OK; + } - if (dyld->handle != NULL) { - nxt_thread_log_debug("dlopen(\"%s\")", dyld->name); - return NXT_OK; - } + err = dlerror(); + if (err == NULL) { + err = "(null)"; + } - err = dlerror(); - if (err == NULL) { - err = "(null)"; - } + nxt_thread_log_alert("dlopen(\"%s\") failed: %s", dyld->name, err); - nxt_thread_log_alert("dlopen(\"%s\") failed: %s", dyld->name, err); - - return NXT_ERROR; + return NXT_ERROR; } +void *nxt_dyld_symbol(nxt_dyld_t *dyld, const char *symbol) { + void *handle, *s; + const char *name; + const char *err; -void * -nxt_dyld_symbol(nxt_dyld_t *dyld, const char *symbol) -{ - void *handle, *s; - const char *name; - const char *err; - - if (dyld == NXT_DYLD_ANY) { - handle = RTLD_DEFAULT; - name = "RTLD_DEFAULT"; + if (dyld == NXT_DYLD_ANY) { + handle = RTLD_DEFAULT; + name = "RTLD_DEFAULT"; - } else { - handle = dyld->handle; - name = dyld->name; - } + } else { + handle = dyld->handle; + name = dyld->name; + } - s = dlsym(handle, symbol); + s = dlsym(handle, symbol); - if (s != NULL) { - nxt_thread_log_debug("dlsym(\"%s\", \"%s\")", name, symbol); - return s; - } + if (s != NULL) { + nxt_thread_log_debug("dlsym(\"%s\", \"%s\")", name, symbol); + return s; + } - err = dlerror(); - if (err == NULL) { - err = "(null)"; - } + err = dlerror(); + if (err == NULL) { + err = "(null)"; + } - nxt_thread_log_alert("dlsym(\"%s\", \"%s\") failed: %s", name, symbol, err); + nxt_thread_log_alert("dlsym(\"%s\", \"%s\") failed: %s", name, symbol, err); - return s; + return s; } +nxt_int_t nxt_dyld_unload(nxt_dyld_t *dyld) { + const char *err; -nxt_int_t -nxt_dyld_unload(nxt_dyld_t *dyld) -{ - const char *err; - - if (dlclose(dyld->handle) == 0) { - nxt_thread_log_debug("dlclose(\"%s\")", dyld->name); - return NXT_OK; - } + if (dlclose(dyld->handle) == 0) { + nxt_thread_log_debug("dlclose(\"%s\")", dyld->name); + return NXT_OK; + } - err = dlerror(); + err = dlerror(); - if (err == NULL) { - err = "(null)"; - } + if (err == NULL) { + err = "(null)"; + } - nxt_thread_log_alert("dlclose(\"%s\") failed: %s", dyld->name, err); + nxt_thread_log_alert("dlclose(\"%s\") failed: %s", dyld->name, err); - return NXT_ERROR; + return NXT_ERROR; } diff --git a/src/nxt_dyld.h b/src/nxt_dyld.h index 65ce1874a..713ef93f8 100644 --- a/src/nxt_dyld.h +++ b/src/nxt_dyld.h @@ -7,23 +7,17 @@ #ifndef _NXT_UNIX_DYLD_H_INCLUDED_ #define _NXT_UNIX_DYLD_H_INCLUDED_ - typedef struct { - void *handle; - char *name; + void *handle; + char *name; } nxt_dyld_t; +#define NXT_DYLD_ANY RTLD_DEFAULT -#define NXT_DYLD_ANY RTLD_DEFAULT - - -#define nxt_dyld_is_valid(dyld) \ - ((dyld)->handle != NULL) - +#define nxt_dyld_is_valid(dyld) ((dyld)->handle != NULL) NXT_EXPORT nxt_int_t nxt_dyld_load(nxt_dyld_t *dyld); NXT_EXPORT void *nxt_dyld_symbol(nxt_dyld_t *dyld, const char *symbol); NXT_EXPORT nxt_int_t nxt_dyld_unload(nxt_dyld_t *dyld); - #endif /* _NXT_UNIX_DYLD_H_INCLUDED_ */ diff --git a/src/nxt_epoll_engine.c b/src/nxt_epoll_engine.c index d53df1bc4..1a0e91d95 100644 --- a/src/nxt_epoll_engine.c +++ b/src/nxt_epoll_engine.c @@ -6,7 +6,6 @@ #include - /* * The first epoll version has been introduced in Linux 2.5.44. The * interface was changed several times since then and the final version @@ -30,43 +29,44 @@ * EPOLLEXCLUSIVE Linux 4.5, glibc 2.24. */ - #if (NXT_HAVE_EPOLL_EDGE) static nxt_int_t nxt_epoll_edge_create(nxt_event_engine_t *engine, - nxt_uint_t mchanges, nxt_uint_t mevents); + nxt_uint_t mchanges, nxt_uint_t mevents); #endif static nxt_int_t nxt_epoll_level_create(nxt_event_engine_t *engine, - nxt_uint_t mchanges, nxt_uint_t mevents); + nxt_uint_t mchanges, + nxt_uint_t mevents); static nxt_int_t nxt_epoll_create(nxt_event_engine_t *engine, - nxt_uint_t mchanges, nxt_uint_t mevents, nxt_conn_io_t *io, uint32_t mode); + nxt_uint_t mchanges, nxt_uint_t mevents, + nxt_conn_io_t *io, uint32_t mode); static void nxt_epoll_test_accept4(nxt_event_engine_t *engine, - nxt_conn_io_t *io); + nxt_conn_io_t *io); static void nxt_epoll_free(nxt_event_engine_t *engine); static void nxt_epoll_enable(nxt_event_engine_t *engine, nxt_fd_event_t *ev); static void nxt_epoll_disable(nxt_event_engine_t *engine, nxt_fd_event_t *ev); static void nxt_epoll_delete(nxt_event_engine_t *engine, nxt_fd_event_t *ev); static nxt_bool_t nxt_epoll_close(nxt_event_engine_t *engine, - nxt_fd_event_t *ev); + nxt_fd_event_t *ev); static void nxt_epoll_enable_read(nxt_event_engine_t *engine, - nxt_fd_event_t *ev); + nxt_fd_event_t *ev); static void nxt_epoll_enable_write(nxt_event_engine_t *engine, - nxt_fd_event_t *ev); + nxt_fd_event_t *ev); static void nxt_epoll_disable_read(nxt_event_engine_t *engine, - nxt_fd_event_t *ev); + nxt_fd_event_t *ev); static void nxt_epoll_disable_write(nxt_event_engine_t *engine, - nxt_fd_event_t *ev); + nxt_fd_event_t *ev); static void nxt_epoll_block_read(nxt_event_engine_t *engine, - nxt_fd_event_t *ev); + nxt_fd_event_t *ev); static void nxt_epoll_block_write(nxt_event_engine_t *engine, - nxt_fd_event_t *ev); + nxt_fd_event_t *ev); static void nxt_epoll_oneshot_read(nxt_event_engine_t *engine, - nxt_fd_event_t *ev); + nxt_fd_event_t *ev); static void nxt_epoll_oneshot_write(nxt_event_engine_t *engine, - nxt_fd_event_t *ev); + nxt_fd_event_t *ev); static void nxt_epoll_enable_accept(nxt_event_engine_t *engine, - nxt_fd_event_t *ev); + nxt_fd_event_t *ev); static void nxt_epoll_change(nxt_event_engine_t *engine, nxt_fd_event_t *ev, - int op, uint32_t events); + int op, uint32_t events); static void nxt_epoll_commit_changes(nxt_event_engine_t *engine); static void nxt_epoll_error_handler(nxt_task_t *task, void *obj, void *data); #if (NXT_HAVE_SIGNALFD) @@ -75,28 +75,25 @@ static void nxt_epoll_signalfd_handler(nxt_task_t *task, void *obj, void *data); #endif #if (NXT_HAVE_EVENTFD) static nxt_int_t nxt_epoll_enable_post(nxt_event_engine_t *engine, - nxt_work_handler_t handler); + nxt_work_handler_t handler); static void nxt_epoll_eventfd_handler(nxt_task_t *task, void *obj, void *data); static void nxt_epoll_signal(nxt_event_engine_t *engine, nxt_uint_t signo); #endif static void nxt_epoll_poll(nxt_event_engine_t *engine, nxt_msec_t timeout); #if (NXT_HAVE_ACCEPT4) -static void nxt_epoll_conn_io_accept4(nxt_task_t *task, void *obj, - void *data); +static void nxt_epoll_conn_io_accept4(nxt_task_t *task, void *obj, void *data); #endif - #if (NXT_HAVE_EPOLL_EDGE) static void nxt_epoll_edge_conn_io_connect(nxt_task_t *task, void *obj, - void *data); + void *data); static void nxt_epoll_edge_conn_connected(nxt_task_t *task, void *obj, - void *data); + void *data); static ssize_t nxt_epoll_edge_conn_io_recvbuf(nxt_conn_t *c, nxt_buf_t *b); - -static nxt_conn_io_t nxt_epoll_edge_conn_io = { +static nxt_conn_io_t nxt_epoll_edge_conn_io = { .connect = nxt_epoll_edge_conn_io_connect, .accept = nxt_conn_io_accept, @@ -117,8 +114,7 @@ static nxt_conn_io_t nxt_epoll_edge_conn_io = { .send = nxt_event_conn_io_send, }; - -const nxt_event_interface_t nxt_epoll_edge_engine = { +const nxt_event_interface_t nxt_epoll_edge_engine = { "epoll_edge", nxt_epoll_edge_create, nxt_epoll_free, @@ -163,8 +159,7 @@ const nxt_event_interface_t nxt_epoll_edge_engine = { #endif - -const nxt_event_interface_t nxt_epoll_level_engine = { +const nxt_event_interface_t nxt_epoll_level_engine = { "epoll_level", nxt_epoll_level_create, nxt_epoll_free, @@ -207,187 +202,164 @@ const nxt_event_interface_t nxt_epoll_level_engine = { #endif }; - #if (NXT_HAVE_EPOLL_EDGE) -static nxt_int_t -nxt_epoll_edge_create(nxt_event_engine_t *engine, nxt_uint_t mchanges, - nxt_uint_t mevents) -{ - return nxt_epoll_create(engine, mchanges, mevents, &nxt_epoll_edge_conn_io, - EPOLLET | EPOLLRDHUP); +static nxt_int_t nxt_epoll_edge_create(nxt_event_engine_t *engine, + nxt_uint_t mchanges, + nxt_uint_t mevents) { + return nxt_epoll_create(engine, mchanges, mevents, &nxt_epoll_edge_conn_io, + EPOLLET | EPOLLRDHUP); } #endif - -static nxt_int_t -nxt_epoll_level_create(nxt_event_engine_t *engine, nxt_uint_t mchanges, - nxt_uint_t mevents) -{ - return nxt_epoll_create(engine, mchanges, mevents, - &nxt_unix_conn_io, 0); +static nxt_int_t nxt_epoll_level_create(nxt_event_engine_t *engine, + nxt_uint_t mchanges, + nxt_uint_t mevents) { + return nxt_epoll_create(engine, mchanges, mevents, &nxt_unix_conn_io, 0); } - -static nxt_int_t -nxt_epoll_create(nxt_event_engine_t *engine, nxt_uint_t mchanges, - nxt_uint_t mevents, nxt_conn_io_t *io, uint32_t mode) -{ - engine->u.epoll.fd = -1; - engine->u.epoll.mode = mode; - engine->u.epoll.mchanges = mchanges; - engine->u.epoll.mevents = mevents; +static nxt_int_t nxt_epoll_create(nxt_event_engine_t *engine, + nxt_uint_t mchanges, nxt_uint_t mevents, + nxt_conn_io_t *io, uint32_t mode) { + engine->u.epoll.fd = -1; + engine->u.epoll.mode = mode; + engine->u.epoll.mchanges = mchanges; + engine->u.epoll.mevents = mevents; #if (NXT_HAVE_SIGNALFD) - engine->u.epoll.signalfd.fd = -1; + engine->u.epoll.signalfd.fd = -1; #endif - engine->u.epoll.changes = nxt_malloc(sizeof(nxt_epoll_change_t) * mchanges); - if (engine->u.epoll.changes == NULL) { - goto fail; - } + engine->u.epoll.changes = nxt_malloc(sizeof(nxt_epoll_change_t) * mchanges); + if (engine->u.epoll.changes == NULL) { + goto fail; + } - engine->u.epoll.events = nxt_malloc(sizeof(struct epoll_event) * mevents); - if (engine->u.epoll.events == NULL) { - goto fail; - } + engine->u.epoll.events = nxt_malloc(sizeof(struct epoll_event) * mevents); + if (engine->u.epoll.events == NULL) { + goto fail; + } - engine->u.epoll.fd = epoll_create(1); - if (engine->u.epoll.fd == -1) { - nxt_alert(&engine->task, "epoll_create() failed %E", nxt_errno); - goto fail; - } + engine->u.epoll.fd = epoll_create(1); + if (engine->u.epoll.fd == -1) { + nxt_alert(&engine->task, "epoll_create() failed %E", nxt_errno); + goto fail; + } - nxt_debug(&engine->task, "epoll_create(): %d", engine->u.epoll.fd); + nxt_debug(&engine->task, "epoll_create(): %d", engine->u.epoll.fd); - if (engine->signals != NULL) { + if (engine->signals != NULL) { #if (NXT_HAVE_SIGNALFD) - if (nxt_epoll_add_signal(engine) != NXT_OK) { - goto fail; - } + if (nxt_epoll_add_signal(engine) != NXT_OK) { + goto fail; + } #endif - nxt_epoll_test_accept4(engine, io); - } + nxt_epoll_test_accept4(engine, io); + } - return NXT_OK; + return NXT_OK; fail: - nxt_epoll_free(engine); + nxt_epoll_free(engine); - return NXT_ERROR; + return NXT_ERROR; } +static void nxt_epoll_test_accept4(nxt_event_engine_t *engine, + nxt_conn_io_t *io) { + static nxt_work_handler_t handler; -static void -nxt_epoll_test_accept4(nxt_event_engine_t *engine, nxt_conn_io_t *io) -{ - static nxt_work_handler_t handler; - - if (handler == NULL) { + if (handler == NULL) { - handler = io->accept; + handler = io->accept; #if (NXT_HAVE_ACCEPT4) - (void) accept4(-1, NULL, NULL, SOCK_NONBLOCK); + (void)accept4(-1, NULL, NULL, SOCK_NONBLOCK); - if (nxt_errno != NXT_ENOSYS) { - handler = nxt_epoll_conn_io_accept4; + if (nxt_errno != NXT_ENOSYS) { + handler = nxt_epoll_conn_io_accept4; - } else { - nxt_log(&engine->task, NXT_LOG_INFO, "accept4() failed %E", - NXT_ENOSYS); - } + } else { + nxt_log(&engine->task, NXT_LOG_INFO, "accept4() failed %E", NXT_ENOSYS); + } #endif - } + } - io->accept = handler; + io->accept = handler; } +static void nxt_epoll_free(nxt_event_engine_t *engine) { + int fd; -static void -nxt_epoll_free(nxt_event_engine_t *engine) -{ - int fd; - - nxt_debug(&engine->task, "epoll %d free", engine->u.epoll.fd); + nxt_debug(&engine->task, "epoll %d free", engine->u.epoll.fd); #if (NXT_HAVE_SIGNALFD) - fd = engine->u.epoll.signalfd.fd; + fd = engine->u.epoll.signalfd.fd; - if (fd != -1 && close(fd) != 0) { - nxt_alert(&engine->task, "signalfd close(%d) failed %E", fd, nxt_errno); - } + if (fd != -1 && close(fd) != 0) { + nxt_alert(&engine->task, "signalfd close(%d) failed %E", fd, nxt_errno); + } #endif #if (NXT_HAVE_EVENTFD) - fd = engine->u.epoll.eventfd.fd; + fd = engine->u.epoll.eventfd.fd; - if (fd != -1 && close(fd) != 0) { - nxt_alert(&engine->task, "eventfd close(%d) failed %E", fd, nxt_errno); - } + if (fd != -1 && close(fd) != 0) { + nxt_alert(&engine->task, "eventfd close(%d) failed %E", fd, nxt_errno); + } #endif - fd = engine->u.epoll.fd; + fd = engine->u.epoll.fd; - if (fd != -1 && close(fd) != 0) { - nxt_alert(&engine->task, "epoll close(%d) failed %E", fd, nxt_errno); - } + if (fd != -1 && close(fd) != 0) { + nxt_alert(&engine->task, "epoll close(%d) failed %E", fd, nxt_errno); + } - nxt_free(engine->u.epoll.events); - nxt_free(engine->u.epoll.changes); + nxt_free(engine->u.epoll.events); + nxt_free(engine->u.epoll.changes); - nxt_memzero(&engine->u.epoll, sizeof(nxt_epoll_engine_t)); + nxt_memzero(&engine->u.epoll, sizeof(nxt_epoll_engine_t)); } +static void nxt_epoll_enable(nxt_event_engine_t *engine, nxt_fd_event_t *ev) { + ev->read = NXT_EVENT_ACTIVE; + ev->write = NXT_EVENT_ACTIVE; -static void -nxt_epoll_enable(nxt_event_engine_t *engine, nxt_fd_event_t *ev) -{ - ev->read = NXT_EVENT_ACTIVE; - ev->write = NXT_EVENT_ACTIVE; - - nxt_epoll_change(engine, ev, EPOLL_CTL_ADD, - EPOLLIN | EPOLLOUT | engine->u.epoll.mode); + nxt_epoll_change(engine, ev, EPOLL_CTL_ADD, + EPOLLIN | EPOLLOUT | engine->u.epoll.mode); } +static void nxt_epoll_disable(nxt_event_engine_t *engine, nxt_fd_event_t *ev) { + if (ev->read > NXT_EVENT_DISABLED || ev->write > NXT_EVENT_DISABLED) { -static void -nxt_epoll_disable(nxt_event_engine_t *engine, nxt_fd_event_t *ev) -{ - if (ev->read > NXT_EVENT_DISABLED || ev->write > NXT_EVENT_DISABLED) { - - ev->read = NXT_EVENT_INACTIVE; - ev->write = NXT_EVENT_INACTIVE; + ev->read = NXT_EVENT_INACTIVE; + ev->write = NXT_EVENT_INACTIVE; - nxt_epoll_change(engine, ev, EPOLL_CTL_DEL, 0); - } + nxt_epoll_change(engine, ev, EPOLL_CTL_DEL, 0); + } } +static void nxt_epoll_delete(nxt_event_engine_t *engine, nxt_fd_event_t *ev) { + if (ev->read != NXT_EVENT_INACTIVE || ev->write != NXT_EVENT_INACTIVE) { -static void -nxt_epoll_delete(nxt_event_engine_t *engine, nxt_fd_event_t *ev) -{ - if (ev->read != NXT_EVENT_INACTIVE || ev->write != NXT_EVENT_INACTIVE) { - - ev->read = NXT_EVENT_INACTIVE; - ev->write = NXT_EVENT_INACTIVE; + ev->read = NXT_EVENT_INACTIVE; + ev->write = NXT_EVENT_INACTIVE; - nxt_epoll_change(engine, ev, EPOLL_CTL_DEL, 0); - } + nxt_epoll_change(engine, ev, EPOLL_CTL_DEL, 0); + } } - /* * Although calling close() on a file descriptor will remove any epoll * events that reference the descriptor, in this case the close() acquires @@ -397,127 +369,113 @@ nxt_epoll_delete(nxt_event_engine_t *engine, nxt_fd_event_t *ev) * eliminates possible lock contention. */ -static nxt_bool_t -nxt_epoll_close(nxt_event_engine_t *engine, nxt_fd_event_t *ev) -{ - nxt_epoll_delete(engine, ev); +static nxt_bool_t nxt_epoll_close(nxt_event_engine_t *engine, + nxt_fd_event_t *ev) { + nxt_epoll_delete(engine, ev); - return ev->changing; + return ev->changing; } +static void nxt_epoll_enable_read(nxt_event_engine_t *engine, + nxt_fd_event_t *ev) { + int op; + uint32_t events; -static void -nxt_epoll_enable_read(nxt_event_engine_t *engine, nxt_fd_event_t *ev) -{ - int op; - uint32_t events; - - if (ev->read != NXT_EVENT_BLOCKED) { + if (ev->read != NXT_EVENT_BLOCKED) { - op = EPOLL_CTL_MOD; - events = EPOLLIN | engine->u.epoll.mode; + op = EPOLL_CTL_MOD; + events = EPOLLIN | engine->u.epoll.mode; - if (ev->read == NXT_EVENT_INACTIVE && ev->write == NXT_EVENT_INACTIVE) { - op = EPOLL_CTL_ADD; + if (ev->read == NXT_EVENT_INACTIVE && ev->write == NXT_EVENT_INACTIVE) { + op = EPOLL_CTL_ADD; - } else if (ev->write >= NXT_EVENT_BLOCKED) { - events |= EPOLLOUT; - } - - nxt_epoll_change(engine, ev, op, events); + } else if (ev->write >= NXT_EVENT_BLOCKED) { + events |= EPOLLOUT; } - ev->read = NXT_EVENT_ACTIVE; -} + nxt_epoll_change(engine, ev, op, events); + } + ev->read = NXT_EVENT_ACTIVE; +} -static void -nxt_epoll_enable_write(nxt_event_engine_t *engine, nxt_fd_event_t *ev) -{ - int op; - uint32_t events; +static void nxt_epoll_enable_write(nxt_event_engine_t *engine, + nxt_fd_event_t *ev) { + int op; + uint32_t events; - if (ev->write != NXT_EVENT_BLOCKED) { + if (ev->write != NXT_EVENT_BLOCKED) { - op = EPOLL_CTL_MOD; - events = EPOLLOUT | engine->u.epoll.mode; + op = EPOLL_CTL_MOD; + events = EPOLLOUT | engine->u.epoll.mode; - if (ev->read == NXT_EVENT_INACTIVE && ev->write == NXT_EVENT_INACTIVE) { - op = EPOLL_CTL_ADD; + if (ev->read == NXT_EVENT_INACTIVE && ev->write == NXT_EVENT_INACTIVE) { + op = EPOLL_CTL_ADD; - } else if (ev->read >= NXT_EVENT_BLOCKED) { - events |= EPOLLIN; - } - - nxt_epoll_change(engine, ev, op, events); + } else if (ev->read >= NXT_EVENT_BLOCKED) { + events |= EPOLLIN; } - ev->write = NXT_EVENT_ACTIVE; -} + nxt_epoll_change(engine, ev, op, events); + } + ev->write = NXT_EVENT_ACTIVE; +} -static void -nxt_epoll_disable_read(nxt_event_engine_t *engine, nxt_fd_event_t *ev) -{ - int op; - uint32_t events; +static void nxt_epoll_disable_read(nxt_event_engine_t *engine, + nxt_fd_event_t *ev) { + int op; + uint32_t events; - ev->read = NXT_EVENT_INACTIVE; + ev->read = NXT_EVENT_INACTIVE; - if (ev->write <= NXT_EVENT_DISABLED) { - ev->write = NXT_EVENT_INACTIVE; - op = EPOLL_CTL_DEL; - events = 0; + if (ev->write <= NXT_EVENT_DISABLED) { + ev->write = NXT_EVENT_INACTIVE; + op = EPOLL_CTL_DEL; + events = 0; - } else { - op = EPOLL_CTL_MOD; - events = EPOLLOUT | engine->u.epoll.mode; - } + } else { + op = EPOLL_CTL_MOD; + events = EPOLLOUT | engine->u.epoll.mode; + } - nxt_epoll_change(engine, ev, op, events); + nxt_epoll_change(engine, ev, op, events); } +static void nxt_epoll_disable_write(nxt_event_engine_t *engine, + nxt_fd_event_t *ev) { + int op; + uint32_t events; -static void -nxt_epoll_disable_write(nxt_event_engine_t *engine, nxt_fd_event_t *ev) -{ - int op; - uint32_t events; - - ev->write = NXT_EVENT_INACTIVE; + ev->write = NXT_EVENT_INACTIVE; - if (ev->read <= NXT_EVENT_DISABLED) { - ev->read = NXT_EVENT_INACTIVE; - op = EPOLL_CTL_DEL; - events = 0; + if (ev->read <= NXT_EVENT_DISABLED) { + ev->read = NXT_EVENT_INACTIVE; + op = EPOLL_CTL_DEL; + events = 0; - } else { - op = EPOLL_CTL_MOD; - events = EPOLLIN | engine->u.epoll.mode; - } + } else { + op = EPOLL_CTL_MOD; + events = EPOLLIN | engine->u.epoll.mode; + } - nxt_epoll_change(engine, ev, op, events); + nxt_epoll_change(engine, ev, op, events); } - -static void -nxt_epoll_block_read(nxt_event_engine_t *engine, nxt_fd_event_t *ev) -{ - if (ev->read != NXT_EVENT_INACTIVE) { - ev->read = NXT_EVENT_BLOCKED; - } +static void nxt_epoll_block_read(nxt_event_engine_t *engine, + nxt_fd_event_t *ev) { + if (ev->read != NXT_EVENT_INACTIVE) { + ev->read = NXT_EVENT_BLOCKED; + } } - -static void -nxt_epoll_block_write(nxt_event_engine_t *engine, nxt_fd_event_t *ev) -{ - if (ev->write != NXT_EVENT_INACTIVE) { - ev->write = NXT_EVENT_BLOCKED; - } +static void nxt_epoll_block_write(nxt_event_engine_t *engine, + nxt_fd_event_t *ev) { + if (ev->write != NXT_EVENT_INACTIVE) { + ev->write = NXT_EVENT_BLOCKED; + } } - /* * NXT_EVENT_DISABLED state is used to track whether EPOLLONESHOT * event should be added or modified, epoll_ctl(2): @@ -531,517 +489,482 @@ nxt_epoll_block_write(nxt_event_engine_t *engine, nxt_fd_event_t *ev) * descriptor with a new event mask. */ -static void -nxt_epoll_oneshot_read(nxt_event_engine_t *engine, nxt_fd_event_t *ev) -{ - int op; +static void nxt_epoll_oneshot_read(nxt_event_engine_t *engine, + nxt_fd_event_t *ev) { + int op; - op = (ev->read == NXT_EVENT_INACTIVE && ev->write == NXT_EVENT_INACTIVE) ? - EPOLL_CTL_ADD : EPOLL_CTL_MOD; + op = (ev->read == NXT_EVENT_INACTIVE && ev->write == NXT_EVENT_INACTIVE) + ? EPOLL_CTL_ADD + : EPOLL_CTL_MOD; - ev->read = NXT_EVENT_ONESHOT; - ev->write = NXT_EVENT_INACTIVE; + ev->read = NXT_EVENT_ONESHOT; + ev->write = NXT_EVENT_INACTIVE; - nxt_epoll_change(engine, ev, op, EPOLLIN | EPOLLONESHOT); + nxt_epoll_change(engine, ev, op, EPOLLIN | EPOLLONESHOT); } +static void nxt_epoll_oneshot_write(nxt_event_engine_t *engine, + nxt_fd_event_t *ev) { + int op; -static void -nxt_epoll_oneshot_write(nxt_event_engine_t *engine, nxt_fd_event_t *ev) -{ - int op; - - op = (ev->read == NXT_EVENT_INACTIVE && ev->write == NXT_EVENT_INACTIVE) ? - EPOLL_CTL_ADD : EPOLL_CTL_MOD; + op = (ev->read == NXT_EVENT_INACTIVE && ev->write == NXT_EVENT_INACTIVE) + ? EPOLL_CTL_ADD + : EPOLL_CTL_MOD; - ev->read = NXT_EVENT_INACTIVE; - ev->write = NXT_EVENT_ONESHOT; + ev->read = NXT_EVENT_INACTIVE; + ev->write = NXT_EVENT_ONESHOT; - nxt_epoll_change(engine, ev, op, EPOLLOUT | EPOLLONESHOT); + nxt_epoll_change(engine, ev, op, EPOLLOUT | EPOLLONESHOT); } +static void nxt_epoll_enable_accept(nxt_event_engine_t *engine, + nxt_fd_event_t *ev) { + uint32_t events; -static void -nxt_epoll_enable_accept(nxt_event_engine_t *engine, nxt_fd_event_t *ev) -{ - uint32_t events; - - ev->read = NXT_EVENT_ACTIVE; + ev->read = NXT_EVENT_ACTIVE; - events = EPOLLIN; + events = EPOLLIN; #ifdef EPOLLEXCLUSIVE - events |= EPOLLEXCLUSIVE; + events |= EPOLLEXCLUSIVE; #endif - nxt_epoll_change(engine, ev, EPOLL_CTL_ADD, events); + nxt_epoll_change(engine, ev, EPOLL_CTL_ADD, events); } - /* * epoll changes are batched to improve instruction and data cache * locality of several epoll_ctl() calls followed by epoll_wait() call. */ -static void -nxt_epoll_change(nxt_event_engine_t *engine, nxt_fd_event_t *ev, int op, - uint32_t events) -{ - nxt_epoll_change_t *change; +static void nxt_epoll_change(nxt_event_engine_t *engine, nxt_fd_event_t *ev, + int op, uint32_t events) { + nxt_epoll_change_t *change; - nxt_debug(ev->task, "epoll %d set event: fd:%d op:%d ev:%XD", - engine->u.epoll.fd, ev->fd, op, events); + nxt_debug(ev->task, "epoll %d set event: fd:%d op:%d ev:%XD", + engine->u.epoll.fd, ev->fd, op, events); - if (engine->u.epoll.nchanges >= engine->u.epoll.mchanges) { - nxt_epoll_commit_changes(engine); - } + if (engine->u.epoll.nchanges >= engine->u.epoll.mchanges) { + nxt_epoll_commit_changes(engine); + } - ev->changing = 1; + ev->changing = 1; - change = &engine->u.epoll.changes[engine->u.epoll.nchanges++]; - change->op = op; - change->event.events = events; - change->event.data.ptr = ev; + change = &engine->u.epoll.changes[engine->u.epoll.nchanges++]; + change->op = op; + change->event.events = events; + change->event.data.ptr = ev; } +static void nxt_epoll_commit_changes(nxt_event_engine_t *engine) { + int ret; + nxt_fd_event_t *ev; + nxt_epoll_change_t *change, *end; -static void -nxt_epoll_commit_changes(nxt_event_engine_t *engine) -{ - int ret; - nxt_fd_event_t *ev; - nxt_epoll_change_t *change, *end; - - nxt_debug(&engine->task, "epoll %d changes:%ui", - engine->u.epoll.fd, engine->u.epoll.nchanges); + nxt_debug(&engine->task, "epoll %d changes:%ui", engine->u.epoll.fd, + engine->u.epoll.nchanges); - change = engine->u.epoll.changes; - end = change + engine->u.epoll.nchanges; + change = engine->u.epoll.changes; + end = change + engine->u.epoll.nchanges; - do { - ev = change->event.data.ptr; - ev->changing = 0; + do { + ev = change->event.data.ptr; + ev->changing = 0; - nxt_debug(ev->task, "epoll_ctl(%d): fd:%d op:%d ev:%XD", - engine->u.epoll.fd, ev->fd, change->op, - change->event.events); + nxt_debug(ev->task, "epoll_ctl(%d): fd:%d op:%d ev:%XD", engine->u.epoll.fd, + ev->fd, change->op, change->event.events); - ret = epoll_ctl(engine->u.epoll.fd, change->op, ev->fd, &change->event); + ret = epoll_ctl(engine->u.epoll.fd, change->op, ev->fd, &change->event); - if (nxt_slow_path(ret != 0)) { - nxt_alert(ev->task, "epoll_ctl(%d, %d, %d) failed %E", - engine->u.epoll.fd, change->op, ev->fd, nxt_errno); + if (nxt_slow_path(ret != 0)) { + nxt_alert(ev->task, "epoll_ctl(%d, %d, %d) failed %E", engine->u.epoll.fd, + change->op, ev->fd, nxt_errno); - nxt_work_queue_add(&engine->fast_work_queue, - nxt_epoll_error_handler, ev->task, ev, ev->data); + nxt_work_queue_add(&engine->fast_work_queue, nxt_epoll_error_handler, + ev->task, ev, ev->data); - engine->u.epoll.error = 1; - } + engine->u.epoll.error = 1; + } - change++; + change++; - } while (change < end); + } while (change < end); - engine->u.epoll.nchanges = 0; + engine->u.epoll.nchanges = 0; } +static void nxt_epoll_error_handler(nxt_task_t *task, void *obj, void *data) { + nxt_fd_event_t *ev; -static void -nxt_epoll_error_handler(nxt_task_t *task, void *obj, void *data) -{ - nxt_fd_event_t *ev; + ev = obj; - ev = obj; + ev->read = NXT_EVENT_INACTIVE; + ev->write = NXT_EVENT_INACTIVE; - ev->read = NXT_EVENT_INACTIVE; - ev->write = NXT_EVENT_INACTIVE; - - ev->error_handler(ev->task, ev, data); + ev->error_handler(ev->task, ev, data); } - #if (NXT_HAVE_SIGNALFD) -static nxt_int_t -nxt_epoll_add_signal(nxt_event_engine_t *engine) -{ - int fd; - struct epoll_event ee; - - if (sigprocmask(SIG_BLOCK, &engine->signals->sigmask, NULL) != 0) { - nxt_alert(&engine->task, "sigprocmask(SIG_BLOCK) failed %E", nxt_errno); - return NXT_ERROR; - } +static nxt_int_t nxt_epoll_add_signal(nxt_event_engine_t *engine) { + int fd; + struct epoll_event ee; - /* - * Glibc signalfd() wrapper always has the flags argument. Glibc 2.7 - * and 2.8 signalfd() wrappers call the original signalfd() syscall - * without the flags argument. Glibc 2.9+ signalfd() wrapper at first - * tries to call signalfd4() syscall and if it fails then calls the - * original signalfd() syscall. For this reason the non-blocking mode - * is set separately. - */ - - fd = signalfd(-1, &engine->signals->sigmask, 0); - - if (fd == -1) { - nxt_alert(&engine->task, "signalfd(%d) failed %E", - engine->u.epoll.signalfd.fd, nxt_errno); - return NXT_ERROR; - } + if (sigprocmask(SIG_BLOCK, &engine->signals->sigmask, NULL) != 0) { + nxt_alert(&engine->task, "sigprocmask(SIG_BLOCK) failed %E", nxt_errno); + return NXT_ERROR; + } + + /* + * Glibc signalfd() wrapper always has the flags argument. Glibc 2.7 + * and 2.8 signalfd() wrappers call the original signalfd() syscall + * without the flags argument. Glibc 2.9+ signalfd() wrapper at first + * tries to call signalfd4() syscall and if it fails then calls the + * original signalfd() syscall. For this reason the non-blocking mode + * is set separately. + */ + + fd = signalfd(-1, &engine->signals->sigmask, 0); + + if (fd == -1) { + nxt_alert(&engine->task, "signalfd(%d) failed %E", + engine->u.epoll.signalfd.fd, nxt_errno); + return NXT_ERROR; + } - engine->u.epoll.signalfd.fd = fd; + engine->u.epoll.signalfd.fd = fd; - if (nxt_fd_nonblocking(&engine->task, fd) != NXT_OK) { - return NXT_ERROR; - } + if (nxt_fd_nonblocking(&engine->task, fd) != NXT_OK) { + return NXT_ERROR; + } - nxt_debug(&engine->task, "signalfd(): %d", fd); + nxt_debug(&engine->task, "signalfd(): %d", fd); - engine->u.epoll.signalfd.data = engine->signals->handler; - engine->u.epoll.signalfd.read_work_queue = &engine->fast_work_queue; - engine->u.epoll.signalfd.read_handler = nxt_epoll_signalfd_handler; - engine->u.epoll.signalfd.log = engine->task.log; - engine->u.epoll.signalfd.task = &engine->task; + engine->u.epoll.signalfd.data = engine->signals->handler; + engine->u.epoll.signalfd.read_work_queue = &engine->fast_work_queue; + engine->u.epoll.signalfd.read_handler = nxt_epoll_signalfd_handler; + engine->u.epoll.signalfd.log = engine->task.log; + engine->u.epoll.signalfd.task = &engine->task; - ee.events = EPOLLIN; - ee.data.ptr = &engine->u.epoll.signalfd; + ee.events = EPOLLIN; + ee.data.ptr = &engine->u.epoll.signalfd; - if (epoll_ctl(engine->u.epoll.fd, EPOLL_CTL_ADD, fd, &ee) != 0) { - nxt_alert(&engine->task, "epoll_ctl(%d, %d, %d) failed %E", - engine->u.epoll.fd, EPOLL_CTL_ADD, fd, nxt_errno); + if (epoll_ctl(engine->u.epoll.fd, EPOLL_CTL_ADD, fd, &ee) != 0) { + nxt_alert(&engine->task, "epoll_ctl(%d, %d, %d) failed %E", + engine->u.epoll.fd, EPOLL_CTL_ADD, fd, nxt_errno); - return NXT_ERROR; - } + return NXT_ERROR; + } - return NXT_OK; + return NXT_OK; } +static void nxt_epoll_signalfd_handler(nxt_task_t *task, void *obj, + void *data) { + int n; + nxt_fd_event_t *ev; + nxt_work_handler_t handler; + struct signalfd_siginfo sfd; -static void -nxt_epoll_signalfd_handler(nxt_task_t *task, void *obj, void *data) -{ - int n; - nxt_fd_event_t *ev; - nxt_work_handler_t handler; - struct signalfd_siginfo sfd; + ev = obj; + handler = data; - ev = obj; - handler = data; + nxt_debug(task, "signalfd handler"); - nxt_debug(task, "signalfd handler"); + n = read(ev->fd, &sfd, sizeof(struct signalfd_siginfo)); - n = read(ev->fd, &sfd, sizeof(struct signalfd_siginfo)); + nxt_debug(task, "read signalfd(%d): %d", ev->fd, n); - nxt_debug(task, "read signalfd(%d): %d", ev->fd, n); + if (n != sizeof(struct signalfd_siginfo)) { + nxt_alert(task, "read signalfd(%d) failed %E", ev->fd, nxt_errno); + return; + } - if (n != sizeof(struct signalfd_siginfo)) { - nxt_alert(task, "read signalfd(%d) failed %E", ev->fd, nxt_errno); - return; - } + nxt_debug(task, "signalfd(%d) signo:%d", ev->fd, sfd.ssi_signo); - nxt_debug(task, "signalfd(%d) signo:%d", ev->fd, sfd.ssi_signo); - - handler(task, (void *) (uintptr_t) sfd.ssi_signo, NULL); + handler(task, (void *)(uintptr_t)sfd.ssi_signo, NULL); } #endif - #if (NXT_HAVE_EVENTFD) -static nxt_int_t -nxt_epoll_enable_post(nxt_event_engine_t *engine, nxt_work_handler_t handler) -{ - int ret; - struct epoll_event ee; +static nxt_int_t nxt_epoll_enable_post(nxt_event_engine_t *engine, + nxt_work_handler_t handler) { + int ret; + struct epoll_event ee; - engine->u.epoll.post_handler = handler; + engine->u.epoll.post_handler = handler; - /* - * Glibc eventfd() wrapper always has the flags argument. Glibc 2.7 - * and 2.8 eventfd() wrappers call the original eventfd() syscall - * without the flags argument. Glibc 2.9+ eventfd() wrapper at first - * tries to call eventfd2() syscall and if it fails then calls the - * original eventfd() syscall. For this reason the non-blocking mode - * is set separately. - */ + /* + * Glibc eventfd() wrapper always has the flags argument. Glibc 2.7 + * and 2.8 eventfd() wrappers call the original eventfd() syscall + * without the flags argument. Glibc 2.9+ eventfd() wrapper at first + * tries to call eventfd2() syscall and if it fails then calls the + * original eventfd() syscall. For this reason the non-blocking mode + * is set separately. + */ - engine->u.epoll.eventfd.fd = eventfd(0, 0); + engine->u.epoll.eventfd.fd = eventfd(0, 0); - if (engine->u.epoll.eventfd.fd == -1) { - nxt_alert(&engine->task, "eventfd() failed %E", nxt_errno); - return NXT_ERROR; - } + if (engine->u.epoll.eventfd.fd == -1) { + nxt_alert(&engine->task, "eventfd() failed %E", nxt_errno); + return NXT_ERROR; + } - ret = nxt_fd_nonblocking(&engine->task, engine->u.epoll.eventfd.fd); - if (nxt_slow_path(ret != NXT_OK)) { - return NXT_ERROR; - } + ret = nxt_fd_nonblocking(&engine->task, engine->u.epoll.eventfd.fd); + if (nxt_slow_path(ret != NXT_OK)) { + return NXT_ERROR; + } - nxt_debug(&engine->task, "eventfd(): %d", engine->u.epoll.eventfd.fd); + nxt_debug(&engine->task, "eventfd(): %d", engine->u.epoll.eventfd.fd); - engine->u.epoll.eventfd.read_work_queue = &engine->fast_work_queue; - engine->u.epoll.eventfd.read_handler = nxt_epoll_eventfd_handler; - engine->u.epoll.eventfd.data = engine; - engine->u.epoll.eventfd.log = engine->task.log; - engine->u.epoll.eventfd.task = &engine->task; + engine->u.epoll.eventfd.read_work_queue = &engine->fast_work_queue; + engine->u.epoll.eventfd.read_handler = nxt_epoll_eventfd_handler; + engine->u.epoll.eventfd.data = engine; + engine->u.epoll.eventfd.log = engine->task.log; + engine->u.epoll.eventfd.task = &engine->task; - ee.events = EPOLLIN | EPOLLET; - ee.data.ptr = &engine->u.epoll.eventfd; + ee.events = EPOLLIN | EPOLLET; + ee.data.ptr = &engine->u.epoll.eventfd; - ret = epoll_ctl(engine->u.epoll.fd, EPOLL_CTL_ADD, - engine->u.epoll.eventfd.fd, &ee); + ret = epoll_ctl(engine->u.epoll.fd, EPOLL_CTL_ADD, engine->u.epoll.eventfd.fd, + &ee); - if (nxt_fast_path(ret == 0)) { - return NXT_OK; - } + if (nxt_fast_path(ret == 0)) { + return NXT_OK; + } - nxt_alert(&engine->task, "epoll_ctl(%d, %d, %d) failed %E", - engine->u.epoll.fd, EPOLL_CTL_ADD, engine->u.epoll.eventfd.fd, - nxt_errno); + nxt_alert(&engine->task, "epoll_ctl(%d, %d, %d) failed %E", + engine->u.epoll.fd, EPOLL_CTL_ADD, engine->u.epoll.eventfd.fd, + nxt_errno); - return NXT_ERROR; + return NXT_ERROR; } +static void nxt_epoll_eventfd_handler(nxt_task_t *task, void *obj, void *data) { + int n; + uint64_t events; + nxt_event_engine_t *engine; -static void -nxt_epoll_eventfd_handler(nxt_task_t *task, void *obj, void *data) -{ - int n; - uint64_t events; - nxt_event_engine_t *engine; + engine = data; - engine = data; + nxt_debug(task, "eventfd handler, times:%ui", engine->u.epoll.neventfd); - nxt_debug(task, "eventfd handler, times:%ui", engine->u.epoll.neventfd); + /* + * The maximum value after write() to a eventfd() descriptor will + * block or return EAGAIN is 0xFFFFFFFFFFFFFFFE, so the descriptor + * can be read once per many notifications, for example, once per + * 2^32-2 noticifcations. Since the eventfd() file descriptor is + * always registered in EPOLLET mode, epoll returns event about + * only the latest write() to the descriptor. + */ - /* - * The maximum value after write() to a eventfd() descriptor will - * block or return EAGAIN is 0xFFFFFFFFFFFFFFFE, so the descriptor - * can be read once per many notifications, for example, once per - * 2^32-2 noticifcations. Since the eventfd() file descriptor is - * always registered in EPOLLET mode, epoll returns event about - * only the latest write() to the descriptor. - */ - - if (engine->u.epoll.neventfd++ >= 0xFFFFFFFE) { - engine->u.epoll.neventfd = 0; + if (engine->u.epoll.neventfd++ >= 0xFFFFFFFE) { + engine->u.epoll.neventfd = 0; - n = read(engine->u.epoll.eventfd.fd, &events, sizeof(uint64_t)); + n = read(engine->u.epoll.eventfd.fd, &events, sizeof(uint64_t)); - nxt_debug(task, "read(%d): %d events:%uL", - engine->u.epoll.eventfd.fd, n, events); + nxt_debug(task, "read(%d): %d events:%uL", engine->u.epoll.eventfd.fd, n, + events); - if (n != sizeof(uint64_t)) { - nxt_alert(task, "read eventfd(%d) failed %E", - engine->u.epoll.eventfd.fd, nxt_errno); - } + if (n != sizeof(uint64_t)) { + nxt_alert(task, "read eventfd(%d) failed %E", engine->u.epoll.eventfd.fd, + nxt_errno); } + } - engine->u.epoll.post_handler(task, NULL, NULL); + engine->u.epoll.post_handler(task, NULL, NULL); } +static void nxt_epoll_signal(nxt_event_engine_t *engine, nxt_uint_t signo) { + size_t ret; + uint64_t event; -static void -nxt_epoll_signal(nxt_event_engine_t *engine, nxt_uint_t signo) -{ - size_t ret; - uint64_t event; + /* + * eventfd() presents along with signalfd(), so the function + * is used only to post events and the signo argument is ignored. + */ - /* - * eventfd() presents along with signalfd(), so the function - * is used only to post events and the signo argument is ignored. - */ + event = 1; - event = 1; + ret = write(engine->u.epoll.eventfd.fd, &event, sizeof(uint64_t)); - ret = write(engine->u.epoll.eventfd.fd, &event, sizeof(uint64_t)); - - if (nxt_slow_path(ret != sizeof(uint64_t))) { - nxt_alert(&engine->task, "write(%d) to eventfd failed %E", - engine->u.epoll.eventfd.fd, nxt_errno); - } + if (nxt_slow_path(ret != sizeof(uint64_t))) { + nxt_alert(&engine->task, "write(%d) to eventfd failed %E", + engine->u.epoll.eventfd.fd, nxt_errno); + } } #endif +static void nxt_epoll_poll(nxt_event_engine_t *engine, nxt_msec_t timeout) { + int nevents; + uint32_t events; + nxt_int_t i; + nxt_err_t err; + nxt_bool_t error; + nxt_uint_t level; + nxt_fd_event_t *ev; + struct epoll_event *event; -static void -nxt_epoll_poll(nxt_event_engine_t *engine, nxt_msec_t timeout) -{ - int nevents; - uint32_t events; - nxt_int_t i; - nxt_err_t err; - nxt_bool_t error; - nxt_uint_t level; - nxt_fd_event_t *ev; - struct epoll_event *event; - - if (engine->u.epoll.nchanges != 0) { - nxt_epoll_commit_changes(engine); - } + if (engine->u.epoll.nchanges != 0) { + nxt_epoll_commit_changes(engine); + } - if (engine->u.epoll.error) { - engine->u.epoll.error = 0; - /* Error handlers have been enqueued on failure. */ - timeout = 0; - } + if (engine->u.epoll.error) { + engine->u.epoll.error = 0; + /* Error handlers have been enqueued on failure. */ + timeout = 0; + } - nxt_debug(&engine->task, "epoll_wait(%d) timeout:%M", - engine->u.epoll.fd, timeout); + nxt_debug(&engine->task, "epoll_wait(%d) timeout:%M", engine->u.epoll.fd, + timeout); - nevents = epoll_wait(engine->u.epoll.fd, engine->u.epoll.events, - engine->u.epoll.mevents, timeout); + nevents = epoll_wait(engine->u.epoll.fd, engine->u.epoll.events, + engine->u.epoll.mevents, timeout); - err = (nevents == -1) ? nxt_errno : 0; + err = (nevents == -1) ? nxt_errno : 0; - nxt_thread_time_update(engine->task.thread); + nxt_thread_time_update(engine->task.thread); - nxt_debug(&engine->task, "epoll_wait(%d): %d", engine->u.epoll.fd, nevents); + nxt_debug(&engine->task, "epoll_wait(%d): %d", engine->u.epoll.fd, nevents); - if (nevents == -1) { - level = (err == NXT_EINTR) ? NXT_LOG_INFO : NXT_LOG_ALERT; + if (nevents == -1) { + level = (err == NXT_EINTR) ? NXT_LOG_INFO : NXT_LOG_ALERT; - nxt_log(&engine->task, level, "epoll_wait(%d) failed %E", - engine->u.epoll.fd, err); + nxt_log(&engine->task, level, "epoll_wait(%d) failed %E", + engine->u.epoll.fd, err); - return; - } + return; + } - for (i = 0; i < nevents; i++) { + for (i = 0; i < nevents; i++) { - event = &engine->u.epoll.events[i]; - events = event->events; - ev = event->data.ptr; + event = &engine->u.epoll.events[i]; + events = event->events; + ev = event->data.ptr; - nxt_debug(ev->task, "epoll: fd:%d ev:%04XD d:%p rd:%d wr:%d", - ev->fd, events, ev, ev->read, ev->write); + nxt_debug(ev->task, "epoll: fd:%d ev:%04XD d:%p rd:%d wr:%d", ev->fd, + events, ev, ev->read, ev->write); - /* - * On error epoll may set EPOLLERR and EPOLLHUP only without EPOLLIN - * or EPOLLOUT, so the "error" variable enqueues only error handler. - */ - error = ((events & (EPOLLERR | EPOLLHUP)) != 0); - ev->epoll_error = error; - - if (error - && ev->read <= NXT_EVENT_BLOCKED - && ev->write <= NXT_EVENT_BLOCKED) - { - error = 0; - } + /* + * On error epoll may set EPOLLERR and EPOLLHUP only without EPOLLIN + * or EPOLLOUT, so the "error" variable enqueues only error handler. + */ + error = ((events & (EPOLLERR | EPOLLHUP)) != 0); + ev->epoll_error = error; + + if (error && ev->read <= NXT_EVENT_BLOCKED && + ev->write <= NXT_EVENT_BLOCKED) { + error = 0; + } #if (NXT_HAVE_EPOLL_EDGE) - ev->epoll_eof = ((events & EPOLLRDHUP) != 0); + ev->epoll_eof = ((events & EPOLLRDHUP) != 0); #endif - if ((events & EPOLLIN) != 0) { - ev->read_ready = 1; - - if (ev->read != NXT_EVENT_BLOCKED) { - - if (ev->read == NXT_EVENT_ONESHOT) { - ev->read = NXT_EVENT_DISABLED; - } + if ((events & EPOLLIN) != 0) { + ev->read_ready = 1; - nxt_work_queue_add(ev->read_work_queue, ev->read_handler, - ev->task, ev, ev->data); + if (ev->read != NXT_EVENT_BLOCKED) { - error = 0; - - } else if (engine->u.epoll.mode == 0) { - /* Level-triggered mode. */ - nxt_epoll_disable_read(engine, ev); - } + if (ev->read == NXT_EVENT_ONESHOT) { + ev->read = NXT_EVENT_DISABLED; } - if ((events & EPOLLOUT) != 0) { - ev->write_ready = 1; + nxt_work_queue_add(ev->read_work_queue, ev->read_handler, ev->task, ev, + ev->data); - if (ev->write != NXT_EVENT_BLOCKED) { + error = 0; - if (ev->write == NXT_EVENT_ONESHOT) { - ev->write = NXT_EVENT_DISABLED; - } + } else if (engine->u.epoll.mode == 0) { + /* Level-triggered mode. */ + nxt_epoll_disable_read(engine, ev); + } + } - nxt_work_queue_add(ev->write_work_queue, ev->write_handler, - ev->task, ev, ev->data); + if ((events & EPOLLOUT) != 0) { + ev->write_ready = 1; - error = 0; + if (ev->write != NXT_EVENT_BLOCKED) { - } else if (engine->u.epoll.mode == 0) { - /* Level-triggered mode. */ - nxt_epoll_disable_write(engine, ev); - } + if (ev->write == NXT_EVENT_ONESHOT) { + ev->write = NXT_EVENT_DISABLED; } - if (!error) { - continue; - } + nxt_work_queue_add(ev->write_work_queue, ev->write_handler, ev->task, + ev, ev->data); + + error = 0; + + } else if (engine->u.epoll.mode == 0) { + /* Level-triggered mode. */ + nxt_epoll_disable_write(engine, ev); + } + } - ev->read_ready = 1; - ev->write_ready = 1; + if (!error) { + continue; + } - if (ev->read == NXT_EVENT_BLOCKED && ev->write == NXT_EVENT_BLOCKED) { + ev->read_ready = 1; + ev->write_ready = 1; - if (engine->u.epoll.mode == 0) { - /* Level-triggered mode. */ - nxt_epoll_disable(engine, ev); - } + if (ev->read == NXT_EVENT_BLOCKED && ev->write == NXT_EVENT_BLOCKED) { - continue; - } + if (engine->u.epoll.mode == 0) { + /* Level-triggered mode. */ + nxt_epoll_disable(engine, ev); + } - nxt_work_queue_add(&engine->fast_work_queue, nxt_epoll_error_handler, - ev->task, ev, ev->data); + continue; } -} + nxt_work_queue_add(&engine->fast_work_queue, nxt_epoll_error_handler, + ev->task, ev, ev->data); + } +} #if (NXT_HAVE_ACCEPT4) -static void -nxt_epoll_conn_io_accept4(nxt_task_t *task, void *obj, void *data) -{ - socklen_t socklen; - nxt_conn_t *c; - nxt_socket_t s; - struct sockaddr *sa; - nxt_listen_event_t *lev; +static void nxt_epoll_conn_io_accept4(nxt_task_t *task, void *obj, void *data) { + socklen_t socklen; + nxt_conn_t *c; + nxt_socket_t s; + struct sockaddr *sa; + nxt_listen_event_t *lev; - lev = obj; - c = lev->next; + lev = obj; + c = lev->next; - lev->ready--; - lev->socket.read_ready = (lev->ready != 0); + lev->ready--; + lev->socket.read_ready = (lev->ready != 0); - sa = &c->remote->u.sockaddr; - socklen = c->remote->socklen; - /* - * The returned socklen is ignored here, - * see comment in nxt_conn_io_accept(). - */ - s = accept4(lev->socket.fd, sa, &socklen, SOCK_NONBLOCK); + sa = &c->remote->u.sockaddr; + socklen = c->remote->socklen; + /* + * The returned socklen is ignored here, + * see comment in nxt_conn_io_accept(). + */ + s = accept4(lev->socket.fd, sa, &socklen, SOCK_NONBLOCK); - if (s != -1) { - c->socket.fd = s; + if (s != -1) { + c->socket.fd = s; - nxt_debug(task, "accept4(%d): %d", lev->socket.fd, s); + nxt_debug(task, "accept4(%d): %d", lev->socket.fd, s); - nxt_conn_accept(task, lev, c); - return; - } + nxt_conn_accept(task, lev, c); + return; + } - nxt_conn_accept_error(task, lev, "accept4", nxt_errno); + nxt_conn_accept_error(task, lev, "accept4", nxt_errno); } #endif - #if (NXT_HAVE_EPOLL_EDGE) /* @@ -1054,35 +977,34 @@ nxt_epoll_conn_io_accept4(nxt_task_t *task, void *obj, void *data) * with single non-generic connect() interface. */ -static void -nxt_epoll_edge_conn_io_connect(nxt_task_t *task, void *obj, void *data) -{ - nxt_conn_t *c; - nxt_event_engine_t *engine; - nxt_work_handler_t handler; - const nxt_event_conn_state_t *state; +static void nxt_epoll_edge_conn_io_connect(nxt_task_t *task, void *obj, + void *data) { + nxt_conn_t *c; + nxt_event_engine_t *engine; + nxt_work_handler_t handler; + const nxt_event_conn_state_t *state; - c = obj; + c = obj; - state = c->write_state; + state = c->write_state; - switch (nxt_socket_connect(task, c->socket.fd, c->remote)) { + switch (nxt_socket_connect(task, c->socket.fd, c->remote)) { - case NXT_OK: - c->socket.write_ready = 1; - handler = state->ready_handler; - break; + case NXT_OK: + c->socket.write_ready = 1; + handler = state->ready_handler; + break; - case NXT_AGAIN: - c->socket.write_handler = nxt_epoll_edge_conn_connected; - c->socket.error_handler = nxt_conn_connect_error; + case NXT_AGAIN: + c->socket.write_handler = nxt_epoll_edge_conn_connected; + c->socket.error_handler = nxt_conn_connect_error; - engine = task->thread->engine; - nxt_conn_timer(engine, c, state, &c->write_timer); + engine = task->thread->engine; + nxt_conn_timer(engine, c, state, &c->write_timer); - nxt_epoll_enable(engine, &c->socket); - c->socket.read = NXT_EVENT_BLOCKED; - return; + nxt_epoll_enable(engine, &c->socket); + c->socket.read = NXT_EVENT_BLOCKED; + return; #if 0 case NXT_AGAIN: @@ -1113,43 +1035,40 @@ nxt_epoll_edge_conn_io_connect(nxt_task_t *task, void *obj, void *data) break; #endif - case NXT_ERROR: - handler = state->error_handler; - break; + case NXT_ERROR: + handler = state->error_handler; + break; - default: /* NXT_DECLINED: connection refused. */ - handler = state->close_handler; - break; - } + default: /* NXT_DECLINED: connection refused. */ + handler = state->close_handler; + break; + } - nxt_work_queue_add(c->write_work_queue, handler, task, c, data); + nxt_work_queue_add(c->write_work_queue, handler, task, c, data); } +static void nxt_epoll_edge_conn_connected(nxt_task_t *task, void *obj, + void *data) { + nxt_conn_t *c; -static void -nxt_epoll_edge_conn_connected(nxt_task_t *task, void *obj, void *data) -{ - nxt_conn_t *c; - - c = obj; - - nxt_debug(task, "epoll event conn connected fd:%d", c->socket.fd); + c = obj; - if (!c->socket.epoll_error) { - c->socket.write = NXT_EVENT_BLOCKED; + nxt_debug(task, "epoll event conn connected fd:%d", c->socket.fd); - if (c->write_state->timer_autoreset) { - nxt_timer_disable(task->thread->engine, &c->write_timer); - } + if (!c->socket.epoll_error) { + c->socket.write = NXT_EVENT_BLOCKED; - nxt_work_queue_add(c->write_work_queue, c->write_state->ready_handler, - task, c, data); - return; + if (c->write_state->timer_autoreset) { + nxt_timer_disable(task->thread->engine, &c->write_timer); } - nxt_conn_connect_test(task, c, data); -} + nxt_work_queue_add(c->write_work_queue, c->write_state->ready_handler, task, + c, data); + return; + } + nxt_conn_connect_test(task, c, data); +} /* * nxt_epoll_edge_conn_io_recvbuf() is just wrapper around @@ -1157,18 +1076,16 @@ nxt_epoll_edge_conn_connected(nxt_task_t *task, void *obj, void *data) * in edge-triggered mode. */ -static ssize_t -nxt_epoll_edge_conn_io_recvbuf(nxt_conn_t *c, nxt_buf_t *b) -{ - ssize_t n; +static ssize_t nxt_epoll_edge_conn_io_recvbuf(nxt_conn_t *c, nxt_buf_t *b) { + ssize_t n; - n = nxt_conn_io_recvbuf(c, b); + n = nxt_conn_io_recvbuf(c, b); - if (n > 0 && c->socket.epoll_eof) { - c->socket.read_ready = 1; - } + if (n > 0 && c->socket.epoll_eof) { + c->socket.read_ready = 1; + } - return n; + return n; } #endif diff --git a/src/nxt_errno.c b/src/nxt_errno.c index 47479a82f..1624002d1 100644 --- a/src/nxt_errno.c +++ b/src/nxt_errno.c @@ -6,7 +6,6 @@ #include - /* * The strerror() messages are copied because: * @@ -23,130 +22,119 @@ */ static u_char *nxt_bootstrap_strerror(nxt_err_t err, u_char *errstr, - size_t size); + size_t size); static u_char *nxt_runtime_strerror(nxt_err_t err, u_char *errstr, size_t size); +nxt_strerror_t nxt_strerror = nxt_bootstrap_strerror; +static nxt_str_t *nxt_sys_errlist; +static nxt_uint_t nxt_sys_nerr; + +nxt_int_t nxt_strerror_start(void) { + char *msg; + u_char *p; + size_t size, length, n; + nxt_uint_t err, invalid; -nxt_strerror_t nxt_strerror = nxt_bootstrap_strerror; -static nxt_str_t *nxt_sys_errlist; -static nxt_uint_t nxt_sys_nerr; + /* The last entry. */ + size = nxt_length("Unknown error"); + /* + * Linux has holes for error codes 41 and 58, so the loop + * stops only after 100 invalid codes in succession. + */ -nxt_int_t -nxt_strerror_start(void) -{ - char *msg; - u_char *p; - size_t size, length, n; - nxt_uint_t err, invalid; + for (invalid = 0; invalid < 100 && nxt_sys_nerr < 65536; nxt_sys_nerr++) { - /* The last entry. */ - size = nxt_length("Unknown error"); + nxt_set_errno(0); + msg = strerror((int)nxt_sys_nerr); /* - * Linux has holes for error codes 41 and 58, so the loop - * stops only after 100 invalid codes in succession. + * strerror() behaviour on passing invalid error code depends + * on OS and version: + * Linux returns "Unknown error NN"; + * FreeBSD, NetBSD and OpenBSD return "Unknown error: NN" + * and set errno to EINVAL; + * Solaris 10 returns "Unknown error" and sets errno to EINVAL; + * Solaris 9 returns "Unknown error"; + * Solaris 2 returns NULL; + * MacOSX returns "Unknown error: NN"; + * AIX returns "Error NNN occurred."; + * HP-UX returns "Unknown error" for invalid codes lesser than 250 + * or empty string for larger codes. */ - for (invalid = 0; invalid < 100 && nxt_sys_nerr < 65536; nxt_sys_nerr++) { - - nxt_set_errno(0); - msg = strerror((int) nxt_sys_nerr); - - /* - * strerror() behaviour on passing invalid error code depends - * on OS and version: - * Linux returns "Unknown error NN"; - * FreeBSD, NetBSD and OpenBSD return "Unknown error: NN" - * and set errno to EINVAL; - * Solaris 10 returns "Unknown error" and sets errno to EINVAL; - * Solaris 9 returns "Unknown error"; - * Solaris 2 returns NULL; - * MacOSX returns "Unknown error: NN"; - * AIX returns "Error NNN occurred."; - * HP-UX returns "Unknown error" for invalid codes lesser than 250 - * or empty string for larger codes. - */ - - if (msg == NULL) { - invalid++; - continue; - } - - length = nxt_strlen(msg); - size += length; - - if (length == 0 /* HP-UX empty strings. */ - || nxt_errno == NXT_EINVAL - || memcmp(msg, "Unknown error", 13) == 0) - { - invalid++; - continue; - } - -#if (NXT_AIX) + if (msg == NULL) { + invalid++; + continue; + } - if (memcmp(msg, "Error ", 6) == 0 - && memcmp(msg + length - 10, " occurred.", 9) == 0) - { - invalid++; - continue; - } + length = nxt_strlen(msg); + size += length; -#endif + if (length == 0 /* HP-UX empty strings. */ + || nxt_errno == NXT_EINVAL || memcmp(msg, "Unknown error", 13) == 0) { + invalid++; + continue; } - nxt_sys_nerr -= invalid; +#if (NXT_AIX) - nxt_main_log_debug("sys_nerr: %d", nxt_sys_nerr); + if (memcmp(msg, "Error ", 6) == 0 && + memcmp(msg + length - 10, " occurred.", 9) == 0) { + invalid++; + continue; + } - n = (nxt_sys_nerr + 1) * sizeof(nxt_str_t); +#endif + } - nxt_sys_errlist = nxt_malloc(n + size); - if (nxt_sys_errlist == NULL) { - return NXT_ERROR; - } + nxt_sys_nerr -= invalid; - p = nxt_pointer_to(nxt_sys_errlist, n); + nxt_main_log_debug("sys_nerr: %d", nxt_sys_nerr); - for (err = 0; err < nxt_sys_nerr; err++) { - msg = strerror((int) err); - length = nxt_strlen(msg); + n = (nxt_sys_nerr + 1) * sizeof(nxt_str_t); - nxt_sys_errlist[err].length = length; - nxt_sys_errlist[err].start = p; + nxt_sys_errlist = nxt_malloc(n + size); + if (nxt_sys_errlist == NULL) { + return NXT_ERROR; + } - p = nxt_cpymem(p, msg, length); - } + p = nxt_pointer_to(nxt_sys_errlist, n); + + for (err = 0; err < nxt_sys_nerr; err++) { + msg = strerror((int)err); + length = nxt_strlen(msg); - nxt_sys_errlist[err].length = 13; + nxt_sys_errlist[err].length = length; nxt_sys_errlist[err].start = p; - nxt_memcpy(p, "Unknown error", 13); - nxt_strerror = nxt_runtime_strerror; + p = nxt_cpymem(p, msg, length); + } - return NXT_OK; -} + nxt_sys_errlist[err].length = 13; + nxt_sys_errlist[err].start = p; + nxt_memcpy(p, "Unknown error", 13); + nxt_strerror = nxt_runtime_strerror; -static u_char * -nxt_bootstrap_strerror(nxt_err_t err, u_char *errstr, size_t size) -{ - return nxt_cpystrn(errstr, (u_char *) strerror(err), size); + return NXT_OK; } +static u_char *nxt_bootstrap_strerror(nxt_err_t err, u_char *errstr, + size_t size) { + return nxt_cpystrn(errstr, (u_char *)strerror(err), size); +} -static u_char * -nxt_runtime_strerror(nxt_err_t err, u_char *errstr, size_t size) -{ - nxt_str_t *msg; - nxt_uint_t n; +static u_char *nxt_runtime_strerror(nxt_err_t err, u_char *errstr, + size_t size) { + nxt_str_t *msg; + nxt_uint_t n; - n = nxt_min((nxt_uint_t) err, nxt_sys_nerr); + n = nxt_min((nxt_uint_t)err, nxt_sys_nerr); - msg = &nxt_sys_errlist[n]; + msg = &nxt_sys_errlist[n]; - size = nxt_min(size, msg->length); + size = nxt_min(size, msg->length); - return nxt_cpymem(errstr, msg->start, size); + return nxt_cpymem(errstr, msg->start, size); } diff --git a/src/nxt_errno.h b/src/nxt_errno.h index f19d50bab..482b72d15 100644 --- a/src/nxt_errno.h +++ b/src/nxt_errno.h @@ -7,82 +7,71 @@ #ifndef _NXT_UNIX_ERRNO_H_INCLUDED_ #define _NXT_UNIX_ERRNO_H_INCLUDED_ - -typedef int nxt_err_t; - - -#define NXT_EPERM EPERM -#define NXT_ENOENT ENOENT -#define NXT_ENOPATH ENOENT -#define NXT_ESRCH ESRCH -#define NXT_EINTR EINTR -#define NXT_ENXIO ENXIO -#define NXT_ECHILD ECHILD -#define NXT_ENOMEM ENOMEM -#define NXT_EACCES EACCES -#define NXT_EBUSY EBUSY -#define NXT_EEXIST EEXIST -#define NXT_ELOOP ELOOP -#define NXT_EXDEV EXDEV -#define NXT_ENOTDIR ENOTDIR -#define NXT_EISDIR EISDIR -#define NXT_EINVAL EINVAL -#define NXT_ENOSPC ENOSPC -#define NXT_EPIPE EPIPE -#define NXT_EINPROGRESS EINPROGRESS -#define NXT_EOPNOTSUPP EOPNOTSUPP -#define NXT_EADDRINUSE EADDRINUSE -#define NXT_ECONNABORTED ECONNABORTED -#define NXT_ECONNRESET ECONNRESET -#define NXT_ENOTCONN ENOTCONN -#define NXT_ETIMEDOUT ETIMEDOUT -#define NXT_ECONNREFUSED ECONNREFUSED -#define NXT_ENAMETOOLONG ENAMETOOLONG -#define NXT_ENETDOWN ENETDOWN -#define NXT_ENETUNREACH ENETUNREACH -#define NXT_EHOSTDOWN EHOSTDOWN -#define NXT_EHOSTUNREACH EHOSTUNREACH -#define NXT_ENOSYS ENOSYS -#define NXT_ECANCELED ECANCELED -#define NXT_EILSEQ EILSEQ -#define NXT_ETIME ETIME -#define NXT_ENOMOREFILES 0 -#define NXT_ENOBUFS ENOBUFS -#define NXT_ERANGE ERANGE +typedef int nxt_err_t; + +#define NXT_EPERM EPERM +#define NXT_ENOENT ENOENT +#define NXT_ENOPATH ENOENT +#define NXT_ESRCH ESRCH +#define NXT_EINTR EINTR +#define NXT_ENXIO ENXIO +#define NXT_ECHILD ECHILD +#define NXT_ENOMEM ENOMEM +#define NXT_EACCES EACCES +#define NXT_EBUSY EBUSY +#define NXT_EEXIST EEXIST +#define NXT_ELOOP ELOOP +#define NXT_EXDEV EXDEV +#define NXT_ENOTDIR ENOTDIR +#define NXT_EISDIR EISDIR +#define NXT_EINVAL EINVAL +#define NXT_ENOSPC ENOSPC +#define NXT_EPIPE EPIPE +#define NXT_EINPROGRESS EINPROGRESS +#define NXT_EOPNOTSUPP EOPNOTSUPP +#define NXT_EADDRINUSE EADDRINUSE +#define NXT_ECONNABORTED ECONNABORTED +#define NXT_ECONNRESET ECONNRESET +#define NXT_ENOTCONN ENOTCONN +#define NXT_ETIMEDOUT ETIMEDOUT +#define NXT_ECONNREFUSED ECONNREFUSED +#define NXT_ENAMETOOLONG ENAMETOOLONG +#define NXT_ENETDOWN ENETDOWN +#define NXT_ENETUNREACH ENETUNREACH +#define NXT_EHOSTDOWN EHOSTDOWN +#define NXT_EHOSTUNREACH EHOSTUNREACH +#define NXT_ENOSYS ENOSYS +#define NXT_ECANCELED ECANCELED +#define NXT_EILSEQ EILSEQ +#define NXT_ETIME ETIME +#define NXT_ENOMOREFILES 0 +#define NXT_ENOBUFS ENOBUFS +#define NXT_ERANGE ERANGE #if (NXT_HPUX) /* HP-UX uses EWOULDBLOCK instead of EAGAIN. */ -#define NXT_EAGAIN EWOULDBLOCK +#define NXT_EAGAIN EWOULDBLOCK #else -#define NXT_EAGAIN EAGAIN +#define NXT_EAGAIN EAGAIN #endif +#define NXT_OK 0 +#define NXT_ERROR (-1) +#define NXT_AGAIN (-2) +#define NXT_DECLINED (-3) +#define NXT_DONE (-4) -#define NXT_OK 0 -#define NXT_ERROR (-1) -#define NXT_AGAIN (-2) -#define NXT_DECLINED (-3) -#define NXT_DONE (-4) - +#define nxt_errno errno -#define nxt_errno \ - errno +#define nxt_socket_errno errno -#define nxt_socket_errno \ - errno - -#define nxt_set_errno(err) \ - errno = err - -#define nxt_set_socket_errno(err) \ - errno = err +#define nxt_set_errno(err) errno = err +#define nxt_set_socket_errno(err) errno = err nxt_int_t nxt_strerror_start(void); - typedef u_char *(*nxt_strerror_t)(nxt_err_t err, u_char *errstr, size_t size); -extern nxt_strerror_t nxt_strerror; - +extern nxt_strerror_t nxt_strerror; #endif /* _NXT_UNIX_ERRNO_H_INCLUDED_ */ diff --git a/src/nxt_event_conn_job_sendfile.c b/src/nxt_event_conn_job_sendfile.c index 0f6f9353a..b5670c1e1 100644 --- a/src/nxt_event_conn_job_sendfile.c +++ b/src/nxt_event_conn_job_sendfile.c @@ -6,254 +6,240 @@ #include - typedef struct { - nxt_job_t job; - nxt_buf_t *out; - size_t sent; - size_t limit; - nxt_work_handler_t ready_handler; + nxt_job_t job; + nxt_buf_t *out; + size_t sent; + size_t limit; + nxt_work_handler_t ready_handler; } nxt_job_sendfile_t; - static void nxt_event_conn_job_sendfile_start(nxt_task_t *task, void *obj, - void *data); + void *data); static void nxt_event_conn_job_sendfile_handler(nxt_task_t *task, void *obj, - void *data); + void *data); static void nxt_event_conn_job_sendfile_return(nxt_task_t *task, void *obj, - void *data); + void *data); static nxt_buf_t *nxt_event_conn_job_sendfile_completion(nxt_task_t *task, - nxt_conn_t *c, nxt_buf_t *b); + nxt_conn_t *c, + nxt_buf_t *b); +void nxt_event_conn_job_sendfile(nxt_task_t *task, nxt_conn_t *c) { + nxt_fd_event_disable(task->thread->engine, &c->socket); -void -nxt_event_conn_job_sendfile(nxt_task_t *task, nxt_conn_t *c) -{ - nxt_fd_event_disable(task->thread->engine, &c->socket); - - /* A work item data is not used in nxt_event_conn_job_sendfile_start(). */ - nxt_event_conn_job_sendfile_start(task, c, NULL); + /* A work item data is not used in nxt_event_conn_job_sendfile_start(). */ + nxt_event_conn_job_sendfile_start(task, c, NULL); } +static void nxt_event_conn_job_sendfile_start(nxt_task_t *task, void *obj, + void *data) { + nxt_conn_t *c; + nxt_iobuf_t b; + nxt_job_sendfile_t *jbs; + nxt_sendbuf_coalesce_t sb; -static void -nxt_event_conn_job_sendfile_start(nxt_task_t *task, void *obj, void *data) -{ - nxt_conn_t *c; - nxt_iobuf_t b; - nxt_job_sendfile_t *jbs; - nxt_sendbuf_coalesce_t sb; - - c = obj; + c = obj; - nxt_debug(task, "event conn sendfile fd:%d", c->socket.fd); + nxt_debug(task, "event conn sendfile fd:%d", c->socket.fd); - jbs = nxt_job_create(c->mem_pool, sizeof(nxt_job_sendfile_t)); + jbs = nxt_job_create(c->mem_pool, sizeof(nxt_job_sendfile_t)); - if (nxt_slow_path(jbs == NULL)) { - c->write_state->error_handler(task, c, NULL); - return; - } + if (nxt_slow_path(jbs == NULL)) { + c->write_state->error_handler(task, c, NULL); + return; + } - c->socket.write_handler = nxt_event_conn_job_sendfile_start; - c->socket.error_handler = c->write_state->error_handler; + c->socket.write_handler = nxt_event_conn_job_sendfile_start; + c->socket.error_handler = c->write_state->error_handler; - jbs->job.data = c; - nxt_job_set_name(&jbs->job, "job sendfile"); + jbs->job.data = c; + nxt_job_set_name(&jbs->job, "job sendfile"); - jbs->limit = nxt_event_conn_write_limit(c); + jbs->limit = nxt_event_conn_write_limit(c); - if (jbs->limit != 0) { + if (jbs->limit != 0) { - sb.buf = c->write; - sb.iobuf = &b; - sb.nmax = 1; - sb.sync = 0; - sb.size = 0; - sb.limit = jbs->limit; + sb.buf = c->write; + sb.iobuf = &b; + sb.nmax = 1; + sb.sync = 0; + sb.size = 0; + sb.limit = jbs->limit; - if (nxt_sendbuf_mem_coalesce(c->socket.task, &sb) != 0 || !sb.sync) { + if (nxt_sendbuf_mem_coalesce(c->socket.task, &sb) != 0 || !sb.sync) { - jbs->job.thread_pool = c->u.thread_pool; - jbs->job.log = c->socket.log; - jbs->out = c->write; - c->write = NULL; - jbs->ready_handler = nxt_event_conn_job_sendfile_return; + jbs->job.thread_pool = c->u.thread_pool; + jbs->job.log = c->socket.log; + jbs->out = c->write; + c->write = NULL; + jbs->ready_handler = nxt_event_conn_job_sendfile_return; - c->block_read = 1; - c->block_write = 1; + c->block_read = 1; + c->block_write = 1; - nxt_job_start(task, &jbs->job, nxt_event_conn_job_sendfile_handler); - return; - } + nxt_job_start(task, &jbs->job, nxt_event_conn_job_sendfile_handler); + return; } + } - nxt_event_conn_job_sendfile_return(task, jbs, c); + nxt_event_conn_job_sendfile_return(task, jbs, c); } +static void nxt_event_conn_job_sendfile_handler(nxt_task_t *task, void *obj, + void *data) { + ssize_t ret; + nxt_buf_t *b; + nxt_bool_t first; + nxt_conn_t *c; + nxt_job_sendfile_t *jbs; -static void -nxt_event_conn_job_sendfile_handler(nxt_task_t *task, void *obj, void *data) -{ - ssize_t ret; - nxt_buf_t *b; - nxt_bool_t first; - nxt_conn_t *c; - nxt_job_sendfile_t *jbs; - - jbs = obj; - c = data; + jbs = obj; + c = data; - nxt_debug(task, "event conn job sendfile fd:%d", c->socket.fd); + nxt_debug(task, "event conn job sendfile fd:%d", c->socket.fd); - first = c->socket.write_ready; - b = jbs->out; + first = c->socket.write_ready; + b = jbs->out; - do { - ret = c->io->old_sendbuf(c, b, jbs->limit); + do { + ret = c->io->old_sendbuf(c, b, jbs->limit); - if (ret == NXT_AGAIN) { - break; - } + if (ret == NXT_AGAIN) { + break; + } - if (nxt_slow_path(ret == NXT_ERROR)) { - goto done; - } + if (nxt_slow_path(ret == NXT_ERROR)) { + goto done; + } - jbs->sent += ret; - jbs->limit -= ret; + jbs->sent += ret; + jbs->limit -= ret; - b = nxt_sendbuf_update(b, ret); + b = nxt_sendbuf_update(b, ret); - if (b == NULL) { - goto done; - } + if (b == NULL) { + goto done; + } - if (jbs->limit == 0) { + if (jbs->limit == 0) { - if (c->rate == NULL) { - jbs->limit = c->max_chunk; - goto fast; - } + if (c->rate == NULL) { + jbs->limit = c->max_chunk; + goto fast; + } - goto done; - } + goto done; + } - } while (c->socket.write_ready); + } while (c->socket.write_ready); - if (first && task->thread->thread_pool->work_queue.head != NULL) { - goto fast; - } + if (first && task->thread->thread_pool->work_queue.head != NULL) { + goto fast; + } done: - nxt_job_return(task, &jbs->job, jbs->ready_handler); - return; + nxt_job_return(task, &jbs->job, jbs->ready_handler); + return; fast: - nxt_work_set(&jbs->job.work, nxt_event_conn_job_sendfile_handler, - jbs->job.task, jbs, c); + nxt_work_set(&jbs->job.work, nxt_event_conn_job_sendfile_handler, + jbs->job.task, jbs, c); - nxt_thread_pool_post(task->thread->thread_pool, &jbs->job.work); + nxt_thread_pool_post(task->thread->thread_pool, &jbs->job.work); } +static void nxt_event_conn_job_sendfile_return(nxt_task_t *task, void *obj, + void *data) { + size_t sent; + nxt_buf_t *b; + nxt_bool_t done; + nxt_conn_t *c; + nxt_job_sendfile_t *jbs; -static void -nxt_event_conn_job_sendfile_return(nxt_task_t *task, void *obj, void *data) -{ - size_t sent; - nxt_buf_t *b; - nxt_bool_t done; - nxt_conn_t *c; - nxt_job_sendfile_t *jbs; - - jbs = obj; - c = data; - - c->block_read = 0; - c->block_write = 0; - - sent = jbs->sent; - c->sent += sent; - - nxt_debug(task, "event conn sendfile sent:%z", sent); - - b = jbs->out; - - /* The job must be destroyed before connection error handler. */ - nxt_job_destroy(task, jbs); + jbs = obj; + c = data; - if (0 /* STUB: c->write_state->process_buffers */) { - b = nxt_event_conn_job_sendfile_completion(task, c, b); + c->block_read = 0; + c->block_write = 0; - done = (b == NULL); + sent = jbs->sent; + c->sent += sent; - /* Add data which might be added after sendfile job has started. */ - nxt_buf_chain_add(&b, c->write); - c->write = b; + nxt_debug(task, "event conn sendfile sent:%z", sent); - if (done) { - /* All data has been sent. */ + b = jbs->out; - if (b != NULL) { - /* But new data has been added. */ - nxt_event_conn_job_sendfile_start(task, c, NULL); - } + /* The job must be destroyed before connection error handler. */ + nxt_job_destroy(task, jbs); - return; - } - } + if (0 /* STUB: c->write_state->process_buffers */) { + b = nxt_event_conn_job_sendfile_completion(task, c, b); - if (sent != 0 && c->write_state->timer_autoreset) { - nxt_timer_disable(task->thread->engine, &c->write_timer); - } + done = (b == NULL); - if (c->socket.error == 0 - && !nxt_event_conn_write_delayed(task->thread->engine, c, sent)) - { - nxt_conn_timer(task->thread->engine, c, c->write_state, - &c->write_timer); + /* Add data which might be added after sendfile job has started. */ + nxt_buf_chain_add(&b, c->write); + c->write = b; - nxt_fd_event_oneshot_write(task->thread->engine, &c->socket); - } + if (done) { + /* All data has been sent. */ - if (sent != 0) { - nxt_work_queue_add(c->write_work_queue, c->write_state->ready_handler, - task, c, c->socket.data); - /* - * Fall through if first operations were - * successful but the last one failed. - */ - } + if (b != NULL) { + /* But new data has been added. */ + nxt_event_conn_job_sendfile_start(task, c, NULL); + } - if (nxt_slow_path(c->socket.error != 0)) { - nxt_work_queue_add(c->write_work_queue, c->write_state->error_handler, - task, c, c->socket.data); + return; } + } + + if (sent != 0 && c->write_state->timer_autoreset) { + nxt_timer_disable(task->thread->engine, &c->write_timer); + } + + if (c->socket.error == 0 && + !nxt_event_conn_write_delayed(task->thread->engine, c, sent)) { + nxt_conn_timer(task->thread->engine, c, c->write_state, &c->write_timer); + + nxt_fd_event_oneshot_write(task->thread->engine, &c->socket); + } + + if (sent != 0) { + nxt_work_queue_add(c->write_work_queue, c->write_state->ready_handler, task, + c, c->socket.data); + /* + * Fall through if first operations were + * successful but the last one failed. + */ + } + + if (nxt_slow_path(c->socket.error != 0)) { + nxt_work_queue_add(c->write_work_queue, c->write_state->error_handler, task, + c, c->socket.data); + } } +static nxt_buf_t *nxt_event_conn_job_sendfile_completion(nxt_task_t *task, + nxt_conn_t *c, + nxt_buf_t *b) { + while (b != NULL) { -static nxt_buf_t * -nxt_event_conn_job_sendfile_completion(nxt_task_t *task, nxt_conn_t *c, - nxt_buf_t *b) -{ - while (b != NULL) { - - nxt_prefetch(b->next); + nxt_prefetch(b->next); - if (nxt_buf_is_mem(b) && b->mem.pos != b->mem.free) { - break; + if (nxt_buf_is_mem(b) && b->mem.pos != b->mem.free) { + break; - } else if (nxt_buf_is_file(b) && b->file_pos != b->file_end) { - break; - } + } else if (nxt_buf_is_file(b) && b->file_pos != b->file_end) { + break; + } - nxt_work_queue_add(c->write_work_queue, - b->completion_handler, task, b, b->parent); + nxt_work_queue_add(c->write_work_queue, b->completion_handler, task, b, + b->parent); - b = b->next; - } + b = b->next; + } - return b; + return b; } diff --git a/src/nxt_event_engine.c b/src/nxt_event_engine.c index 78c79bb1a..e487e40f3 100644 --- a/src/nxt_event_engine.c +++ b/src/nxt_event_engine.c @@ -6,61 +6,56 @@ #include - -typedef struct nxt_mem_cache_block_s nxt_mem_cache_block_t; +typedef struct nxt_mem_cache_block_s nxt_mem_cache_block_t; struct nxt_mem_cache_block_s { - nxt_mem_cache_block_t *next; + nxt_mem_cache_block_t *next; }; - typedef struct { - nxt_mem_cache_block_t *free; - uint32_t size; - uint32_t count; + nxt_mem_cache_block_t *free; + uint32_t size; + uint32_t count; } nxt_mem_cache_t; - static nxt_int_t nxt_event_engine_post_init(nxt_event_engine_t *engine); -static nxt_int_t nxt_event_engine_signal_pipe_create( - nxt_event_engine_t *engine); +static nxt_int_t +nxt_event_engine_signal_pipe_create(nxt_event_engine_t *engine); static void nxt_event_engine_signal_pipe_close(nxt_task_t *task, void *obj, - void *data); + void *data); static void nxt_event_engine_signal_pipe(nxt_task_t *task, void *obj, - void *data); + void *data); static void nxt_event_engine_post_handler(nxt_task_t *task, void *obj, - void *data); + void *data); static void nxt_event_engine_signal_pipe_error(nxt_task_t *task, void *obj, - void *data); + void *data); static void nxt_event_engine_signal_handler(nxt_task_t *task, void *obj, - void *data); + void *data); static nxt_work_handler_t nxt_event_engine_queue_pop(nxt_event_engine_t *engine, - nxt_task_t **task, void **obj, void **data); - - -nxt_event_engine_t * -nxt_event_engine_create(nxt_task_t *task, - const nxt_event_interface_t *interface, const nxt_sig_event_t *signals, - nxt_uint_t flags, nxt_uint_t batch) -{ - nxt_uint_t events; - nxt_thread_t *thread; - nxt_event_engine_t *engine; - - engine = nxt_zalloc(sizeof(nxt_event_engine_t)); - if (engine == NULL) { - return NULL; - } + nxt_task_t **task, + void **obj, void **data); + +nxt_event_engine_t *nxt_event_engine_create( + nxt_task_t *task, const nxt_event_interface_t *interface, + const nxt_sig_event_t *signals, nxt_uint_t flags, nxt_uint_t batch) { + nxt_uint_t events; + nxt_thread_t *thread; + nxt_event_engine_t *engine; + + engine = nxt_zalloc(sizeof(nxt_event_engine_t)); + if (engine == NULL) { + return NULL; + } - nxt_debug(task, "create engine %p", engine); + nxt_debug(task, "create engine %p", engine); - thread = task->thread; + thread = task->thread; - engine->task.thread = thread; - engine->task.log = thread->log; - engine->task.ident = nxt_task_next_ident(); + engine->task.thread = thread; + engine->task.log = thread->log; + engine->task.ident = nxt_task_next_ident(); - engine->batch = batch; + engine->batch = batch; #if 0 if (flags & NXT_ENGINE_FIBERS) { @@ -71,689 +66,636 @@ nxt_event_engine_create(nxt_task_t *task, } #endif - engine->current_work_queue = &engine->fast_work_queue; - - nxt_work_queue_cache_create(&engine->work_queue_cache, 0); - - engine->fast_work_queue.cache = &engine->work_queue_cache; - engine->accept_work_queue.cache = &engine->work_queue_cache; - engine->read_work_queue.cache = &engine->work_queue_cache; - engine->socket_work_queue.cache = &engine->work_queue_cache; - engine->connect_work_queue.cache = &engine->work_queue_cache; - engine->write_work_queue.cache = &engine->work_queue_cache; - engine->shutdown_work_queue.cache = &engine->work_queue_cache; - engine->close_work_queue.cache = &engine->work_queue_cache; - - nxt_work_queue_name(&engine->fast_work_queue, "fast"); - nxt_work_queue_name(&engine->accept_work_queue, "accept"); - nxt_work_queue_name(&engine->read_work_queue, "read"); - nxt_work_queue_name(&engine->socket_work_queue, "socket"); - nxt_work_queue_name(&engine->connect_work_queue, "connect"); - nxt_work_queue_name(&engine->write_work_queue, "write"); - nxt_work_queue_name(&engine->shutdown_work_queue, "shutdown"); - nxt_work_queue_name(&engine->close_work_queue, "close"); - - if (signals != NULL) { - engine->signals = nxt_event_engine_signals(signals); - if (engine->signals == NULL) { - goto signals_fail; - } + engine->current_work_queue = &engine->fast_work_queue; + + nxt_work_queue_cache_create(&engine->work_queue_cache, 0); + + engine->fast_work_queue.cache = &engine->work_queue_cache; + engine->accept_work_queue.cache = &engine->work_queue_cache; + engine->read_work_queue.cache = &engine->work_queue_cache; + engine->socket_work_queue.cache = &engine->work_queue_cache; + engine->connect_work_queue.cache = &engine->work_queue_cache; + engine->write_work_queue.cache = &engine->work_queue_cache; + engine->shutdown_work_queue.cache = &engine->work_queue_cache; + engine->close_work_queue.cache = &engine->work_queue_cache; + + nxt_work_queue_name(&engine->fast_work_queue, "fast"); + nxt_work_queue_name(&engine->accept_work_queue, "accept"); + nxt_work_queue_name(&engine->read_work_queue, "read"); + nxt_work_queue_name(&engine->socket_work_queue, "socket"); + nxt_work_queue_name(&engine->connect_work_queue, "connect"); + nxt_work_queue_name(&engine->write_work_queue, "write"); + nxt_work_queue_name(&engine->shutdown_work_queue, "shutdown"); + nxt_work_queue_name(&engine->close_work_queue, "close"); + + if (signals != NULL) { + engine->signals = nxt_event_engine_signals(signals); + if (engine->signals == NULL) { + goto signals_fail; + } - engine->signals->handler = nxt_event_engine_signal_handler; + engine->signals->handler = nxt_event_engine_signal_handler; - if (!interface->signal_support) { - if (nxt_event_engine_signals_start(engine) != NXT_OK) { - goto signals_fail; - } - } + if (!interface->signal_support) { + if (nxt_event_engine_signals_start(engine) != NXT_OK) { + goto signals_fail; + } } + } - /* - * Number of event set and timers changes should be at least twice - * more than number of events to avoid premature flushes of the changes. - * Fourfold is for sure. - */ - events = (batch != 0) ? batch : 32; + /* + * Number of event set and timers changes should be at least twice + * more than number of events to avoid premature flushes of the changes. + * Fourfold is for sure. + */ + events = (batch != 0) ? batch : 32; - if (interface->create(engine, 4 * events, events) != NXT_OK) { - goto event_set_fail; - } + if (interface->create(engine, 4 * events, events) != NXT_OK) { + goto event_set_fail; + } - engine->event = *interface; + engine->event = *interface; - if (nxt_event_engine_post_init(engine) != NXT_OK) { - goto post_fail; - } + if (nxt_event_engine_post_init(engine) != NXT_OK) { + goto post_fail; + } - if (nxt_timers_init(&engine->timers, 4 * events) != NXT_OK) { - goto timers_fail; - } + if (nxt_timers_init(&engine->timers, 4 * events) != NXT_OK) { + goto timers_fail; + } - thread = task->thread; + thread = task->thread; - nxt_thread_time_update(thread); - engine->timers.now = nxt_thread_monotonic_time(thread) / 1000000; + nxt_thread_time_update(thread); + engine->timers.now = nxt_thread_monotonic_time(thread) / 1000000; - engine->max_connections = 0xFFFFFFFF; + engine->max_connections = 0xFFFFFFFF; - nxt_queue_init(&engine->joints); - nxt_queue_init(&engine->listen_connections); - nxt_queue_init(&engine->idle_connections); + nxt_queue_init(&engine->joints); + nxt_queue_init(&engine->listen_connections); + nxt_queue_init(&engine->idle_connections); - return engine; + return engine; timers_fail: post_fail: - interface->free(engine); + interface->free(engine); event_set_fail: signals_fail: - nxt_free(engine->signals); - nxt_work_queue_cache_destroy(&engine->work_queue_cache); - nxt_free(engine->fibers); + nxt_free(engine->signals); + nxt_work_queue_cache_destroy(&engine->work_queue_cache); + nxt_free(engine->fibers); #if 0 fibers_fail: #endif - nxt_free(engine); + nxt_free(engine); - return NULL; + return NULL; } +static nxt_int_t nxt_event_engine_post_init(nxt_event_engine_t *engine) { + if (engine->event.enable_post != NULL) { + return engine->event.enable_post(engine, nxt_event_engine_post_handler); + } -static nxt_int_t -nxt_event_engine_post_init(nxt_event_engine_t *engine) -{ - if (engine->event.enable_post != NULL) { - return engine->event.enable_post(engine, nxt_event_engine_post_handler); - } + if (nxt_event_engine_signal_pipe_create(engine) != NXT_OK) { + return NXT_ERROR; + } - if (nxt_event_engine_signal_pipe_create(engine) != NXT_OK) { - return NXT_ERROR; - } - - return NXT_OK; + return NXT_OK; } - static nxt_int_t -nxt_event_engine_signal_pipe_create(nxt_event_engine_t *engine) -{ - nxt_event_engine_pipe_t *pipe; +nxt_event_engine_signal_pipe_create(nxt_event_engine_t *engine) { + nxt_event_engine_pipe_t *pipe; - pipe = nxt_zalloc(sizeof(nxt_event_engine_pipe_t)); - if (pipe == NULL) { - return NXT_ERROR; - } + pipe = nxt_zalloc(sizeof(nxt_event_engine_pipe_t)); + if (pipe == NULL) { + return NXT_ERROR; + } - engine->pipe = pipe; + engine->pipe = pipe; - /* - * An event engine pipe is in blocking mode for writer - * and in non-blocking node for reader. - */ + /* + * An event engine pipe is in blocking mode for writer + * and in non-blocking node for reader. + */ - if (nxt_pipe_create(&engine->task, pipe->fds, 1, 0) != NXT_OK) { - nxt_free(pipe); - return NXT_ERROR; - } + if (nxt_pipe_create(&engine->task, pipe->fds, 1, 0) != NXT_OK) { + nxt_free(pipe); + return NXT_ERROR; + } - pipe->event.fd = pipe->fds[0]; - pipe->event.task = &engine->task; - pipe->event.read_work_queue = &engine->fast_work_queue; - pipe->event.read_handler = nxt_event_engine_signal_pipe; - pipe->event.write_work_queue = &engine->fast_work_queue; - pipe->event.error_handler = nxt_event_engine_signal_pipe_error; - pipe->event.log = engine->task.log; + pipe->event.fd = pipe->fds[0]; + pipe->event.task = &engine->task; + pipe->event.read_work_queue = &engine->fast_work_queue; + pipe->event.read_handler = nxt_event_engine_signal_pipe; + pipe->event.write_work_queue = &engine->fast_work_queue; + pipe->event.error_handler = nxt_event_engine_signal_pipe_error; + pipe->event.log = engine->task.log; - nxt_fd_event_enable_read(engine, &pipe->event); + nxt_fd_event_enable_read(engine, &pipe->event); - return NXT_OK; + return NXT_OK; } +static void nxt_event_engine_signal_pipe_free(nxt_event_engine_t *engine) { + nxt_event_engine_pipe_t *pipe; -static void -nxt_event_engine_signal_pipe_free(nxt_event_engine_t *engine) -{ - nxt_event_engine_pipe_t *pipe; - - pipe = engine->pipe; + pipe = engine->pipe; - if (pipe != NULL) { - - if (pipe->event.read_work_queue != NULL) { - nxt_fd_event_close(engine, &pipe->event); - nxt_pipe_close(pipe->event.task, pipe->fds); - } + if (pipe != NULL) { - nxt_free(pipe); + if (pipe->event.read_work_queue != NULL) { + nxt_fd_event_close(engine, &pipe->event); + nxt_pipe_close(pipe->event.task, pipe->fds); } -} + nxt_free(pipe); + } +} -static void -nxt_event_engine_signal_pipe_close(nxt_task_t *task, void *obj, void *data) -{ - nxt_event_engine_pipe_t *pipe; +static void nxt_event_engine_signal_pipe_close(nxt_task_t *task, void *obj, + void *data) { + nxt_event_engine_pipe_t *pipe; - pipe = obj; + pipe = obj; - nxt_pipe_close(pipe->event.task, pipe->fds); - nxt_free(pipe); + nxt_pipe_close(pipe->event.task, pipe->fds); + nxt_free(pipe); } - -void -nxt_event_engine_post(nxt_event_engine_t *engine, nxt_work_t *work) -{ - nxt_debug(&engine->task, "event engine post"); +void nxt_event_engine_post(nxt_event_engine_t *engine, nxt_work_t *work) { + nxt_debug(&engine->task, "event engine post"); #if (NXT_DEBUG) - if (nxt_slow_path(work->next != NULL)) { - nxt_debug(&engine->task, "event engine post multiple works"); - } + if (nxt_slow_path(work->next != NULL)) { + nxt_debug(&engine->task, "event engine post multiple works"); + } #endif - nxt_locked_work_queue_add(&engine->locked_work_queue, work); + nxt_locked_work_queue_add(&engine->locked_work_queue, work); - nxt_event_engine_signal(engine, 0); + nxt_event_engine_signal(engine, 0); } +void nxt_event_engine_signal(nxt_event_engine_t *engine, nxt_uint_t signo) { + u_char buf; -void -nxt_event_engine_signal(nxt_event_engine_t *engine, nxt_uint_t signo) -{ - u_char buf; + nxt_debug(&engine->task, "event engine signal:%ui", signo); - nxt_debug(&engine->task, "event engine signal:%ui", signo); + /* + * A signal number may be sent in a signal context, so the signal + * information cannot be passed via a locked work queue. + */ - /* - * A signal number may be sent in a signal context, so the signal - * information cannot be passed via a locked work queue. - */ + if (engine->event.signal != NULL) { + engine->event.signal(engine, signo); + return; + } - if (engine->event.signal != NULL) { - engine->event.signal(engine, signo); - return; - } - - buf = (u_char) signo; - (void) nxt_fd_write(engine->pipe->fds[1], &buf, 1); + buf = (u_char)signo; + (void)nxt_fd_write(engine->pipe->fds[1], &buf, 1); } +static void nxt_event_engine_signal_pipe(nxt_task_t *task, void *obj, + void *data) { + int i, n; + u_char signo; + nxt_bool_t post; + nxt_fd_event_t *ev; + u_char buf[128]; -static void -nxt_event_engine_signal_pipe(nxt_task_t *task, void *obj, void *data) -{ - int i, n; - u_char signo; - nxt_bool_t post; - nxt_fd_event_t *ev; - u_char buf[128]; - - ev = obj; + ev = obj; - nxt_debug(task, "engine signal pipe"); + nxt_debug(task, "engine signal pipe"); - post = 0; + post = 0; - do { - n = nxt_fd_read(ev->fd, buf, sizeof(buf)); + do { + n = nxt_fd_read(ev->fd, buf, sizeof(buf)); - for (i = 0; i < n; i++) { - signo = buf[i]; + for (i = 0; i < n; i++) { + signo = buf[i]; - nxt_debug(task, "engine pipe signo:%d", signo); + nxt_debug(task, "engine pipe signo:%d", signo); - if (signo == 0) { - /* A post should be processed only once. */ - post = 1; + if (signo == 0) { + /* A post should be processed only once. */ + post = 1; - } else { - nxt_event_engine_signal_handler(task, - (void *) (uintptr_t) signo, NULL); - } - } + } else { + nxt_event_engine_signal_handler(task, (void *)(uintptr_t)signo, NULL); + } + } - } while (n == sizeof(buf)); + } while (n == sizeof(buf)); - if (post) { - nxt_event_engine_post_handler(task, NULL, NULL); - } + if (post) { + nxt_event_engine_post_handler(task, NULL, NULL); + } } +static void nxt_event_engine_post_handler(nxt_task_t *task, void *obj, + void *data) { + nxt_thread_t *thread; + nxt_event_engine_t *engine; -static void -nxt_event_engine_post_handler(nxt_task_t *task, void *obj, void *data) -{ - nxt_thread_t *thread; - nxt_event_engine_t *engine; - - thread = task->thread; - engine = thread->engine; + thread = task->thread; + engine = thread->engine; - nxt_locked_work_queue_move(thread, &engine->locked_work_queue, - &engine->fast_work_queue); + nxt_locked_work_queue_move(thread, &engine->locked_work_queue, + &engine->fast_work_queue); } +static void nxt_event_engine_signal_pipe_error(nxt_task_t *task, void *obj, + void *data) { + nxt_event_engine_t *engine; + nxt_event_engine_pipe_t *pipe; -static void -nxt_event_engine_signal_pipe_error(nxt_task_t *task, void *obj, void *data) -{ - nxt_event_engine_t *engine; - nxt_event_engine_pipe_t *pipe; - - engine = task->thread->engine; - pipe = engine->pipe; + engine = task->thread->engine; + pipe = engine->pipe; - nxt_alert(task, "engine pipe(%FD:%FD) event error", - pipe->fds[0], pipe->fds[1]); + nxt_alert(task, "engine pipe(%FD:%FD) event error", pipe->fds[0], + pipe->fds[1]); - nxt_fd_event_close(engine, &pipe->event); - nxt_pipe_close(pipe->event.task, pipe->fds); + nxt_fd_event_close(engine, &pipe->event); + nxt_pipe_close(pipe->event.task, pipe->fds); } +static void nxt_event_engine_signal_handler(nxt_task_t *task, void *obj, + void *data) { + uintptr_t signo; + const nxt_sig_event_t *sigev; -static void -nxt_event_engine_signal_handler(nxt_task_t *task, void *obj, void *data) -{ - uintptr_t signo; - const nxt_sig_event_t *sigev; - - signo = (uintptr_t) obj; + signo = (uintptr_t)obj; - for (sigev = task->thread->engine->signals->sigev; - sigev->signo != 0; - sigev++) - { - if (signo == (nxt_uint_t) sigev->signo) { - sigev->handler(task, (void *) signo, (void *) sigev->name); - return; - } + for (sigev = task->thread->engine->signals->sigev; sigev->signo != 0; + sigev++) { + if (signo == (nxt_uint_t)sigev->signo) { + sigev->handler(task, (void *)signo, (void *)sigev->name); + return; } + } - nxt_alert(task, "signal %ui handler not found", (nxt_uint_t) signo); + nxt_alert(task, "signal %ui handler not found", (nxt_uint_t)signo); } +nxt_int_t nxt_event_engine_change(nxt_event_engine_t *engine, + const nxt_event_interface_t *interface, + nxt_uint_t batch) { + nxt_uint_t events; -nxt_int_t -nxt_event_engine_change(nxt_event_engine_t *engine, - const nxt_event_interface_t *interface, nxt_uint_t batch) -{ - nxt_uint_t events; + engine->batch = batch; - engine->batch = batch; - - if (!engine->event.signal_support && interface->signal_support) { - /* - * Block signal processing if the current event - * facility does not support signal processing. - */ - nxt_event_engine_signals_stop(engine); - - /* - * Add to engine fast work queue the signal events possibly - * received before the blocking signal processing. - */ - nxt_event_engine_signal_pipe(&engine->task, &engine->pipe->event, NULL); - } + if (!engine->event.signal_support && interface->signal_support) { + /* + * Block signal processing if the current event + * facility does not support signal processing. + */ + nxt_event_engine_signals_stop(engine); - if (engine->pipe != NULL && interface->enable_post != NULL) { - /* - * An engine pipe must be closed after all signal events - * added above to engine fast work queue will be processed. - */ - nxt_work_queue_add(&engine->fast_work_queue, - nxt_event_engine_signal_pipe_close, - &engine->task, engine->pipe, NULL); + /* + * Add to engine fast work queue the signal events possibly + * received before the blocking signal processing. + */ + nxt_event_engine_signal_pipe(&engine->task, &engine->pipe->event, NULL); + } - engine->pipe = NULL; - } + if (engine->pipe != NULL && interface->enable_post != NULL) { + /* + * An engine pipe must be closed after all signal events + * added above to engine fast work queue will be processed. + */ + nxt_work_queue_add(&engine->fast_work_queue, + nxt_event_engine_signal_pipe_close, &engine->task, + engine->pipe, NULL); - engine->event.free(engine); + engine->pipe = NULL; + } - events = (batch != 0) ? batch : 32; + engine->event.free(engine); - if (interface->create(engine, 4 * events, events) != NXT_OK) { - return NXT_ERROR; - } + events = (batch != 0) ? batch : 32; - engine->event = *interface; + if (interface->create(engine, 4 * events, events) != NXT_OK) { + return NXT_ERROR; + } - if (nxt_event_engine_post_init(engine) != NXT_OK) { - return NXT_ERROR; - } + engine->event = *interface; - if (engine->signals != NULL) { + if (nxt_event_engine_post_init(engine) != NXT_OK) { + return NXT_ERROR; + } - if (!engine->event.signal_support) { - return nxt_event_engine_signals_start(engine); - } + if (engine->signals != NULL) { - /* - * Reset the PID flag to start the signal thread if - * some future event facility will not support signals. - */ - engine->signals->process = 0; + if (!engine->event.signal_support) { + return nxt_event_engine_signals_start(engine); } - return NXT_OK; -} + /* + * Reset the PID flag to start the signal thread if + * some future event facility will not support signals. + */ + engine->signals->process = 0; + } + return NXT_OK; +} -void -nxt_event_engine_free(nxt_event_engine_t *engine) -{ - nxt_thread_log_debug("free engine %p", engine); +void nxt_event_engine_free(nxt_event_engine_t *engine) { + nxt_thread_log_debug("free engine %p", engine); - nxt_event_engine_signal_pipe_free(engine); - nxt_free(engine->signals); + nxt_event_engine_signal_pipe_free(engine); + nxt_free(engine->signals); - nxt_work_queue_cache_destroy(&engine->work_queue_cache); + nxt_work_queue_cache_destroy(&engine->work_queue_cache); - engine->event.free(engine); + engine->event.free(engine); - /* TODO: free timers */ + /* TODO: free timers */ - nxt_free(engine); + nxt_free(engine); } +static nxt_work_handler_t nxt_event_engine_queue_pop(nxt_event_engine_t *engine, + nxt_task_t **task, + void **obj, void **data) { + nxt_work_queue_t *wq, *last; -static nxt_work_handler_t -nxt_event_engine_queue_pop(nxt_event_engine_t *engine, nxt_task_t **task, - void **obj, void **data) -{ - nxt_work_queue_t *wq, *last; + wq = engine->current_work_queue; + last = wq; - wq = engine->current_work_queue; - last = wq; + if (wq->head == NULL) { + wq = &engine->fast_work_queue; if (wq->head == NULL) { - wq = &engine->fast_work_queue; - if (wq->head == NULL) { + do { + engine->current_work_queue++; + wq = engine->current_work_queue; - do { - engine->current_work_queue++; - wq = engine->current_work_queue; - - if (wq > &engine->close_work_queue) { - wq = &engine->fast_work_queue; - engine->current_work_queue = wq; - } + if (wq > &engine->close_work_queue) { + wq = &engine->fast_work_queue; + engine->current_work_queue = wq; + } - if (wq->head != NULL) { - goto found; - } + if (wq->head != NULL) { + goto found; + } - } while (wq != last); + } while (wq != last); - engine->current_work_queue = &engine->fast_work_queue; + engine->current_work_queue = &engine->fast_work_queue; - return NULL; - } + return NULL; } + } found: - nxt_debug(&engine->task, "work queue: %s", wq->name); + nxt_debug(&engine->task, "work queue: %s", wq->name); - return nxt_work_queue_pop(wq, task, obj, data); + return nxt_work_queue_pop(wq, task, obj, data); } +void nxt_event_engine_start(nxt_event_engine_t *engine) { + void *obj, *data; + nxt_task_t *task; + nxt_msec_t timeout, now; + nxt_thread_t *thr; + nxt_work_handler_t handler; -void -nxt_event_engine_start(nxt_event_engine_t *engine) -{ - void *obj, *data; - nxt_task_t *task; - nxt_msec_t timeout, now; - nxt_thread_t *thr; - nxt_work_handler_t handler; - - thr = nxt_thread(); + thr = nxt_thread(); - if (engine->fibers) { - /* - * _setjmp() cannot be wrapped in a function since return from - * the function clobbers stack used by future _setjmp() returns. - */ - _setjmp(engine->fibers->fiber.jmp); + if (engine->fibers) { + /* + * _setjmp() cannot be wrapped in a function since return from + * the function clobbers stack used by future _setjmp() returns. + */ + _setjmp(engine->fibers->fiber.jmp); - /* A return point from fibers. */ - } + /* A return point from fibers. */ + } - thr->log = engine->task.log; + thr->log = engine->task.log; - for ( ;; ) { + for (;;) { - for ( ;; ) { - handler = nxt_event_engine_queue_pop(engine, &task, &obj, &data); + for (;;) { + handler = nxt_event_engine_queue_pop(engine, &task, &obj, &data); - if (handler == NULL) { - break; - } + if (handler == NULL) { + break; + } - thr->task = task; + thr->task = task; - handler(task, obj, data); - } + handler(task, obj, data); + } - /* Attach some event engine work queues in preferred order. */ + /* Attach some event engine work queues in preferred order. */ - timeout = nxt_timer_find(engine); + timeout = nxt_timer_find(engine); - engine->event.poll(engine, timeout); + engine->event.poll(engine, timeout); - now = nxt_thread_monotonic_time(thr) / 1000000; + now = nxt_thread_monotonic_time(thr) / 1000000; - nxt_timer_expire(engine, now); - } + nxt_timer_expire(engine, now); + } } +void *nxt_event_engine_mem_alloc(nxt_event_engine_t *engine, uint8_t *hint, + size_t size) { + uint32_t n; + nxt_uint_t items; + nxt_array_t *mem_cache; + nxt_mem_cache_t *cache; + nxt_mem_cache_block_t *block; -void * -nxt_event_engine_mem_alloc(nxt_event_engine_t *engine, uint8_t *hint, - size_t size) -{ - uint32_t n; - nxt_uint_t items; - nxt_array_t *mem_cache; - nxt_mem_cache_t *cache; - nxt_mem_cache_block_t *block; + mem_cache = engine->mem_cache; + n = *hint; - mem_cache = engine->mem_cache; - n = *hint; + if (n == NXT_EVENT_ENGINE_NO_MEM_HINT) { - if (n == NXT_EVENT_ENGINE_NO_MEM_HINT) { - - if (mem_cache == NULL) { - /* IPv4 nxt_sockaddr_t and HTTP/1 and HTTP/2 buffers. */ - items = 3; + if (mem_cache == NULL) { + /* IPv4 nxt_sockaddr_t and HTTP/1 and HTTP/2 buffers. */ + items = 3; #if (NXT_INET6) - items++; + items++; #endif #if (NXT_HAVE_UNIX_DOMAIN) - items++; + items++; #endif - mem_cache = nxt_array_create(engine->mem_pool, items, - sizeof(nxt_mem_cache_t)); - if (nxt_slow_path(mem_cache == NULL)) { - return mem_cache; - } + mem_cache = + nxt_array_create(engine->mem_pool, items, sizeof(nxt_mem_cache_t)); + if (nxt_slow_path(mem_cache == NULL)) { + return mem_cache; + } - engine->mem_cache = mem_cache; - } + engine->mem_cache = mem_cache; + } - cache = mem_cache->elts; - for (n = 0; n < mem_cache->nelts; n++) { - if (cache[n].size == size) { - goto found; - } - } + cache = mem_cache->elts; + for (n = 0; n < mem_cache->nelts; n++) { + if (cache[n].size == size) { + goto found; + } + } - cache = nxt_array_add(mem_cache); - if (nxt_slow_path(cache == NULL)) { - return cache; - } + cache = nxt_array_add(mem_cache); + if (nxt_slow_path(cache == NULL)) { + return cache; + } - cache->free = NULL; - cache->size = size; - cache->count = 0; + cache->free = NULL; + cache->size = size; + cache->count = 0; - found: + found: - if (n < NXT_EVENT_ENGINE_NO_MEM_HINT) { - *hint = (uint8_t) n; - } + if (n < NXT_EVENT_ENGINE_NO_MEM_HINT) { + *hint = (uint8_t)n; } + } - cache = mem_cache->elts; - cache = cache + n; + cache = mem_cache->elts; + cache = cache + n; - block = cache->free; + block = cache->free; - if (block != NULL) { - cache->free = block->next; - cache->count--; - return block; - } + if (block != NULL) { + cache->free = block->next; + cache->count--; + return block; + } - return nxt_mp_alloc(engine->mem_pool, size); + return nxt_mp_alloc(engine->mem_pool, size); } +void nxt_event_engine_mem_free(nxt_event_engine_t *engine, uint8_t hint, + void *p, size_t size) { + uint32_t n; + nxt_array_t *mem_cache; + nxt_mem_cache_t *cache; + nxt_mem_cache_block_t *block; -void -nxt_event_engine_mem_free(nxt_event_engine_t *engine, uint8_t hint, void *p, - size_t size) -{ - uint32_t n; - nxt_array_t *mem_cache; - nxt_mem_cache_t *cache; - nxt_mem_cache_block_t *block; + block = p; + mem_cache = engine->mem_cache; + cache = mem_cache->elts; - block = p; - mem_cache = engine->mem_cache; - cache = mem_cache->elts; + n = hint; - n = hint; + if (nxt_slow_path(n == NXT_EVENT_ENGINE_NO_MEM_HINT)) { - if (nxt_slow_path(n == NXT_EVENT_ENGINE_NO_MEM_HINT)) { - - if (size != 0) { - for (n = 0; n < mem_cache->nelts; n++) { - if (cache[n].size == size) { - goto found; - } - } - - nxt_alert(&engine->task, - "event engine mem free(%p, %z) not found", p, size); + if (size != 0) { + for (n = 0; n < mem_cache->nelts; n++) { + if (cache[n].size == size) { + goto found; } + } - goto done; + nxt_alert(&engine->task, "event engine mem free(%p, %z) not found", p, + size); } + goto done; + } + found: - cache = cache + n; + cache = cache + n; - if (cache->count < 16) { - cache->count++; - block->next = cache->free; - cache->free = block; + if (cache->count < 16) { + cache->count++; + block->next = cache->free; + cache->free = block; - return; - } + return; + } done: - nxt_mp_free(engine->mem_pool, p); + nxt_mp_free(engine->mem_pool, p); } +void *nxt_event_engine_buf_mem_alloc(nxt_event_engine_t *engine, size_t size) { + nxt_buf_t *b; + uint8_t hint; -void * -nxt_event_engine_buf_mem_alloc(nxt_event_engine_t *engine, size_t size) -{ - nxt_buf_t *b; - uint8_t hint; - - hint = NXT_EVENT_ENGINE_NO_MEM_HINT; + hint = NXT_EVENT_ENGINE_NO_MEM_HINT; - b = nxt_event_engine_mem_alloc(engine, &hint, NXT_BUF_MEM_SIZE + size); - if (nxt_slow_path(b == NULL)) { - return NULL; - } + b = nxt_event_engine_mem_alloc(engine, &hint, NXT_BUF_MEM_SIZE + size); + if (nxt_slow_path(b == NULL)) { + return NULL; + } - nxt_memzero(b, NXT_BUF_MEM_SIZE); + nxt_memzero(b, NXT_BUF_MEM_SIZE); - b->cache_hint = hint; - b->data = engine; - b->completion_handler = nxt_event_engine_buf_mem_completion; + b->cache_hint = hint; + b->data = engine; + b->completion_handler = nxt_event_engine_buf_mem_completion; - if (size != 0) { - b->mem.start = nxt_pointer_to(b, NXT_BUF_MEM_SIZE); - b->mem.pos = b->mem.start; - b->mem.free = b->mem.start; - b->mem.end = b->mem.start + size; - } + if (size != 0) { + b->mem.start = nxt_pointer_to(b, NXT_BUF_MEM_SIZE); + b->mem.pos = b->mem.start; + b->mem.free = b->mem.start; + b->mem.end = b->mem.start + size; + } - return b; + return b; } +void nxt_event_engine_buf_mem_free(nxt_event_engine_t *engine, nxt_buf_t *b) { + size_t size; -void -nxt_event_engine_buf_mem_free(nxt_event_engine_t *engine, nxt_buf_t *b) -{ - size_t size; + size = NXT_BUF_MEM_SIZE + nxt_buf_mem_size(&b->mem); - size = NXT_BUF_MEM_SIZE + nxt_buf_mem_size(&b->mem); - - nxt_event_engine_mem_free(engine, b->cache_hint, b, size); + nxt_event_engine_mem_free(engine, b->cache_hint, b, size); } +void nxt_event_engine_buf_mem_completion(nxt_task_t *task, void *obj, + void *data) { + nxt_buf_t *b, *next, *parent; + nxt_event_engine_t *engine; -void -nxt_event_engine_buf_mem_completion(nxt_task_t *task, void *obj, void *data) -{ - nxt_buf_t *b, *next, *parent; - nxt_event_engine_t *engine; - - b = obj; + b = obj; - nxt_debug(task, "buf completion: %p %p", b, b->mem.start); + nxt_debug(task, "buf completion: %p %p", b, b->mem.start); - engine = b->data; + engine = b->data; - do { - next = b->next; - parent = b->parent; + do { + next = b->next; + parent = b->parent; - nxt_event_engine_buf_mem_free(engine, b); + nxt_event_engine_buf_mem_free(engine, b); - nxt_buf_parent_completion(task, parent); + nxt_buf_parent_completion(task, parent); - b = next; - } while (b != NULL); + b = next; + } while (b != NULL); } - #if (NXT_DEBUG) -void nxt_event_engine_thread_adopt(nxt_event_engine_t *engine) -{ - nxt_work_queue_thread_adopt(&engine->fast_work_queue); - nxt_work_queue_thread_adopt(&engine->accept_work_queue); - nxt_work_queue_thread_adopt(&engine->read_work_queue); - nxt_work_queue_thread_adopt(&engine->socket_work_queue); - nxt_work_queue_thread_adopt(&engine->connect_work_queue); - nxt_work_queue_thread_adopt(&engine->write_work_queue); - nxt_work_queue_thread_adopt(&engine->shutdown_work_queue); - nxt_work_queue_thread_adopt(&engine->close_work_queue); +void nxt_event_engine_thread_adopt(nxt_event_engine_t *engine) { + nxt_work_queue_thread_adopt(&engine->fast_work_queue); + nxt_work_queue_thread_adopt(&engine->accept_work_queue); + nxt_work_queue_thread_adopt(&engine->read_work_queue); + nxt_work_queue_thread_adopt(&engine->socket_work_queue); + nxt_work_queue_thread_adopt(&engine->connect_work_queue); + nxt_work_queue_thread_adopt(&engine->write_work_queue); + nxt_work_queue_thread_adopt(&engine->shutdown_work_queue); + nxt_work_queue_thread_adopt(&engine->close_work_queue); } #endif diff --git a/src/nxt_event_engine.h b/src/nxt_event_engine.h index 291ea749b..936e81ad1 100644 --- a/src/nxt_event_engine.h +++ b/src/nxt_event_engine.h @@ -13,519 +13,466 @@ * signals, etc. */ -#define NXT_FILE_EVENTS 1 -#define NXT_NO_FILE_EVENTS 0 - -#define NXT_SIGNAL_EVENTS 1 -#define NXT_NO_SIGNAL_EVENTS 0 +#define NXT_FILE_EVENTS 1 +#define NXT_NO_FILE_EVENTS 0 +#define NXT_SIGNAL_EVENTS 1 +#define NXT_NO_SIGNAL_EVENTS 0 typedef struct { - /* The canonical event set name. */ - const char *name; - - /* - * Create an event set. The mchanges argument is a maximum number of - * changes to send to the kernel. The mevents argument is a maximum - * number of events to retrieve from the kernel at once, if underlying - * event facility supports batch operations. - */ - nxt_int_t (*create)(nxt_event_engine_t *engine, - nxt_uint_t mchanges, nxt_uint_t mevents); - - /* Close and free an event set. */ - void (*free)(nxt_event_engine_t *engine); - - /* - * Add a file descriptor to an event set and enable the most - * effective read and write event notification method provided - * by underlying event facility. - */ - void (*enable)(nxt_event_engine_t *engine, - nxt_fd_event_t *ev); - - /* Disable file descriptor event notifications. */ - void (*disable)(nxt_event_engine_t *engine, - nxt_fd_event_t *ev); - - /* - * Delete a file descriptor from an event set. A possible usage - * is a moving of the file descriptor from one event set to another. - */ - void (*delete)(nxt_event_engine_t *engine, - nxt_fd_event_t *ev); - - /* - * Delete a file descriptor from an event set before closing the - * file descriptor. The most event facilities such as Linux epoll, - * BSD kqueue, Solaris event ports, AIX pollset, and HP-UX /dev/poll - * delete a file descriptor automatically on the file descriptor close. - * Some facilities such as Solaris /dev/poll require to delete a file - * descriptor explicitly. - */ - nxt_bool_t (*close)(nxt_event_engine_t *engine, - nxt_fd_event_t *ev); - - /* - * Add a file descriptor to an event set and enable the most effective - * read event notification method provided by underlying event facility. - */ - void (*enable_read)(nxt_event_engine_t *engine, - nxt_fd_event_t *ev); - - /* - * Add a file descriptor to an event set and enable the most effective - * write event notification method provided by underlying event facility. - */ - void (*enable_write)(nxt_event_engine_t *engine, - nxt_fd_event_t *ev); - - /* Disable file descriptor read event notifications. */ - void (*disable_read)(nxt_event_engine_t *engine, - nxt_fd_event_t *ev); - - /* Disable file descriptor write event notifications. */ - void (*disable_write)(nxt_event_engine_t *engine, - nxt_fd_event_t *ev); - - /* Block file descriptor read event notifications. */ - void (*block_read)(nxt_event_engine_t *engine, - nxt_fd_event_t *ev); - - /* Block file descriptor write event notifications. */ - void (*block_write)(nxt_event_engine_t *engine, - nxt_fd_event_t *ev); - - /* - * Add a file descriptor to an event set and enable an oneshot - * read event notification method. - */ - void (*oneshot_read)(nxt_event_engine_t *engine, - nxt_fd_event_t *ev); - - /* - * Add a file descriptor to an event set and enable an oneshot - * write event notification method. - */ - void (*oneshot_write)(nxt_event_engine_t *engine, - nxt_fd_event_t *ev); - - /* - * Add a listening socket descriptor to an event set and enable - * a level-triggered read event notification method. - */ - void (*enable_accept)(nxt_event_engine_t *engine, - nxt_fd_event_t *ev); - - /* - * Add a file to an event set and enable a file change notification - * events. - */ - void (*enable_file)(nxt_event_engine_t *engine, - nxt_file_event_t *ev); - - /* - * Delete a file from an event set before closing the file descriptor. - */ - void (*close_file)(nxt_event_engine_t *engine, - nxt_file_event_t *ev); - - /* - * Enable post event notifications and set a post handler to handle - * the zero signal. - */ - nxt_int_t (*enable_post)(nxt_event_engine_t *engine, - nxt_work_handler_t handler); - - /* - * Signal an event set. If a signal number is non-zero then - * a signal handler added to the event set is called. This is - * a way to route Unix signals to an event engine if underlying - * event facility does not support signal events. - * - * If a signal number is zero, then the post_handler of the event - * set is called. This has no relation to Unix signals but is - * a way to wake up the event set to process works posted to - * the event engine locked work queue. - */ - void (*signal)(nxt_event_engine_t *engine, - nxt_uint_t signo); - - /* Poll an event set for new event notifications. */ - void (*poll)(nxt_event_engine_t *engine, - nxt_msec_t timeout); - - /* I/O operations suitable to underlying event facility. */ - nxt_conn_io_t *io; - - /* True if an event facility supports file change event notifications. */ - uint8_t file_support; /* 1 bit */ - - /* True if an event facility supports signal event notifications. */ - uint8_t signal_support; /* 1 bit */ + /* The canonical event set name. */ + const char *name; + + /* + * Create an event set. The mchanges argument is a maximum number of + * changes to send to the kernel. The mevents argument is a maximum + * number of events to retrieve from the kernel at once, if underlying + * event facility supports batch operations. + */ + nxt_int_t (*create)(nxt_event_engine_t *engine, nxt_uint_t mchanges, + nxt_uint_t mevents); + + /* Close and free an event set. */ + void (*free)(nxt_event_engine_t *engine); + + /* + * Add a file descriptor to an event set and enable the most + * effective read and write event notification method provided + * by underlying event facility. + */ + void (*enable)(nxt_event_engine_t *engine, nxt_fd_event_t *ev); + + /* Disable file descriptor event notifications. */ + void (*disable)(nxt_event_engine_t *engine, nxt_fd_event_t *ev); + + /* + * Delete a file descriptor from an event set. A possible usage + * is a moving of the file descriptor from one event set to another. + */ + void (*delete)(nxt_event_engine_t *engine, nxt_fd_event_t *ev); + + /* + * Delete a file descriptor from an event set before closing the + * file descriptor. The most event facilities such as Linux epoll, + * BSD kqueue, Solaris event ports, AIX pollset, and HP-UX /dev/poll + * delete a file descriptor automatically on the file descriptor close. + * Some facilities such as Solaris /dev/poll require to delete a file + * descriptor explicitly. + */ + nxt_bool_t (*close)(nxt_event_engine_t *engine, nxt_fd_event_t *ev); + + /* + * Add a file descriptor to an event set and enable the most effective + * read event notification method provided by underlying event facility. + */ + void (*enable_read)(nxt_event_engine_t *engine, nxt_fd_event_t *ev); + + /* + * Add a file descriptor to an event set and enable the most effective + * write event notification method provided by underlying event facility. + */ + void (*enable_write)(nxt_event_engine_t *engine, nxt_fd_event_t *ev); + + /* Disable file descriptor read event notifications. */ + void (*disable_read)(nxt_event_engine_t *engine, nxt_fd_event_t *ev); + + /* Disable file descriptor write event notifications. */ + void (*disable_write)(nxt_event_engine_t *engine, nxt_fd_event_t *ev); + + /* Block file descriptor read event notifications. */ + void (*block_read)(nxt_event_engine_t *engine, nxt_fd_event_t *ev); + + /* Block file descriptor write event notifications. */ + void (*block_write)(nxt_event_engine_t *engine, nxt_fd_event_t *ev); + + /* + * Add a file descriptor to an event set and enable an oneshot + * read event notification method. + */ + void (*oneshot_read)(nxt_event_engine_t *engine, nxt_fd_event_t *ev); + + /* + * Add a file descriptor to an event set and enable an oneshot + * write event notification method. + */ + void (*oneshot_write)(nxt_event_engine_t *engine, nxt_fd_event_t *ev); + + /* + * Add a listening socket descriptor to an event set and enable + * a level-triggered read event notification method. + */ + void (*enable_accept)(nxt_event_engine_t *engine, nxt_fd_event_t *ev); + + /* + * Add a file to an event set and enable a file change notification + * events. + */ + void (*enable_file)(nxt_event_engine_t *engine, nxt_file_event_t *ev); + + /* + * Delete a file from an event set before closing the file descriptor. + */ + void (*close_file)(nxt_event_engine_t *engine, nxt_file_event_t *ev); + + /* + * Enable post event notifications and set a post handler to handle + * the zero signal. + */ + nxt_int_t (*enable_post)(nxt_event_engine_t *engine, + nxt_work_handler_t handler); + + /* + * Signal an event set. If a signal number is non-zero then + * a signal handler added to the event set is called. This is + * a way to route Unix signals to an event engine if underlying + * event facility does not support signal events. + * + * If a signal number is zero, then the post_handler of the event + * set is called. This has no relation to Unix signals but is + * a way to wake up the event set to process works posted to + * the event engine locked work queue. + */ + void (*signal)(nxt_event_engine_t *engine, nxt_uint_t signo); + + /* Poll an event set for new event notifications. */ + void (*poll)(nxt_event_engine_t *engine, nxt_msec_t timeout); + + /* I/O operations suitable to underlying event facility. */ + nxt_conn_io_t *io; + + /* True if an event facility supports file change event notifications. */ + uint8_t file_support; /* 1 bit */ + + /* True if an event facility supports signal event notifications. */ + uint8_t signal_support; /* 1 bit */ } nxt_event_interface_t; - #if (NXT_HAVE_KQUEUE) typedef struct { - int fd; - int nchanges; - int mchanges; - int mevents; - nxt_pid_t pid; + int fd; + int nchanges; + int mchanges; + int mevents; + nxt_pid_t pid; - nxt_work_handler_t post_handler; + nxt_work_handler_t post_handler; - struct kevent *changes; - struct kevent *events; + struct kevent *changes; + struct kevent *events; } nxt_kqueue_engine_t; -extern const nxt_event_interface_t nxt_kqueue_engine; +extern const nxt_event_interface_t nxt_kqueue_engine; #endif - #if (NXT_HAVE_EPOLL) typedef struct { - int op; - struct epoll_event event; + int op; + struct epoll_event event; } nxt_epoll_change_t; - typedef struct { - int fd; - uint32_t mode; - nxt_uint_t nchanges; - nxt_uint_t mchanges; - int mevents; + int fd; + uint32_t mode; + nxt_uint_t nchanges; + nxt_uint_t mchanges; + int mevents; - uint8_t error; /* 1 bit */ + uint8_t error; /* 1 bit */ - nxt_epoll_change_t *changes; - struct epoll_event *events; + nxt_epoll_change_t *changes; + struct epoll_event *events; #if (NXT_HAVE_EVENTFD) - nxt_work_handler_t post_handler; - nxt_fd_event_t eventfd; - uint32_t neventfd; + nxt_work_handler_t post_handler; + nxt_fd_event_t eventfd; + uint32_t neventfd; #endif #if (NXT_HAVE_SIGNALFD) - nxt_fd_event_t signalfd; + nxt_fd_event_t signalfd; #endif } nxt_epoll_engine_t; - -extern const nxt_event_interface_t nxt_epoll_edge_engine; -extern const nxt_event_interface_t nxt_epoll_level_engine; +extern const nxt_event_interface_t nxt_epoll_edge_engine; +extern const nxt_event_interface_t nxt_epoll_level_engine; #endif - #if (NXT_HAVE_EVENTPORT) typedef struct { - int events; - nxt_fd_event_t *event; + int events; + nxt_fd_event_t *event; } nxt_eventport_change_t; - typedef struct { - int fd; - nxt_uint_t nchanges; - nxt_uint_t mchanges; - u_int mevents; + int fd; + nxt_uint_t nchanges; + nxt_uint_t mchanges; + u_int mevents; - nxt_eventport_change_t *changes; - port_event_t *events; + nxt_eventport_change_t *changes; + port_event_t *events; - nxt_work_handler_t post_handler; - nxt_work_handler_t signal_handler; + nxt_work_handler_t post_handler; + nxt_work_handler_t signal_handler; } nxt_eventport_engine_t; -extern const nxt_event_interface_t nxt_eventport_engine; +extern const nxt_event_interface_t nxt_eventport_engine; #endif - #if (NXT_HAVE_DEVPOLL) typedef struct { - uint8_t op; - short events; - nxt_fd_event_t *event; + uint8_t op; + short events; + nxt_fd_event_t *event; } nxt_devpoll_change_t; - typedef struct { - int fd; - int nchanges; - int mchanges; - int mevents; - - nxt_devpoll_change_t *changes; - struct pollfd *write_changes; - struct pollfd *events; - nxt_lvlhsh_t fd_hash; + int fd; + int nchanges; + int mchanges; + int mevents; + + nxt_devpoll_change_t *changes; + struct pollfd *write_changes; + struct pollfd *events; + nxt_lvlhsh_t fd_hash; } nxt_devpoll_engine_t; -extern const nxt_event_interface_t nxt_devpoll_engine; +extern const nxt_event_interface_t nxt_devpoll_engine; #endif - #if (NXT_HAVE_POLLSET) typedef struct { - uint8_t op; - uint8_t cmd; - short events; - nxt_fd_event_t *event; + uint8_t op; + uint8_t cmd; + short events; + nxt_fd_event_t *event; } nxt_pollset_change_t; - typedef struct { - pollset_t ps; - int nchanges; - int mchanges; - int mevents; - - nxt_pollset_change_t *changes; - struct poll_ctl *write_changes; - struct pollfd *events; - nxt_lvlhsh_t fd_hash; + pollset_t ps; + int nchanges; + int mchanges; + int mevents; + + nxt_pollset_change_t *changes; + struct poll_ctl *write_changes; + struct pollfd *events; + nxt_lvlhsh_t fd_hash; } nxt_pollset_engine_t; -extern const nxt_event_interface_t nxt_pollset_engine; +extern const nxt_event_interface_t nxt_pollset_engine; #endif - typedef struct { - uint8_t op; - short events; - nxt_fd_event_t *event; + uint8_t op; + short events; + nxt_fd_event_t *event; } nxt_poll_change_t; - typedef struct { - nxt_uint_t max_nfds; - nxt_uint_t nfds; + nxt_uint_t max_nfds; + nxt_uint_t nfds; - nxt_uint_t nchanges; - nxt_uint_t mchanges; + nxt_uint_t nchanges; + nxt_uint_t mchanges; - nxt_poll_change_t *changes; - struct pollfd *set; + nxt_poll_change_t *changes; + struct pollfd *set; - nxt_lvlhsh_t fd_hash; + nxt_lvlhsh_t fd_hash; } nxt_poll_engine_t; -extern const nxt_event_interface_t nxt_poll_engine; - +extern const nxt_event_interface_t nxt_poll_engine; typedef struct { - int nfds; - uint32_t update_nfds; /* 1 bit */ + int nfds; + uint32_t update_nfds; /* 1 bit */ - nxt_fd_event_t **events; + nxt_fd_event_t **events; - fd_set main_read_fd_set; - fd_set main_write_fd_set; - fd_set work_read_fd_set; - fd_set work_write_fd_set; + fd_set main_read_fd_set; + fd_set main_write_fd_set; + fd_set work_read_fd_set; + fd_set work_write_fd_set; } nxt_select_engine_t; -extern const nxt_event_interface_t nxt_select_engine; - +extern const nxt_event_interface_t nxt_select_engine; nxt_int_t nxt_fd_event_hash_add(nxt_lvlhsh_t *lvlhsh, nxt_fd_t fd, - nxt_fd_event_t *ev); + nxt_fd_event_t *ev); void *nxt_fd_event_hash_get(nxt_task_t *task, nxt_lvlhsh_t *lvlhsh, - nxt_fd_t fd); + nxt_fd_t fd); void nxt_fd_event_hash_delete(nxt_task_t *task, nxt_lvlhsh_t *lvlhsh, - nxt_fd_t fd, nxt_bool_t ignore); + nxt_fd_t fd, nxt_bool_t ignore); void nxt_fd_event_hash_destroy(nxt_lvlhsh_t *lvlhsh); +#define nxt_fd_event_disable(engine, ev) (engine)->event.disable(engine, ev) -#define nxt_fd_event_disable(engine, ev) \ - (engine)->event.disable(engine, ev) - - -#define nxt_fd_event_delete(engine, ev) \ - (engine)->event.delete(engine, ev) +#define nxt_fd_event_delete(engine, ev) (engine)->event.delete(engine, ev) +#define nxt_fd_event_close(engine, ev) (engine)->event.close(engine, ev) -#define nxt_fd_event_close(engine, ev) \ - (engine)->event.close(engine, ev) +#define nxt_fd_event_enable_read(engine, ev) \ + (engine)->event.enable_read(engine, ev) +#define nxt_fd_event_enable_write(engine, ev) \ + (engine)->event.enable_write(engine, ev) -#define nxt_fd_event_enable_read(engine, ev) \ - (engine)->event.enable_read(engine, ev) +#define nxt_fd_event_disable_read(engine, ev) \ + (engine)->event.disable_read(engine, ev) +#define nxt_fd_event_disable_write(engine, ev) \ + (engine)->event.disable_write(engine, ev) -#define nxt_fd_event_enable_write(engine, ev) \ - (engine)->event.enable_write(engine, ev) +#define nxt_fd_event_block_read(engine, ev) \ + do { \ + if (nxt_fd_event_is_active((ev)->read)) { \ + (engine)->event.block_read(engine, ev); \ + } \ + } while (0) +#define nxt_fd_event_block_write(engine, ev) \ + do { \ + if (nxt_fd_event_is_active((ev)->write)) { \ + (engine)->event.block_write(engine, ev); \ + } \ + } while (0) -#define nxt_fd_event_disable_read(engine, ev) \ - (engine)->event.disable_read(engine, ev) +#define nxt_fd_event_oneshot_read(engine, ev) \ + (engine)->event.oneshot_read(engine, ev) +#define nxt_fd_event_oneshot_write(engine, ev) \ + (engine)->event.oneshot_write(engine, ev) -#define nxt_fd_event_disable_write(engine, ev) \ - (engine)->event.disable_write(engine, ev) - - -#define nxt_fd_event_block_read(engine, ev) \ - do { \ - if (nxt_fd_event_is_active((ev)->read)) { \ - (engine)->event.block_read(engine, ev); \ - } \ - } while (0) - - -#define nxt_fd_event_block_write(engine, ev) \ - do { \ - if (nxt_fd_event_is_active((ev)->write)) { \ - (engine)->event.block_write(engine, ev); \ - } \ - } while (0) - - -#define nxt_fd_event_oneshot_read(engine, ev) \ - (engine)->event.oneshot_read(engine, ev) - - -#define nxt_fd_event_oneshot_write(engine, ev) \ - (engine)->event.oneshot_write(engine, ev) - - -#define nxt_fd_event_enable_accept(engine, ev) \ - (engine)->event.enable_accept(engine, ev) - - -#define NXT_ENGINE_FIBERS 1 +#define nxt_fd_event_enable_accept(engine, ev) \ + (engine)->event.enable_accept(engine, ev) +#define NXT_ENGINE_FIBERS 1 typedef struct { - nxt_fd_t fds[2]; - nxt_fd_event_t event; + nxt_fd_t fds[2]; + nxt_fd_event_t event; } nxt_event_engine_pipe_t; - struct nxt_event_engine_s { - nxt_task_t task; + nxt_task_t task; - union { - nxt_poll_engine_t poll; - nxt_select_engine_t select; + union { + nxt_poll_engine_t poll; + nxt_select_engine_t select; #if (NXT_HAVE_KQUEUE) - nxt_kqueue_engine_t kqueue; + nxt_kqueue_engine_t kqueue; #endif #if (NXT_HAVE_EPOLL) - nxt_epoll_engine_t epoll; + nxt_epoll_engine_t epoll; #endif #if (NXT_HAVE_EVENTPORT) - nxt_eventport_engine_t eventport; + nxt_eventport_engine_t eventport; #endif #if (NXT_HAVE_DEVPOLL) - nxt_devpoll_engine_t devpoll; + nxt_devpoll_engine_t devpoll; #endif #if (NXT_HAVE_POLLSET) - nxt_pollset_engine_t pollset; + nxt_pollset_engine_t pollset; #endif - } u; + } u; - nxt_timers_t timers; + nxt_timers_t timers; - nxt_work_queue_cache_t work_queue_cache; - nxt_work_queue_t *current_work_queue; - nxt_work_queue_t fast_work_queue; - nxt_work_queue_t accept_work_queue; - nxt_work_queue_t read_work_queue; - nxt_work_queue_t socket_work_queue; - nxt_work_queue_t connect_work_queue; - nxt_work_queue_t write_work_queue; - nxt_work_queue_t shutdown_work_queue; - nxt_work_queue_t close_work_queue; + nxt_work_queue_cache_t work_queue_cache; + nxt_work_queue_t *current_work_queue; + nxt_work_queue_t fast_work_queue; + nxt_work_queue_t accept_work_queue; + nxt_work_queue_t read_work_queue; + nxt_work_queue_t socket_work_queue; + nxt_work_queue_t connect_work_queue; + nxt_work_queue_t write_work_queue; + nxt_work_queue_t shutdown_work_queue; + nxt_work_queue_t close_work_queue; - nxt_locked_work_queue_t locked_work_queue; + nxt_locked_work_queue_t locked_work_queue; - nxt_event_interface_t event; + nxt_event_interface_t event; - /* - * A pipe to pass event signals to the engine, if the engine's - * underlying event facility does not support user events. - */ - nxt_event_engine_pipe_t *pipe; + /* + * A pipe to pass event signals to the engine, if the engine's + * underlying event facility does not support user events. + */ + nxt_event_engine_pipe_t *pipe; - nxt_event_signals_t *signals; + nxt_event_signals_t *signals; - nxt_fiber_main_t *fibers; + nxt_fiber_main_t *fibers; - /* The engine ID, the main engine has ID 0. */ - uint32_t id; + /* The engine ID, the main engine has ID 0. */ + uint32_t id; - uint8_t shutdown; /* 1 bit */ + uint8_t shutdown; /* 1 bit */ - uint32_t batch; - uint32_t connections; - uint32_t max_connections; + uint32_t batch; + uint32_t connections; + uint32_t max_connections; - nxt_port_t *port; - nxt_mp_t *mem_pool; - nxt_queue_t joints; - nxt_queue_t listen_connections; - nxt_queue_t idle_connections; - nxt_array_t *mem_cache; + nxt_port_t *port; + nxt_mp_t *mem_pool; + nxt_queue_t joints; + nxt_queue_t listen_connections; + nxt_queue_t idle_connections; + nxt_array_t *mem_cache; - nxt_atomic_uint_t accepted_conns_cnt; - nxt_atomic_uint_t idle_conns_cnt; - nxt_atomic_uint_t closed_conns_cnt; - nxt_atomic_uint_t requests_cnt; + nxt_atomic_uint_t accepted_conns_cnt; + nxt_atomic_uint_t idle_conns_cnt; + nxt_atomic_uint_t closed_conns_cnt; + nxt_atomic_uint_t requests_cnt; - nxt_queue_link_t link; - // STUB: router link - nxt_queue_link_t link0; + nxt_queue_link_t link; + // STUB: router link + nxt_queue_link_t link0; }; - -NXT_EXPORT nxt_event_engine_t *nxt_event_engine_create(nxt_task_t *task, - const nxt_event_interface_t *interface, const nxt_sig_event_t *signals, - nxt_uint_t flags, nxt_uint_t batch); -NXT_EXPORT nxt_int_t nxt_event_engine_change(nxt_event_engine_t *engine, - const nxt_event_interface_t *interface, nxt_uint_t batch); +NXT_EXPORT nxt_event_engine_t *nxt_event_engine_create( + nxt_task_t *task, const nxt_event_interface_t *interface, + const nxt_sig_event_t *signals, nxt_uint_t flags, nxt_uint_t batch); +NXT_EXPORT nxt_int_t nxt_event_engine_change( + nxt_event_engine_t *engine, const nxt_event_interface_t *interface, + nxt_uint_t batch); NXT_EXPORT void nxt_event_engine_free(nxt_event_engine_t *engine); NXT_EXPORT void nxt_event_engine_start(nxt_event_engine_t *engine); NXT_EXPORT void nxt_event_engine_post(nxt_event_engine_t *engine, - nxt_work_t *work); + nxt_work_t *work); NXT_EXPORT void nxt_event_engine_signal(nxt_event_engine_t *engine, - nxt_uint_t signo); + nxt_uint_t signo); -#define NXT_EVENT_ENGINE_NO_MEM_HINT 255 +#define NXT_EVENT_ENGINE_NO_MEM_HINT 255 void *nxt_event_engine_mem_alloc(nxt_event_engine_t *engine, uint8_t *hint, - size_t size); + size_t size); void nxt_event_engine_mem_free(nxt_event_engine_t *engine, uint8_t hint, - void *p, size_t size); + void *p, size_t size); void *nxt_event_engine_buf_mem_alloc(nxt_event_engine_t *engine, size_t size); void nxt_event_engine_buf_mem_free(nxt_event_engine_t *engine, nxt_buf_t *b); void nxt_event_engine_buf_mem_completion(nxt_task_t *task, void *obj, - void *data); + void *data); +nxt_inline nxt_event_engine_t *nxt_thread_event_engine(void) { + nxt_thread_t *thr; -nxt_inline nxt_event_engine_t * -nxt_thread_event_engine(void) -{ - nxt_thread_t *thr; - - thr = nxt_thread(); - return thr->engine; + thr = nxt_thread(); + return thr->engine; } #if (NXT_DEBUG) @@ -538,5 +485,4 @@ NXT_EXPORT void nxt_event_engine_thread_adopt(nxt_event_engine_t *engine); #endif - #endif /* _NXT_EVENT_ENGINE_H_INCLUDED_ */ diff --git a/src/nxt_eventport_engine.c b/src/nxt_eventport_engine.c index 7ac7f44de..bb958a7fe 100644 --- a/src/nxt_eventport_engine.c +++ b/src/nxt_eventport_engine.c @@ -6,56 +6,52 @@ #include - /* * The event ports have been introduced in Solaris 10. * The PORT_SOURCE_MQ and PORT_SOURCE_FILE sources have * been added in OpenSolaris. */ - static nxt_int_t nxt_eventport_create(nxt_event_engine_t *engine, - nxt_uint_t mchanges, nxt_uint_t mevents); + nxt_uint_t mchanges, nxt_uint_t mevents); static void nxt_eventport_free(nxt_event_engine_t *engine); static void nxt_eventport_enable(nxt_event_engine_t *engine, - nxt_fd_event_t *ev); + nxt_fd_event_t *ev); static void nxt_eventport_disable(nxt_event_engine_t *engine, - nxt_fd_event_t *ev); + nxt_fd_event_t *ev); static nxt_bool_t nxt_eventport_close(nxt_event_engine_t *engine, - nxt_fd_event_t *ev); + nxt_fd_event_t *ev); static void nxt_eventport_enable_read(nxt_event_engine_t *engine, - nxt_fd_event_t *ev); + nxt_fd_event_t *ev); static void nxt_eventport_enable_write(nxt_event_engine_t *engine, - nxt_fd_event_t *ev); + nxt_fd_event_t *ev); static void nxt_eventport_enable_event(nxt_event_engine_t *engine, - nxt_fd_event_t *ev, nxt_uint_t events); + nxt_fd_event_t *ev, nxt_uint_t events); static void nxt_eventport_disable_read(nxt_event_engine_t *engine, - nxt_fd_event_t *ev); + nxt_fd_event_t *ev); static void nxt_eventport_disable_write(nxt_event_engine_t *engine, - nxt_fd_event_t *ev); + nxt_fd_event_t *ev); static void nxt_eventport_disable_event(nxt_event_engine_t *engine, - nxt_fd_event_t *ev); + nxt_fd_event_t *ev); static nxt_int_t nxt_eventport_commit_changes(nxt_event_engine_t *engine); static void nxt_eventport_error_handler(nxt_task_t *task, void *obj, - void *data); + void *data); static void nxt_eventport_block_read(nxt_event_engine_t *engine, - nxt_fd_event_t *ev); + nxt_fd_event_t *ev); static void nxt_eventport_block_write(nxt_event_engine_t *engine, - nxt_fd_event_t *ev); + nxt_fd_event_t *ev); static void nxt_eventport_oneshot_read(nxt_event_engine_t *engine, - nxt_fd_event_t *ev); + nxt_fd_event_t *ev); static void nxt_eventport_oneshot_write(nxt_event_engine_t *engine, - nxt_fd_event_t *ev); + nxt_fd_event_t *ev); static void nxt_eventport_enable_accept(nxt_event_engine_t *engine, - nxt_fd_event_t *ev); + nxt_fd_event_t *ev); static nxt_int_t nxt_eventport_enable_post(nxt_event_engine_t *engine, - nxt_work_handler_t handler); + nxt_work_handler_t handler); static void nxt_eventport_signal(nxt_event_engine_t *engine, nxt_uint_t signo); -static void nxt_eventport_poll(nxt_event_engine_t *engine, - nxt_msec_t timeout); +static void nxt_eventport_poll(nxt_event_engine_t *engine, nxt_msec_t timeout); - -const nxt_event_interface_t nxt_eventport_engine = { +const nxt_event_interface_t nxt_eventport_engine = { "eventport", nxt_eventport_create, nxt_eventport_free, @@ -84,530 +80,473 @@ const nxt_event_interface_t nxt_eventport_engine = { NXT_NO_SIGNAL_EVENTS, }; +static nxt_int_t nxt_eventport_create(nxt_event_engine_t *engine, + nxt_uint_t mchanges, nxt_uint_t mevents) { + nxt_eventport_change_t *changes; -static nxt_int_t -nxt_eventport_create(nxt_event_engine_t *engine, nxt_uint_t mchanges, - nxt_uint_t mevents) -{ - nxt_eventport_change_t *changes; + engine->u.eventport.fd = -1; + engine->u.eventport.mchanges = mchanges; + engine->u.eventport.mevents = mevents; - engine->u.eventport.fd = -1; - engine->u.eventport.mchanges = mchanges; - engine->u.eventport.mevents = mevents; + changes = nxt_malloc(sizeof(nxt_eventport_change_t) * mchanges); + if (changes == NULL) { + goto fail; + } - changes = nxt_malloc(sizeof(nxt_eventport_change_t) * mchanges); - if (changes == NULL) { - goto fail; - } + engine->u.eventport.changes = changes; - engine->u.eventport.changes = changes; + engine->u.eventport.events = nxt_malloc(sizeof(port_event_t) * mevents); + if (engine->u.eventport.events == NULL) { + goto fail; + } - engine->u.eventport.events = nxt_malloc(sizeof(port_event_t) * mevents); - if (engine->u.eventport.events == NULL) { - goto fail; - } + engine->u.eventport.fd = port_create(); + if (engine->u.eventport.fd == -1) { + nxt_alert(&engine->task, "port_create() failed %E", nxt_errno); + goto fail; + } - engine->u.eventport.fd = port_create(); - if (engine->u.eventport.fd == -1) { - nxt_alert(&engine->task, "port_create() failed %E", nxt_errno); - goto fail; - } + nxt_debug(&engine->task, "port_create(): %d", engine->u.eventport.fd); - nxt_debug(&engine->task, "port_create(): %d", engine->u.eventport.fd); + if (engine->signals != NULL) { + engine->u.eventport.signal_handler = engine->signals->handler; + } - if (engine->signals != NULL) { - engine->u.eventport.signal_handler = engine->signals->handler; - } - - return NXT_OK; + return NXT_OK; fail: - nxt_eventport_free(engine); + nxt_eventport_free(engine); - return NXT_ERROR; + return NXT_ERROR; } +static void nxt_eventport_free(nxt_event_engine_t *engine) { + int port; -static void -nxt_eventport_free(nxt_event_engine_t *engine) -{ - int port; - - port = engine->u.eventport.fd; + port = engine->u.eventport.fd; - nxt_debug(&engine->task, "eventport %d free", port); + nxt_debug(&engine->task, "eventport %d free", port); - if (port != -1 && close(port) != 0) { - nxt_alert(&engine->task, "eventport close(%d) failed %E", - port, nxt_errno); - } + if (port != -1 && close(port) != 0) { + nxt_alert(&engine->task, "eventport close(%d) failed %E", port, nxt_errno); + } - nxt_free(engine->u.eventport.events); + nxt_free(engine->u.eventport.events); - nxt_memzero(&engine->u.eventport, sizeof(nxt_eventport_engine_t)); + nxt_memzero(&engine->u.eventport, sizeof(nxt_eventport_engine_t)); } +static void nxt_eventport_enable(nxt_event_engine_t *engine, + nxt_fd_event_t *ev) { + ev->read = NXT_EVENT_ACTIVE; + ev->write = NXT_EVENT_ACTIVE; -static void -nxt_eventport_enable(nxt_event_engine_t *engine, nxt_fd_event_t *ev) -{ - ev->read = NXT_EVENT_ACTIVE; - ev->write = NXT_EVENT_ACTIVE; - - nxt_eventport_enable_event(engine, ev, POLLIN | POLLOUT); + nxt_eventport_enable_event(engine, ev, POLLIN | POLLOUT); } +static void nxt_eventport_disable(nxt_event_engine_t *engine, + nxt_fd_event_t *ev) { + if (ev->read != NXT_EVENT_INACTIVE || ev->write != NXT_EVENT_INACTIVE) { -static void -nxt_eventport_disable(nxt_event_engine_t *engine, nxt_fd_event_t *ev) -{ - if (ev->read != NXT_EVENT_INACTIVE || ev->write != NXT_EVENT_INACTIVE) { - - ev->read = NXT_EVENT_INACTIVE; - ev->write = NXT_EVENT_INACTIVE; + ev->read = NXT_EVENT_INACTIVE; + ev->write = NXT_EVENT_INACTIVE; - nxt_eventport_disable_event(engine, ev); - } + nxt_eventport_disable_event(engine, ev); + } } - /* * port_dissociate(3): * * The association is removed if the owner of the association closes the port. */ -static nxt_bool_t -nxt_eventport_close(nxt_event_engine_t *engine, nxt_fd_event_t *ev) -{ - ev->read = NXT_EVENT_INACTIVE; - ev->write = NXT_EVENT_INACTIVE; +static nxt_bool_t nxt_eventport_close(nxt_event_engine_t *engine, + nxt_fd_event_t *ev) { + ev->read = NXT_EVENT_INACTIVE; + ev->write = NXT_EVENT_INACTIVE; - return ev->changing; + return ev->changing; } +static void nxt_eventport_enable_read(nxt_event_engine_t *engine, + nxt_fd_event_t *ev) { + nxt_uint_t events; -static void -nxt_eventport_enable_read(nxt_event_engine_t *engine, nxt_fd_event_t *ev) -{ - nxt_uint_t events; - - if (ev->read != NXT_EVENT_BLOCKED) { - events = (ev->write == NXT_EVENT_INACTIVE) ? POLLIN - : (POLLIN | POLLOUT); - nxt_eventport_enable_event(engine, ev, events); - } + if (ev->read != NXT_EVENT_BLOCKED) { + events = (ev->write == NXT_EVENT_INACTIVE) ? POLLIN : (POLLIN | POLLOUT); + nxt_eventport_enable_event(engine, ev, events); + } - ev->read = NXT_EVENT_ACTIVE; + ev->read = NXT_EVENT_ACTIVE; } +static void nxt_eventport_enable_write(nxt_event_engine_t *engine, + nxt_fd_event_t *ev) { + nxt_uint_t events; -static void -nxt_eventport_enable_write(nxt_event_engine_t *engine, nxt_fd_event_t *ev) -{ - nxt_uint_t events; + if (ev->write != NXT_EVENT_BLOCKED) { + events = (ev->read == NXT_EVENT_INACTIVE) ? POLLOUT : (POLLIN | POLLOUT); + nxt_eventport_enable_event(engine, ev, events); + } - if (ev->write != NXT_EVENT_BLOCKED) { - events = (ev->read == NXT_EVENT_INACTIVE) ? POLLOUT - : (POLLIN | POLLOUT); - nxt_eventport_enable_event(engine, ev, events); - } - - ev->write = NXT_EVENT_ACTIVE; + ev->write = NXT_EVENT_ACTIVE; } - /* * eventport changes are batched to improve instruction and data * cache locality of several port_associate() and port_dissociate() * calls followed by port_getn() call. */ -static void -nxt_eventport_enable_event(nxt_event_engine_t *engine, nxt_fd_event_t *ev, - nxt_uint_t events) -{ - nxt_eventport_change_t *change; +static void nxt_eventport_enable_event(nxt_event_engine_t *engine, + nxt_fd_event_t *ev, nxt_uint_t events) { + nxt_eventport_change_t *change; - nxt_debug(ev->task, "port %d set event: fd:%d ev:%04XD u:%p", - engine->u.eventport.fd, ev->fd, events, ev); + nxt_debug(ev->task, "port %d set event: fd:%d ev:%04XD u:%p", + engine->u.eventport.fd, ev->fd, events, ev); - if (engine->u.eventport.nchanges >= engine->u.eventport.mchanges) { - (void) nxt_eventport_commit_changes(engine); - } + if (engine->u.eventport.nchanges >= engine->u.eventport.mchanges) { + (void)nxt_eventport_commit_changes(engine); + } - ev->changing = 1; + ev->changing = 1; - change = &engine->u.eventport.changes[engine->u.eventport.nchanges++]; - change->events = events; - change->event = ev; + change = &engine->u.eventport.changes[engine->u.eventport.nchanges++]; + change->events = events; + change->event = ev; } +static void nxt_eventport_disable_read(nxt_event_engine_t *engine, + nxt_fd_event_t *ev) { + ev->read = NXT_EVENT_INACTIVE; -static void -nxt_eventport_disable_read(nxt_event_engine_t *engine, nxt_fd_event_t *ev) -{ - ev->read = NXT_EVENT_INACTIVE; - - if (ev->write == NXT_EVENT_INACTIVE) { - nxt_eventport_disable_event(engine, ev); + if (ev->write == NXT_EVENT_INACTIVE) { + nxt_eventport_disable_event(engine, ev); - } else { - nxt_eventport_enable_event(engine, ev, POLLOUT); - } + } else { + nxt_eventport_enable_event(engine, ev, POLLOUT); + } } +static void nxt_eventport_disable_write(nxt_event_engine_t *engine, + nxt_fd_event_t *ev) { + ev->write = NXT_EVENT_INACTIVE; -static void -nxt_eventport_disable_write(nxt_event_engine_t *engine, nxt_fd_event_t *ev) -{ - ev->write = NXT_EVENT_INACTIVE; - - if (ev->read == NXT_EVENT_INACTIVE) { - nxt_eventport_disable_event(engine, ev); + if (ev->read == NXT_EVENT_INACTIVE) { + nxt_eventport_disable_event(engine, ev); - } else { - nxt_eventport_enable_event(engine, ev, POLLIN); - } + } else { + nxt_eventport_enable_event(engine, ev, POLLIN); + } } +static void nxt_eventport_disable_event(nxt_event_engine_t *engine, + nxt_fd_event_t *ev) { + nxt_eventport_change_t *change; -static void -nxt_eventport_disable_event(nxt_event_engine_t *engine, nxt_fd_event_t *ev) -{ - nxt_eventport_change_t *change; - - nxt_debug(ev->task, "port %d disable event : fd:%d", - engine->u.eventport.fd, ev->fd); + nxt_debug(ev->task, "port %d disable event : fd:%d", engine->u.eventport.fd, + ev->fd); - if (engine->u.eventport.nchanges >= engine->u.eventport.mchanges) { - (void) nxt_eventport_commit_changes(engine); - } + if (engine->u.eventport.nchanges >= engine->u.eventport.mchanges) { + (void)nxt_eventport_commit_changes(engine); + } - ev->changing = 1; + ev->changing = 1; - change = &engine->u.eventport.changes[engine->u.eventport.nchanges++]; - change->events = 0; - change->event = ev; + change = &engine->u.eventport.changes[engine->u.eventport.nchanges++]; + change->events = 0; + change->event = ev; } +static nxt_int_t nxt_eventport_commit_changes(nxt_event_engine_t *engine) { + int ret, port; + nxt_int_t retval; + nxt_fd_event_t *ev; + nxt_eventport_change_t *change, *end; -static nxt_int_t -nxt_eventport_commit_changes(nxt_event_engine_t *engine) -{ - int ret, port; - nxt_int_t retval; - nxt_fd_event_t *ev; - nxt_eventport_change_t *change, *end; + port = engine->u.eventport.fd; - port = engine->u.eventport.fd; + nxt_debug(&engine->task, "eventport %d changes:%ui", port, + engine->u.eventport.nchanges); - nxt_debug(&engine->task, "eventport %d changes:%ui", - port, engine->u.eventport.nchanges); + retval = NXT_OK; + change = engine->u.eventport.changes; + end = change + engine->u.eventport.nchanges; - retval = NXT_OK; - change = engine->u.eventport.changes; - end = change + engine->u.eventport.nchanges; + do { + ev = change->event; + ev->changing = 0; - do { - ev = change->event; - ev->changing = 0; + if (change->events != 0) { + nxt_debug(ev->task, "port_associate(%d): fd:%d ev:%04XD u:%p", port, + ev->fd, change->events, ev); - if (change->events != 0) { - nxt_debug(ev->task, "port_associate(%d): fd:%d ev:%04XD u:%p", - port, ev->fd, change->events, ev); + ret = port_associate(port, PORT_SOURCE_FD, ev->fd, change->events, ev); - ret = port_associate(port, PORT_SOURCE_FD, - ev->fd, change->events, ev); + if (nxt_fast_path(ret == 0)) { + goto next; + } - if (nxt_fast_path(ret == 0)) { - goto next; - } + nxt_alert(ev->task, "port_associate(%d, %d, %d, %04XD) failed %E", port, + PORT_SOURCE_FD, ev->fd, change->events, nxt_errno); - nxt_alert(ev->task, "port_associate(%d, %d, %d, %04XD) failed %E", - port, PORT_SOURCE_FD, ev->fd, change->events, nxt_errno); - - } else { - nxt_debug(ev->task, "port_dissociate(%d): fd:%d", port, ev->fd); + } else { + nxt_debug(ev->task, "port_dissociate(%d): fd:%d", port, ev->fd); - ret = port_dissociate(port, PORT_SOURCE_FD, ev->fd); + ret = port_dissociate(port, PORT_SOURCE_FD, ev->fd); - if (nxt_fast_path(ret == 0)) { - goto next; - } + if (nxt_fast_path(ret == 0)) { + goto next; + } - nxt_alert(ev->task, "port_dissociate(%d, %d, %d) failed %E", - port, PORT_SOURCE_FD, ev->fd, nxt_errno); - } + nxt_alert(ev->task, "port_dissociate(%d, %d, %d) failed %E", port, + PORT_SOURCE_FD, ev->fd, nxt_errno); + } - nxt_work_queue_add(&engine->fast_work_queue, - nxt_eventport_error_handler, - ev->task, ev, ev->data); + nxt_work_queue_add(&engine->fast_work_queue, nxt_eventport_error_handler, + ev->task, ev, ev->data); - retval = NXT_ERROR; + retval = NXT_ERROR; - next: + next: - change++; + change++; - } while (change < end); + } while (change < end); - engine->u.eventport.nchanges = 0; + engine->u.eventport.nchanges = 0; - return retval; + return retval; } +static void nxt_eventport_error_handler(nxt_task_t *task, void *obj, + void *data) { + nxt_fd_event_t *ev; -static void -nxt_eventport_error_handler(nxt_task_t *task, void *obj, void *data) -{ - nxt_fd_event_t *ev; - - ev = obj; + ev = obj; - ev->read = NXT_EVENT_INACTIVE; - ev->write = NXT_EVENT_INACTIVE; + ev->read = NXT_EVENT_INACTIVE; + ev->write = NXT_EVENT_INACTIVE; - ev->error_handler(task, ev, data); + ev->error_handler(task, ev, data); } - -static void -nxt_eventport_block_read(nxt_event_engine_t *engine, nxt_fd_event_t *ev) -{ - if (ev->read != NXT_EVENT_INACTIVE) { - ev->read = NXT_EVENT_BLOCKED; - } +static void nxt_eventport_block_read(nxt_event_engine_t *engine, + nxt_fd_event_t *ev) { + if (ev->read != NXT_EVENT_INACTIVE) { + ev->read = NXT_EVENT_BLOCKED; + } } - -static void -nxt_eventport_block_write(nxt_event_engine_t *engine, nxt_fd_event_t *ev) -{ - if (ev->write != NXT_EVENT_INACTIVE) { - ev->write = NXT_EVENT_BLOCKED; - } +static void nxt_eventport_block_write(nxt_event_engine_t *engine, + nxt_fd_event_t *ev) { + if (ev->write != NXT_EVENT_INACTIVE) { + ev->write = NXT_EVENT_BLOCKED; + } } +static void nxt_eventport_oneshot_read(nxt_event_engine_t *engine, + nxt_fd_event_t *ev) { + if (ev->read == NXT_EVENT_INACTIVE) { + ev->read = NXT_EVENT_ACTIVE; -static void -nxt_eventport_oneshot_read(nxt_event_engine_t *engine, nxt_fd_event_t *ev) -{ - if (ev->read == NXT_EVENT_INACTIVE) { - ev->read = NXT_EVENT_ACTIVE; - - nxt_eventport_enable_event(engine, ev, POLLIN); - } + nxt_eventport_enable_event(engine, ev, POLLIN); + } } +static void nxt_eventport_oneshot_write(nxt_event_engine_t *engine, + nxt_fd_event_t *ev) { + if (ev->write == NXT_EVENT_INACTIVE) { + ev->write = NXT_EVENT_ACTIVE; -static void -nxt_eventport_oneshot_write(nxt_event_engine_t *engine, nxt_fd_event_t *ev) -{ - if (ev->write == NXT_EVENT_INACTIVE) { - ev->write = NXT_EVENT_ACTIVE; - - nxt_eventport_enable_event(engine, ev, POLLOUT); - } + nxt_eventport_enable_event(engine, ev, POLLOUT); + } } +static void nxt_eventport_enable_accept(nxt_event_engine_t *engine, + nxt_fd_event_t *ev) { + ev->read = NXT_EVENT_LEVEL; -static void -nxt_eventport_enable_accept(nxt_event_engine_t *engine, nxt_fd_event_t *ev) -{ - ev->read = NXT_EVENT_LEVEL; - - nxt_eventport_enable_event(engine, ev, POLLIN); + nxt_eventport_enable_event(engine, ev, POLLIN); } +static nxt_int_t nxt_eventport_enable_post(nxt_event_engine_t *engine, + nxt_work_handler_t handler) { + engine->u.eventport.post_handler = handler; -static nxt_int_t -nxt_eventport_enable_post(nxt_event_engine_t *engine, - nxt_work_handler_t handler) -{ - engine->u.eventport.post_handler = handler; - - return NXT_OK; + return NXT_OK; } +static void nxt_eventport_signal(nxt_event_engine_t *engine, nxt_uint_t signo) { + int port; -static void -nxt_eventport_signal(nxt_event_engine_t *engine, nxt_uint_t signo) -{ - int port; + port = engine->u.eventport.fd; - port = engine->u.eventport.fd; + nxt_debug(&engine->task, "port_send(%d, %ui)", port, signo); - nxt_debug(&engine->task, "port_send(%d, %ui)", port, signo); - - if (port_send(port, signo, NULL) != 0) { - nxt_alert(&engine->task, "port_send(%d) failed %E", port, nxt_errno); - } + if (port_send(port, signo, NULL) != 0) { + nxt_alert(&engine->task, "port_send(%d) failed %E", port, nxt_errno); + } } - -static void -nxt_eventport_poll(nxt_event_engine_t *engine, nxt_msec_t timeout) -{ - int n, events, signo; - uint_t nevents; - nxt_err_t err; - nxt_uint_t i, level; - timespec_t ts, *tp; - port_event_t *event; - nxt_fd_event_t *ev; - nxt_work_handler_t handler; - - if (engine->u.eventport.nchanges != 0) { - if (nxt_eventport_commit_changes(engine) != NXT_OK) { - /* Error handlers have been enqueued on failure. */ - timeout = 0; - } +static void nxt_eventport_poll(nxt_event_engine_t *engine, nxt_msec_t timeout) { + int n, events, signo; + uint_t nevents; + nxt_err_t err; + nxt_uint_t i, level; + timespec_t ts, *tp; + port_event_t *event; + nxt_fd_event_t *ev; + nxt_work_handler_t handler; + + if (engine->u.eventport.nchanges != 0) { + if (nxt_eventport_commit_changes(engine) != NXT_OK) { + /* Error handlers have been enqueued on failure. */ + timeout = 0; } - - if (timeout == NXT_INFINITE_MSEC) { - tp = NULL; - - } else { - ts.tv_sec = timeout / 1000; - ts.tv_nsec = (timeout % 1000) * 1000000; - tp = &ts; + } + + if (timeout == NXT_INFINITE_MSEC) { + tp = NULL; + + } else { + ts.tv_sec = timeout / 1000; + ts.tv_nsec = (timeout % 1000) * 1000000; + tp = &ts; + } + + nxt_debug(&engine->task, "port_getn(%d) timeout: %M", engine->u.eventport.fd, + timeout); + + /* + * A trap for possible error when Solaris does not update nevents + * if ETIME or EINTR is returned. This issue will be logged as + * "unexpected port_getn() event". + * + * The details are in OpenSolaris mailing list thread "port_getn() + * and timeouts - is this a bug or an undocumented feature?" + */ + event = &engine->u.eventport.events[0]; + event->portev_events = -1; /* invalid port events */ + event->portev_source = -1; /* invalid port source */ + event->portev_object = -1; + event->portev_user = (void *)-1; + + nevents = 1; + n = port_getn(engine->u.eventport.fd, engine->u.eventport.events, + engine->u.eventport.mevents, &nevents, tp); + + /* + * 32-bit port_getn() on Solaris 10 x86 returns large negative + * values instead of 0 when returning immediately. + */ + err = (n < 0) ? nxt_errno : 0; + + nxt_thread_time_update(engine->task.thread); + + if (n == -1) { + if (err == NXT_ETIME || err == NXT_EINTR) { + if (nevents != 0) { + nxt_alert(&engine->task, "port_getn(%d) failed %E, events:%ud", + engine->u.eventport.fd, err, nevents); + } } - nxt_debug(&engine->task, "port_getn(%d) timeout: %M", - engine->u.eventport.fd, timeout); - - /* - * A trap for possible error when Solaris does not update nevents - * if ETIME or EINTR is returned. This issue will be logged as - * "unexpected port_getn() event". - * - * The details are in OpenSolaris mailing list thread "port_getn() - * and timeouts - is this a bug or an undocumented feature?" - */ - event = &engine->u.eventport.events[0]; - event->portev_events = -1; /* invalid port events */ - event->portev_source = -1; /* invalid port source */ - event->portev_object = -1; - event->portev_user = (void *) -1; - - nevents = 1; - n = port_getn(engine->u.eventport.fd, engine->u.eventport.events, - engine->u.eventport.mevents, &nevents, tp); - - /* - * 32-bit port_getn() on Solaris 10 x86 returns large negative - * values instead of 0 when returning immediately. - */ - err = (n < 0) ? nxt_errno : 0; - - nxt_thread_time_update(engine->task.thread); - - if (n == -1) { - if (err == NXT_ETIME || err == NXT_EINTR) { - if (nevents != 0) { - nxt_alert(&engine->task, "port_getn(%d) failed %E, events:%ud", - engine->u.eventport.fd, err, nevents); - } - } - - if (err != NXT_ETIME) { - level = (err == NXT_EINTR) ? NXT_LOG_INFO : NXT_LOG_ALERT; + if (err != NXT_ETIME) { + level = (err == NXT_EINTR) ? NXT_LOG_INFO : NXT_LOG_ALERT; - nxt_log(&engine->task, level, "port_getn(%d) failed %E", - engine->u.eventport.fd, err); + nxt_log(&engine->task, level, "port_getn(%d) failed %E", + engine->u.eventport.fd, err); - if (err != NXT_EINTR) { - return; - } - } + if (err != NXT_EINTR) { + return; + } } + } - nxt_debug(&engine->task, "port_getn(%d) events: %d", - engine->u.eventport.fd, nevents); - - for (i = 0; i < nevents; i++) { - event = &engine->u.eventport.events[i]; + nxt_debug(&engine->task, "port_getn(%d) events: %d", engine->u.eventport.fd, + nevents); - switch (event->portev_source) { + for (i = 0; i < nevents; i++) { + event = &engine->u.eventport.events[i]; - case PORT_SOURCE_FD: - ev = event->portev_user; - events = event->portev_events; + switch (event->portev_source) { - nxt_debug(ev->task, "eventport: fd:%d ev:%04Xd u:%p rd:%d wr:%d", - event->portev_object, events, ev, ev->read, ev->write); + case PORT_SOURCE_FD: + ev = event->portev_user; + events = event->portev_events; - if (nxt_slow_path(events & (POLLERR | POLLHUP | POLLNVAL)) != 0) { - nxt_alert(ev->task, "port_getn(%d) error fd:%d events:%04Xud", - engine->u.eventport.fd, ev->fd, events); + nxt_debug(ev->task, "eventport: fd:%d ev:%04Xd u:%p rd:%d wr:%d", + event->portev_object, events, ev, ev->read, ev->write); - nxt_work_queue_add(&engine->fast_work_queue, - nxt_eventport_error_handler, - ev->task, ev, ev->data); - continue; - } + if (nxt_slow_path(events & (POLLERR | POLLHUP | POLLNVAL)) != 0) { + nxt_alert(ev->task, "port_getn(%d) error fd:%d events:%04Xud", + engine->u.eventport.fd, ev->fd, events); - if (events & POLLIN) { - ev->read_ready = 1; + nxt_work_queue_add(&engine->fast_work_queue, + nxt_eventport_error_handler, ev->task, ev, ev->data); + continue; + } - if (ev->read != NXT_EVENT_BLOCKED) { - nxt_work_queue_add(ev->read_work_queue, ev->read_handler, - ev->task, ev, ev->data); + if (events & POLLIN) { + ev->read_ready = 1; - } + if (ev->read != NXT_EVENT_BLOCKED) { + nxt_work_queue_add(ev->read_work_queue, ev->read_handler, ev->task, + ev, ev->data); + } - if (ev->read != NXT_EVENT_LEVEL) { - ev->read = NXT_EVENT_INACTIVE; - } - } + if (ev->read != NXT_EVENT_LEVEL) { + ev->read = NXT_EVENT_INACTIVE; + } + } - if (events & POLLOUT) { - ev->write_ready = 1; + if (events & POLLOUT) { + ev->write_ready = 1; - if (ev->write != NXT_EVENT_BLOCKED) { - nxt_work_queue_add(ev->write_work_queue, ev->write_handler, - ev->task, ev, ev->data); - } + if (ev->write != NXT_EVENT_BLOCKED) { + nxt_work_queue_add(ev->write_work_queue, ev->write_handler, ev->task, + ev, ev->data); + } - ev->write = NXT_EVENT_INACTIVE; - } + ev->write = NXT_EVENT_INACTIVE; + } - /* - * Reactivate counterpart direction, because the - * eventport is oneshot notification facility. - */ - events = (ev->read == NXT_EVENT_INACTIVE) ? 0 : POLLIN; - events |= (ev->write == NXT_EVENT_INACTIVE) ? 0 : POLLOUT; + /* + * Reactivate counterpart direction, because the + * eventport is oneshot notification facility. + */ + events = (ev->read == NXT_EVENT_INACTIVE) ? 0 : POLLIN; + events |= (ev->write == NXT_EVENT_INACTIVE) ? 0 : POLLOUT; - if (events != 0) { - nxt_eventport_enable_event(engine, ev, events); - } + if (events != 0) { + nxt_eventport_enable_event(engine, ev, events); + } - break; + break; - case PORT_SOURCE_USER: - nxt_debug(&engine->task, "eventport: user ev:%d u:%p", - event->portev_events, event->portev_user); + case PORT_SOURCE_USER: + nxt_debug(&engine->task, "eventport: user ev:%d u:%p", + event->portev_events, event->portev_user); - signo = event->portev_events; + signo = event->portev_events; - handler = (signo == 0) ? engine->u.eventport.post_handler - : engine->u.eventport.signal_handler; + handler = (signo == 0) ? engine->u.eventport.post_handler + : engine->u.eventport.signal_handler; - nxt_work_queue_add(&engine->fast_work_queue, handler, - &engine->task, (void *) (uintptr_t) signo, NULL); + nxt_work_queue_add(&engine->fast_work_queue, handler, &engine->task, + (void *)(uintptr_t)signo, NULL); - break; + break; - default: - nxt_alert(&engine->task, - "unexpected port_getn(%d) event: " - "ev:%d src:%d obj:%p u:%p", - engine->u.eventport.fd, event->portev_events, - event->portev_source, event->portev_object, - event->portev_user); - } + default: + nxt_alert(&engine->task, + "unexpected port_getn(%d) event: " + "ev:%d src:%d obj:%p u:%p", + engine->u.eventport.fd, event->portev_events, + event->portev_source, event->portev_object, event->portev_user); } + } } diff --git a/src/nxt_external.c b/src/nxt_external.c index c724b9bd2..ede0842d3 100644 --- a/src/nxt_external.c +++ b/src/nxt_external.c @@ -8,201 +8,185 @@ #include #include - static nxt_int_t nxt_external_start(nxt_task_t *task, nxt_process_data_t *data); - -nxt_app_module_t nxt_external_module = { - 0, - NULL, - nxt_string("external"), - "*", - NULL, - 0, - NULL, - nxt_external_start, +nxt_app_module_t nxt_external_module = { + 0, NULL, nxt_string("external"), "*", NULL, 0, NULL, nxt_external_start, }; +extern char **environ; -extern char **environ; - +nxt_inline nxt_int_t nxt_external_fd_no_cloexec(nxt_task_t *task, + nxt_socket_t fd) { + int res, flags; -nxt_inline nxt_int_t -nxt_external_fd_no_cloexec(nxt_task_t *task, nxt_socket_t fd) -{ - int res, flags; - - if (fd == -1) { - return NXT_OK; - } + if (fd == -1) { + return NXT_OK; + } - flags = fcntl(fd, F_GETFD); + flags = fcntl(fd, F_GETFD); - if (nxt_slow_path(flags == -1)) { - nxt_alert(task, "fcntl(%d, F_GETFD) failed %E", fd, nxt_errno); - return NXT_ERROR; - } + if (nxt_slow_path(flags == -1)) { + nxt_alert(task, "fcntl(%d, F_GETFD) failed %E", fd, nxt_errno); + return NXT_ERROR; + } - flags &= ~FD_CLOEXEC; + flags &= ~FD_CLOEXEC; - res = fcntl(fd, F_SETFD, flags); + res = fcntl(fd, F_SETFD, flags); - if (nxt_slow_path(res == -1)) { - nxt_alert(task, "fcntl(%d, F_SETFD) failed %E", fd, nxt_errno); - return NXT_ERROR; - } + if (nxt_slow_path(res == -1)) { + nxt_alert(task, "fcntl(%d, F_SETFD) failed %E", fd, nxt_errno); + return NXT_ERROR; + } - return NXT_OK; + return NXT_OK; } +static nxt_int_t nxt_external_start(nxt_task_t *task, + nxt_process_data_t *data) { + char **argv; + u_char buf[256]; + u_char *p, *end; + uint32_t index; + size_t size; + nxt_str_t str; + nxt_int_t rc; + nxt_uint_t i, argc; + nxt_port_t *my_port, *proto_port, *router_port; + nxt_runtime_t *rt; + nxt_conf_value_t *value; + nxt_common_app_conf_t *conf; + nxt_external_app_conf_t *c; + + rt = task->thread->runtime; + conf = data->app; + + proto_port = rt->port_by_type[NXT_PROCESS_PROTOTYPE]; + router_port = rt->port_by_type[NXT_PROCESS_ROUTER]; + my_port = nxt_runtime_port_find(rt, nxt_pid, 0); + + if (nxt_slow_path(proto_port == NULL || my_port == NULL || + router_port == NULL)) { + return NXT_ERROR; + } -static nxt_int_t -nxt_external_start(nxt_task_t *task, nxt_process_data_t *data) -{ - char **argv; - u_char buf[256]; - u_char *p, *end; - uint32_t index; - size_t size; - nxt_str_t str; - nxt_int_t rc; - nxt_uint_t i, argc; - nxt_port_t *my_port, *proto_port, *router_port; - nxt_runtime_t *rt; - nxt_conf_value_t *value; - nxt_common_app_conf_t *conf; - nxt_external_app_conf_t *c; - - rt = task->thread->runtime; - conf = data->app; - - proto_port = rt->port_by_type[NXT_PROCESS_PROTOTYPE]; - router_port = rt->port_by_type[NXT_PROCESS_ROUTER]; - my_port = nxt_runtime_port_find(rt, nxt_pid, 0); - - if (nxt_slow_path(proto_port == NULL || my_port == NULL - || router_port == NULL)) - { - return NXT_ERROR; - } - - rc = nxt_external_fd_no_cloexec(task, proto_port->pair[1]); - if (nxt_slow_path(rc != NXT_OK)) { - return NXT_ERROR; - } + rc = nxt_external_fd_no_cloexec(task, proto_port->pair[1]); + if (nxt_slow_path(rc != NXT_OK)) { + return NXT_ERROR; + } - rc = nxt_external_fd_no_cloexec(task, router_port->pair[1]); - if (nxt_slow_path(rc != NXT_OK)) { - return NXT_ERROR; - } + rc = nxt_external_fd_no_cloexec(task, router_port->pair[1]); + if (nxt_slow_path(rc != NXT_OK)) { + return NXT_ERROR; + } - rc = nxt_external_fd_no_cloexec(task, my_port->pair[0]); - if (nxt_slow_path(rc != NXT_OK)) { - return NXT_ERROR; - } + rc = nxt_external_fd_no_cloexec(task, my_port->pair[0]); + if (nxt_slow_path(rc != NXT_OK)) { + return NXT_ERROR; + } - rc = nxt_external_fd_no_cloexec(task, my_port->pair[1]); - if (nxt_slow_path(rc != NXT_OK)) { - return NXT_ERROR; - } + rc = nxt_external_fd_no_cloexec(task, my_port->pair[1]); + if (nxt_slow_path(rc != NXT_OK)) { + return NXT_ERROR; + } - rc = nxt_external_fd_no_cloexec(task, conf->shared_port_fd); - if (nxt_slow_path(rc != NXT_OK)) { - return NXT_ERROR; - } + rc = nxt_external_fd_no_cloexec(task, conf->shared_port_fd); + if (nxt_slow_path(rc != NXT_OK)) { + return NXT_ERROR; + } - rc = nxt_external_fd_no_cloexec(task, conf->shared_queue_fd); - if (nxt_slow_path(rc != NXT_OK)) { - return NXT_ERROR; - } + rc = nxt_external_fd_no_cloexec(task, conf->shared_queue_fd); + if (nxt_slow_path(rc != NXT_OK)) { + return NXT_ERROR; + } + + end = buf + sizeof(buf); + + p = nxt_sprintf(buf, end, + "%s;%uD;" + "%PI,%ud,%d;" + "%PI,%ud,%d;" + "%PI,%ud,%d,%d;" + "%d,%d;" + "%d,%z,%uD,%Z", + NXT_VERSION, my_port->process->stream, proto_port->pid, + proto_port->id, proto_port->pair[1], router_port->pid, + router_port->id, router_port->pair[1], my_port->pid, + my_port->id, my_port->pair[0], my_port->pair[1], + conf->shared_port_fd, conf->shared_queue_fd, 2, + conf->shm_limit, conf->request_limit); + + if (nxt_slow_path(p == end)) { + nxt_alert(task, "internal error: buffer too small for NXT_UNIT_INIT"); - end = buf + sizeof(buf); - - p = nxt_sprintf(buf, end, - "%s;%uD;" - "%PI,%ud,%d;" - "%PI,%ud,%d;" - "%PI,%ud,%d,%d;" - "%d,%d;" - "%d,%z,%uD,%Z", - NXT_VERSION, my_port->process->stream, - proto_port->pid, proto_port->id, proto_port->pair[1], - router_port->pid, router_port->id, router_port->pair[1], - my_port->pid, my_port->id, my_port->pair[0], - my_port->pair[1], - conf->shared_port_fd, conf->shared_queue_fd, - 2, conf->shm_limit, conf->request_limit); - - if (nxt_slow_path(p == end)) { - nxt_alert(task, "internal error: buffer too small for NXT_UNIT_INIT"); - - return NXT_ERROR; - } + return NXT_ERROR; + } - nxt_debug(task, "update "NXT_UNIT_INIT_ENV"=%s", buf); + nxt_debug(task, "update " NXT_UNIT_INIT_ENV "=%s", buf); - rc = setenv(NXT_UNIT_INIT_ENV, (char *) buf, 1); - if (nxt_slow_path(rc == -1)) { - nxt_alert(task, "setenv("NXT_UNIT_INIT_ENV", %s) failed %E", buf, - nxt_errno); + rc = setenv(NXT_UNIT_INIT_ENV, (char *)buf, 1); + if (nxt_slow_path(rc == -1)) { + nxt_alert(task, "setenv(" NXT_UNIT_INIT_ENV ", %s) failed %E", buf, + nxt_errno); - return NXT_ERROR; - } + return NXT_ERROR; + } - c = &conf->u.external; + c = &conf->u.external; - argc = 2; - size = 0; + argc = 2; + size = 0; - if (c->arguments != NULL) { + if (c->arguments != NULL) { - for (index = 0; /* void */ ; index++) { - value = nxt_conf_get_array_element(c->arguments, index); - if (value == NULL) { - break; - } + for (index = 0; /* void */; index++) { + value = nxt_conf_get_array_element(c->arguments, index); + if (value == NULL) { + break; + } - nxt_conf_get_string(value, &str); + nxt_conf_get_string(value, &str); - size += str.length + 1; - argc++; - } + size += str.length + 1; + argc++; } + } - argv = nxt_malloc(argc * sizeof(argv[0]) + size); - if (nxt_slow_path(argv == NULL)) { - nxt_alert(task, "failed to allocate arguments"); - return NXT_ERROR; - } + argv = nxt_malloc(argc * sizeof(argv[0]) + size); + if (nxt_slow_path(argv == NULL)) { + nxt_alert(task, "failed to allocate arguments"); + return NXT_ERROR; + } - argv[0] = c->executable; - i = 1; + argv[0] = c->executable; + i = 1; - if (c->arguments != NULL) { - p = (u_char *) &argv[argc]; + if (c->arguments != NULL) { + p = (u_char *)&argv[argc]; - for (index = 0; /* void */ ; index++) { - value = nxt_conf_get_array_element(c->arguments, index); - if (value == NULL) { - break; - } + for (index = 0; /* void */; index++) { + value = nxt_conf_get_array_element(c->arguments, index); + if (value == NULL) { + break; + } - argv[i++] = (char *) p; + argv[i++] = (char *)p; - nxt_conf_get_string(value, &str); + nxt_conf_get_string(value, &str); - p = nxt_cpymem(p, str.start, str.length); - *p++ = '\0'; - } + p = nxt_cpymem(p, str.start, str.length); + *p++ = '\0'; } + } - argv[i] = NULL; + argv[i] = NULL; - (void) execve(c->executable, argv, environ); + (void)execve(c->executable, argv, environ); - nxt_alert(task, "execve(%s) failed %E", c->executable, nxt_errno); + nxt_alert(task, "execve(%s) failed %E", c->executable, nxt_errno); - nxt_free(argv); + nxt_free(argv); - return NXT_ERROR; + return NXT_ERROR; } diff --git a/src/nxt_fd_event.c b/src/nxt_fd_event.c index dffe1026f..65f4dcc01 100644 --- a/src/nxt_fd_event.c +++ b/src/nxt_fd_event.c @@ -6,107 +6,88 @@ #include - static nxt_int_t nxt_fd_event_hash_test(nxt_lvlhsh_query_t *lhq, void *data); static void nxt_fd_event_hash_error(nxt_task_t *task, nxt_fd_t fd); - -static const nxt_lvlhsh_proto_t nxt_event_set_fd_hash_proto nxt_aligned(64) = -{ +static const nxt_lvlhsh_proto_t nxt_event_set_fd_hash_proto nxt_aligned(64) = { NXT_LVLHSH_LARGE_MEMALIGN, nxt_fd_event_hash_test, nxt_lvlhsh_alloc, nxt_lvlhsh_free, }; - /* nxt_murmur_hash2() is unique for 4 bytes. */ -static nxt_int_t -nxt_fd_event_hash_test(nxt_lvlhsh_query_t *lhq, void *data) -{ - return NXT_OK; +static nxt_int_t nxt_fd_event_hash_test(nxt_lvlhsh_query_t *lhq, void *data) { + return NXT_OK; } +nxt_int_t nxt_fd_event_hash_add(nxt_lvlhsh_t *lvlhsh, nxt_fd_t fd, + nxt_fd_event_t *ev) { + nxt_int_t ret; + nxt_lvlhsh_query_t lhq; -nxt_int_t -nxt_fd_event_hash_add(nxt_lvlhsh_t *lvlhsh, nxt_fd_t fd, nxt_fd_event_t *ev) -{ - nxt_int_t ret; - nxt_lvlhsh_query_t lhq; - - lhq.key_hash = nxt_murmur_hash2(&fd, sizeof(nxt_fd_t)); - lhq.replace = 0; - lhq.value = ev; - lhq.proto = &nxt_event_set_fd_hash_proto; + lhq.key_hash = nxt_murmur_hash2(&fd, sizeof(nxt_fd_t)); + lhq.replace = 0; + lhq.value = ev; + lhq.proto = &nxt_event_set_fd_hash_proto; - ret = nxt_lvlhsh_insert(lvlhsh, &lhq); + ret = nxt_lvlhsh_insert(lvlhsh, &lhq); - if (nxt_fast_path(ret == NXT_OK)) { - return NXT_OK; - } + if (nxt_fast_path(ret == NXT_OK)) { + return NXT_OK; + } - nxt_alert(ev->task, "fd event %d is already in hash", ev->fd); + nxt_alert(ev->task, "fd event %d is already in hash", ev->fd); - return NXT_ERROR; + return NXT_ERROR; } +void *nxt_fd_event_hash_get(nxt_task_t *task, nxt_lvlhsh_t *lvlhsh, + nxt_fd_t fd) { + nxt_int_t ret; + nxt_lvlhsh_query_t lhq; -void * -nxt_fd_event_hash_get(nxt_task_t *task, nxt_lvlhsh_t *lvlhsh, nxt_fd_t fd) -{ - nxt_int_t ret; - nxt_lvlhsh_query_t lhq; - - lhq.key_hash = nxt_murmur_hash2(&fd, sizeof(nxt_fd_t)); - lhq.proto = &nxt_event_set_fd_hash_proto; + lhq.key_hash = nxt_murmur_hash2(&fd, sizeof(nxt_fd_t)); + lhq.proto = &nxt_event_set_fd_hash_proto; - ret = nxt_lvlhsh_find(lvlhsh, &lhq); + ret = nxt_lvlhsh_find(lvlhsh, &lhq); - if (nxt_fast_path(ret == NXT_OK)) { - return lhq.value; - } + if (nxt_fast_path(ret == NXT_OK)) { + return lhq.value; + } - nxt_fd_event_hash_error(task, fd); + nxt_fd_event_hash_error(task, fd); - return NULL; + return NULL; } +void nxt_fd_event_hash_delete(nxt_task_t *task, nxt_lvlhsh_t *lvlhsh, + nxt_fd_t fd, nxt_bool_t ignore) { + nxt_int_t ret; + nxt_lvlhsh_query_t lhq; -void -nxt_fd_event_hash_delete(nxt_task_t *task, nxt_lvlhsh_t *lvlhsh, nxt_fd_t fd, - nxt_bool_t ignore) -{ - nxt_int_t ret; - nxt_lvlhsh_query_t lhq; + lhq.key_hash = nxt_murmur_hash2(&fd, sizeof(nxt_fd_t)); + lhq.proto = &nxt_event_set_fd_hash_proto; - lhq.key_hash = nxt_murmur_hash2(&fd, sizeof(nxt_fd_t)); - lhq.proto = &nxt_event_set_fd_hash_proto; + ret = nxt_lvlhsh_delete(lvlhsh, &lhq); - ret = nxt_lvlhsh_delete(lvlhsh, &lhq); - - if (nxt_slow_path(ret != NXT_OK)) { - if (!ignore) { - nxt_fd_event_hash_error(task, fd); - } + if (nxt_slow_path(ret != NXT_OK)) { + if (!ignore) { + nxt_fd_event_hash_error(task, fd); } + } } +void nxt_fd_event_hash_destroy(nxt_lvlhsh_t *lvlhsh) { + nxt_fd_event_t *ev; -void -nxt_fd_event_hash_destroy(nxt_lvlhsh_t *lvlhsh) -{ - nxt_fd_event_t *ev; - - do { - ev = nxt_lvlhsh_retrieve(lvlhsh, &nxt_event_set_fd_hash_proto, NULL); + do { + ev = nxt_lvlhsh_retrieve(lvlhsh, &nxt_event_set_fd_hash_proto, NULL); - } while (ev != NULL); + } while (ev != NULL); } - -static void -nxt_fd_event_hash_error(nxt_task_t *task, nxt_fd_t fd) -{ - nxt_alert(task, "fd event %d not found in hash", fd); +static void nxt_fd_event_hash_error(nxt_task_t *task, nxt_fd_t fd) { + nxt_alert(task, "fd event %d not found in hash", fd); } diff --git a/src/nxt_fd_event.h b/src/nxt_fd_event.h index 3a8d94604..3990edc1f 100644 --- a/src/nxt_fd_event.h +++ b/src/nxt_fd_event.h @@ -7,112 +7,105 @@ #ifndef _NXT_FD_EVENT_H_INCLUDED_ #define _NXT_FD_EVENT_H_INCLUDED_ - typedef enum { - /* A completely inactive event. */ - NXT_EVENT_INACTIVE = 0, - - /* - * An event presents in the kernel but disabled after oneshot. - * Used by epoll. - */ - NXT_EVENT_DISABLED, - - /* - * An event is active in the kernel but blocked by application. - * Used by kqueue, epoll, eventport, devpoll, and pollset. - */ - NXT_EVENT_BLOCKED, - - /* - * An active oneshot event. - * Used by epoll, devpoll, pollset, poll, and select. - */ - NXT_EVENT_ONESHOT, - - /* An active level-triggered event. Used by eventport. */ - NXT_EVENT_LEVEL, - - /* - * An active default event. The event type depends on interface: - * edge-triggered for kqueue, and modern epoll; - * level-triggered for old epoll, devpoll, pollset, poll, and select; - * oneshot for kqueue and eventport. - */ - NXT_EVENT_DEFAULT, - NXT_EVENT_ACTIVE = NXT_EVENT_DEFAULT, + /* A completely inactive event. */ + NXT_EVENT_INACTIVE = 0, + + /* + * An event presents in the kernel but disabled after oneshot. + * Used by epoll. + */ + NXT_EVENT_DISABLED, + + /* + * An event is active in the kernel but blocked by application. + * Used by kqueue, epoll, eventport, devpoll, and pollset. + */ + NXT_EVENT_BLOCKED, + + /* + * An active oneshot event. + * Used by epoll, devpoll, pollset, poll, and select. + */ + NXT_EVENT_ONESHOT, + + /* An active level-triggered event. Used by eventport. */ + NXT_EVENT_LEVEL, + + /* + * An active default event. The event type depends on interface: + * edge-triggered for kqueue, and modern epoll; + * level-triggered for old epoll, devpoll, pollset, poll, and select; + * oneshot for kqueue and eventport. + */ + NXT_EVENT_DEFAULT, + NXT_EVENT_ACTIVE = NXT_EVENT_DEFAULT, } nxt_fd_event_state_t; +#define nxt_fd_event_is_disabled(state) ((state) < NXT_EVENT_ONESHOT) -#define nxt_fd_event_is_disabled(state) \ - ((state) < NXT_EVENT_ONESHOT) - - -#define nxt_fd_event_is_active(state) \ - ((state) >= NXT_EVENT_ONESHOT) - +#define nxt_fd_event_is_active(state) ((state) >= NXT_EVENT_ONESHOT) struct nxt_fd_event_s { - void *data; + void *data; - /* Both are int's. */ - nxt_socket_t fd; - nxt_err_t error; + /* Both are int's. */ + nxt_socket_t fd; + nxt_err_t error; - /* The flags should also be prefetched by nxt_work_queue_pop(). */ + /* The flags should also be prefetched by nxt_work_queue_pop(). */ #if (NXT_64BIT) - nxt_fd_event_state_t read:8; /* 3 bits. */ - nxt_fd_event_state_t write:8; /* 3 bits. */ - uint8_t read_ready; - uint8_t write_ready; - uint8_t changing; - uint8_t closed; - uint8_t timedout; - uint8_t shutdown:1; + nxt_fd_event_state_t read : 8; /* 3 bits. */ + nxt_fd_event_state_t write : 8; /* 3 bits. */ + uint8_t read_ready; + uint8_t write_ready; + uint8_t changing; + uint8_t closed; + uint8_t timedout; + uint8_t shutdown : 1; #if (NXT_HAVE_EPOLL) - uint8_t epoll_eof:1; - uint8_t epoll_error:1; + uint8_t epoll_eof : 1; + uint8_t epoll_error : 1; #endif #if (NXT_HAVE_KQUEUE) - uint8_t kq_eof:1; + uint8_t kq_eof : 1; #endif #else /* NXT_32BIT */ - nxt_fd_event_state_t read:3; - nxt_fd_event_state_t write:3; - uint8_t read_ready:1; - uint8_t write_ready:1; - uint8_t changing:1; - uint8_t closed:1; - uint8_t timedout:1; - uint8_t shutdown:1; + nxt_fd_event_state_t read : 3; + nxt_fd_event_state_t write : 3; + uint8_t read_ready : 1; + uint8_t write_ready : 1; + uint8_t changing : 1; + uint8_t closed : 1; + uint8_t timedout : 1; + uint8_t shutdown : 1; #if (NXT_HAVE_EPOLL) - uint8_t epoll_eof:1; - uint8_t epoll_error:1; + uint8_t epoll_eof : 1; + uint8_t epoll_error : 1; #endif #if (NXT_HAVE_KQUEUE) - uint8_t kq_eof:1; + uint8_t kq_eof : 1; #endif #endif /* NXT_64BIT */ #if (NXT_HAVE_KQUEUE) - /* nxt_err_t is int. */ - nxt_err_t kq_errno; - /* struct kevent.data is intptr_t, however int32_t is enough. */ - int32_t kq_available; + /* nxt_err_t is int. */ + nxt_err_t kq_errno; + /* struct kevent.data is intptr_t, however int32_t is enough. */ + int32_t kq_available; #endif - nxt_task_t *task; + nxt_task_t *task; - nxt_work_queue_t *read_work_queue; - nxt_work_handler_t read_handler; - nxt_work_queue_t *write_work_queue; - nxt_work_handler_t write_handler; - nxt_work_handler_t error_handler; + nxt_work_queue_t *read_work_queue; + nxt_work_handler_t read_handler; + nxt_work_queue_t *write_work_queue; + nxt_work_handler_t write_handler; + nxt_work_handler_t error_handler; - nxt_log_t *log; + nxt_log_t *log; }; - #endif /* _NXT_FD_EVENT_H_INCLUDED_ */ diff --git a/src/nxt_fiber.c b/src/nxt_fiber.c index d6cac8930..5cb58447a 100644 --- a/src/nxt_fiber.c +++ b/src/nxt_fiber.c @@ -6,189 +6,176 @@ #include - static char *nxt_fiber_create_stack(nxt_task_t *task, nxt_fiber_t *fib); static void nxt_fiber_switch_stack(nxt_fiber_t *fib, jmp_buf *parent); static void nxt_fiber_switch_handler(nxt_task_t *task, void *obj, void *data); static void nxt_fiber_switch(nxt_task_t *task, nxt_fiber_t *fib); static void nxt_fiber_timer_handler(nxt_task_t *task, void *obj, void *data); +#define nxt_fiber_enqueue(thr, task, fib) \ + nxt_work_queue_add(&(thr)->engine->fast_work_queue, \ + nxt_fiber_switch_handler, task, fib, NULL) -#define nxt_fiber_enqueue(thr, task, fib) \ - nxt_work_queue_add(&(thr)->engine->fast_work_queue, \ - nxt_fiber_switch_handler, task, fib, NULL) - +nxt_fiber_main_t *nxt_fiber_main_create(nxt_event_engine_t *engine) { + nxt_fiber_main_t *fm; -nxt_fiber_main_t * -nxt_fiber_main_create(nxt_event_engine_t *engine) -{ - nxt_fiber_main_t *fm; - - fm = nxt_zalloc(sizeof(nxt_fiber_main_t)); - if (nxt_slow_path(fm == NULL)) { - return NULL; - } + fm = nxt_zalloc(sizeof(nxt_fiber_main_t)); + if (nxt_slow_path(fm == NULL)) { + return NULL; + } - fm->engine = engine; - fm->stack_size = 512 * 1024 - nxt_pagesize; - fm->idle = NULL; + fm->engine = engine; + fm->stack_size = 512 * 1024 - nxt_pagesize; + fm->idle = NULL; - return fm; + return fm; } +nxt_int_t nxt_fiber_create(nxt_fiber_start_t start, void *data, size_t stack) { + int ret; + jmp_buf parent; + nxt_fid_t fid; + nxt_fiber_t *fib; + nxt_thread_t *thr; + nxt_fiber_main_t *fm; -nxt_int_t -nxt_fiber_create(nxt_fiber_start_t start, void *data, size_t stack) -{ - int ret; - jmp_buf parent; - nxt_fid_t fid; - nxt_fiber_t *fib; - nxt_thread_t *thr; - nxt_fiber_main_t *fm; + thr = nxt_thread(); + fm = thr->engine->fibers; - thr = nxt_thread(); - fm = thr->engine->fibers; + fid = ++fm->fid; + if (fid == 0) { fid = ++fm->fid; + } - if (fid == 0) { - fid = ++fm->fid; - } - - fib = fm->idle; - - if (fib != NULL) { - fm->idle = fib->next; - fib->fid = fid; - fib->start = start; - fib->data = data; - fib->main = fm; - - fib->task.thread = thr; - fib->task.log = thr->log; - fib->task.ident = nxt_task_next_ident(); - - nxt_debug(&fib->task, "fiber create cached: %PF", fib->fid); - - nxt_fiber_enqueue(thr, &fm->engine->task, fib); - - return NXT_OK; - } - - nxt_log_debug(thr->log, "fiber create"); - - fib = nxt_malloc(sizeof(nxt_fiber_t)); - if (nxt_slow_path(fib == NULL)) { - return NXT_ERROR; - } + fib = fm->idle; + if (fib != NULL) { + fm->idle = fib->next; fib->fid = fid; fib->start = start; fib->data = data; - fib->stack_size = fm->stack_size; fib->main = fm; fib->task.thread = thr; fib->task.log = thr->log; fib->task.ident = nxt_task_next_ident(); - fib->stack = nxt_fiber_create_stack(&fib->task, fib); + nxt_debug(&fib->task, "fiber create cached: %PF", fib->fid); - if (nxt_fast_path(fib->stack != NULL)) { + nxt_fiber_enqueue(thr, &fm->engine->task, fib); - if (_setjmp(parent) != 0) { - nxt_log_debug(thr->log, "fiber create: %PF", fib->fid); - return NXT_OK; - } + return NXT_OK; + } - nxt_fiber_switch_stack(fib, &parent); - /* It does not return if the switch was successful. */ - } + nxt_log_debug(thr->log, "fiber create"); - ret = munmap(fib->stack - nxt_pagesize, fib->stack_size + nxt_pagesize); + fib = nxt_malloc(sizeof(nxt_fiber_t)); + if (nxt_slow_path(fib == NULL)) { + return NXT_ERROR; + } + + fib->fid = fid; + fib->start = start; + fib->data = data; + fib->stack_size = fm->stack_size; + fib->main = fm; + + fib->task.thread = thr; + fib->task.log = thr->log; + fib->task.ident = nxt_task_next_ident(); + + fib->stack = nxt_fiber_create_stack(&fib->task, fib); - if (nxt_slow_path(ret != 0)) { - nxt_log_alert(thr->log, "munmap() failed %E", nxt_errno); + if (nxt_fast_path(fib->stack != NULL)) { + + if (_setjmp(parent) != 0) { + nxt_log_debug(thr->log, "fiber create: %PF", fib->fid); + return NXT_OK; } - nxt_free(fib); + nxt_fiber_switch_stack(fib, &parent); + /* It does not return if the switch was successful. */ + } - return NXT_ERROR; -} + ret = munmap(fib->stack - nxt_pagesize, fib->stack_size + nxt_pagesize); + + if (nxt_slow_path(ret != 0)) { + nxt_log_alert(thr->log, "munmap() failed %E", nxt_errno); + } + nxt_free(fib); + + return NXT_ERROR; +} #if (NXT_LINUX) -static char * -nxt_fiber_create_stack(nxt_task_t *task, nxt_fiber_t *fib) -{ - char *s; - size_t size; +static char *nxt_fiber_create_stack(nxt_task_t *task, nxt_fiber_t *fib) { + char *s; + size_t size; - size = fib->stack_size + nxt_pagesize; + size = fib->stack_size + nxt_pagesize; - s = mmap(NULL, size, PROT_READ | PROT_WRITE, - MAP_PRIVATE | MAP_ANON | MAP_GROWSDOWN, -1, 0); + s = mmap(NULL, size, PROT_READ | PROT_WRITE, + MAP_PRIVATE | MAP_ANON | MAP_GROWSDOWN, -1, 0); - if (nxt_slow_path(s == MAP_FAILED)) { - nxt_alert(task, "fiber stack " - "mmap(%uz, MAP_PRIVATE|MAP_ANON|MAP_GROWSDOWN) failed %E", - size, nxt_errno); + if (nxt_slow_path(s == MAP_FAILED)) { + nxt_alert(task, + "fiber stack " + "mmap(%uz, MAP_PRIVATE|MAP_ANON|MAP_GROWSDOWN) failed %E", + size, nxt_errno); - return NULL; - } + return NULL; + } - if (nxt_slow_path(mprotect(s, nxt_pagesize, PROT_NONE) != 0)) { - nxt_alert(task, "fiber stack mprotect(%uz, PROT_NONE) failed %E", - size, nxt_errno); + if (nxt_slow_path(mprotect(s, nxt_pagesize, PROT_NONE) != 0)) { + nxt_alert(task, "fiber stack mprotect(%uz, PROT_NONE) failed %E", size, + nxt_errno); - return NULL; - } + return NULL; + } - s += nxt_pagesize; + s += nxt_pagesize; - nxt_debug(task, "fiber stack mmap: %p", s); + nxt_debug(task, "fiber stack mmap: %p", s); - return s; + return s; } #else /* Generic version. */ -static char * -nxt_fiber_create_stack(nxt_task_t *task, nxt_fiber_t *fib) -{ - char *s; - size_t size; +static char *nxt_fiber_create_stack(nxt_task_t *task, nxt_fiber_t *fib) { + char *s; + size_t size; - size = fib->stack_size + nxt_pagesize; + size = fib->stack_size + nxt_pagesize; - s = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANON, -1, 0); + s = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANON, -1, 0); - if (nxt_slow_path(s == MAP_FAILED)) { - nxt_alert(task, "fiber stack mmap(%uz, MAP_PRIVATE|MAP_ANON) failed %E", - size, nxt_errno); + if (nxt_slow_path(s == MAP_FAILED)) { + nxt_alert(task, "fiber stack mmap(%uz, MAP_PRIVATE|MAP_ANON) failed %E", + size, nxt_errno); - return NULL; - } + return NULL; + } - if (nxt_slow_path(mprotect(s, nxt_pagesize, PROT_NONE) != 0)) { - nxt_alert(task, "fiber stack mprotect(%uz, PROT_NONE) failed %E", - size, nxt_errno); + if (nxt_slow_path(mprotect(s, nxt_pagesize, PROT_NONE) != 0)) { + nxt_alert(task, "fiber stack mprotect(%uz, PROT_NONE) failed %E", size, + nxt_errno); - return NULL; - } + return NULL; + } - s += nxt_pagesize; + s += nxt_pagesize; - nxt_debug(task, "fiber stack mmap: %p", s); + nxt_debug(task, "fiber stack mmap: %p", s); - return s; + return s; } #endif - #if (NXT_LINUX && NXT_64BIT) /* @@ -197,66 +184,61 @@ nxt_fiber_create_stack(nxt_task_t *task, nxt_fiber_t *fib) */ static void nxt_fiber_trampoline(uint32_t fh, uint32_t fl, uint32_t ph, - uint32_t pl); + uint32_t pl); +static void nxt_fiber_switch_stack(nxt_fiber_t *fib, jmp_buf *parent) { + ucontext_t uc; -static void -nxt_fiber_switch_stack(nxt_fiber_t *fib, jmp_buf *parent) -{ - ucontext_t uc; + nxt_debug(&fib->task, "fiber switch to stack: %p", fib->stack); - nxt_debug(&fib->task, "fiber switch to stack: %p", fib->stack); + if (nxt_slow_path(getcontext(&uc) != 0)) { + nxt_alert(&fib->task, "getcontext() failed"); + return; + } - if (nxt_slow_path(getcontext(&uc) != 0)) { - nxt_alert(&fib->task, "getcontext() failed"); - return; - } - - uc.uc_link = NULL; - uc.uc_stack.ss_sp = fib->stack; - uc.uc_stack.ss_size = fib->stack_size; + uc.uc_link = NULL; + uc.uc_stack.ss_sp = fib->stack; + uc.uc_stack.ss_size = fib->stack_size; - makecontext(&uc, (void (*)(void)) nxt_fiber_trampoline, 4, - (uint32_t) ((uintptr_t) fib >> 32), - (uint32_t) ((uintptr_t) fib & 0xFFFFFFFF), - (uint32_t) ((uintptr_t) parent >> 32), - (uint32_t) ((uintptr_t) parent & 0xFFFFFFFF)); + makecontext(&uc, (void (*)(void))nxt_fiber_trampoline, 4, + (uint32_t)((uintptr_t)fib >> 32), + (uint32_t)((uintptr_t)fib & 0xFFFFFFFF), + (uint32_t)((uintptr_t)parent >> 32), + (uint32_t)((uintptr_t)parent & 0xFFFFFFFF)); - setcontext(&uc); + setcontext(&uc); - nxt_alert(&fib->task, "setcontext() failed"); + nxt_alert(&fib->task, "setcontext() failed"); } +static void nxt_fiber_trampoline(uint32_t fh, uint32_t fl, uint32_t ph, + uint32_t pl) { + jmp_buf *parent; + nxt_task_t *task; + nxt_fiber_t *fib; -static void -nxt_fiber_trampoline(uint32_t fh, uint32_t fl, uint32_t ph, uint32_t pl) -{ - jmp_buf *parent; - nxt_task_t *task; - nxt_fiber_t *fib; - - fib = (nxt_fiber_t *) (((uintptr_t) fh << 32) + fl); - parent = (jmp_buf *) (((uintptr_t) ph << 32) + pl); + fib = (nxt_fiber_t *)(((uintptr_t)fh << 32) + fl); + parent = (jmp_buf *)(((uintptr_t)ph << 32) + pl); - task = &fib->task; + task = &fib->task; - if (_setjmp(fib->jmp) == 0) { - nxt_debug(task, "fiber return to parent stack"); + if (_setjmp(fib->jmp) == 0) { + nxt_debug(task, "fiber return to parent stack"); - nxt_fiber_enqueue(task->thread, task, fib); + nxt_fiber_enqueue(task->thread, task, fib); - _longjmp(*parent, 1); + _longjmp(*parent, 1); - nxt_unreachable(); - } + nxt_unreachable(); + } - nxt_debug(task, "fiber start"); + nxt_debug(task, "fiber start"); - fib->start(fib->data); + fib->start(fib->data); - nxt_fiber_exit(task, &fib->main->fiber, NULL); + nxt_fiber_exit(task, &fib->main->fiber, NULL); - nxt_unreachable(); + nxt_unreachable(); } #elif (NXT_HAVE_UCONTEXT) @@ -265,59 +247,53 @@ nxt_fiber_trampoline(uint32_t fh, uint32_t fl, uint32_t ph, uint32_t pl) static void nxt_fiber_trampoline(nxt_fiber_t *fib, jmp_buf *parent); +static void nxt_fiber_switch_stack(nxt_fiber_t *fib, jmp_buf *parent) { + ucontext_t uc; -static void -nxt_fiber_switch_stack(nxt_fiber_t *fib, jmp_buf *parent) -{ - ucontext_t uc; - - nxt_debug(&fib->task, "fiber switch to stack: %p", fib->stack); + nxt_debug(&fib->task, "fiber switch to stack: %p", fib->stack); - if (nxt_slow_path(getcontext(&uc) != 0)) { - nxt_alert(&fib->task, "getcontext() failed"); - return; - } + if (nxt_slow_path(getcontext(&uc) != 0)) { + nxt_alert(&fib->task, "getcontext() failed"); + return; + } - uc.uc_link = NULL; - uc.uc_stack.ss_sp = fib->stack; - uc.uc_stack.ss_size = fib->stack_size; + uc.uc_link = NULL; + uc.uc_stack.ss_sp = fib->stack; + uc.uc_stack.ss_size = fib->stack_size; - makecontext(&uc, (void (*)(void)) nxt_fiber_trampoline, 2, fib, parent); + makecontext(&uc, (void (*)(void))nxt_fiber_trampoline, 2, fib, parent); - setcontext(&uc); + setcontext(&uc); #if !(NXT_SOLARIS) - /* Solaris declares setcontext() as __NORETURN. */ + /* Solaris declares setcontext() as __NORETURN. */ - nxt_alert(&fib->task, "setcontext() failed"); + nxt_alert(&fib->task, "setcontext() failed"); #endif } +static void nxt_fiber_trampoline(nxt_fiber_t *fib, jmp_buf *parent) { + nxt_task_t *task; -static void -nxt_fiber_trampoline(nxt_fiber_t *fib, jmp_buf *parent) -{ - nxt_task_t *task; - - task = &fib->task; + task = &fib->task; - if (_setjmp(fib->jmp) == 0) { - nxt_debug(task, "fiber return to parent stack"); + if (_setjmp(fib->jmp) == 0) { + nxt_debug(task, "fiber return to parent stack"); - nxt_fiber_enqueue(task->thread, task, fib); + nxt_fiber_enqueue(task->thread, task, fib); - _longjmp(*parent, 1); + _longjmp(*parent, 1); - nxt_unreachable(); - } + nxt_unreachable(); + } - nxt_debug(task, "fiber start"); + nxt_debug(task, "fiber start"); - fib->start(fib->data); + fib->start(fib->data); - nxt_fiber_exit(task, &fib->main->fiber, NULL); + nxt_fiber_exit(task, &fib->main->fiber, NULL); - nxt_unreachable(); + nxt_unreachable(); } #else @@ -326,140 +302,116 @@ nxt_fiber_trampoline(nxt_fiber_t *fib, jmp_buf *parent) #endif +static void nxt_fiber_switch_handler(nxt_task_t *task, void *obj, void *data) { + nxt_fiber_t *fib; -static void -nxt_fiber_switch_handler(nxt_task_t *task, void *obj, void *data) -{ - nxt_fiber_t *fib; - - fib = obj; + fib = obj; - nxt_fiber_switch(task, fib); - nxt_unreachable(); + nxt_fiber_switch(task, fib); + nxt_unreachable(); } +static void nxt_fiber_switch(nxt_task_t *task, nxt_fiber_t *fib) { + nxt_debug(task, "fiber switch: %PF", fib->fid); -static void -nxt_fiber_switch(nxt_task_t *task, nxt_fiber_t *fib) -{ - nxt_debug(task, "fiber switch: %PF", fib->fid); - - task->thread->fiber = fib; + task->thread->fiber = fib; - _longjmp(fib->jmp, 1); + _longjmp(fib->jmp, 1); - nxt_unreachable(); + nxt_unreachable(); } - -nxt_fiber_t * -nxt_fiber_self(nxt_thread_t *thr) -{ - return (nxt_fast_path(thr != NULL)) ? thr->fiber : NULL; +nxt_fiber_t *nxt_fiber_self(nxt_thread_t *thr) { + return (nxt_fast_path(thr != NULL)) ? thr->fiber : NULL; } +void nxt_fiber_yield(nxt_task_t *task) { + nxt_fiber_t *fib; -void -nxt_fiber_yield(nxt_task_t *task) -{ - nxt_fiber_t *fib; + fib = task->thread->fiber; - fib = task->thread->fiber; + if (_setjmp(fib->jmp) == 0) { - if (_setjmp(fib->jmp) == 0) { + nxt_debug(task, "fiber yield"); - nxt_debug(task, "fiber yield"); + nxt_fiber_enqueue(task->thread, &fib->main->engine->task, fib); - nxt_fiber_enqueue(task->thread, &fib->main->engine->task, fib); + nxt_fiber_switch(task, &fib->main->fiber); - nxt_fiber_switch(task, &fib->main->fiber); - - nxt_unreachable(); - } + nxt_unreachable(); + } - nxt_debug(task, "fiber yield return"); + nxt_debug(task, "fiber yield return"); } +void nxt_fiber_sleep(nxt_task_t *task, nxt_msec_t timeout) { + nxt_fiber_t *fib; -void -nxt_fiber_sleep(nxt_task_t *task, nxt_msec_t timeout) -{ - nxt_fiber_t *fib; - - fib = task->thread->fiber; + fib = task->thread->fiber; - fib->timer.work_queue = &task->thread->engine->fast_work_queue; - fib->timer.handler = nxt_fiber_timer_handler; - fib->timer.log = &nxt_main_log; + fib->timer.work_queue = &task->thread->engine->fast_work_queue; + fib->timer.handler = nxt_fiber_timer_handler; + fib->timer.log = &nxt_main_log; - task = &fib->task; + task = &fib->task; - nxt_timer_add(task->thread->engine, &fib->timer, timeout); + nxt_timer_add(task->thread->engine, &fib->timer, timeout); - if (_setjmp(fib->jmp) == 0) { + if (_setjmp(fib->jmp) == 0) { - nxt_debug(task, "fiber sleep: %T", timeout); + nxt_debug(task, "fiber sleep: %T", timeout); - nxt_fiber_switch(task, &fib->main->fiber); + nxt_fiber_switch(task, &fib->main->fiber); - nxt_unreachable(); - } + nxt_unreachable(); + } - nxt_debug(task, "fiber sleep return"); + nxt_debug(task, "fiber sleep return"); } +static void nxt_fiber_timer_handler(nxt_task_t *task, void *obj, void *data) { + nxt_fiber_t *fib; + nxt_timer_t *ev; -static void -nxt_fiber_timer_handler(nxt_task_t *task, void *obj, void *data) -{ - nxt_fiber_t *fib; - nxt_timer_t *ev; + ev = obj; - ev = obj; + nxt_debug(task, "fiber timer handler"); - nxt_debug(task, "fiber timer handler"); + fib = nxt_timer_data(ev, nxt_fiber_t, timer); - fib = nxt_timer_data(ev, nxt_fiber_t, timer); + nxt_fiber_switch(task, fib); - nxt_fiber_switch(task, fib); - - nxt_unreachable(); + nxt_unreachable(); } +void nxt_fiber_wait(nxt_task_t *task) { + nxt_fiber_t *fib; -void -nxt_fiber_wait(nxt_task_t *task) -{ - nxt_fiber_t *fib; + fib = task->thread->fiber; - fib = task->thread->fiber; + if (_setjmp(fib->jmp) == 0) { + nxt_debug(task, "fiber wait"); - if (_setjmp(fib->jmp) == 0) { - nxt_debug(task, "fiber wait"); + nxt_fiber_switch(task, &fib->main->fiber); - nxt_fiber_switch(task, &fib->main->fiber); - - nxt_unreachable(); - } + nxt_unreachable(); + } - nxt_debug(task, "fiber wait return"); + nxt_debug(task, "fiber wait return"); } +void nxt_fiber_exit(nxt_task_t *task, nxt_fiber_t *next, void *data) { + nxt_fiber_t *fib; -void -nxt_fiber_exit(nxt_task_t *task, nxt_fiber_t *next, void *data) -{ - nxt_fiber_t *fib; - - fib = task->thread->fiber; + fib = task->thread->fiber; - nxt_debug(task, "fiber exit"); + nxt_debug(task, "fiber exit"); - /* TODO: limit idle fibers. */ - fib->next = fib->main->idle; - fib->main->idle = fib; + /* TODO: limit idle fibers. */ + fib->next = fib->main->idle; + fib->main->idle = fib; - nxt_fiber_switch(task, next); + nxt_fiber_switch(task, next); - nxt_unreachable(); + nxt_unreachable(); } diff --git a/src/nxt_fiber.h b/src/nxt_fiber.h index 7f1beace6..06962388f 100644 --- a/src/nxt_fiber.h +++ b/src/nxt_fiber.h @@ -7,44 +7,39 @@ #ifndef _NXT_FIBER_H_INCLUDED_ #define _NXT_FIBER_H_INCLUDED_ - -typedef struct nxt_fiber_main_s nxt_fiber_main_t; +typedef struct nxt_fiber_main_s nxt_fiber_main_t; typedef void (*nxt_fiber_start_t)(void *data); +typedef uint32_t nxt_fid_t; +#define nxt_fiber_id(f) (f)->fid; -typedef uint32_t nxt_fid_t; -#define nxt_fiber_id(f) (f)->fid; - - -typedef struct nxt_fiber_s nxt_fiber_t; +typedef struct nxt_fiber_s nxt_fiber_t; struct nxt_fiber_s { - jmp_buf jmp; - nxt_fid_t fid; - nxt_fiber_start_t start; - void *data; - char *stack; - size_t stack_size; - nxt_err_t err; + jmp_buf jmp; + nxt_fid_t fid; + nxt_fiber_start_t start; + void *data; + char *stack; + size_t stack_size; + nxt_err_t err; - nxt_task_t task; + nxt_task_t task; - nxt_fiber_main_t *main; - nxt_fiber_t *next; + nxt_fiber_main_t *main; + nxt_fiber_t *next; - nxt_timer_t timer; + nxt_timer_t timer; }; - struct nxt_fiber_main_s { - nxt_fiber_t fiber; - nxt_fiber_t *idle; - nxt_event_engine_t *engine; - size_t stack_size; - nxt_fid_t fid; + nxt_fiber_t fiber; + nxt_fiber_t *idle; + nxt_event_engine_t *engine; + size_t stack_size; + nxt_fid_t fid; }; - nxt_fiber_main_t *nxt_fiber_main_create(nxt_event_engine_t *engine); nxt_int_t nxt_fiber_create(nxt_fiber_start_t start, void *data, size_t stack); void nxt_fiber_yield(nxt_task_t *task); @@ -53,5 +48,4 @@ void nxt_fiber_wait(nxt_task_t *task); void nxt_fiber_exit(nxt_task_t *task, nxt_fiber_t *next, void *data); NXT_EXPORT nxt_fiber_t *nxt_fiber_self(nxt_thread_t *thr); - #endif /* _NXT_FIBER_H_INCLUDED_ */ diff --git a/src/nxt_file.c b/src/nxt_file.c index 4047d9d7c..d80f22ba9 100644 --- a/src/nxt_file.c +++ b/src/nxt_file.c @@ -6,177 +6,157 @@ #include - -nxt_int_t -nxt_file_open(nxt_task_t *task, nxt_file_t *file, nxt_uint_t mode, - nxt_uint_t create, nxt_file_access_t access) -{ +nxt_int_t nxt_file_open(nxt_task_t *task, nxt_file_t *file, nxt_uint_t mode, + nxt_uint_t create, nxt_file_access_t access) { #ifdef __CYGWIN__ - mode |= O_BINARY; + mode |= O_BINARY; #endif - /* O_NONBLOCK is to prevent blocking on FIFOs, special devices, etc. */ - mode |= (O_NONBLOCK | create); + /* O_NONBLOCK is to prevent blocking on FIFOs, special devices, etc. */ + mode |= (O_NONBLOCK | create); - file->fd = open((char *) file->name, mode, access); + file->fd = open((char *)file->name, mode, access); - file->error = (file->fd == -1) ? nxt_errno : 0; + file->error = (file->fd == -1) ? nxt_errno : 0; #if (NXT_DEBUG) - nxt_thread_time_update(task->thread); + nxt_thread_time_update(task->thread); #endif - nxt_debug(task, "open(\"%FN\", 0x%uXi, 0x%uXi): %FD err:%d", - file->name, mode, access, file->fd, file->error); + nxt_debug(task, "open(\"%FN\", 0x%uXi, 0x%uXi): %FD err:%d", file->name, mode, + access, file->fd, file->error); - if (file->fd != -1) { - return NXT_OK; - } + if (file->fd != -1) { + return NXT_OK; + } - if (file->log_level != 0) { - nxt_log(task, file->log_level, "open(\"%FN\") failed %E", - file->name, file->error); - } + if (file->log_level != 0) { + nxt_log(task, file->log_level, "open(\"%FN\") failed %E", file->name, + file->error); + } - return NXT_ERROR; + return NXT_ERROR; } - #if (NXT_HAVE_OPENAT2) -nxt_int_t -nxt_file_openat2(nxt_task_t *task, nxt_file_t *file, nxt_uint_t mode, - nxt_uint_t create, nxt_file_access_t access, nxt_fd_t dfd, - nxt_uint_t resolve) -{ - struct open_how how; +nxt_int_t nxt_file_openat2(nxt_task_t *task, nxt_file_t *file, nxt_uint_t mode, + nxt_uint_t create, nxt_file_access_t access, + nxt_fd_t dfd, nxt_uint_t resolve) { + struct open_how how; - nxt_memzero(&how, sizeof(how)); + nxt_memzero(&how, sizeof(how)); - /* O_NONBLOCK is to prevent blocking on FIFOs, special devices, etc. */ - mode |= (O_NONBLOCK | create); + /* O_NONBLOCK is to prevent blocking on FIFOs, special devices, etc. */ + mode |= (O_NONBLOCK | create); - how.flags = mode; - how.mode = access; - how.resolve = resolve; + how.flags = mode; + how.mode = access; + how.resolve = resolve; - file->fd = syscall(SYS_openat2, dfd, file->name, &how, sizeof(how)); + file->fd = syscall(SYS_openat2, dfd, file->name, &how, sizeof(how)); - file->error = (file->fd == -1) ? nxt_errno : 0; + file->error = (file->fd == -1) ? nxt_errno : 0; #if (NXT_DEBUG) - nxt_thread_time_update(task->thread); + nxt_thread_time_update(task->thread); #endif - nxt_debug(task, "openat2(%FD, \"%FN\"): %FD err:%d", dfd, file->name, - file->fd, file->error); + nxt_debug(task, "openat2(%FD, \"%FN\"): %FD err:%d", dfd, file->name, + file->fd, file->error); - if (file->fd != -1) { - return NXT_OK; - } + if (file->fd != -1) { + return NXT_OK; + } - if (file->log_level != 0) { - nxt_log(task, file->log_level, "openat2(%FD, \"%FN\") failed %E", dfd, - file->name, file->error); - } + if (file->log_level != 0) { + nxt_log(task, file->log_level, "openat2(%FD, \"%FN\") failed %E", dfd, + file->name, file->error); + } - return NXT_ERROR; + return NXT_ERROR; } #endif +void nxt_file_close(nxt_task_t *task, nxt_file_t *file) { + nxt_debug(task, "close(%FD)", file->fd); -void -nxt_file_close(nxt_task_t *task, nxt_file_t *file) -{ - nxt_debug(task, "close(%FD)", file->fd); - - if (close(file->fd) != 0) { - nxt_alert(task, "close(%FD, \"%FN\") failed %E", - file->fd, file->name, nxt_errno); - } + if (close(file->fd) != 0) { + nxt_alert(task, "close(%FD, \"%FN\") failed %E", file->fd, file->name, + nxt_errno); + } } +ssize_t nxt_file_write(nxt_file_t *file, const u_char *buf, size_t size, + nxt_off_t offset) { + ssize_t n; -ssize_t -nxt_file_write(nxt_file_t *file, const u_char *buf, size_t size, - nxt_off_t offset) -{ - ssize_t n; + nxt_thread_debug(thr); - nxt_thread_debug(thr); + n = pwrite(file->fd, buf, size, offset); - n = pwrite(file->fd, buf, size, offset); + file->error = (n < 0) ? nxt_errno : 0; - file->error = (n < 0) ? nxt_errno : 0; + nxt_thread_time_debug_update(thr); - nxt_thread_time_debug_update(thr); + nxt_log_debug(thr->log, "pwrite(%FD, %p, %uz, %O): %z", file->fd, buf, size, + offset, n); - nxt_log_debug(thr->log, "pwrite(%FD, %p, %uz, %O): %z", - file->fd, buf, size, offset, n); - - if (nxt_fast_path(n >= 0)) { - return n; - } + if (nxt_fast_path(n >= 0)) { + return n; + } - nxt_thread_log_alert("pwrite(%FD, \"%FN\", %p, %uz, %O) failed %E", - file->fd, file->name, buf, size, - offset, file->error); + nxt_thread_log_alert("pwrite(%FD, \"%FN\", %p, %uz, %O) failed %E", file->fd, + file->name, buf, size, offset, file->error); - return NXT_ERROR; + return NXT_ERROR; } +ssize_t nxt_file_read(nxt_file_t *file, u_char *buf, size_t size, + nxt_off_t offset) { + ssize_t n; -ssize_t -nxt_file_read(nxt_file_t *file, u_char *buf, size_t size, nxt_off_t offset) -{ - ssize_t n; + nxt_thread_debug(thr); - nxt_thread_debug(thr); + n = pread(file->fd, buf, size, offset); - n = pread(file->fd, buf, size, offset); + file->error = (n <= 0) ? nxt_errno : 0; - file->error = (n <= 0) ? nxt_errno : 0; + nxt_thread_time_debug_update(thr); - nxt_thread_time_debug_update(thr); + nxt_log_debug(thr->log, "pread(%FD, %p, %uz, %O): %z", file->fd, buf, size, + offset, n); - nxt_log_debug(thr->log, "pread(%FD, %p, %uz, %O): %z", - file->fd, buf, size, offset, n); - - if (nxt_fast_path(n >= 0)) { - return n; - } + if (nxt_fast_path(n >= 0)) { + return n; + } - nxt_thread_log_alert("pread(%FD, \"%FN\", %p, %uz, %O) failed %E", - file->fd, file->name, buf, size, - offset, file->error); + nxt_thread_log_alert("pread(%FD, \"%FN\", %p, %uz, %O) failed %E", file->fd, + file->name, buf, size, offset, file->error); - return NXT_ERROR; + return NXT_ERROR; } - #if (NXT_HAVE_READAHEAD) /* FreeBSD 8.0 fcntl(F_READAHEAD, size) enables read ahead up to the size. */ -void -nxt_file_read_ahead(nxt_file_t *file, nxt_off_t offset, size_t size) -{ - int ret; - u_char buf; +void nxt_file_read_ahead(nxt_file_t *file, nxt_off_t offset, size_t size) { + int ret; + u_char buf; - ret = fcntl(file->fd, F_READAHEAD, (int) size); + ret = fcntl(file->fd, F_READAHEAD, (int)size); - nxt_thread_log_debug("fcntl(%FD, F_READAHEAD, %uz): %d", - file->fd, size, ret); + nxt_thread_log_debug("fcntl(%FD, F_READAHEAD, %uz): %d", file->fd, size, ret); - if (nxt_fast_path(ret != -1)) { - (void) nxt_file_read(file, &buf, 1, offset); - return; - } + if (nxt_fast_path(ret != -1)) { + (void)nxt_file_read(file, &buf, 1, offset); + return; + } - nxt_thread_log_alert("fcntl(%FD, \"%FN\", F_READAHEAD, %uz) failed %E", - file->fd, file->name, size, nxt_errno); + nxt_thread_log_alert("fcntl(%FD, \"%FN\", F_READAHEAD, %uz) failed %E", + file->fd, file->name, size, nxt_errno); } #elif (NXT_HAVE_POSIX_FADVISE) @@ -197,235 +177,212 @@ nxt_file_read_ahead(nxt_file_t *file, nxt_off_t offset, size_t size) * FreeBSD does nothing. */ -void -nxt_file_read_ahead(nxt_file_t *file, nxt_off_t offset, size_t size) -{ - nxt_err_t err; +void nxt_file_read_ahead(nxt_file_t *file, nxt_off_t offset, size_t size) { + nxt_err_t err; - err = posix_fadvise(file->fd, offset, size, POSIX_FADV_WILLNEED); + err = posix_fadvise(file->fd, offset, size, POSIX_FADV_WILLNEED); - nxt_thread_log_debug("posix_fadvise(%FD, \"%FN\", %O, %uz, %d): %d", - file->fd, file->name, offset, size, - POSIX_FADV_WILLNEED, err); + nxt_thread_log_debug("posix_fadvise(%FD, \"%FN\", %O, %uz, %d): %d", file->fd, + file->name, offset, size, POSIX_FADV_WILLNEED, err); - if (nxt_fast_path(err == 0)) { - return; - } + if (nxt_fast_path(err == 0)) { + return; + } - nxt_thread_log_alert("posix_fadvise(%FD, \"%FN\", %O, %uz, %d) failed %E", - file->fd, file->name, offset, size, - POSIX_FADV_WILLNEED, err); + nxt_thread_log_alert("posix_fadvise(%FD, \"%FN\", %O, %uz, %d) failed %E", + file->fd, file->name, offset, size, POSIX_FADV_WILLNEED, + err); } #elif (NXT_HAVE_RDAHEAD) /* MacOSX fcntl(F_RDAHEAD). */ -void -nxt_file_read_ahead(nxt_file_t *file, nxt_off_t offset, size_t size) -{ - int ret; - u_char buf; +void nxt_file_read_ahead(nxt_file_t *file, nxt_off_t offset, size_t size) { + int ret; + u_char buf; - ret = fcntl(file->fd, F_RDAHEAD, 1); + ret = fcntl(file->fd, F_RDAHEAD, 1); - nxt_thread_log_debug("fcntl(%FD, F_RDAHEAD, 1): %d", file->fd, ret); + nxt_thread_log_debug("fcntl(%FD, F_RDAHEAD, 1): %d", file->fd, ret); - if (nxt_fast_path(ret != -1)) { - (void) nxt_file_read(file, &buf, 1, offset); - return; - } + if (nxt_fast_path(ret != -1)) { + (void)nxt_file_read(file, &buf, 1, offset); + return; + } - nxt_thread_log_alert("fcntl(%FD, \"%FN\", F_RDAHEAD, 1) failed %E", - file->fd, file->name, nxt_errno); + nxt_thread_log_alert("fcntl(%FD, \"%FN\", F_RDAHEAD, 1) failed %E", file->fd, + file->name, nxt_errno); } #else -void -nxt_file_read_ahead(nxt_file_t *file, nxt_off_t offset, size_t size) -{ - u_char buf; +void nxt_file_read_ahead(nxt_file_t *file, nxt_off_t offset, size_t size) { + u_char buf; - (void) nxt_file_read(file, &buf, 1, offset); + (void)nxt_file_read(file, &buf, 1, offset); } #endif +nxt_int_t nxt_file_info(nxt_file_t *file, nxt_file_info_t *fi) { + int n; -nxt_int_t -nxt_file_info(nxt_file_t *file, nxt_file_info_t *fi) -{ - int n; - - if (file->fd == NXT_FILE_INVALID) { - n = stat((char *) file->name, fi); - - file->error = (n != 0) ? nxt_errno : 0; + if (file->fd == NXT_FILE_INVALID) { + n = stat((char *)file->name, fi); - nxt_thread_log_debug("stat(\"%FN)\": %d", file->name, n); + file->error = (n != 0) ? nxt_errno : 0; - if (n == 0) { - return NXT_OK; - } + nxt_thread_log_debug("stat(\"%FN)\": %d", file->name, n); - if (file->log_level != 0) { - nxt_thread_log_error(file->log_level, "stat(\"%FN\") failed %E", - file->name, file->error); - } - - return NXT_ERROR; - - } else { - n = fstat(file->fd, fi); + if (n == 0) { + return NXT_OK; + } - file->error = (n != 0) ? nxt_errno : 0; + if (file->log_level != 0) { + nxt_thread_log_error(file->log_level, "stat(\"%FN\") failed %E", + file->name, file->error); + } - nxt_thread_log_debug("fstat(%FD): %d", file->fd, n); + return NXT_ERROR; - if (n == 0) { - return NXT_OK; - } + } else { + n = fstat(file->fd, fi); - /* Use NXT_LOG_ALERT because fstat() error on open file is strange. */ + file->error = (n != 0) ? nxt_errno : 0; - nxt_thread_log_alert("fstat(%FD, \"%FN\") failed %E", - file->fd, file->name, file->error); + nxt_thread_log_debug("fstat(%FD): %d", file->fd, n); - return NXT_ERROR; + if (n == 0) { + return NXT_OK; } -} + /* Use NXT_LOG_ALERT because fstat() error on open file is strange. */ -nxt_int_t -nxt_file_delete(nxt_file_name_t *name) -{ - nxt_thread_log_debug("unlink(\"%FN\")", name); - - if (nxt_fast_path(unlink((char *) name) == 0)) { - return NXT_OK; - } - - nxt_thread_log_alert("unlink(\"%FN\") failed %E", name, nxt_errno); + nxt_thread_log_alert("fstat(%FD, \"%FN\") failed %E", file->fd, file->name, + file->error); return NXT_ERROR; + } } +nxt_int_t nxt_file_delete(nxt_file_name_t *name) { + nxt_thread_log_debug("unlink(\"%FN\")", name); -nxt_int_t -nxt_file_set_access(nxt_file_name_t *name, nxt_file_access_t access) -{ - if (nxt_fast_path(chmod((char *) name, access) == 0)) { - return NXT_OK; - } + if (nxt_fast_path(unlink((char *)name) == 0)) { + return NXT_OK; + } - nxt_thread_log_alert("chmod(\"%FN\") failed %E", name, nxt_errno); + nxt_thread_log_alert("unlink(\"%FN\") failed %E", name, nxt_errno); - return NXT_ERROR; + return NXT_ERROR; } +nxt_int_t nxt_file_set_access(nxt_file_name_t *name, nxt_file_access_t access) { + if (nxt_fast_path(chmod((char *)name, access) == 0)) { + return NXT_OK; + } -nxt_int_t -nxt_file_chown(nxt_file_name_t *name, const char *owner, const char *group) -{ - int err; - char *buf; - long bufsize; - gid_t gid = ~0; - uid_t uid = ~0; + nxt_thread_log_alert("chmod(\"%FN\") failed %E", name, nxt_errno); - if (owner == NULL && group == NULL) { - return NXT_OK; - } - - if (owner != NULL) { - struct passwd pwd, *result; + return NXT_ERROR; +} - bufsize = sysconf(_SC_GETPW_R_SIZE_MAX); - if (bufsize == -1) { - bufsize = 32768; - } +nxt_int_t nxt_file_chown(nxt_file_name_t *name, const char *owner, + const char *group) { + int err; + char *buf; + long bufsize; + gid_t gid = ~0; + uid_t uid = ~0; - buf = nxt_malloc(bufsize); - if (buf == NULL) { - return NXT_ERROR; - } + if (owner == NULL && group == NULL) { + return NXT_OK; + } - err = getpwnam_r(owner, &pwd, buf, bufsize, &result); - if (result == NULL) { - nxt_thread_log_alert("getpwnam_r(\"%s\", ...) failed %E %s", - owner, nxt_errno, - err == 0 ? "(User not found)" : ""); - goto out_err_free; - } + if (owner != NULL) { + struct passwd pwd, *result; - uid = pwd.pw_uid; + bufsize = sysconf(_SC_GETPW_R_SIZE_MAX); + if (bufsize == -1) { + bufsize = 32768; + } - nxt_free(buf); + buf = nxt_malloc(bufsize); + if (buf == NULL) { + return NXT_ERROR; } - if (group != NULL) { - struct group grp, *result; + err = getpwnam_r(owner, &pwd, buf, bufsize, &result); + if (result == NULL) { + nxt_thread_log_alert("getpwnam_r(\"%s\", ...) failed %E %s", owner, + nxt_errno, err == 0 ? "(User not found)" : ""); + goto out_err_free; + } - bufsize = sysconf(_SC_GETGR_R_SIZE_MAX); - if (bufsize == -1) { - bufsize = 32768; - } + uid = pwd.pw_uid; - buf = nxt_malloc(bufsize); - if (buf == NULL) { - return NXT_ERROR; - } + nxt_free(buf); + } - err = getgrnam_r(group, &grp, buf, bufsize, &result); - if (result == NULL) { - nxt_thread_log_alert("getgrnam_r(\"%s\", ...) failed %E %s", - group, nxt_errno, - err == 0 ? "(Group not found)" : ""); - goto out_err_free; - } + if (group != NULL) { + struct group grp, *result; - gid = grp.gr_gid; + bufsize = sysconf(_SC_GETGR_R_SIZE_MAX); + if (bufsize == -1) { + bufsize = 32768; + } - nxt_free(buf); + buf = nxt_malloc(bufsize); + if (buf == NULL) { + return NXT_ERROR; } - if (nxt_fast_path(chown((const char *) name, uid, gid) == 0)) { - return NXT_OK; + err = getgrnam_r(group, &grp, buf, bufsize, &result); + if (result == NULL) { + nxt_thread_log_alert("getgrnam_r(\"%s\", ...) failed %E %s", group, + nxt_errno, err == 0 ? "(Group not found)" : ""); + goto out_err_free; } - nxt_thread_log_alert("chown(\"%FN\", %l, %l) failed %E", name, - owner != NULL ? (long) uid : -1, - group != NULL ? (long) gid : -1, nxt_errno); + gid = grp.gr_gid; - return NXT_ERROR; + nxt_free(buf); + } + + if (nxt_fast_path(chown((const char *)name, uid, gid) == 0)) { + return NXT_OK; + } + + nxt_thread_log_alert("chown(\"%FN\", %l, %l) failed %E", name, + owner != NULL ? (long)uid : -1, + group != NULL ? (long)gid : -1, nxt_errno); + + return NXT_ERROR; out_err_free: - nxt_free(buf); + nxt_free(buf); - return NXT_ERROR; + return NXT_ERROR; } +nxt_int_t nxt_file_rename(nxt_file_name_t *old_name, + nxt_file_name_t *new_name) { + int ret; -nxt_int_t -nxt_file_rename(nxt_file_name_t *old_name, nxt_file_name_t *new_name) -{ - int ret; + nxt_thread_log_debug("rename(\"%FN\", \"%FN\")", old_name, new_name); - nxt_thread_log_debug("rename(\"%FN\", \"%FN\")", old_name, new_name); - - ret = rename((char *) old_name, (char *) new_name); - if (nxt_fast_path(ret == 0)) { - return NXT_OK; - } + ret = rename((char *)old_name, (char *)new_name); + if (nxt_fast_path(ret == 0)) { + return NXT_OK; + } - nxt_thread_log_alert("rename(\"%FN\", \"%FN\") failed %E", - old_name, new_name, nxt_errno); + nxt_thread_log_alert("rename(\"%FN\", \"%FN\") failed %E", old_name, new_name, + nxt_errno); - return NXT_ERROR; + return NXT_ERROR; } - /* * ioctl(FIONBIO) sets a non-blocking mode using one syscall, * thereas fcntl(F_SETFL, O_NONBLOCK) needs to learn the current state @@ -440,338 +397,289 @@ nxt_file_rename(nxt_file_name_t *old_name, nxt_file_name_t *new_name) #if (NXT_HAVE_FIONBIO) -nxt_int_t -nxt_fd_nonblocking(nxt_task_t *task, nxt_fd_t fd) -{ - int nb; +nxt_int_t nxt_fd_nonblocking(nxt_task_t *task, nxt_fd_t fd) { + int nb; - nb = 1; - - if (nxt_fast_path(ioctl(fd, FIONBIO, &nb) != -1)) { - return NXT_OK; - } + nb = 1; - nxt_alert(task, "ioctl(%d, FIONBIO) failed %E", fd, nxt_errno); + if (nxt_fast_path(ioctl(fd, FIONBIO, &nb) != -1)) { + return NXT_OK; + } - return NXT_ERROR; + nxt_alert(task, "ioctl(%d, FIONBIO) failed %E", fd, nxt_errno); + return NXT_ERROR; } +nxt_int_t nxt_fd_blocking(nxt_task_t *task, nxt_fd_t fd) { + int nb; -nxt_int_t -nxt_fd_blocking(nxt_task_t *task, nxt_fd_t fd) -{ - int nb; + nb = 0; - nb = 0; - - if (nxt_fast_path(ioctl(fd, FIONBIO, &nb) != -1)) { - return NXT_OK; - } + if (nxt_fast_path(ioctl(fd, FIONBIO, &nb) != -1)) { + return NXT_OK; + } - nxt_alert(task, "ioctl(%d, !FIONBIO) failed %E", fd, nxt_errno); + nxt_alert(task, "ioctl(%d, !FIONBIO) failed %E", fd, nxt_errno); - return NXT_ERROR; + return NXT_ERROR; } #else /* !(NXT_HAVE_FIONBIO) */ -nxt_int_t -nxt_fd_nonblocking(nxt_task_t *task, nxt_fd_t fd) -{ - int flags; +nxt_int_t nxt_fd_nonblocking(nxt_task_t *task, nxt_fd_t fd) { + int flags; - flags = fcntl(fd, F_GETFL); + flags = fcntl(fd, F_GETFL); - if (nxt_slow_path(flags == -1)) { - nxt_alert(task, "fcntl(%d, F_GETFL) failed %E", fd, nxt_errno); - return NXT_ERROR; - } + if (nxt_slow_path(flags == -1)) { + nxt_alert(task, "fcntl(%d, F_GETFL) failed %E", fd, nxt_errno); + return NXT_ERROR; + } - flags |= O_NONBLOCK; + flags |= O_NONBLOCK; - if (nxt_slow_path(fcntl(fd, F_SETFL, flags) == -1)) { - nxt_alert(task, "fcntl(%d, F_SETFL, O_NONBLOCK) failed %E", - fd, nxt_errno); - return NXT_ERROR; - } + if (nxt_slow_path(fcntl(fd, F_SETFL, flags) == -1)) { + nxt_alert(task, "fcntl(%d, F_SETFL, O_NONBLOCK) failed %E", fd, nxt_errno); + return NXT_ERROR; + } - return NXT_OK; + return NXT_OK; } +nxt_int_t nxt_fd_blocking(nxt_task_t *task, nxt_fd_t fd) { + int flags; -nxt_int_t -nxt_fd_blocking(nxt_task_t *task, nxt_fd_t fd) -{ - int flags; - - flags = fcntl(fd, F_GETFL); + flags = fcntl(fd, F_GETFL); - if (nxt_slow_path(flags == -1)) { - nxt_alert(task, "fcntl(%d, F_GETFL) failed %E", fd, nxt_errno); - return NXT_ERROR; - } + if (nxt_slow_path(flags == -1)) { + nxt_alert(task, "fcntl(%d, F_GETFL) failed %E", fd, nxt_errno); + return NXT_ERROR; + } - flags &= O_NONBLOCK; + flags &= O_NONBLOCK; - if (nxt_slow_path(fcntl(fd, F_SETFL, flags) == -1)) { - nxt_alert(task, "fcntl(%d, F_SETFL, !O_NONBLOCK) failed %E", - fd, nxt_errno); - return NXT_ERROR; - } + if (nxt_slow_path(fcntl(fd, F_SETFL, flags) == -1)) { + nxt_alert(task, "fcntl(%d, F_SETFL, !O_NONBLOCK) failed %E", fd, nxt_errno); + return NXT_ERROR; + } - return NXT_OK; + return NXT_OK; } #endif /* NXT_HAVE_FIONBIO */ +ssize_t nxt_fd_write(nxt_fd_t fd, u_char *buf, size_t size) { + ssize_t n; + nxt_err_t err; -ssize_t -nxt_fd_write(nxt_fd_t fd, u_char *buf, size_t size) -{ - ssize_t n; - nxt_err_t err; - - n = write(fd, buf, size); + n = write(fd, buf, size); - err = (n == -1) ? nxt_errno : 0; + err = (n == -1) ? nxt_errno : 0; - nxt_thread_log_debug("write(%FD, %p, %uz): %z", fd, buf, size, n); + nxt_thread_log_debug("write(%FD, %p, %uz): %z", fd, buf, size, n); - if (nxt_slow_path(n <= 0)) { - nxt_thread_log_alert("write(%FD) failed %E", fd, err); - } + if (nxt_slow_path(n <= 0)) { + nxt_thread_log_alert("write(%FD) failed %E", fd, err); + } - return n; + return n; } +ssize_t nxt_fd_read(nxt_fd_t fd, u_char *buf, size_t size) { + ssize_t n; + nxt_err_t err; -ssize_t -nxt_fd_read(nxt_fd_t fd, u_char *buf, size_t size) -{ - ssize_t n; - nxt_err_t err; + n = read(fd, buf, size); - n = read(fd, buf, size); + err = (n == -1) ? nxt_errno : 0; - err = (n == -1) ? nxt_errno : 0; + nxt_thread_log_debug("read(%FD, %p, %uz): %z", fd, buf, size, n); - nxt_thread_log_debug("read(%FD, %p, %uz): %z", fd, buf, size, n); + if (nxt_slow_path(n <= 0)) { - if (nxt_slow_path(n <= 0)) { - - if (err == NXT_EAGAIN) { - return 0; - } - - nxt_thread_log_alert("read(%FD) failed %E", fd, err); + if (err == NXT_EAGAIN) { + return 0; } - return n; -} + nxt_thread_log_alert("read(%FD) failed %E", fd, err); + } + return n; +} -void -nxt_fd_close(nxt_fd_t fd) -{ - nxt_thread_log_debug("close(%FD)", fd); +void nxt_fd_close(nxt_fd_t fd) { + nxt_thread_log_debug("close(%FD)", fd); - if (nxt_slow_path(close(fd) != 0)) { - nxt_thread_log_alert("close(%FD) failed %E", fd, nxt_errno); - } + if (nxt_slow_path(close(fd) != 0)) { + nxt_thread_log_alert("close(%FD) failed %E", fd, nxt_errno); + } } - -FILE * -nxt_file_fopen(nxt_task_t *task, const char *pathname, const char *mode) -{ - int err; - FILE *fp; +FILE *nxt_file_fopen(nxt_task_t *task, const char *pathname, const char *mode) { + int err; + FILE *fp; #if (NXT_DEBUG) - nxt_thread_time_update(task->thread); + nxt_thread_time_update(task->thread); #endif - fp = fopen(pathname, mode); - err = (fp == NULL) ? nxt_errno : 0; + fp = fopen(pathname, mode); + err = (fp == NULL) ? nxt_errno : 0; - nxt_debug(task, "fopen(\"%s\", \"%s\"): fp:%p err:%d", pathname, mode, fp, - err); + nxt_debug(task, "fopen(\"%s\", \"%s\"): fp:%p err:%d", pathname, mode, fp, + err); - if (nxt_fast_path(fp != NULL)) { - return fp; - } + if (nxt_fast_path(fp != NULL)) { + return fp; + } - nxt_alert(task, "fopen(\"%s\") failed %E", pathname, err); + nxt_alert(task, "fopen(\"%s\") failed %E", pathname, err); - return NULL; + return NULL; } +void nxt_file_fclose(nxt_task_t *task, FILE *fp) { + nxt_debug(task, "fclose(%p)", fp); -void -nxt_file_fclose(nxt_task_t *task, FILE *fp) -{ - nxt_debug(task, "fclose(%p)", fp); - - if (nxt_slow_path(fclose(fp) == -1)) { - nxt_alert(task, "fclose() failed %E", nxt_errno); - } + if (nxt_slow_path(fclose(fp) == -1)) { + nxt_alert(task, "fclose() failed %E", nxt_errno); + } } - /* * nxt_file_redirect() redirects the file to the fd descriptor. * Then the fd descriptor is closed. */ -nxt_int_t -nxt_file_redirect(nxt_file_t *file, nxt_fd_t fd) -{ - nxt_thread_log_debug("dup2(%FD, %FD, \"%FN\")", fd, file->fd, file->name); +nxt_int_t nxt_file_redirect(nxt_file_t *file, nxt_fd_t fd) { + nxt_thread_log_debug("dup2(%FD, %FD, \"%FN\")", fd, file->fd, file->name); - if (dup2(fd, file->fd) == -1) { - nxt_thread_log_alert("dup2(%FD, %FD, \"%FN\") failed %E", - fd, file->fd, file->name, nxt_errno); - return NXT_ERROR; - } + if (dup2(fd, file->fd) == -1) { + nxt_thread_log_alert("dup2(%FD, %FD, \"%FN\") failed %E", fd, file->fd, + file->name, nxt_errno); + return NXT_ERROR; + } - if (close(fd) != 0) { - nxt_thread_log_alert("close(%FD, \"%FN\") failed %E", - fd, file->name, nxt_errno); - return NXT_ERROR; - } + if (close(fd) != 0) { + nxt_thread_log_alert("close(%FD, \"%FN\") failed %E", fd, file->name, + nxt_errno); + return NXT_ERROR; + } - return NXT_OK; + return NXT_OK; } - /* nxt_file_stdout() redirects the stdout descriptor to the file. */ -nxt_int_t -nxt_file_stdout(nxt_file_t *file) -{ - nxt_thread_log_debug("dup2(%FD, %FD, \"%FN\")", - file->fd, STDOUT_FILENO, file->name); +nxt_int_t nxt_file_stdout(nxt_file_t *file) { + nxt_thread_log_debug("dup2(%FD, %FD, \"%FN\")", file->fd, STDOUT_FILENO, + file->name); - if (dup2(file->fd, STDOUT_FILENO) != -1) { - return NXT_OK; - } + if (dup2(file->fd, STDOUT_FILENO) != -1) { + return NXT_OK; + } - nxt_thread_log_alert("dup2(%FD, %FD, \"%FN\") failed %E", - file->fd, STDOUT_FILENO, file->name, nxt_errno); + nxt_thread_log_alert("dup2(%FD, %FD, \"%FN\") failed %E", file->fd, + STDOUT_FILENO, file->name, nxt_errno); - return NXT_ERROR; + return NXT_ERROR; } - /* nxt_file_stderr() redirects the stderr descriptor to the file. */ -nxt_int_t -nxt_file_stderr(nxt_file_t *file) -{ - nxt_thread_log_debug("dup2(%FD, %FD, \"%FN\")", - file->fd, STDERR_FILENO, file->name); +nxt_int_t nxt_file_stderr(nxt_file_t *file) { + nxt_thread_log_debug("dup2(%FD, %FD, \"%FN\")", file->fd, STDERR_FILENO, + file->name); - if (dup2(file->fd, STDERR_FILENO) != -1) { - return NXT_OK; - } + if (dup2(file->fd, STDERR_FILENO) != -1) { + return NXT_OK; + } - nxt_thread_log_alert("dup2(%FD, %FD, \"%FN\") failed %E", - file->fd, STDERR_FILENO, file->name, nxt_errno); + nxt_thread_log_alert("dup2(%FD, %FD, \"%FN\") failed %E", file->fd, + STDERR_FILENO, file->name, nxt_errno); - return NXT_ERROR; + return NXT_ERROR; } +nxt_int_t nxt_stderr_start(void) { + int flags, fd; -nxt_int_t -nxt_stderr_start(void) -{ - int flags, fd; - - flags = fcntl(nxt_stderr, F_GETFL); - - if (flags != -1) { - /* - * If the stderr output of a multithreaded application is - * redirected to a file: - * Linux, Solaris and MacOSX do not write atomically to the output; - * MacOSX besides adds zeroes to the output. - * O_APPEND fixes this. - */ - (void) fcntl(nxt_stderr, F_SETFL, flags | O_APPEND); - - } else { - /* - * The stderr descriptor is closed before application start. - * Reserve the stderr descriptor for future use. Errors are - * ignored because anyway they could be written nowhere. - */ - fd = open("/dev/null", O_WRONLY | O_APPEND); - - if (fd != -1) { - (void) dup2(fd, nxt_stderr); - - if (fd != nxt_stderr) { - (void) close(fd); - } - } - } + flags = fcntl(nxt_stderr, F_GETFL); - return flags; -} + if (flags != -1) { + /* + * If the stderr output of a multithreaded application is + * redirected to a file: + * Linux, Solaris and MacOSX do not write atomically to the output; + * MacOSX besides adds zeroes to the output. + * O_APPEND fixes this. + */ + (void)fcntl(nxt_stderr, F_SETFL, flags | O_APPEND); + } else { + /* + * The stderr descriptor is closed before application start. + * Reserve the stderr descriptor for future use. Errors are + * ignored because anyway they could be written nowhere. + */ + fd = open("/dev/null", O_WRONLY | O_APPEND); -nxt_int_t -nxt_pipe_create(nxt_task_t *task, nxt_fd_t *pp, nxt_bool_t nbread, - nxt_bool_t nbwrite) -{ - if (pipe(pp) != 0) { - nxt_alert(task, "pipe() failed %E", nxt_errno); + if (fd != -1) { + (void)dup2(fd, nxt_stderr); - return NXT_ERROR; + if (fd != nxt_stderr) { + (void)close(fd); + } } + } - nxt_debug(task, "pipe(): %FD:%FD", pp[0], pp[1]); + return flags; +} + +nxt_int_t nxt_pipe_create(nxt_task_t *task, nxt_fd_t *pp, nxt_bool_t nbread, + nxt_bool_t nbwrite) { + if (pipe(pp) != 0) { + nxt_alert(task, "pipe() failed %E", nxt_errno); + + return NXT_ERROR; + } - if (nbread) { - if (nxt_fd_nonblocking(task, pp[0]) != NXT_OK) { - return NXT_ERROR; - } + nxt_debug(task, "pipe(): %FD:%FD", pp[0], pp[1]); + + if (nbread) { + if (nxt_fd_nonblocking(task, pp[0]) != NXT_OK) { + return NXT_ERROR; } + } - if (nbwrite) { - if (nxt_fd_nonblocking(task, pp[1]) != NXT_OK) { - return NXT_ERROR; - } + if (nbwrite) { + if (nxt_fd_nonblocking(task, pp[1]) != NXT_OK) { + return NXT_ERROR; } + } - return NXT_OK; + return NXT_OK; } +void nxt_pipe_close(nxt_task_t *task, nxt_fd_t *pp) { + nxt_debug(task, "pipe close(%FD:%FD)", pp[0], pp[1]); -void -nxt_pipe_close(nxt_task_t *task, nxt_fd_t *pp) -{ - nxt_debug(task, "pipe close(%FD:%FD)", pp[0], pp[1]); - - if (close(pp[0]) != 0) { - nxt_alert(task, "pipe close(%FD) failed %E", pp[0], nxt_errno); - } + if (close(pp[0]) != 0) { + nxt_alert(task, "pipe close(%FD) failed %E", pp[0], nxt_errno); + } - if (close(pp[1]) != 0) { - nxt_alert(task, "pipe close(%FD) failed %E", pp[1], nxt_errno); - } + if (close(pp[1]) != 0) { + nxt_alert(task, "pipe close(%FD) failed %E", pp[1], nxt_errno); + } } +size_t nxt_dir_current(char *buf, size_t len) { + if (nxt_fast_path(getcwd(buf, len) != NULL)) { + return nxt_strlen(buf); + } -size_t -nxt_dir_current(char *buf, size_t len) -{ - if (nxt_fast_path(getcwd(buf, len) != NULL)) { - return nxt_strlen(buf); - } - - nxt_thread_log_alert("getcwd(%uz) failed %E", len, nxt_errno); + nxt_thread_log_alert("getcwd(%uz) failed %E", len, nxt_errno); - return 0; + return 0; } diff --git a/src/nxt_file.h b/src/nxt_file.h index 0c03a5f90..2206d05d6 100644 --- a/src/nxt_file.h +++ b/src/nxt_file.h @@ -7,127 +7,109 @@ #ifndef _NXT_UNIX_FILE_H_INCLUDED_ #define _NXT_UNIX_FILE_H_INCLUDED_ +typedef int nxt_fd_t; -typedef int nxt_fd_t; +#define NXT_FILE_INVALID -1 -#define NXT_FILE_INVALID -1 +typedef nxt_uint_t nxt_file_access_t; +typedef struct stat nxt_file_info_t; -typedef nxt_uint_t nxt_file_access_t; -typedef struct stat nxt_file_info_t; - - -#define NXT_FILE_SYSTEM_NAME_UTF8 1 - -typedef u_char nxt_file_name_t; +#define NXT_FILE_SYSTEM_NAME_UTF8 1 +typedef u_char nxt_file_name_t; typedef struct { - size_t len; - nxt_file_name_t *start; + size_t len; + nxt_file_name_t *start; } nxt_file_name_str_t; +#define nxt_file_name_str_set(file_name, mem_pool, name) \ + ((file_name) = (nxt_file_name_t *)(name), NXT_OK) -#define nxt_file_name_str_set(file_name, mem_pool, name) \ - ((file_name) = (nxt_file_name_t *) (name), NXT_OK) - - -#define nxt_file_name_alloc(mem_pool, len) \ - nxt_mp_nget(mem_pool, len) - +#define nxt_file_name_alloc(mem_pool, len) nxt_mp_nget(mem_pool, len) -#define nxt_file_name_copy(dst, src, len) \ - nxt_cpymem(dst, src, len) - - -#define nxt_file_name_add(dst, src, len) \ - nxt_cpymem(dst, src, len) +#define nxt_file_name_copy(dst, src, len) nxt_cpymem(dst, src, len) +#define nxt_file_name_add(dst, src, len) nxt_cpymem(dst, src, len) #if (NXT_HAVE_CASELESS_FILESYSTEM) /* MacOSX, Cygwin. */ -#define nxt_file_name_eq(fn1, fn2) \ - (nxt_strcasecmp(fn1, fn2) == 0) +#define nxt_file_name_eq(fn1, fn2) (nxt_strcasecmp(fn1, fn2) == 0) #else -#define nxt_file_name_eq(fn1, fn2) \ - (nxt_strcmp(fn1, fn2) == 0) +#define nxt_file_name_eq(fn1, fn2) (nxt_strcmp(fn1, fn2) == 0) #endif +#define nxt_file_name_is_absolute(name) (name[0] == '/') -#define nxt_file_name_is_absolute(name) \ - (name[0] == '/') - - -#define NXT_MAX_PATH_LEN MAXPATHLEN - +#define NXT_MAX_PATH_LEN MAXPATHLEN typedef enum { - NXT_FILE_UNKNOWN = 0, - NXT_FILE_REGULAR, - NXT_FILE_DIRECTORY, + NXT_FILE_UNKNOWN = 0, + NXT_FILE_REGULAR, + NXT_FILE_DIRECTORY, } nxt_file_type_t; - typedef struct { - nxt_file_name_t *name; + nxt_file_name_t *name; - /* Both are int's. */ - nxt_fd_t fd; - nxt_err_t error; + /* Both are int's. */ + nxt_fd_t fd; + nxt_err_t error; -#define NXT_FILE_ACCESSED_LONG_AGO 0xFFFF - /* - * Number of seconds ago the file content was last - * read. The maximum value is about 18 hours. - */ - uint16_t accessed; +#define NXT_FILE_ACCESSED_LONG_AGO 0xFFFF + /* + * Number of seconds ago the file content was last + * read. The maximum value is about 18 hours. + */ + uint16_t accessed; - uint8_t type; /* nxt_file_type_t */ + uint8_t type; /* nxt_file_type_t */ - /* - * Log open() file error with given log level if it is non zero. - * Note that zero log level is NXT_LOG_ALERT. - */ - uint8_t log_level; + /* + * Log open() file error with given log level if it is non zero. + * Note that zero log level is NXT_LOG_ALERT. + */ + uint8_t log_level; - nxt_time_t mtime; - nxt_off_t size; + nxt_time_t mtime; + nxt_off_t size; } nxt_file_t; - NXT_EXPORT nxt_int_t nxt_file_open(nxt_task_t *task, nxt_file_t *file, - nxt_uint_t mode, nxt_uint_t create, nxt_file_access_t access); + nxt_uint_t mode, nxt_uint_t create, + nxt_file_access_t access); #if (NXT_HAVE_OPENAT2) NXT_EXPORT nxt_int_t nxt_file_openat2(nxt_task_t *task, nxt_file_t *file, - nxt_uint_t mode, nxt_uint_t create, nxt_file_access_t access, nxt_fd_t dfd, - nxt_uint_t resolve); + nxt_uint_t mode, nxt_uint_t create, + nxt_file_access_t access, nxt_fd_t dfd, + nxt_uint_t resolve); #endif - /* The file open access modes. */ -#define NXT_FILE_RDONLY O_RDONLY -#define NXT_FILE_WRONLY O_WRONLY -#define NXT_FILE_RDWR O_RDWR -#define NXT_FILE_APPEND (O_WRONLY | O_APPEND) +#define NXT_FILE_RDONLY O_RDONLY +#define NXT_FILE_WRONLY O_WRONLY +#define NXT_FILE_RDWR O_RDWR +#define NXT_FILE_APPEND (O_WRONLY | O_APPEND) #if (NXT_HAVE_OPENAT2) #if defined(O_DIRECTORY) -#define NXT_FILE_DIRECTORY O_DIRECTORY +#define NXT_FILE_DIRECTORY O_DIRECTORY #else -#define NXT_FILE_DIRECTORY 0 +#define NXT_FILE_DIRECTORY 0 #endif #if defined(O_SEARCH) -#define NXT_FILE_SEARCH (O_SEARCH|NXT_FILE_DIRECTORY) +#define NXT_FILE_SEARCH (O_SEARCH | NXT_FILE_DIRECTORY) #elif defined(O_EXEC) -#define NXT_FILE_SEARCH (O_EXEC|NXT_FILE_DIRECTORY) +#define NXT_FILE_SEARCH (O_EXEC | NXT_FILE_DIRECTORY) #else /* @@ -136,51 +118,44 @@ NXT_EXPORT nxt_int_t nxt_file_openat2(nxt_task_t *task, nxt_file_t *file, * modern system (i.e. glibc 2.14+) and run with a kernel older than 2.6.39. * Then O_PATH is unknown to the kernel and ignored, while O_RDONLY is used. */ -#define NXT_FILE_SEARCH (O_PATH|O_RDONLY|NXT_FILE_DIRECTORY) +#define NXT_FILE_SEARCH (O_PATH | O_RDONLY | NXT_FILE_DIRECTORY) #endif #endif /* NXT_HAVE_OPENAT2 */ /* The file creation modes. */ -#define NXT_FILE_CREATE_OR_OPEN O_CREAT -#define NXT_FILE_OPEN 0 -#define NXT_FILE_TRUNCATE (O_CREAT | O_TRUNC) +#define NXT_FILE_CREATE_OR_OPEN O_CREAT +#define NXT_FILE_OPEN 0 +#define NXT_FILE_TRUNCATE (O_CREAT | O_TRUNC) /* The file access rights. */ -#define NXT_FILE_DEFAULT_ACCESS 0644 -#define NXT_FILE_OWNER_ACCESS 0600 - +#define NXT_FILE_DEFAULT_ACCESS 0644 +#define NXT_FILE_OWNER_ACCESS 0600 NXT_EXPORT void nxt_file_close(nxt_task_t *task, nxt_file_t *file); NXT_EXPORT ssize_t nxt_file_write(nxt_file_t *file, const u_char *buf, - size_t size, nxt_off_t offset); + size_t size, nxt_off_t offset); NXT_EXPORT ssize_t nxt_file_read(nxt_file_t *file, u_char *buf, size_t size, - nxt_off_t offset); + nxt_off_t offset); NXT_EXPORT void nxt_file_read_ahead(nxt_file_t *file, nxt_off_t offset, - size_t size); + size_t size); NXT_EXPORT nxt_int_t nxt_file_info(nxt_file_t *file, nxt_file_info_t *fi); +#define nxt_is_dir(fi) (S_ISDIR((fi)->st_mode)) -#define nxt_is_dir(fi) \ - (S_ISDIR((fi)->st_mode)) - -#define nxt_is_file(fi) \ - (S_ISREG((fi)->st_mode)) +#define nxt_is_file(fi) (S_ISREG((fi)->st_mode)) -#define nxt_file_size(fi) \ - (fi)->st_size - -#define nxt_file_mtime(fi) \ - (fi)->st_mtime +#define nxt_file_size(fi) (fi)->st_size +#define nxt_file_mtime(fi) (fi)->st_mtime NXT_EXPORT nxt_int_t nxt_file_delete(nxt_file_name_t *name); NXT_EXPORT nxt_int_t nxt_file_set_access(nxt_file_name_t *name, - nxt_file_access_t access); + nxt_file_access_t access); NXT_EXPORT nxt_int_t nxt_file_chown(nxt_file_name_t *name, const char *owner, - const char *group); + const char *group); NXT_EXPORT nxt_int_t nxt_file_rename(nxt_file_name_t *old_name, - nxt_file_name_t *new_name); + nxt_file_name_t *new_name); NXT_EXPORT nxt_int_t nxt_fd_nonblocking(nxt_task_t *task, nxt_fd_t fd); NXT_EXPORT nxt_int_t nxt_fd_blocking(nxt_task_t *task, nxt_fd_t fd); @@ -189,7 +164,7 @@ NXT_EXPORT ssize_t nxt_fd_read(nxt_fd_t fd, u_char *buf, size_t size); NXT_EXPORT void nxt_fd_close(nxt_fd_t fd); NXT_EXPORT FILE *nxt_file_fopen(nxt_task_t *task, const char *pathname, - const char *mode); + const char *mode); NXT_EXPORT void nxt_file_fclose(nxt_task_t *task, FILE *fp); NXT_EXPORT nxt_int_t nxt_file_redirect(nxt_file_t *file, nxt_fd_t fd); @@ -197,23 +172,17 @@ NXT_EXPORT nxt_int_t nxt_file_stdout(nxt_file_t *file); NXT_EXPORT nxt_int_t nxt_file_stderr(nxt_file_t *file); NXT_EXPORT nxt_int_t nxt_stderr_start(void); +#define nxt_stdout STDOUT_FILENO +#define nxt_stderr STDERR_FILENO -#define nxt_stdout STDOUT_FILENO -#define nxt_stderr STDERR_FILENO - - -#define nxt_write_console(fd, buf, size) \ - write(fd, buf, size) - -#define nxt_write_syslog(priority, message) \ - syslog(priority, "%s", message) +#define nxt_write_console(fd, buf, size) write(fd, buf, size) +#define nxt_write_syslog(priority, message) syslog(priority, "%s", message) NXT_EXPORT nxt_int_t nxt_pipe_create(nxt_task_t *task, nxt_fd_t *pp, - nxt_bool_t nbread, nxt_bool_t nbwrite); + nxt_bool_t nbread, nxt_bool_t nbwrite); NXT_EXPORT void nxt_pipe_close(nxt_task_t *task, nxt_fd_t *pp); NXT_EXPORT size_t nxt_dir_current(char *buf, size_t len); - #endif /* _NXT_UNIX_FILE_H_INCLUDED_ */ diff --git a/src/nxt_file_event.h b/src/nxt_file_event.h index d4255ce94..6c53d3166 100644 --- a/src/nxt_file_event.h +++ b/src/nxt_file_event.h @@ -6,13 +6,11 @@ #ifndef _NXT_FILE_EVENT_H_INCLUDED_ #define _NXT_FILE_EVENT_H_INCLUDED_ - typedef struct { - void *data; - nxt_file_t *file; - nxt_work_handler_t handler; - nxt_task_t *task; + void *data; + nxt_file_t *file; + nxt_work_handler_t handler; + nxt_task_t *task; } nxt_file_event_t; - #endif /* _NXT_FILE_EVENT_H_INCLUDED_ */ diff --git a/src/nxt_file_name.c b/src/nxt_file_name.c index 935479ead..c7a288ef2 100644 --- a/src/nxt_file_name.c +++ b/src/nxt_file_name.c @@ -6,7 +6,6 @@ #include - /* * Supported formats: * %s null-terminated string @@ -16,186 +15,184 @@ * %Z '\0', this null is not counted in file name lenght. */ -nxt_int_t -nxt_file_name_create(nxt_mp_t *mp, nxt_file_name_str_t *file_name, - const char *format, ...) -{ - u_char ch, *p; - size_t length; - va_list args; - nxt_str_t *v; - nxt_bool_t zero; - const char *fmt; - nxt_file_name_t *dst, *fn; - - va_start(args, format); - fmt = format; - zero = 0; - length = 0; - - for ( ;; ) { - ch = *fmt++; - - if (ch != '%') { - - if (ch != '\0') { - length++; - continue; - } - - break; - } +nxt_int_t nxt_file_name_create(nxt_mp_t *mp, nxt_file_name_str_t *file_name, + const char *format, ...) { + u_char ch, *p; + size_t length; + va_list args; + nxt_str_t *v; + nxt_bool_t zero; + const char *fmt; + nxt_file_name_t *dst, *fn; - ch = *fmt++; + va_start(args, format); + fmt = format; + zero = 0; + length = 0; - switch (ch) { + for (;;) { + ch = *fmt++; - case 'V': - v = va_arg(args, nxt_str_t *); + if (ch != '%') { - if (nxt_fast_path(v != NULL)) { - length += v->length; - } + if (ch != '\0') { + length++; + continue; + } - continue; + break; + } - case 's': - p = va_arg(args, u_char *); + ch = *fmt++; - if (nxt_fast_path(p != NULL)) { - while (*p != '\0') { - p++; - length++; - } - } + switch (ch) { - continue; + case 'V': + v = va_arg(args, nxt_str_t *); - case '*': - length += va_arg(args, u_int); - fmt++; + if (nxt_fast_path(v != NULL)) { + length += v->length; + } - continue; + continue; - case 'F': - ch = *fmt++; + case 's': + p = va_arg(args, u_char *); - if (nxt_fast_path(ch == 'N')) { - fn = va_arg(args, nxt_file_name_t *); + if (nxt_fast_path(p != NULL)) { + while (*p != '\0') { + p++; + length++; + } + } - if (nxt_fast_path(fn != NULL)) { - while (*fn != '\0') { - fn++; - length += sizeof(nxt_file_name_t); - } - } - } + continue; - continue; + case '*': + length += va_arg(args, u_int); + fmt++; - case 'Z': - zero = 1; - length++; - continue; + continue; - default: - continue; - } - } + case 'F': + ch = *fmt++; - va_end(args); + if (nxt_fast_path(ch == 'N')) { + fn = va_arg(args, nxt_file_name_t *); - if (length == 0) { - return NXT_ERROR; - } + if (nxt_fast_path(fn != NULL)) { + while (*fn != '\0') { + fn++; + length += sizeof(nxt_file_name_t); + } + } + } - file_name->len = length - zero; + continue; - fn = nxt_file_name_alloc(mp, length); - if (nxt_slow_path(fn == NULL)) { - return NXT_ERROR; + case 'Z': + zero = 1; + length++; + continue; + + default: + continue; } + } - file_name->start = fn; - dst = fn; + va_end(args); - va_start(args, format); - fmt = format; + if (length == 0) { + return NXT_ERROR; + } - for ( ;; ) { - ch = *fmt++; + file_name->len = length - zero; - if (ch != '%') { + fn = nxt_file_name_alloc(mp, length); + if (nxt_slow_path(fn == NULL)) { + return NXT_ERROR; + } - if (ch != '\0') { - *dst++ = (nxt_file_name_t) ch; - continue; - } + file_name->start = fn; + dst = fn; - break; - } + va_start(args, format); + fmt = format; - ch = *fmt++; + for (;;) { + ch = *fmt++; - switch (ch) { + if (ch != '%') { - case 'V': - v = va_arg(args, nxt_str_t *); + if (ch != '\0') { + *dst++ = (nxt_file_name_t)ch; + continue; + } + + break; + } - if (nxt_fast_path(v != NULL)) { - dst = nxt_file_name_add(dst, v->start, v->length); - } + ch = *fmt++; - continue; + switch (ch) { - case 's': - p = va_arg(args, u_char *); + case 'V': + v = va_arg(args, nxt_str_t *); - if (nxt_fast_path(p != NULL)) { - while (*p != '\0') { - *dst++ = (nxt_file_name_t) (*p++); - } - } + if (nxt_fast_path(v != NULL)) { + dst = nxt_file_name_add(dst, v->start, v->length); + } - continue; + continue; - case '*': - length += va_arg(args, u_int); + case 's': + p = va_arg(args, u_char *); - ch = *fmt++; + if (nxt_fast_path(p != NULL)) { + while (*p != '\0') { + *dst++ = (nxt_file_name_t)(*p++); + } + } - if (nxt_fast_path(ch == 's')) { - p = va_arg(args, u_char *); - dst = nxt_file_name_add(dst, p, length); - } + continue; - continue; + case '*': + length += va_arg(args, u_int); - case 'F': - ch = *fmt++; + ch = *fmt++; - if (nxt_fast_path(ch == 'N')) { - fn = va_arg(args, nxt_file_name_t *); + if (nxt_fast_path(ch == 's')) { + p = va_arg(args, u_char *); + dst = nxt_file_name_add(dst, p, length); + } - if (nxt_fast_path(fn != NULL)) { - while (*fn != '\0') { - *dst++ = *fn++; - } - } - } + continue; - continue; + case 'F': + ch = *fmt++; - case 'Z': - *dst++ = '\0'; - continue; + if (nxt_fast_path(ch == 'N')) { + fn = va_arg(args, nxt_file_name_t *); - default: - continue; + if (nxt_fast_path(fn != NULL)) { + while (*fn != '\0') { + *dst++ = *fn++; + } } + } + + continue; + + case 'Z': + *dst++ = '\0'; + continue; + + default: + continue; } + } - va_end(args); + va_end(args); - return NXT_OK; + return NXT_OK; } diff --git a/src/nxt_file_name.h b/src/nxt_file_name.h index f8e7a3ba9..828e52c44 100644 --- a/src/nxt_file_name.h +++ b/src/nxt_file_name.h @@ -7,9 +7,7 @@ #ifndef _NXT_FILE_NAME_H_INCLUDED_ #define _NXT_FILE_NAME_H_INCLUDED_ - -NXT_EXPORT nxt_int_t nxt_file_name_create(nxt_mp_t *mp, - nxt_file_name_str_t *fn, const char *format, ...); - +NXT_EXPORT nxt_int_t nxt_file_name_create(nxt_mp_t *mp, nxt_file_name_str_t *fn, + const char *format, ...); #endif /* _NXT_FILE_NAME_H_INCLUDED_ */ diff --git a/src/nxt_freebsd_sendfile.c b/src/nxt_freebsd_sendfile.c index a9535c109..a6792c4f2 100644 --- a/src/nxt_freebsd_sendfile.c +++ b/src/nxt_freebsd_sendfile.c @@ -6,7 +6,6 @@ #include - /* * sendfile() has been introduced in FreeBSD 3.1, * however, early implementation had various bugs. @@ -16,128 +15,123 @@ #ifdef NXT_TEST_BUILD_FREEBSD_SENDFILE ssize_t nxt_freebsd_event_conn_io_sendfile(nxt_event_conn_t *c, nxt_buf_t *b, - size_t limit); + size_t limit); static int nxt_sys_sendfile(int fd, int s, off_t offset, size_t nbytes, - struct sf_hdtr *hdtr, off_t *sbytes, int flags) -{ - return -1; + struct sf_hdtr *hdtr, off_t *sbytes, int flags) { + return -1; } #else -#define nxt_sys_sendfile sendfile +#define nxt_sys_sendfile sendfile #endif +ssize_t nxt_freebsd_event_conn_io_sendfile(nxt_event_conn_t *c, nxt_buf_t *b, + size_t limit) { + size_t file_size; + ssize_t n; + nxt_buf_t *fb; + nxt_err_t err; + nxt_off_t sent; + nxt_uint_t nhd, ntr; + struct iovec hd[NXT_IOBUF_MAX], tr[NXT_IOBUF_MAX]; + struct sf_hdtr hdtr, *ht; + nxt_sendbuf_coalesce_t sb; -ssize_t -nxt_freebsd_event_conn_io_sendfile(nxt_event_conn_t *c, nxt_buf_t *b, - size_t limit) -{ - size_t file_size; - ssize_t n; - nxt_buf_t *fb; - nxt_err_t err; - nxt_off_t sent; - nxt_uint_t nhd, ntr; - struct iovec hd[NXT_IOBUF_MAX], tr[NXT_IOBUF_MAX]; - struct sf_hdtr hdtr, *ht; - nxt_sendbuf_coalesce_t sb; - - sb.buf = b; - sb.iobuf = hd; - sb.nmax = NXT_IOBUF_MAX; - sb.sync = 0; - sb.size = 0; - sb.limit = limit; - - nhd = nxt_sendbuf_mem_coalesce(c->socket.task, &sb); - - if (nhd == 0 && sb.sync) { - return 0; - } - - if (sb.buf == NULL || !nxt_buf_is_file(sb.buf)) { - return nxt_event_conn_io_writev(c, hd, nhd); - } - - fb = sb.buf; + sb.buf = b; + sb.iobuf = hd; + sb.nmax = NXT_IOBUF_MAX; + sb.sync = 0; + sb.size = 0; + sb.limit = limit; - file_size = nxt_sendbuf_file_coalesce(&sb); + nhd = nxt_sendbuf_mem_coalesce(c->socket.task, &sb); - if (file_size == 0) { - return nxt_event_conn_io_writev(c, hd, nhd); - } + if (nhd == 0 && sb.sync) { + return 0; + } - sb.iobuf = tr; + if (sb.buf == NULL || !nxt_buf_is_file(sb.buf)) { + return nxt_event_conn_io_writev(c, hd, nhd); + } - ntr = nxt_sendbuf_mem_coalesce(c->socket.task, &sb); + fb = sb.buf; - /* - * Disposal of surplus kernel operations - * if there are no headers or trailers. - */ + file_size = nxt_sendbuf_file_coalesce(&sb); - ht = NULL; - nxt_memzero(&hdtr, sizeof(struct sf_hdtr)); + if (file_size == 0) { + return nxt_event_conn_io_writev(c, hd, nhd); + } - if (nhd != 0) { - ht = &hdtr; - hdtr.headers = hd; - hdtr.hdr_cnt = nhd; - } + sb.iobuf = tr; - if (ntr != 0) { - ht = &hdtr; - hdtr.trailers = tr; - hdtr.trl_cnt = ntr; - } + ntr = nxt_sendbuf_mem_coalesce(c->socket.task, &sb); - nxt_debug(c->socket.task, "sendfile(%FD, %d, @%O, %uz) hd:%ui tr:%ui", - fb->file->fd, c->socket.fd, fb->file_pos, file_size, - nhd, ntr); + /* + * Disposal of surplus kernel operations + * if there are no headers or trailers. + */ - sent = 0; - n = nxt_sys_sendfile(fb->file->fd, c->socket.fd, fb->file_pos, - file_size, ht, &sent, 0); + ht = NULL; + nxt_memzero(&hdtr, sizeof(struct sf_hdtr)); - err = (n == -1) ? nxt_errno : 0; + if (nhd != 0) { + ht = &hdtr; + hdtr.headers = hd; + hdtr.hdr_cnt = nhd; + } - nxt_debug(c->socket.task, "sendfile(): %d sent:%O", n, sent); + if (ntr != 0) { + ht = &hdtr; + hdtr.trailers = tr; + hdtr.trl_cnt = ntr; + } - if (n == -1) { - switch (err) { + nxt_debug(c->socket.task, "sendfile(%FD, %d, @%O, %uz) hd:%ui tr:%ui", + fb->file->fd, c->socket.fd, fb->file_pos, file_size, nhd, ntr); - case NXT_EAGAIN: - c->socket.write_ready = 0; - break; + sent = 0; + n = nxt_sys_sendfile(fb->file->fd, c->socket.fd, fb->file_pos, file_size, ht, + &sent, 0); - case NXT_EINTR: - break; + err = (n == -1) ? nxt_errno : 0; - default: - c->socket.error = err; - nxt_log(c->socket.task, nxt_socket_error_level(err), - "sendfile(%FD, %d, %O, %uz) failed %E \"%FN\" hd:%ui tr:%ui", - fb->file->fd, c->socket.fd, fb->file_pos, file_size, err, - fb->file->name, nhd, ntr); + nxt_debug(c->socket.task, "sendfile(): %d sent:%O", n, sent); - return NXT_ERROR; - } + if (n == -1) { + switch (err) { - nxt_debug(c->socket.task, "sendfile() %E", err); + case NXT_EAGAIN: + c->socket.write_ready = 0; + break; - return sent; + case NXT_EINTR: + break; - } else if (sent == 0) { - nxt_log(c->socket.task, NXT_LOG_ERR, - "file \"%FN\" was truncated while sendfile()", fb->file->name); + default: + c->socket.error = err; + nxt_log(c->socket.task, nxt_socket_error_level(err), + "sendfile(%FD, %d, %O, %uz) failed %E \"%FN\" hd:%ui tr:%ui", + fb->file->fd, c->socket.fd, fb->file_pos, file_size, err, + fb->file->name, nhd, ntr); - return NXT_ERROR; + return NXT_ERROR; } - if (sent < (nxt_off_t) sb.size) { - c->socket.write_ready = 0; - } + nxt_debug(c->socket.task, "sendfile() %E", err); return sent; + + } else if (sent == 0) { + nxt_log(c->socket.task, NXT_LOG_ERR, + "file \"%FN\" was truncated while sendfile()", fb->file->name); + + return NXT_ERROR; + } + + if (sent < (nxt_off_t)sb.size) { + c->socket.write_ready = 0; + } + + return sent; } diff --git a/src/nxt_fs.c b/src/nxt_fs.c index 8ea8e1867..d7c5a13f2 100644 --- a/src/nxt_fs.c +++ b/src/nxt_fs.c @@ -5,80 +5,70 @@ #include - static nxt_int_t nxt_fs_mkdir(const u_char *dir, mode_t mode); +nxt_int_t nxt_fs_mkdir_p(const u_char *dir, mode_t mode) { + char *start, *end, *dst; + size_t dirlen; + nxt_int_t ret; + char path[PATH_MAX]; -nxt_int_t -nxt_fs_mkdir_p(const u_char *dir, mode_t mode) -{ - char *start, *end, *dst; - size_t dirlen; - nxt_int_t ret; - char path[PATH_MAX]; - - dirlen = nxt_strlen(dir); + dirlen = nxt_strlen(dir); - nxt_assert(dirlen < PATH_MAX && dirlen > 0); + nxt_assert(dirlen < PATH_MAX && dirlen > 0); - dst = path; - start = (char *) dir; + dst = path; + start = (char *)dir; - while (*start != '\0') { - end = strchr(start + 1, '/'); - if (end == NULL) { - end = ((char *)dir + dirlen); - } - - dst = nxt_cpymem(dst, start, end - start); - *dst = '\0'; + while (*start != '\0') { + end = strchr(start + 1, '/'); + if (end == NULL) { + end = ((char *)dir + dirlen); + } - ret = nxt_fs_mkdir((u_char *) path, mode); - if (nxt_slow_path(ret != NXT_OK && nxt_errno != EEXIST)) { - return NXT_ERROR; - } + dst = nxt_cpymem(dst, start, end - start); + *dst = '\0'; - start = end; + ret = nxt_fs_mkdir((u_char *)path, mode); + if (nxt_slow_path(ret != NXT_OK && nxt_errno != EEXIST)) { + return NXT_ERROR; } - return NXT_OK; -} + start = end; + } + return NXT_OK; +} -nxt_int_t -nxt_fs_mkdir_p_dirname(const u_char *path, mode_t mode) -{ - char *ptr, *dir; - nxt_int_t ret; +nxt_int_t nxt_fs_mkdir_p_dirname(const u_char *path, mode_t mode) { + char *ptr, *dir; + nxt_int_t ret; - dir = nxt_strdup(path); - if (nxt_slow_path(dir == NULL)) { - return NXT_ERROR; - } + dir = nxt_strdup(path); + if (nxt_slow_path(dir == NULL)) { + return NXT_ERROR; + } - ret = NXT_OK; + ret = NXT_OK; - ptr = strrchr(dir, '/'); - if (ptr == dir || nxt_slow_path(ptr == NULL)) { - goto out_free; - } + ptr = strrchr(dir, '/'); + if (ptr == dir || nxt_slow_path(ptr == NULL)) { + goto out_free; + } - *ptr = '\0'; - ret = nxt_fs_mkdir_p((const u_char *) dir, mode); + *ptr = '\0'; + ret = nxt_fs_mkdir_p((const u_char *)dir, mode); out_free: - nxt_free(dir); + nxt_free(dir); - return ret; + return ret; } +static nxt_int_t nxt_fs_mkdir(const u_char *dir, mode_t mode) { + if (nxt_fast_path(mkdir((const char *)dir, mode) == 0)) { + return NXT_OK; + } -static nxt_int_t -nxt_fs_mkdir(const u_char *dir, mode_t mode) -{ - if (nxt_fast_path(mkdir((const char *) dir, mode) == 0)) { - return NXT_OK; - } - - return NXT_ERROR; + return NXT_ERROR; } diff --git a/src/nxt_fs.h b/src/nxt_fs.h index a06e4d3d8..f95d1581e 100644 --- a/src/nxt_fs.h +++ b/src/nxt_fs.h @@ -5,9 +5,7 @@ #ifndef _NXT_FS_H_INCLUDED_ #define _NXT_FS_H_INCLUDED_ - nxt_int_t nxt_fs_mkdir_p_dirname(const u_char *path, mode_t mode); nxt_int_t nxt_fs_mkdir_p(const u_char *dir, mode_t mode); - -#endif /* _NXT_FS_H_INCLUDED_ */ +#endif /* _NXT_FS_H_INCLUDED_ */ diff --git a/src/nxt_fs_mount.c b/src/nxt_fs_mount.c index d9b384e43..401ae5125 100644 --- a/src/nxt_fs_mount.c +++ b/src/nxt_fs_mount.c @@ -9,222 +9,211 @@ #include #endif - #if (NXT_HAVE_LINUX_MOUNT) -nxt_int_t -nxt_fs_mount(nxt_task_t *task, nxt_fs_mount_t *mnt) -{ - int rc; - const char *fsname; - unsigned long flags; +nxt_int_t nxt_fs_mount(nxt_task_t *task, nxt_fs_mount_t *mnt) { + int rc; + const char *fsname; + unsigned long flags; - flags = 0; + flags = 0; - switch (mnt->type) { - case NXT_FS_BIND: - if (nxt_slow_path(mnt->flags != 0)) { - nxt_log(task, NXT_LOG_WARN, - "bind mount ignores additional flags"); - } + switch (mnt->type) { + case NXT_FS_BIND: + if (nxt_slow_path(mnt->flags != 0)) { + nxt_log(task, NXT_LOG_WARN, "bind mount ignores additional flags"); + } - fsname = "bind"; - flags = MS_BIND | MS_REC; - break; + fsname = "bind"; + flags = MS_BIND | MS_REC; + break; - case NXT_FS_PROC: - fsname = "proc"; - goto getflags; + case NXT_FS_PROC: + fsname = "proc"; + goto getflags; - case NXT_FS_TMP: - fsname = "tmpfs"; - goto getflags; + case NXT_FS_TMP: + fsname = "tmpfs"; + goto getflags; - default: - fsname = (const char *) mnt->name; + default: + fsname = (const char *)mnt->name; - getflags: + getflags: - if (mnt->flags & NXT_FS_FLAGS_NODEV) { - flags |= MS_NODEV; - } + if (mnt->flags & NXT_FS_FLAGS_NODEV) { + flags |= MS_NODEV; + } - if (mnt->flags & NXT_FS_FLAGS_NOEXEC) { - flags |= MS_NOEXEC; - } + if (mnt->flags & NXT_FS_FLAGS_NOEXEC) { + flags |= MS_NOEXEC; + } - if (mnt->flags & NXT_FS_FLAGS_NOSUID) { - flags |= MS_NOSUID; - } + if (mnt->flags & NXT_FS_FLAGS_NOSUID) { + flags |= MS_NOSUID; + } - if (!(mnt->flags & NXT_FS_FLAGS_NOTIME)) { - flags |= MS_RELATIME; - } + if (!(mnt->flags & NXT_FS_FLAGS_NOTIME)) { + flags |= MS_RELATIME; } + } - rc = mount((const char *) mnt->src, (const char *) mnt->dst, fsname, flags, - mnt->data); + rc = mount((const char *)mnt->src, (const char *)mnt->dst, fsname, flags, + mnt->data); - if (nxt_slow_path(rc < 0)) { - nxt_alert(task, "mount(\"%s\", \"%s\", \"%s\", %ul, \"%s\") %E", - mnt->src, mnt->dst, fsname, flags, mnt->data, nxt_errno); + if (nxt_slow_path(rc < 0)) { + nxt_alert(task, "mount(\"%s\", \"%s\", \"%s\", %ul, \"%s\") %E", mnt->src, + mnt->dst, fsname, flags, mnt->data, nxt_errno); - return NXT_ERROR; - } + return NXT_ERROR; + } - return NXT_OK; + return NXT_OK; } #elif (NXT_HAVE_FREEBSD_NMOUNT) -nxt_int_t -nxt_fs_mount(nxt_task_t *task, nxt_fs_mount_t *mnt) -{ - int flags; - u_char *data, *p, *end; - size_t iovlen; - nxt_int_t ret; - const char *fsname; - struct iovec iov[128]; - char errmsg[256]; - - if (nxt_slow_path((mnt->flags & NXT_FS_FLAGS_NODEV) && !mnt->builtin)) { - nxt_alert(task, "nmount(2) doesn't support \"nodev\" option"); - - return NXT_ERROR; - } +nxt_int_t nxt_fs_mount(nxt_task_t *task, nxt_fs_mount_t *mnt) { + int flags; + u_char *data, *p, *end; + size_t iovlen; + nxt_int_t ret; + const char *fsname; + struct iovec iov[128]; + char errmsg[256]; - flags = 0; + if (nxt_slow_path((mnt->flags & NXT_FS_FLAGS_NODEV) && !mnt->builtin)) { + nxt_alert(task, "nmount(2) doesn't support \"nodev\" option"); - switch (mnt->type) { - case NXT_FS_BIND: - fsname = "nullfs"; - break; + return NXT_ERROR; + } - case NXT_FS_PROC: - fsname = "procfs"; - goto getflags; + flags = 0; - case NXT_FS_TMP: - fsname = "tmpfs"; - goto getflags; + switch (mnt->type) { + case NXT_FS_BIND: + fsname = "nullfs"; + break; - default: - fsname = (const char *) mnt->name; + case NXT_FS_PROC: + fsname = "procfs"; + goto getflags; - getflags: + case NXT_FS_TMP: + fsname = "tmpfs"; + goto getflags; - if (mnt->flags & NXT_FS_FLAGS_NOEXEC) { - flags |= MNT_NOEXEC; - } + default: + fsname = (const char *)mnt->name; - if (mnt->flags & NXT_FS_FLAGS_NOSUID) { - flags |= MNT_NOSUID; - } + getflags: - if (mnt->flags & NXT_FS_FLAGS_NOTIME) { - flags |= MNT_NOATIME; - } - - if (mnt->flags & NXT_FS_FLAGS_RDONLY) { - flags |= MNT_RDONLY; - } + if (mnt->flags & NXT_FS_FLAGS_NOEXEC) { + flags |= MNT_NOEXEC; } - iov[0].iov_base = (void *) "fstype"; - iov[0].iov_len = 7; - iov[1].iov_base = (void *) fsname; - iov[1].iov_len = nxt_strlen(fsname) + 1; - iov[2].iov_base = (void *) "fspath"; - iov[2].iov_len = 7; - iov[3].iov_base = (void *) mnt->dst; - iov[3].iov_len = nxt_strlen(mnt->dst) + 1; - iov[4].iov_base = (void *) "target"; - iov[4].iov_len = 7; - iov[5].iov_base = (void *) mnt->src; - iov[5].iov_len = nxt_strlen(mnt->src) + 1; - iov[6].iov_base = (void *) "errmsg"; - iov[6].iov_len = 7; - iov[7].iov_base = (void *) errmsg; - iov[7].iov_len = sizeof(errmsg); - - iovlen = 8; + if (mnt->flags & NXT_FS_FLAGS_NOSUID) { + flags |= MNT_NOSUID; + } - data = NULL; + if (mnt->flags & NXT_FS_FLAGS_NOTIME) { + flags |= MNT_NOATIME; + } - if (mnt->data != NULL) { - data = (u_char *) nxt_strdup(mnt->data); - if (nxt_slow_path(data == NULL)) { - return NXT_ERROR; - } + if (mnt->flags & NXT_FS_FLAGS_RDONLY) { + flags |= MNT_RDONLY; + } + } + + iov[0].iov_base = (void *)"fstype"; + iov[0].iov_len = 7; + iov[1].iov_base = (void *)fsname; + iov[1].iov_len = nxt_strlen(fsname) + 1; + iov[2].iov_base = (void *)"fspath"; + iov[2].iov_len = 7; + iov[3].iov_base = (void *)mnt->dst; + iov[3].iov_len = nxt_strlen(mnt->dst) + 1; + iov[4].iov_base = (void *)"target"; + iov[4].iov_len = 7; + iov[5].iov_base = (void *)mnt->src; + iov[5].iov_len = nxt_strlen(mnt->src) + 1; + iov[6].iov_base = (void *)"errmsg"; + iov[6].iov_len = 7; + iov[7].iov_base = (void *)errmsg; + iov[7].iov_len = sizeof(errmsg); + + iovlen = 8; + + data = NULL; + + if (mnt->data != NULL) { + data = (u_char *)nxt_strdup(mnt->data); + if (nxt_slow_path(data == NULL)) { + return NXT_ERROR; + } - end = data - 1; + end = data - 1; - do { - p = end + 1; - end = nxt_strchr(p, '='); - if (end == NULL) { - break; - } + do { + p = end + 1; + end = nxt_strchr(p, '='); + if (end == NULL) { + break; + } - *end = '\0'; + *end = '\0'; - iov[iovlen].iov_base = (void *) p; - iov[iovlen].iov_len = (end - p) + 1; + iov[iovlen].iov_base = (void *)p; + iov[iovlen].iov_len = (end - p) + 1; - iovlen++; + iovlen++; - p = end + 1; + p = end + 1; - end = nxt_strchr(p, ','); - if (end != NULL) { - *end = '\0'; - } + end = nxt_strchr(p, ','); + if (end != NULL) { + *end = '\0'; + } - iov[iovlen].iov_base = (void *) p; - iov[iovlen].iov_len = nxt_strlen(p) + 1; + iov[iovlen].iov_base = (void *)p; + iov[iovlen].iov_len = nxt_strlen(p) + 1; - iovlen++; + iovlen++; - } while (end != NULL && nxt_nitems(iov) > (iovlen + 2)); - } + } while (end != NULL && nxt_nitems(iov) > (iovlen + 2)); + } - ret = NXT_OK; + ret = NXT_OK; - if (nxt_slow_path(nmount(iov, iovlen, flags) < 0)) { - nxt_alert(task, "nmount(%p, %d, 0) %s", iov, iovlen, errmsg); - ret = NXT_ERROR; - } + if (nxt_slow_path(nmount(iov, iovlen, flags) < 0)) { + nxt_alert(task, "nmount(%p, %d, 0) %s", iov, iovlen, errmsg); + ret = NXT_ERROR; + } - if (data != NULL) { - free(data); - } + if (data != NULL) { + free(data); + } - return ret; + return ret; } #endif - #if (NXT_HAVE_LINUX_UMOUNT2) -void -nxt_fs_unmount(const u_char *path) -{ - if (nxt_slow_path(umount2((const char *) path, MNT_DETACH) < 0)) { - nxt_thread_log_error(NXT_LOG_WARN, "umount2(%s, MNT_DETACH) %E", - path, nxt_errno); - } +void nxt_fs_unmount(const u_char *path) { + if (nxt_slow_path(umount2((const char *)path, MNT_DETACH) < 0)) { + nxt_thread_log_error(NXT_LOG_WARN, "umount2(%s, MNT_DETACH) %E", path, + nxt_errno); + } } #elif (NXT_HAVE_UNMOUNT) -void -nxt_fs_unmount(const u_char *path) -{ - if (nxt_slow_path(unmount((const char *) path, MNT_FORCE) < 0)) { - nxt_thread_log_error(NXT_LOG_WARN, "unmount(%s) %E", path, nxt_errno); - } +void nxt_fs_unmount(const u_char *path) { + if (nxt_slow_path(unmount((const char *)path, MNT_FORCE) < 0)) { + nxt_thread_log_error(NXT_LOG_WARN, "unmount(%s) %E", path, nxt_errno); + } } #endif diff --git a/src/nxt_fs_mount.h b/src/nxt_fs_mount.h index e0fe6eb2c..3b56f3767 100644 --- a/src/nxt_fs_mount.h +++ b/src/nxt_fs_mount.h @@ -5,44 +5,38 @@ #ifndef _NXT_FS_MOUNT_H_INCLUDED_ #define _NXT_FS_MOUNT_H_INCLUDED_ - -typedef enum nxt_fs_type_s nxt_fs_type_t; -typedef enum nxt_fs_flags_s nxt_fs_flags_t; -typedef struct nxt_fs_mount_s nxt_fs_mount_t; - +typedef enum nxt_fs_type_s nxt_fs_type_t; +typedef enum nxt_fs_flags_s nxt_fs_flags_t; +typedef struct nxt_fs_mount_s nxt_fs_mount_t; enum nxt_fs_type_s { - NXT_FS_UNKNOWN = 0, - NXT_FS_BIND, - NXT_FS_TMP, - NXT_FS_PROC, - NXT_FS_LAST, + NXT_FS_UNKNOWN = 0, + NXT_FS_BIND, + NXT_FS_TMP, + NXT_FS_PROC, + NXT_FS_LAST, }; - enum nxt_fs_flags_s { - NXT_FS_FLAGS_NOSUID = 1 << 0, - NXT_FS_FLAGS_NOEXEC = 1 << 1, - NXT_FS_FLAGS_NOTIME = 1 << 2, - NXT_FS_FLAGS_NODEV = 1 << 3, - NXT_FS_FLAGS_RDONLY = 1 << 4, + NXT_FS_FLAGS_NOSUID = 1 << 0, + NXT_FS_FLAGS_NOEXEC = 1 << 1, + NXT_FS_FLAGS_NOTIME = 1 << 2, + NXT_FS_FLAGS_NODEV = 1 << 3, + NXT_FS_FLAGS_RDONLY = 1 << 4, }; - struct nxt_fs_mount_s { - u_char *src; - u_char *dst; - nxt_fs_type_t type; - u_char *name; - nxt_fs_flags_t flags; - u_char *data; - nxt_uint_t builtin; /* 1-bit */ - nxt_uint_t deps; /* 1-bit */ + u_char *src; + u_char *dst; + nxt_fs_type_t type; + u_char *name; + nxt_fs_flags_t flags; + u_char *data; + nxt_uint_t builtin; /* 1-bit */ + nxt_uint_t deps; /* 1-bit */ }; - nxt_int_t nxt_fs_mount(nxt_task_t *task, nxt_fs_mount_t *mnt); void nxt_fs_unmount(const u_char *path); - -#endif /* _NXT_FS_MOUNT_H_INCLUDED_ */ +#endif /* _NXT_FS_MOUNT_H_INCLUDED_ */ diff --git a/src/nxt_gmtime.c b/src/nxt_gmtime.c index 9c3fa190c..39e25ce67 100644 --- a/src/nxt_gmtime.c +++ b/src/nxt_gmtime.c @@ -6,74 +6,71 @@ #include - /* The function is valid for positive nxt_time_t only. */ -void -nxt_gmtime(nxt_time_t s, struct tm *tm) -{ - nxt_int_t yday; - nxt_uint_t daytime, mday, mon, year, days, leap; +void nxt_gmtime(nxt_time_t s, struct tm *tm) { + nxt_int_t yday; + nxt_uint_t daytime, mday, mon, year, days, leap; - days = (nxt_uint_t) (s / 86400); - daytime = (nxt_uint_t) (s % 86400); + days = (nxt_uint_t)(s / 86400); + daytime = (nxt_uint_t)(s % 86400); - /* January 1, 1970 was Thursday. */ - tm->tm_wday = (4 + days) % 7; + /* January 1, 1970 was Thursday. */ + tm->tm_wday = (4 + days) % 7; - /* The algorithm based on Gauss' formula. */ + /* The algorithm based on Gauss' formula. */ - /* Days since March 1, 1 BCE. */ - days = days - (31 + 28) + 719527; + /* Days since March 1, 1 BCE. */ + days = days - (31 + 28) + 719527; - /* - * The "days" should be adjusted by 1 only, however some March 1st's - * go to previous year, so "days" are adjusted by 2. This also shifts - * the last February days to the next year, but this is catched by - * negative "yday". - */ - year = (days + 2) * 400 / (365 * 400 + 100 - 4 + 1); + /* + * The "days" should be adjusted by 1 only, however some March 1st's + * go to previous year, so "days" are adjusted by 2. This also shifts + * the last February days to the next year, but this is catched by + * negative "yday". + */ + year = (days + 2) * 400 / (365 * 400 + 100 - 4 + 1); - yday = days - (365 * year + year / 4 - year / 100 + year / 400); + yday = days - (365 * year + year / 4 - year / 100 + year / 400); - leap = (year % 4 == 0) && (year % 100 || (year % 400 == 0)); + leap = (year % 4 == 0) && (year % 100 || (year % 400 == 0)); - if (yday < 0) { - yday = 365 + leap + yday; - year--; - } + if (yday < 0) { + yday = 365 + leap + yday; + year--; + } - /* - * An empirical formula that maps "yday" to month. - * There are at least 10 variants, some of them are: - * mon = (yday + 31) * 15 / 459 - * mon = (yday + 31) * 17 / 520 - * mon = (yday + 31) * 20 / 612 - */ + /* + * An empirical formula that maps "yday" to month. + * There are at least 10 variants, some of them are: + * mon = (yday + 31) * 15 / 459 + * mon = (yday + 31) * 17 / 520 + * mon = (yday + 31) * 20 / 612 + */ - mon = (yday + 31) * 10 / 306; + mon = (yday + 31) * 10 / 306; - /* The Gauss' formula that evaluates days before month. */ + /* The Gauss' formula that evaluates days before month. */ - mday = yday - (367 * mon / 12 - 30) + 1; + mday = yday - (367 * mon / 12 - 30) + 1; - if (yday >= 306) { - year++; - mon -= 11; - yday -= 306; + if (yday >= 306) { + year++; + mon -= 11; + yday -= 306; - } else { - mon++; - yday += 31 + 28 + leap; - } + } else { + mon++; + yday += 31 + 28 + leap; + } - tm->tm_mday = mday; - tm->tm_mon = mon; - tm->tm_year = year - 1900; - tm->tm_yday = yday; + tm->tm_mday = mday; + tm->tm_mon = mon; + tm->tm_year = year - 1900; + tm->tm_yday = yday; - tm->tm_hour = daytime / 3600; - daytime %= 3600; - tm->tm_min = daytime / 60; - tm->tm_sec = daytime % 60; + tm->tm_hour = daytime / 3600; + daytime %= 3600; + tm->tm_min = daytime / 60; + tm->tm_sec = daytime % 60; } diff --git a/src/nxt_gnutls.c b/src/nxt_gnutls.c index aab4699c6..45d04a67f 100644 --- a/src/nxt_gnutls.c +++ b/src/nxt_gnutls.c @@ -7,24 +7,20 @@ #include #include - typedef struct { - gnutls_session_t session; + gnutls_session_t session; - uint8_t times; /* 2 bits */ - uint8_t no_shutdown; /* 1 bit */ + uint8_t times; /* 2 bits */ + uint8_t no_shutdown; /* 1 bit */ - nxt_buf_mem_t buffer; + nxt_buf_mem_t buffer; } nxt_gnutls_conn_t; - typedef struct { - gnutls_priority_t ciphers; - gnutls_certificate_credentials_t certificate; + gnutls_priority_t ciphers; + gnutls_certificate_credentials_t certificate; } nxt_gnutls_ctx_t; - - #if (NXT_HAVE_GNUTLS_SET_TIME) time_t nxt_gnutls_time(time_t *tp); #endif @@ -32,40 +28,41 @@ static nxt_int_t nxt_gnutls_server_init(nxt_ssltls_conf_t *conf); static nxt_int_t nxt_gnutls_set_ciphers(nxt_ssltls_conf_t *conf); static void nxt_gnutls_conn_init(nxt_thread_t *thr, nxt_ssltls_conf_t *conf, - nxt_event_conn_t *c); + nxt_event_conn_t *c); static void nxt_gnutls_session_cleanup(void *data); static ssize_t nxt_gnutls_pull(gnutls_transport_ptr_t data, void *buf, - size_t size); + size_t size); static ssize_t nxt_gnutls_push(gnutls_transport_ptr_t data, const void *buf, - size_t size); + size_t size); #if (NXT_HAVE_GNUTLS_VEC_PUSH) static ssize_t nxt_gnutls_vec_push(gnutls_transport_ptr_t data, - const giovec_t *iov, int iovcnt); + const giovec_t *iov, int iovcnt); #endif static void nxt_gnutls_conn_handshake(nxt_thread_t *thr, void *obj, void *data); static void nxt_gnutls_conn_io_read(nxt_thread_t *thr, void *obj, void *data); static ssize_t nxt_gnutls_conn_io_write_chunk(nxt_thread_t *thr, - nxt_event_conn_t *c, nxt_buf_t *b, size_t limit); + nxt_event_conn_t *c, nxt_buf_t *b, + size_t limit); static ssize_t nxt_gnutls_conn_io_send(nxt_event_conn_t *c, void *buf, - size_t size); + size_t size); static void nxt_gnutls_conn_io_shutdown(nxt_thread_t *thr, void *obj, - void *data); + void *data); static nxt_int_t nxt_gnutls_conn_test_error(nxt_thread_t *thr, - nxt_event_conn_t *c, ssize_t err, nxt_work_handler_t handler); + nxt_event_conn_t *c, ssize_t err, + nxt_work_handler_t handler); static void nxt_cdecl nxt_gnutls_conn_log_error(nxt_event_conn_t *c, - ssize_t err, const char *fmt, ...); + ssize_t err, const char *fmt, + ...); static nxt_uint_t nxt_gnutls_log_error_level(nxt_event_conn_t *c, ssize_t err); static void nxt_cdecl nxt_gnutls_log_error(nxt_uint_t level, nxt_log_t *log, - int err, const char *fmt, ...); + int err, const char *fmt, ...); - -const nxt_ssltls_lib_t nxt_gnutls_lib = { +const nxt_ssltls_lib_t nxt_gnutls_lib = { nxt_gnutls_server_init, NULL, }; - -static nxt_event_conn_io_t nxt_gnutls_event_conn_io = { +static nxt_event_conn_io_t nxt_gnutls_event_conn_io = { NULL, NULL, @@ -82,661 +79,606 @@ static nxt_event_conn_io_t nxt_gnutls_event_conn_io = { nxt_gnutls_conn_io_shutdown, }; +static nxt_int_t nxt_gnutls_start(void) { + int ret; + static nxt_bool_t started; -static nxt_int_t -nxt_gnutls_start(void) -{ - int ret; - static nxt_bool_t started; - - if (nxt_fast_path(started)) { - return NXT_OK; - } + if (nxt_fast_path(started)) { + return NXT_OK; + } - started = 1; + started = 1; - /* TODO: gnutls_global_deinit */ + /* TODO: gnutls_global_deinit */ - ret = gnutls_global_init(); - if (ret != GNUTLS_E_SUCCESS) { - nxt_gnutls_log_error(NXT_LOG_ALERT, nxt_thread_log(), ret, - "gnutls_global_init() failed"); - return NXT_ERROR; - } + ret = gnutls_global_init(); + if (ret != GNUTLS_E_SUCCESS) { + nxt_gnutls_log_error(NXT_LOG_ALERT, nxt_thread_log(), ret, + "gnutls_global_init() failed"); + return NXT_ERROR; + } - nxt_thread_log_error(NXT_LOG_INFO, "GnuTLS version: %s", - gnutls_check_version(NULL)); + nxt_thread_log_error(NXT_LOG_INFO, "GnuTLS version: %s", + gnutls_check_version(NULL)); #if (NXT_HAVE_GNUTLS_SET_TIME) - gnutls_global_set_time_function(nxt_gnutls_time); + gnutls_global_set_time_function(nxt_gnutls_time); #endif - return NXT_OK; + return NXT_OK; } - #if (NXT_HAVE_GNUTLS_SET_TIME) /* GnuTLS 2.12.0 */ -time_t -nxt_gnutls_time(time_t *tp) -{ - time_t t; - nxt_thread_t *thr; +time_t nxt_gnutls_time(time_t *tp) { + time_t t; + nxt_thread_t *thr; - thr = nxt_thread(); - nxt_log_debug(thr->log, "gnutls time"); + thr = nxt_thread(); + nxt_log_debug(thr->log, "gnutls time"); - t = (time_t) nxt_thread_time(thr); + t = (time_t)nxt_thread_time(thr); - if (tp != NULL) { - *tp = t; - } + if (tp != NULL) { + *tp = t; + } - return t; + return t; } #endif +static nxt_int_t nxt_gnutls_server_init(nxt_ssltls_conf_t *conf) { + int ret; + char *certificate, *key, *ca_certificate; + nxt_thread_t *thr; + nxt_gnutls_ctx_t *ctx; -static nxt_int_t -nxt_gnutls_server_init(nxt_ssltls_conf_t *conf) -{ - int ret; - char *certificate, *key, *ca_certificate; - nxt_thread_t *thr; - nxt_gnutls_ctx_t *ctx; - - if (nxt_slow_path(nxt_gnutls_start() != NXT_OK)) { - return NXT_ERROR; - } - - /* TODO: mem_pool, cleanup: gnutls_certificate_free_credentials, - gnutls_priority_deinit */ - - ctx = nxt_zalloc(sizeof(nxt_gnutls_ctx_t)); - if (ctx == NULL) { - return NXT_ERROR; - } - - conf->ctx = ctx; - conf->conn_init = nxt_gnutls_conn_init; - - thr = nxt_thread(); + if (nxt_slow_path(nxt_gnutls_start() != NXT_OK)) { + return NXT_ERROR; + } - ret = gnutls_certificate_allocate_credentials(&ctx->certificate); - if (ret != GNUTLS_E_SUCCESS) { - nxt_gnutls_log_error(NXT_LOG_ALERT, thr->log, ret, - "gnutls_certificate_allocate_credentials() failed"); - return NXT_ERROR; - } + /* TODO: mem_pool, cleanup: gnutls_certificate_free_credentials, + gnutls_priority_deinit */ - certificate = conf->certificate; - key = conf->certificate_key; + ctx = nxt_zalloc(sizeof(nxt_gnutls_ctx_t)); + if (ctx == NULL) { + return NXT_ERROR; + } - ret = gnutls_certificate_set_x509_key_file(ctx->certificate, certificate, - key, GNUTLS_X509_FMT_PEM); - if (ret != GNUTLS_E_SUCCESS) { - nxt_gnutls_log_error(NXT_LOG_ALERT, thr->log, ret, - "gnutls_certificate_set_x509_key_file(\"%s\", \"%s\") failed", - certificate, key); - goto certificate_fail; - } + conf->ctx = ctx; + conf->conn_init = nxt_gnutls_conn_init; - if (nxt_gnutls_set_ciphers(conf) != NXT_OK) { - goto ciphers_fail; - } + thr = nxt_thread(); - if (conf->ca_certificate != NULL) { - ca_certificate = conf->ca_certificate; - - ret = gnutls_certificate_set_x509_trust_file(ctx->certificate, - ca_certificate, - GNUTLS_X509_FMT_PEM); - if (ret < 0) { - nxt_gnutls_log_error(NXT_LOG_ALERT, thr->log, ret, - "gnutls_certificate_set_x509_trust_file(\"%s\") failed", - ca_certificate); - goto ca_certificate_fail; - } + ret = gnutls_certificate_allocate_credentials(&ctx->certificate); + if (ret != GNUTLS_E_SUCCESS) { + nxt_gnutls_log_error(NXT_LOG_ALERT, thr->log, ret, + "gnutls_certificate_allocate_credentials() failed"); + return NXT_ERROR; + } + + certificate = conf->certificate; + key = conf->certificate_key; + + ret = gnutls_certificate_set_x509_key_file(ctx->certificate, certificate, key, + GNUTLS_X509_FMT_PEM); + if (ret != GNUTLS_E_SUCCESS) { + nxt_gnutls_log_error( + NXT_LOG_ALERT, thr->log, ret, + "gnutls_certificate_set_x509_key_file(\"%s\", \"%s\") failed", + certificate, key); + goto certificate_fail; + } + + if (nxt_gnutls_set_ciphers(conf) != NXT_OK) { + goto ciphers_fail; + } + + if (conf->ca_certificate != NULL) { + ca_certificate = conf->ca_certificate; + + ret = gnutls_certificate_set_x509_trust_file( + ctx->certificate, ca_certificate, GNUTLS_X509_FMT_PEM); + if (ret < 0) { + nxt_gnutls_log_error( + NXT_LOG_ALERT, thr->log, ret, + "gnutls_certificate_set_x509_trust_file(\"%s\") failed", + ca_certificate); + goto ca_certificate_fail; } + } - return NXT_OK; + return NXT_OK; ca_certificate_fail: - gnutls_priority_deinit(ctx->ciphers); + gnutls_priority_deinit(ctx->ciphers); ciphers_fail: certificate_fail: - gnutls_certificate_free_credentials(ctx->certificate); + gnutls_certificate_free_credentials(ctx->certificate); - return NXT_ERROR; + return NXT_ERROR; } +static nxt_int_t nxt_gnutls_set_ciphers(nxt_ssltls_conf_t *conf) { + int ret; + const char *ciphers; + const char *err; + nxt_gnutls_ctx_t *ctx; -static nxt_int_t -nxt_gnutls_set_ciphers(nxt_ssltls_conf_t *conf) -{ - int ret; - const char *ciphers; - const char *err; - nxt_gnutls_ctx_t *ctx; - - ciphers = (conf->ciphers != NULL) ? conf->ciphers : "NORMAL:!COMP-DEFLATE"; - ctx = conf->ctx; + ciphers = (conf->ciphers != NULL) ? conf->ciphers : "NORMAL:!COMP-DEFLATE"; + ctx = conf->ctx; - ret = gnutls_priority_init(&ctx->ciphers, ciphers, &err); + ret = gnutls_priority_init(&ctx->ciphers, ciphers, &err); - switch (ret) { + switch (ret) { - case GNUTLS_E_SUCCESS: - return NXT_OK; + case GNUTLS_E_SUCCESS: + return NXT_OK; - case GNUTLS_E_INVALID_REQUEST: - nxt_gnutls_log_error(NXT_LOG_ALERT, nxt_thread_log(), ret, - "gnutls_priority_init(\"%s\") failed at \"%s\"", - ciphers, err); - return NXT_ERROR; + case GNUTLS_E_INVALID_REQUEST: + nxt_gnutls_log_error(NXT_LOG_ALERT, nxt_thread_log(), ret, + "gnutls_priority_init(\"%s\") failed at \"%s\"", + ciphers, err); + return NXT_ERROR; - default: - nxt_gnutls_log_error(NXT_LOG_ALERT, nxt_thread_log(), ret, - "gnutls_priority_init() failed"); - return NXT_ERROR; - } + default: + nxt_gnutls_log_error(NXT_LOG_ALERT, nxt_thread_log(), ret, + "gnutls_priority_init() failed"); + return NXT_ERROR; + } } - -static void -nxt_gnutls_conn_init(nxt_thread_t *thr, nxt_ssltls_conf_t *conf, - nxt_event_conn_t *c) -{ - int ret; - gnutls_session_t sess; - nxt_gnutls_ctx_t *ctx; - nxt_gnutls_conn_t *ssltls; - nxt_mem_pool_cleanup_t *mpcl; - - nxt_log_debug(c->socket.log, "gnutls conn init"); - - ssltls = nxt_mp_zget(c->mem_pool, sizeof(nxt_gnutls_conn_t)); - if (ssltls == NULL) { - goto fail; - } - - c->u.ssltls = ssltls; - nxt_buf_mem_set_size(&ssltls->buffer, conf->buffer_size); - - mpcl = nxt_mem_pool_cleanup(c->mem_pool, 0); - if (mpcl == NULL) { - goto fail; - } - - ret = gnutls_init(&ssltls->session, GNUTLS_SERVER); - if (ret != GNUTLS_E_SUCCESS) { - nxt_gnutls_log_error(NXT_LOG_ALERT, c->socket.log, ret, - "gnutls_init() failed"); - goto fail; - } - - sess = ssltls->session; - mpcl->handler = nxt_gnutls_session_cleanup; - mpcl->data = ssltls; - - ctx = conf->ctx; - - ret = gnutls_priority_set(sess, ctx->ciphers); - if (ret != GNUTLS_E_SUCCESS) { - nxt_gnutls_log_error(NXT_LOG_ALERT, c->socket.log, ret, - "gnutls_priority_set() failed"); - goto fail; - } - - /* - * Disable TLS random padding of records in CBC ciphers, - * which may be up to 255 bytes. - */ - gnutls_record_disable_padding(sess); - - ret = gnutls_credentials_set(sess, GNUTLS_CRD_CERTIFICATE, - ctx->certificate); - if (ret != GNUTLS_E_SUCCESS) { - nxt_gnutls_log_error(NXT_LOG_ALERT, c->socket.log, ret, - "gnutls_credentials_set() failed"); - goto fail; - } - - if (conf->ca_certificate != NULL) { - gnutls_certificate_server_set_request(sess, GNUTLS_CERT_REQUEST); - } - - gnutls_transport_set_ptr(sess, (gnutls_transport_ptr_t) c); - gnutls_transport_set_pull_function(sess, nxt_gnutls_pull); - gnutls_transport_set_push_function(sess, nxt_gnutls_push); +static void nxt_gnutls_conn_init(nxt_thread_t *thr, nxt_ssltls_conf_t *conf, + nxt_event_conn_t *c) { + int ret; + gnutls_session_t sess; + nxt_gnutls_ctx_t *ctx; + nxt_gnutls_conn_t *ssltls; + nxt_mem_pool_cleanup_t *mpcl; + + nxt_log_debug(c->socket.log, "gnutls conn init"); + + ssltls = nxt_mp_zget(c->mem_pool, sizeof(nxt_gnutls_conn_t)); + if (ssltls == NULL) { + goto fail; + } + + c->u.ssltls = ssltls; + nxt_buf_mem_set_size(&ssltls->buffer, conf->buffer_size); + + mpcl = nxt_mem_pool_cleanup(c->mem_pool, 0); + if (mpcl == NULL) { + goto fail; + } + + ret = gnutls_init(&ssltls->session, GNUTLS_SERVER); + if (ret != GNUTLS_E_SUCCESS) { + nxt_gnutls_log_error(NXT_LOG_ALERT, c->socket.log, ret, + "gnutls_init() failed"); + goto fail; + } + + sess = ssltls->session; + mpcl->handler = nxt_gnutls_session_cleanup; + mpcl->data = ssltls; + + ctx = conf->ctx; + + ret = gnutls_priority_set(sess, ctx->ciphers); + if (ret != GNUTLS_E_SUCCESS) { + nxt_gnutls_log_error(NXT_LOG_ALERT, c->socket.log, ret, + "gnutls_priority_set() failed"); + goto fail; + } + + /* + * Disable TLS random padding of records in CBC ciphers, + * which may be up to 255 bytes. + */ + gnutls_record_disable_padding(sess); + + ret = gnutls_credentials_set(sess, GNUTLS_CRD_CERTIFICATE, ctx->certificate); + if (ret != GNUTLS_E_SUCCESS) { + nxt_gnutls_log_error(NXT_LOG_ALERT, c->socket.log, ret, + "gnutls_credentials_set() failed"); + goto fail; + } + + if (conf->ca_certificate != NULL) { + gnutls_certificate_server_set_request(sess, GNUTLS_CERT_REQUEST); + } + + gnutls_transport_set_ptr(sess, (gnutls_transport_ptr_t)c); + gnutls_transport_set_pull_function(sess, nxt_gnutls_pull); + gnutls_transport_set_push_function(sess, nxt_gnutls_push); #if (NXT_HAVE_GNUTLS_VEC_PUSH) - gnutls_transport_set_vec_push_function(sess, nxt_gnutls_vec_push); + gnutls_transport_set_vec_push_function(sess, nxt_gnutls_vec_push); #endif - c->io = &nxt_gnutls_event_conn_io; - c->sendfile = NXT_CONN_SENDFILE_OFF; + c->io = &nxt_gnutls_event_conn_io; + c->sendfile = NXT_CONN_SENDFILE_OFF; - nxt_gnutls_conn_handshake(thr, c, c->socket.data); - return; + nxt_gnutls_conn_handshake(thr, c, c->socket.data); + return; fail: - nxt_event_conn_io_handle(thr, c->read_work_queue, - c->read_state->error_handler, c, c->socket.data); + nxt_event_conn_io_handle(thr, c->read_work_queue, + c->read_state->error_handler, c, c->socket.data); } +static void nxt_gnutls_session_cleanup(void *data) { + nxt_gnutls_conn_t *ssltls; -static void -nxt_gnutls_session_cleanup(void *data) -{ - nxt_gnutls_conn_t *ssltls; + ssltls = data; - ssltls = data; + nxt_thread_log_debug("gnutls session cleanup"); - nxt_thread_log_debug("gnutls session cleanup"); + nxt_free(ssltls->buffer.start); - nxt_free(ssltls->buffer.start); - - gnutls_deinit(ssltls->session); + gnutls_deinit(ssltls->session); } +static ssize_t nxt_gnutls_pull(gnutls_transport_ptr_t data, void *buf, + size_t size) { + ssize_t n; + nxt_thread_t *thr; + nxt_event_conn_t *c; -static ssize_t -nxt_gnutls_pull(gnutls_transport_ptr_t data, void *buf, size_t size) -{ - ssize_t n; - nxt_thread_t *thr; - nxt_event_conn_t *c; - - c = data; - thr = nxt_thread(); + c = data; + thr = nxt_thread(); - n = thr->engine->event->io->recv(c, buf, size, 0); + n = thr->engine->event->io->recv(c, buf, size, 0); - if (n == NXT_AGAIN) { - nxt_set_errno(NXT_EAGAIN); - return -1; - } + if (n == NXT_AGAIN) { + nxt_set_errno(NXT_EAGAIN); + return -1; + } - return n; + return n; } +static ssize_t nxt_gnutls_push(gnutls_transport_ptr_t data, const void *buf, + size_t size) { + ssize_t n; + nxt_thread_t *thr; + nxt_event_conn_t *c; -static ssize_t -nxt_gnutls_push(gnutls_transport_ptr_t data, const void *buf, size_t size) -{ - ssize_t n; - nxt_thread_t *thr; - nxt_event_conn_t *c; - - c = data; - thr = nxt_thread(); + c = data; + thr = nxt_thread(); - n = thr->engine->event->io->send(c, (u_char *) buf, size); + n = thr->engine->event->io->send(c, (u_char *)buf, size); - if (n == NXT_AGAIN) { - nxt_set_errno(NXT_EAGAIN); - return -1; - } + if (n == NXT_AGAIN) { + nxt_set_errno(NXT_EAGAIN); + return -1; + } - return n; + return n; } - #if (NXT_HAVE_GNUTLS_VEC_PUSH) /* GnuTLS 2.12.0 */ -static ssize_t -nxt_gnutls_vec_push(gnutls_transport_ptr_t data, const giovec_t *iov, - int iovcnt) -{ - ssize_t n; - nxt_thread_t *thr; - nxt_event_conn_t *c; - - c = data; - thr = nxt_thread(); - - /* - * This code assumes that giovec_t is the same as "struct iovec" - * and nxt_iobuf_t. It is not true for Windows. - */ - n = thr->engine->event->io->writev(c, (nxt_iobuf_t *) iov, iovcnt); - - if (n == NXT_AGAIN) { - nxt_set_errno(NXT_EAGAIN); - return -1; - } - - return n; +static ssize_t nxt_gnutls_vec_push(gnutls_transport_ptr_t data, + const giovec_t *iov, int iovcnt) { + ssize_t n; + nxt_thread_t *thr; + nxt_event_conn_t *c; + + c = data; + thr = nxt_thread(); + + /* + * This code assumes that giovec_t is the same as "struct iovec" + * and nxt_iobuf_t. It is not true for Windows. + */ + n = thr->engine->event->io->writev(c, (nxt_iobuf_t *)iov, iovcnt); + + if (n == NXT_AGAIN) { + nxt_set_errno(NXT_EAGAIN); + return -1; + } + + return n; } #endif +static void nxt_gnutls_conn_handshake(nxt_thread_t *thr, void *obj, + void *data) { + int err; + nxt_int_t ret; + nxt_event_conn_t *c; + nxt_gnutls_conn_t *ssltls; -static void -nxt_gnutls_conn_handshake(nxt_thread_t *thr, void *obj, void *data) -{ - int err; - nxt_int_t ret; - nxt_event_conn_t *c; - nxt_gnutls_conn_t *ssltls; - - c = obj; - ssltls = c->u.ssltls; + c = obj; + ssltls = c->u.ssltls; - nxt_log_debug(thr->log, "gnutls conn handshake: %d", ssltls->times); + nxt_log_debug(thr->log, "gnutls conn handshake: %d", ssltls->times); - /* "ssltls->times == 1" is suitable to run gnutls_handshake() in job. */ + /* "ssltls->times == 1" is suitable to run gnutls_handshake() in job. */ - err = gnutls_handshake(ssltls->session); + err = gnutls_handshake(ssltls->session); - nxt_thread_time_debug_update(thr); + nxt_thread_time_debug_update(thr); - nxt_log_debug(thr->log, "gnutls_handshake(): %d", err); + nxt_log_debug(thr->log, "gnutls_handshake(): %d", err); - if (err == GNUTLS_E_SUCCESS) { - nxt_gnutls_conn_io_read(thr, c, data); - return; - } + if (err == GNUTLS_E_SUCCESS) { + nxt_gnutls_conn_io_read(thr, c, data); + return; + } - ret = nxt_gnutls_conn_test_error(thr, c, err, nxt_gnutls_conn_handshake); + ret = nxt_gnutls_conn_test_error(thr, c, err, nxt_gnutls_conn_handshake); - if (ret == NXT_ERROR) { - nxt_gnutls_conn_log_error(c, err, "gnutls_handshake() failed"); + if (ret == NXT_ERROR) { + nxt_gnutls_conn_log_error(c, err, "gnutls_handshake() failed"); - nxt_event_conn_io_handle(thr, c->read_work_queue, - c->read_state->error_handler, c, data); + nxt_event_conn_io_handle(thr, c->read_work_queue, + c->read_state->error_handler, c, data); - } else if (err == GNUTLS_E_AGAIN - && ssltls->times < 2 - && gnutls_record_get_direction(ssltls->session) == 0) - { - ssltls->times++; - } + } else if (err == GNUTLS_E_AGAIN && ssltls->times < 2 && + gnutls_record_get_direction(ssltls->session) == 0) { + ssltls->times++; + } } +static void nxt_gnutls_conn_io_read(nxt_thread_t *thr, void *obj, void *data) { + ssize_t n; + nxt_buf_t *b; + nxt_int_t ret; + nxt_event_conn_t *c; + nxt_gnutls_conn_t *ssltls; + nxt_work_handler_t handler; -static void -nxt_gnutls_conn_io_read(nxt_thread_t *thr, void *obj, void *data) -{ - ssize_t n; - nxt_buf_t *b; - nxt_int_t ret; - nxt_event_conn_t *c; - nxt_gnutls_conn_t *ssltls; - nxt_work_handler_t handler; - - c = obj; + c = obj; - nxt_log_debug(thr->log, "gnutls conn read"); + nxt_log_debug(thr->log, "gnutls conn read"); - handler = c->read_state->ready_handler; - b = c->read; + handler = c->read_state->ready_handler; + b = c->read; - /* b == NULL is used to test descriptor readiness. */ + /* b == NULL is used to test descriptor readiness. */ - if (b != NULL) { - ssltls = c->u.ssltls; + if (b != NULL) { + ssltls = c->u.ssltls; - n = gnutls_record_recv(ssltls->session, b->mem.free, - b->mem.end - b->mem.free); + n = gnutls_record_recv(ssltls->session, b->mem.free, + b->mem.end - b->mem.free); - nxt_log_debug(thr->log, "gnutls_record_recv(%d, %p, %uz): %z", - c->socket.fd, b->mem.free, b->mem.end - b->mem.free, n); + nxt_log_debug(thr->log, "gnutls_record_recv(%d, %p, %uz): %z", c->socket.fd, + b->mem.free, b->mem.end - b->mem.free, n); - if (n > 0) { - /* c->socket.read_ready is kept. */ - b->mem.free += n; - handler = c->read_state->ready_handler; + if (n > 0) { + /* c->socket.read_ready is kept. */ + b->mem.free += n; + handler = c->read_state->ready_handler; - } else if (n == 0) { - handler = c->read_state->close_handler; + } else if (n == 0) { + handler = c->read_state->close_handler; - } else { - ret = nxt_gnutls_conn_test_error(thr, c, n, - nxt_gnutls_conn_io_read); + } else { + ret = nxt_gnutls_conn_test_error(thr, c, n, nxt_gnutls_conn_io_read); - if (nxt_fast_path(ret != NXT_ERROR)) { - return; - } + if (nxt_fast_path(ret != NXT_ERROR)) { + return; + } - nxt_gnutls_conn_log_error(c, n, - "gnutls_record_recv(%d, %p, %uz): failed", - c->socket.fd, b->mem.free, - b->mem.end - b->mem.free); + nxt_gnutls_conn_log_error(c, n, "gnutls_record_recv(%d, %p, %uz): failed", + c->socket.fd, b->mem.free, + b->mem.end - b->mem.free); - handler = c->read_state->error_handler; - } + handler = c->read_state->error_handler; } + } - nxt_event_conn_io_handle(thr, c->read_work_queue, handler, c, data); + nxt_event_conn_io_handle(thr, c->read_work_queue, handler, c, data); } +static ssize_t nxt_gnutls_conn_io_write_chunk(nxt_thread_t *thr, + nxt_event_conn_t *c, nxt_buf_t *b, + size_t limit) { + nxt_gnutls_conn_t *ssltls; -static ssize_t -nxt_gnutls_conn_io_write_chunk(nxt_thread_t *thr, nxt_event_conn_t *c, - nxt_buf_t *b, size_t limit) -{ - nxt_gnutls_conn_t *ssltls; + nxt_log_debug(thr->log, "gnutls conn write chunk"); - nxt_log_debug(thr->log, "gnutls conn write chunk"); + ssltls = c->u.ssltls; - ssltls = c->u.ssltls; - - return nxt_sendbuf_copy_coalesce(c, &ssltls->buffer, b, limit); + return nxt_sendbuf_copy_coalesce(c, &ssltls->buffer, b, limit); } +static ssize_t nxt_gnutls_conn_io_send(nxt_event_conn_t *c, void *buf, + size_t size) { + ssize_t n; + nxt_int_t ret; + nxt_gnutls_conn_t *ssltls; -static ssize_t -nxt_gnutls_conn_io_send(nxt_event_conn_t *c, void *buf, size_t size) -{ - ssize_t n; - nxt_int_t ret; - nxt_gnutls_conn_t *ssltls; + ssltls = c->u.ssltls; - ssltls = c->u.ssltls; + n = gnutls_record_send(ssltls->session, buf, size); - n = gnutls_record_send(ssltls->session, buf, size); + nxt_log_debug(c->socket.log, "gnutls_record_send(%d, %p, %uz): %z", + c->socket.fd, buf, size, n); - nxt_log_debug(c->socket.log, "gnutls_record_send(%d, %p, %uz): %z", - c->socket.fd, buf, size, n); + if (n > 0) { + return n; + } - if (n > 0) { - return n; - } + ret = nxt_gnutls_conn_test_error(nxt_thread(), c, n, nxt_event_conn_io_write); - ret = nxt_gnutls_conn_test_error(nxt_thread(), c, n, - nxt_event_conn_io_write); + if (nxt_slow_path(ret == NXT_ERROR)) { + nxt_gnutls_conn_log_error(c, n, "gnutls_record_send(%d, %p, %uz): failed", + c->socket.fd, buf, size); + } - if (nxt_slow_path(ret == NXT_ERROR)) { - nxt_gnutls_conn_log_error(c, n, - "gnutls_record_send(%d, %p, %uz): failed", - c->socket.fd, buf, size); - } - - return ret; + return ret; } +static void nxt_gnutls_conn_io_shutdown(nxt_thread_t *thr, void *obj, + void *data) { + int err; + nxt_int_t ret; + nxt_event_conn_t *c; + nxt_gnutls_conn_t *ssltls; + nxt_work_handler_t handler; + gnutls_close_request_t how; -static void -nxt_gnutls_conn_io_shutdown(nxt_thread_t *thr, void *obj, void *data) -{ - int err; - nxt_int_t ret; - nxt_event_conn_t *c; - nxt_gnutls_conn_t *ssltls; - nxt_work_handler_t handler; - gnutls_close_request_t how; - - c = obj; - ssltls = c->u.ssltls; + c = obj; + ssltls = c->u.ssltls; - if (ssltls->session == NULL || ssltls->no_shutdown) { - handler = c->write_state->close_handler; - goto done; - } + if (ssltls->session == NULL || ssltls->no_shutdown) { + handler = c->write_state->close_handler; + goto done; + } - nxt_log_debug(c->socket.log, "gnutls conn shutdown"); + nxt_log_debug(c->socket.log, "gnutls conn shutdown"); - if (c->socket.timedout || c->socket.error != 0) { - how = GNUTLS_SHUT_WR; + if (c->socket.timedout || c->socket.error != 0) { + how = GNUTLS_SHUT_WR; - } else if (c->socket.closed) { - how = GNUTLS_SHUT_RDWR; + } else if (c->socket.closed) { + how = GNUTLS_SHUT_RDWR; - } else { - how = GNUTLS_SHUT_RDWR; - } + } else { + how = GNUTLS_SHUT_RDWR; + } - err = gnutls_bye(ssltls->session, how); + err = gnutls_bye(ssltls->session, how); - nxt_log_debug(c->socket.log, "gnutls_bye(%d, %d): %d", - c->socket.fd, how, err); + nxt_log_debug(c->socket.log, "gnutls_bye(%d, %d): %d", c->socket.fd, how, + err); - if (err == GNUTLS_E_SUCCESS) { - handler = c->write_state->close_handler; + if (err == GNUTLS_E_SUCCESS) { + handler = c->write_state->close_handler; - } else { - ret = nxt_gnutls_conn_test_error(thr, c, err, - nxt_gnutls_conn_io_shutdown); + } else { + ret = nxt_gnutls_conn_test_error(thr, c, err, nxt_gnutls_conn_io_shutdown); - if (ret != NXT_ERROR) { /* ret == NXT_AGAIN */ - c->socket.error_handler = c->read_state->error_handler; - nxt_event_timer_add(thr->engine, &c->read_timer, 5000); - return; - } + if (ret != NXT_ERROR) { /* ret == NXT_AGAIN */ + c->socket.error_handler = c->read_state->error_handler; + nxt_event_timer_add(thr->engine, &c->read_timer, 5000); + return; + } - nxt_gnutls_conn_log_error(c, err, "gnutls_bye(%d) failed", - c->socket.fd); + nxt_gnutls_conn_log_error(c, err, "gnutls_bye(%d) failed", c->socket.fd); - handler = c->write_state->error_handler; - } + handler = c->write_state->error_handler; + } done: - nxt_event_conn_io_handle(thr, c->write_work_queue, handler, c, data); + nxt_event_conn_io_handle(thr, c->write_work_queue, handler, c, data); } +static nxt_int_t nxt_gnutls_conn_test_error(nxt_thread_t *thr, + nxt_event_conn_t *c, ssize_t err, + nxt_work_handler_t handler) { + int ret; + nxt_gnutls_conn_t *ssltls; -static nxt_int_t -nxt_gnutls_conn_test_error(nxt_thread_t *thr, nxt_event_conn_t *c, ssize_t err, - nxt_work_handler_t handler) -{ - int ret; - nxt_gnutls_conn_t *ssltls; - - switch (err) { + switch (err) { - case GNUTLS_E_REHANDSHAKE: - case GNUTLS_E_AGAIN: - ssltls = c->u.ssltls; - ret = gnutls_record_get_direction(ssltls->session); + case GNUTLS_E_REHANDSHAKE: + case GNUTLS_E_AGAIN: + ssltls = c->u.ssltls; + ret = gnutls_record_get_direction(ssltls->session); - nxt_log_debug(thr->log, "gnutls_record_get_direction(): %d", ret); + nxt_log_debug(thr->log, "gnutls_record_get_direction(): %d", ret); - if (ret == 0) { - /* A read direction. */ + if (ret == 0) { + /* A read direction. */ - nxt_event_fd_block_write(thr->engine, &c->socket); + nxt_event_fd_block_write(thr->engine, &c->socket); - c->socket.read_ready = 0; - c->socket.read_handler = handler; + c->socket.read_ready = 0; + c->socket.read_handler = handler; - if (nxt_event_fd_is_disabled(c->socket.read)) { - nxt_event_fd_enable_read(thr->engine, &c->socket); - } + if (nxt_event_fd_is_disabled(c->socket.read)) { + nxt_event_fd_enable_read(thr->engine, &c->socket); + } - } else { - /* A write direction. */ + } else { + /* A write direction. */ - nxt_event_fd_block_read(thr->engine, &c->socket); + nxt_event_fd_block_read(thr->engine, &c->socket); - c->socket.write_ready = 0; - c->socket.write_handler = handler; + c->socket.write_ready = 0; + c->socket.write_handler = handler; - if (nxt_event_fd_is_disabled(c->socket.write)) { - nxt_event_fd_enable_write(thr->engine, &c->socket); - } - } + if (nxt_event_fd_is_disabled(c->socket.write)) { + nxt_event_fd_enable_write(thr->engine, &c->socket); + } + } - return NXT_AGAIN; + return NXT_AGAIN; - default: - c->socket.error = 1000; /* Nonexistent errno code. */ - return NXT_ERROR; - } + default: + c->socket.error = 1000; /* Nonexistent errno code. */ + return NXT_ERROR; + } } +static void nxt_gnutls_conn_log_error(nxt_event_conn_t *c, ssize_t err, + const char *fmt, ...) { + va_list args; + nxt_uint_t level; + u_char *p, msg[NXT_MAX_ERROR_STR]; -static void -nxt_gnutls_conn_log_error(nxt_event_conn_t *c, ssize_t err, - const char *fmt, ...) -{ - va_list args; - nxt_uint_t level; - u_char *p, msg[NXT_MAX_ERROR_STR]; + level = nxt_gnutls_log_error_level(c, err); - level = nxt_gnutls_log_error_level(c, err); + if (nxt_log_level_enough(c->socket.log, level)) { - if (nxt_log_level_enough(c->socket.log, level)) { - - va_start(args, fmt); - p = nxt_vsprintf(msg, msg + sizeof(msg), fmt, args); - va_end(args); + va_start(args, fmt); + p = nxt_vsprintf(msg, msg + sizeof(msg), fmt, args); + va_end(args); - nxt_log_error(level, c->socket.log, "%*s (%d: %s)", - p - msg, msg, err, gnutls_strerror(err)); - } + nxt_log_error(level, c->socket.log, "%*s (%d: %s)", p - msg, msg, err, + gnutls_strerror(err)); + } } +static nxt_uint_t nxt_gnutls_log_error_level(nxt_event_conn_t *c, ssize_t err) { + nxt_gnutls_conn_t *ssltls; -static nxt_uint_t -nxt_gnutls_log_error_level(nxt_event_conn_t *c, ssize_t err) -{ - nxt_gnutls_conn_t *ssltls; + switch (err) { - switch (err) { + case GNUTLS_E_UNKNOWN_CIPHER_SUITE: /* -21 */ - case GNUTLS_E_UNKNOWN_CIPHER_SUITE: /* -21 */ - - /* Disable gnutls_bye(), because it returns GNUTLS_E_INTERNAL_ERROR. */ - ssltls = c->u.ssltls; - ssltls->no_shutdown = 1; + /* Disable gnutls_bye(), because it returns GNUTLS_E_INTERNAL_ERROR. */ + ssltls = c->u.ssltls; + ssltls->no_shutdown = 1; - /* Fall through. */ + /* Fall through. */ - case GNUTLS_E_UNEXPECTED_PACKET_LENGTH: /* -9 */ - c->socket.error = 1000; /* Nonexistent errno code. */ - break; + case GNUTLS_E_UNEXPECTED_PACKET_LENGTH: /* -9 */ + c->socket.error = 1000; /* Nonexistent errno code. */ + break; - default: - return NXT_LOG_ALERT; - } + default: + return NXT_LOG_ALERT; + } - return NXT_LOG_INFO; + return NXT_LOG_INFO; } +static void nxt_gnutls_log_error(nxt_uint_t level, nxt_log_t *log, int err, + const char *fmt, ...) { + va_list args; + u_char *p, msg[NXT_MAX_ERROR_STR]; -static void -nxt_gnutls_log_error(nxt_uint_t level, nxt_log_t *log, int err, - const char *fmt, ...) -{ - va_list args; - u_char *p, msg[NXT_MAX_ERROR_STR]; - - va_start(args, fmt); - p = nxt_vsprintf(msg, msg + sizeof(msg), fmt, args); - va_end(args); + va_start(args, fmt); + p = nxt_vsprintf(msg, msg + sizeof(msg), fmt, args); + va_end(args); - nxt_log_error(level, log, "%*s (%d: %s)", - p - msg, msg, err, gnutls_strerror(err)); + nxt_log_error(level, log, "%*s (%d: %s)", p - msg, msg, err, + gnutls_strerror(err)); } diff --git a/src/nxt_h1proto.c b/src/nxt_h1proto.c index 48c2697bc..47b15e9b9 100644 --- a/src/nxt_h1proto.c +++ b/src/nxt_h1proto.c @@ -11,7 +11,6 @@ #include #include - /* * nxt_http_conn_ and nxt_h1p_conn_ prefixes are used for connection handlers. * nxt_h1p_idle_ prefix is used for idle connection handlers. @@ -26,60 +25,62 @@ static ssize_t nxt_h1p_idle_io_read_handler(nxt_task_t *task, nxt_conn_t *c); static void nxt_h1p_conn_proto_init(nxt_task_t *task, void *obj, void *data); static void nxt_h1p_conn_request_init(nxt_task_t *task, void *obj, void *data); static void nxt_h1p_conn_request_header_parse(nxt_task_t *task, void *obj, - void *data); + void *data); static nxt_int_t nxt_h1p_header_process(nxt_task_t *task, nxt_h1proto_t *h1p, - nxt_http_request_t *r); + nxt_http_request_t *r); static nxt_int_t nxt_h1p_header_buffer_test(nxt_task_t *task, - nxt_h1proto_t *h1p, nxt_conn_t *c, nxt_socket_conf_t *skcf); + nxt_h1proto_t *h1p, nxt_conn_t *c, + nxt_socket_conf_t *skcf); static nxt_int_t nxt_h1p_connection(void *ctx, nxt_http_field_t *field, - uintptr_t data); + uintptr_t data); static nxt_int_t nxt_h1p_upgrade(void *ctx, nxt_http_field_t *field, - uintptr_t data); + uintptr_t data); static nxt_int_t nxt_h1p_websocket_key(void *ctx, nxt_http_field_t *field, - uintptr_t data); + uintptr_t data); static nxt_int_t nxt_h1p_websocket_version(void *ctx, nxt_http_field_t *field, - uintptr_t data); + uintptr_t data); static nxt_int_t nxt_h1p_transfer_encoding(void *ctx, nxt_http_field_t *field, - uintptr_t data); + uintptr_t data); static void nxt_h1p_request_body_read(nxt_task_t *task, nxt_http_request_t *r); static void nxt_h1p_conn_request_body_read(nxt_task_t *task, void *obj, - void *data); + void *data); static void nxt_h1p_request_local_addr(nxt_task_t *task, nxt_http_request_t *r); -static void nxt_h1p_request_header_send(nxt_task_t *task, - nxt_http_request_t *r, nxt_work_handler_t body_handler, void *data); +static void nxt_h1p_request_header_send(nxt_task_t *task, nxt_http_request_t *r, + nxt_work_handler_t body_handler, + void *data); static void nxt_h1p_request_send(nxt_task_t *task, nxt_http_request_t *r, - nxt_buf_t *out); + nxt_buf_t *out); static nxt_buf_t *nxt_h1p_chunk_create(nxt_task_t *task, nxt_http_request_t *r, - nxt_buf_t *out); + nxt_buf_t *out); static nxt_off_t nxt_h1p_request_body_bytes_sent(nxt_task_t *task, - nxt_http_proto_t proto); + nxt_http_proto_t proto); static void nxt_h1p_request_discard(nxt_task_t *task, nxt_http_request_t *r, - nxt_buf_t *last); + nxt_buf_t *last); static void nxt_h1p_conn_request_error(nxt_task_t *task, void *obj, void *data); static void nxt_h1p_conn_request_timeout(nxt_task_t *task, void *obj, - void *data); + void *data); static void nxt_h1p_conn_request_send_timeout(nxt_task_t *task, void *obj, - void *data); + void *data); nxt_inline void nxt_h1p_request_error(nxt_task_t *task, nxt_h1proto_t *h1p, - nxt_http_request_t *r); + nxt_http_request_t *r); static void nxt_h1p_request_close(nxt_task_t *task, nxt_http_proto_t proto, - nxt_socket_conf_joint_t *joint); + nxt_socket_conf_joint_t *joint); static void nxt_h1p_conn_sent(nxt_task_t *task, void *obj, void *data); static void nxt_h1p_conn_close(nxt_task_t *task, void *obj, void *data); static void nxt_h1p_conn_error(nxt_task_t *task, void *obj, void *data); static nxt_msec_t nxt_h1p_conn_timer_value(nxt_conn_t *c, uintptr_t data); static void nxt_h1p_keepalive(nxt_task_t *task, nxt_h1proto_t *h1p, - nxt_conn_t *c); + nxt_conn_t *c); static void nxt_h1p_idle_close(nxt_task_t *task, void *obj, void *data); static void nxt_h1p_idle_timeout(nxt_task_t *task, void *obj, void *data); static void nxt_h1p_idle_response(nxt_task_t *task, nxt_conn_t *c); static void nxt_h1p_idle_response_sent(nxt_task_t *task, void *obj, void *data); static void nxt_h1p_idle_response_error(nxt_task_t *task, void *obj, - void *data); + void *data); static void nxt_h1p_idle_response_timeout(nxt_task_t *task, void *obj, - void *data); + void *data); static nxt_msec_t nxt_h1p_idle_response_timer_value(nxt_conn_t *c, - uintptr_t data); + uintptr_t data); static void nxt_h1p_shutdown(nxt_task_t *task, nxt_conn_t *c); static void nxt_h1p_closing(nxt_task_t *task, nxt_conn_t *c); static void nxt_h1p_conn_ws_shutdown(nxt_task_t *task, void *obj, void *data); @@ -91,17 +92,18 @@ static void nxt_h1p_peer_connected(nxt_task_t *task, void *obj, void *data); static void nxt_h1p_peer_refused(nxt_task_t *task, void *obj, void *data); static void nxt_h1p_peer_header_send(nxt_task_t *task, nxt_http_peer_t *peer); static nxt_int_t nxt_h1p_peer_request_target(nxt_http_request_t *r, - nxt_str_t *target); + nxt_str_t *target); static void nxt_h1p_peer_header_sent(nxt_task_t *task, void *obj, void *data); static void nxt_h1p_peer_header_read(nxt_task_t *task, nxt_http_peer_t *peer); static ssize_t nxt_h1p_peer_io_read_handler(nxt_task_t *task, nxt_conn_t *c); static void nxt_h1p_peer_header_read_done(nxt_task_t *task, void *obj, - void *data); + void *data); static nxt_int_t nxt_h1p_peer_header_parse(nxt_http_peer_t *peer, - nxt_buf_mem_t *bm); + nxt_buf_mem_t *bm); static void nxt_h1p_peer_read(nxt_task_t *task, nxt_http_peer_t *peer); static void nxt_h1p_peer_read_done(nxt_task_t *task, void *obj, void *data); -static void nxt_h1p_peer_body_process(nxt_task_t *task, nxt_http_peer_t *peer, nxt_buf_t *out); +static void nxt_h1p_peer_body_process(nxt_task_t *task, nxt_http_peer_t *peer, + nxt_buf_t *out); static void nxt_h1p_peer_closed(nxt_task_t *task, void *obj, void *data); static void nxt_h1p_peer_error(nxt_task_t *task, void *obj, void *data); static void nxt_h1p_peer_send_timeout(nxt_task_t *task, void *obj, void *data); @@ -110,145 +112,132 @@ static nxt_msec_t nxt_h1p_peer_timer_value(nxt_conn_t *c, uintptr_t data); static void nxt_h1p_peer_close(nxt_task_t *task, nxt_http_peer_t *peer); static void nxt_h1p_peer_free(nxt_task_t *task, void *obj, void *data); static nxt_int_t nxt_h1p_peer_transfer_encoding(void *ctx, - nxt_http_field_t *field, uintptr_t data); + nxt_http_field_t *field, + uintptr_t data); #if (NXT_TLS) -static const nxt_conn_state_t nxt_http_idle_state; -static const nxt_conn_state_t nxt_h1p_shutdown_state; +static const nxt_conn_state_t nxt_http_idle_state; +static const nxt_conn_state_t nxt_h1p_shutdown_state; #endif -static const nxt_conn_state_t nxt_h1p_idle_state; -static const nxt_conn_state_t nxt_h1p_header_parse_state; -static const nxt_conn_state_t nxt_h1p_read_body_state; -static const nxt_conn_state_t nxt_h1p_request_send_state; -static const nxt_conn_state_t nxt_h1p_timeout_response_state; -static const nxt_conn_state_t nxt_h1p_keepalive_state; -static const nxt_conn_state_t nxt_h1p_close_state; -static const nxt_conn_state_t nxt_h1p_peer_connect_state; -static const nxt_conn_state_t nxt_h1p_peer_header_send_state; -static const nxt_conn_state_t nxt_h1p_peer_header_body_send_state; -static const nxt_conn_state_t nxt_h1p_peer_header_read_state; -static const nxt_conn_state_t nxt_h1p_peer_header_read_timer_state; -static const nxt_conn_state_t nxt_h1p_peer_read_state; -static const nxt_conn_state_t nxt_h1p_peer_close_state; - - -const nxt_http_proto_table_t nxt_http_proto[3] = { +static const nxt_conn_state_t nxt_h1p_idle_state; +static const nxt_conn_state_t nxt_h1p_header_parse_state; +static const nxt_conn_state_t nxt_h1p_read_body_state; +static const nxt_conn_state_t nxt_h1p_request_send_state; +static const nxt_conn_state_t nxt_h1p_timeout_response_state; +static const nxt_conn_state_t nxt_h1p_keepalive_state; +static const nxt_conn_state_t nxt_h1p_close_state; +static const nxt_conn_state_t nxt_h1p_peer_connect_state; +static const nxt_conn_state_t nxt_h1p_peer_header_send_state; +static const nxt_conn_state_t nxt_h1p_peer_header_body_send_state; +static const nxt_conn_state_t nxt_h1p_peer_header_read_state; +static const nxt_conn_state_t nxt_h1p_peer_header_read_timer_state; +static const nxt_conn_state_t nxt_h1p_peer_read_state; +static const nxt_conn_state_t nxt_h1p_peer_close_state; + +const nxt_http_proto_table_t nxt_http_proto[3] = { /* NXT_HTTP_PROTO_H1 */ { - .body_read = nxt_h1p_request_body_read, - .local_addr = nxt_h1p_request_local_addr, - .header_send = nxt_h1p_request_header_send, - .send = nxt_h1p_request_send, - .body_bytes_sent = nxt_h1p_request_body_bytes_sent, - .discard = nxt_h1p_request_discard, - .close = nxt_h1p_request_close, - - .peer_connect = nxt_h1p_peer_connect, + .body_read = nxt_h1p_request_body_read, + .local_addr = nxt_h1p_request_local_addr, + .header_send = nxt_h1p_request_header_send, + .send = nxt_h1p_request_send, + .body_bytes_sent = nxt_h1p_request_body_bytes_sent, + .discard = nxt_h1p_request_discard, + .close = nxt_h1p_request_close, + + .peer_connect = nxt_h1p_peer_connect, .peer_header_send = nxt_h1p_peer_header_send, .peer_header_read = nxt_h1p_peer_header_read, - .peer_read = nxt_h1p_peer_read, - .peer_close = nxt_h1p_peer_close, + .peer_read = nxt_h1p_peer_read, + .peer_close = nxt_h1p_peer_close, - .ws_frame_start = nxt_h1p_websocket_frame_start, + .ws_frame_start = nxt_h1p_websocket_frame_start, }, /* NXT_HTTP_PROTO_H2 */ /* NXT_HTTP_PROTO_DEVNULL */ }; - -static nxt_lvlhsh_t nxt_h1p_fields_hash; - -static nxt_http_field_proc_t nxt_h1p_fields[] = { - { nxt_string("Connection"), &nxt_h1p_connection, 0 }, - { nxt_string("Upgrade"), &nxt_h1p_upgrade, 0 }, - { nxt_string("Sec-WebSocket-Key"), &nxt_h1p_websocket_key, 0 }, - { nxt_string("Sec-WebSocket-Version"), - &nxt_h1p_websocket_version, 0 }, - { nxt_string("Transfer-Encoding"), &nxt_h1p_transfer_encoding, 0 }, - - { nxt_string("Host"), &nxt_http_request_host, 0 }, - { nxt_string("Cookie"), &nxt_http_request_field, - offsetof(nxt_http_request_t, cookie) }, - { nxt_string("Referer"), &nxt_http_request_field, - offsetof(nxt_http_request_t, referer) }, - { nxt_string("User-Agent"), &nxt_http_request_field, - offsetof(nxt_http_request_t, user_agent) }, - { nxt_string("Content-Type"), &nxt_http_request_field, - offsetof(nxt_http_request_t, content_type) }, - { nxt_string("Content-Length"), &nxt_http_request_content_length, 0 }, - { nxt_string("Authorization"), &nxt_http_request_field, - offsetof(nxt_http_request_t, authorization) }, +static nxt_lvlhsh_t nxt_h1p_fields_hash; + +static nxt_http_field_proc_t nxt_h1p_fields[] = { + {nxt_string("Connection"), &nxt_h1p_connection, 0}, + {nxt_string("Upgrade"), &nxt_h1p_upgrade, 0}, + {nxt_string("Sec-WebSocket-Key"), &nxt_h1p_websocket_key, 0}, + {nxt_string("Sec-WebSocket-Version"), &nxt_h1p_websocket_version, 0}, + {nxt_string("Transfer-Encoding"), &nxt_h1p_transfer_encoding, 0}, + + {nxt_string("Host"), &nxt_http_request_host, 0}, + {nxt_string("Cookie"), &nxt_http_request_field, + offsetof(nxt_http_request_t, cookie)}, + {nxt_string("Referer"), &nxt_http_request_field, + offsetof(nxt_http_request_t, referer)}, + {nxt_string("User-Agent"), &nxt_http_request_field, + offsetof(nxt_http_request_t, user_agent)}, + {nxt_string("Content-Type"), &nxt_http_request_field, + offsetof(nxt_http_request_t, content_type)}, + {nxt_string("Content-Length"), &nxt_http_request_content_length, 0}, + {nxt_string("Authorization"), &nxt_http_request_field, + offsetof(nxt_http_request_t, authorization)}, }; +static nxt_lvlhsh_t nxt_h1p_peer_fields_hash; -static nxt_lvlhsh_t nxt_h1p_peer_fields_hash; - -static nxt_http_field_proc_t nxt_h1p_peer_fields[] = { - { nxt_string("Connection"), &nxt_http_proxy_skip, 0 }, - { nxt_string("Transfer-Encoding"), &nxt_h1p_peer_transfer_encoding, 0 }, - { nxt_string("Server"), &nxt_http_proxy_skip, 0 }, - { nxt_string("Date"), &nxt_http_proxy_date, 0 }, - { nxt_string("Content-Length"), &nxt_http_proxy_content_length, 0 }, +static nxt_http_field_proc_t nxt_h1p_peer_fields[] = { + {nxt_string("Connection"), &nxt_http_proxy_skip, 0}, + {nxt_string("Transfer-Encoding"), &nxt_h1p_peer_transfer_encoding, 0}, + {nxt_string("Server"), &nxt_http_proxy_skip, 0}, + {nxt_string("Date"), &nxt_http_proxy_date, 0}, + {nxt_string("Content-Length"), &nxt_http_proxy_content_length, 0}, }; +nxt_int_t nxt_h1p_init(nxt_task_t *task) { + nxt_int_t ret; -nxt_int_t -nxt_h1p_init(nxt_task_t *task) -{ - nxt_int_t ret; - - ret = nxt_http_fields_hash(&nxt_h1p_fields_hash, - nxt_h1p_fields, nxt_nitems(nxt_h1p_fields)); + ret = nxt_http_fields_hash(&nxt_h1p_fields_hash, nxt_h1p_fields, + nxt_nitems(nxt_h1p_fields)); - if (nxt_fast_path(ret == NXT_OK)) { - ret = nxt_http_fields_hash(&nxt_h1p_peer_fields_hash, - nxt_h1p_peer_fields, - nxt_nitems(nxt_h1p_peer_fields)); - } + if (nxt_fast_path(ret == NXT_OK)) { + ret = nxt_http_fields_hash(&nxt_h1p_peer_fields_hash, nxt_h1p_peer_fields, + nxt_nitems(nxt_h1p_peer_fields)); + } - return ret; + return ret; } +void nxt_http_conn_init(nxt_task_t *task, void *obj, void *data) { + nxt_conn_t *c; + nxt_socket_conf_t *skcf; + nxt_event_engine_t *engine; + nxt_listen_event_t *lev; + nxt_socket_conf_joint_t *joint; -void -nxt_http_conn_init(nxt_task_t *task, void *obj, void *data) -{ - nxt_conn_t *c; - nxt_socket_conf_t *skcf; - nxt_event_engine_t *engine; - nxt_listen_event_t *lev; - nxt_socket_conf_joint_t *joint; - - c = obj; - lev = data; + c = obj; + lev = data; - nxt_debug(task, "http conn init"); + nxt_debug(task, "http conn init"); - joint = lev->socket.data; - skcf = joint->socket_conf; - c->local = skcf->sockaddr; + joint = lev->socket.data; + skcf = joint->socket_conf; + c->local = skcf->sockaddr; - engine = task->thread->engine; - c->read_work_queue = &engine->fast_work_queue; - c->write_work_queue = &engine->fast_work_queue; + engine = task->thread->engine; + c->read_work_queue = &engine->fast_work_queue; + c->write_work_queue = &engine->fast_work_queue; - c->read_state = &nxt_h1p_idle_state; + c->read_state = &nxt_h1p_idle_state; #if (NXT_TLS) - if (skcf->tls != NULL) { - c->read_state = &nxt_http_idle_state; - } + if (skcf->tls != NULL) { + c->read_state = &nxt_http_idle_state; + } #endif - nxt_conn_read(engine, c); + nxt_conn_read(engine, c); } - #if (NXT_TLS) -static const nxt_conn_state_t nxt_http_idle_state - nxt_aligned(64) = -{ +static const nxt_conn_state_t nxt_http_idle_state nxt_aligned(64) = { .ready_handler = nxt_http_conn_test, .close_handler = nxt_h1p_conn_close, .error_handler = nxt_h1p_conn_error, @@ -260,130 +249,121 @@ static const nxt_conn_state_t nxt_http_idle_state .timer_data = offsetof(nxt_socket_conf_t, idle_timeout), }; +static ssize_t nxt_http_idle_io_read_handler(nxt_task_t *task, nxt_conn_t *c) { + size_t size; + ssize_t n; + nxt_buf_t *b; + nxt_socket_conf_joint_t *joint; -static ssize_t -nxt_http_idle_io_read_handler(nxt_task_t *task, nxt_conn_t *c) -{ - size_t size; - ssize_t n; - nxt_buf_t *b; - nxt_socket_conf_joint_t *joint; + joint = c->listen->socket.data; - joint = c->listen->socket.data; - - if (nxt_slow_path(joint == NULL)) { - /* - * Listening socket had been closed while - * connection was in keep-alive state. - */ - c->read_state = &nxt_h1p_idle_close_state; - return 0; - } + if (nxt_slow_path(joint == NULL)) { + /* + * Listening socket had been closed while + * connection was in keep-alive state. + */ + c->read_state = &nxt_h1p_idle_close_state; + return 0; + } - size = joint->socket_conf->header_buffer_size; + size = joint->socket_conf->header_buffer_size; - b = nxt_event_engine_buf_mem_alloc(task->thread->engine, size); - if (nxt_slow_path(b == NULL)) { - c->socket.error = NXT_ENOMEM; - return NXT_ERROR; - } + b = nxt_event_engine_buf_mem_alloc(task->thread->engine, size); + if (nxt_slow_path(b == NULL)) { + c->socket.error = NXT_ENOMEM; + return NXT_ERROR; + } - /* - * 1 byte is enough to distinguish between SSLv3/TLS and plain HTTP. - * 11 bytes are enough to log supported SSLv3/TLS version. - * 16 bytes are just for more optimized kernel copy-out operation. - */ - n = c->io->recv(c, b->mem.pos, 16, MSG_PEEK); + /* + * 1 byte is enough to distinguish between SSLv3/TLS and plain HTTP. + * 11 bytes are enough to log supported SSLv3/TLS version. + * 16 bytes are just for more optimized kernel copy-out operation. + */ + n = c->io->recv(c, b->mem.pos, 16, MSG_PEEK); - if (n > 0) { - c->read = b; + if (n > 0) { + c->read = b; - } else { - c->read = NULL; - nxt_event_engine_buf_mem_free(task->thread->engine, b); - } + } else { + c->read = NULL; + nxt_event_engine_buf_mem_free(task->thread->engine, b); + } - return n; + return n; } +static void nxt_http_conn_test(nxt_task_t *task, void *obj, void *data) { + u_char *p; + nxt_buf_t *b; + nxt_conn_t *c; + nxt_tls_conf_t *tls; + nxt_event_engine_t *engine; + nxt_socket_conf_joint_t *joint; -static void -nxt_http_conn_test(nxt_task_t *task, void *obj, void *data) -{ - u_char *p; - nxt_buf_t *b; - nxt_conn_t *c; - nxt_tls_conf_t *tls; - nxt_event_engine_t *engine; - nxt_socket_conf_joint_t *joint; - - c = obj; + c = obj; - nxt_debug(task, "h1p conn https test"); + nxt_debug(task, "h1p conn https test"); - engine = task->thread->engine; - b = c->read; - p = b->mem.pos; + engine = task->thread->engine; + b = c->read; + p = b->mem.pos; - c->read_state = &nxt_h1p_idle_state; + c->read_state = &nxt_h1p_idle_state; - if (p[0] != 0x16) { - b->mem.free = b->mem.pos; + if (p[0] != 0x16) { + b->mem.free = b->mem.pos; - nxt_conn_read(engine, c); - return; - } + nxt_conn_read(engine, c); + return; + } - /* SSLv3/TLS ClientHello message. */ + /* SSLv3/TLS ClientHello message. */ #if (NXT_DEBUG) - if (nxt_buf_mem_used_size(&b->mem) >= 11) { - u_char major, minor; - const char *protocol; + if (nxt_buf_mem_used_size(&b->mem) >= 11) { + u_char major, minor; + const char *protocol; - major = p[9]; - minor = p[10]; + major = p[9]; + minor = p[10]; - if (major == 3) { - if (minor == 0) { - protocol = "SSLv"; + if (major == 3) { + if (minor == 0) { + protocol = "SSLv"; - } else { - protocol = "TLSv"; - major -= 2; - minor -= 1; - } + } else { + protocol = "TLSv"; + major -= 2; + minor -= 1; + } - nxt_debug(task, "SSL/TLS: %s%ud.%ud", protocol, major, minor); - } + nxt_debug(task, "SSL/TLS: %s%ud.%ud", protocol, major, minor); } + } #endif - c->read = NULL; - nxt_event_engine_buf_mem_free(engine, b); + c->read = NULL; + nxt_event_engine_buf_mem_free(engine, b); - joint = c->listen->socket.data; + joint = c->listen->socket.data; - if (nxt_slow_path(joint == NULL)) { - /* - * Listening socket had been closed while - * connection was in keep-alive state. - */ - nxt_h1p_closing(task, c); - return; - } + if (nxt_slow_path(joint == NULL)) { + /* + * Listening socket had been closed while + * connection was in keep-alive state. + */ + nxt_h1p_closing(task, c); + return; + } - tls = joint->socket_conf->tls; + tls = joint->socket_conf->tls; - tls->conn_init(task, tls, c); + tls->conn_init(task, tls, c); } #endif - -static const nxt_conn_state_t nxt_h1p_idle_state - nxt_aligned(64) = -{ +static const nxt_conn_state_t nxt_h1p_idle_state nxt_aligned(64) = { .ready_handler = nxt_h1p_conn_proto_init, .close_handler = nxt_h1p_conn_close, .error_handler = nxt_h1p_conn_error, @@ -396,145 +376,133 @@ static const nxt_conn_state_t nxt_h1p_idle_state .timer_autoreset = 1, }; +static ssize_t nxt_h1p_idle_io_read_handler(nxt_task_t *task, nxt_conn_t *c) { + size_t size; + ssize_t n; + nxt_buf_t *b; + nxt_socket_conf_joint_t *joint; -static ssize_t -nxt_h1p_idle_io_read_handler(nxt_task_t *task, nxt_conn_t *c) -{ - size_t size; - ssize_t n; - nxt_buf_t *b; - nxt_socket_conf_joint_t *joint; + joint = c->listen->socket.data; - joint = c->listen->socket.data; - - if (nxt_slow_path(joint == NULL)) { - /* - * Listening socket had been closed while - * connection was in keep-alive state. - */ - c->read_state = &nxt_h1p_idle_close_state; - return 0; - } + if (nxt_slow_path(joint == NULL)) { + /* + * Listening socket had been closed while + * connection was in keep-alive state. + */ + c->read_state = &nxt_h1p_idle_close_state; + return 0; + } - b = c->read; + b = c->read; - if (b == NULL) { - size = joint->socket_conf->header_buffer_size; + if (b == NULL) { + size = joint->socket_conf->header_buffer_size; - b = nxt_event_engine_buf_mem_alloc(task->thread->engine, size); - if (nxt_slow_path(b == NULL)) { - c->socket.error = NXT_ENOMEM; - return NXT_ERROR; - } + b = nxt_event_engine_buf_mem_alloc(task->thread->engine, size); + if (nxt_slow_path(b == NULL)) { + c->socket.error = NXT_ENOMEM; + return NXT_ERROR; } + } - n = c->io->recvbuf(c, b); + n = c->io->recvbuf(c, b); - if (n > 0) { - c->read = b; + if (n > 0) { + c->read = b; - } else { - c->read = NULL; - nxt_event_engine_buf_mem_free(task->thread->engine, b); - } + } else { + c->read = NULL; + nxt_event_engine_buf_mem_free(task->thread->engine, b); + } - return n; + return n; } +static void nxt_h1p_conn_proto_init(nxt_task_t *task, void *obj, void *data) { + nxt_conn_t *c; + nxt_h1proto_t *h1p; -static void -nxt_h1p_conn_proto_init(nxt_task_t *task, void *obj, void *data) -{ - nxt_conn_t *c; - nxt_h1proto_t *h1p; - - c = obj; + c = obj; - nxt_debug(task, "h1p conn proto init"); + nxt_debug(task, "h1p conn proto init"); - h1p = nxt_mp_zget(c->mem_pool, sizeof(nxt_h1proto_t)); - if (nxt_slow_path(h1p == NULL)) { - nxt_h1p_closing(task, c); - return; - } + h1p = nxt_mp_zget(c->mem_pool, sizeof(nxt_h1proto_t)); + if (nxt_slow_path(h1p == NULL)) { + nxt_h1p_closing(task, c); + return; + } - c->socket.data = h1p; - h1p->conn = c; + c->socket.data = h1p; + h1p->conn = c; - nxt_h1p_conn_request_init(task, c, h1p); + nxt_h1p_conn_request_init(task, c, h1p); } +static void nxt_h1p_conn_request_init(nxt_task_t *task, void *obj, void *data) { + nxt_int_t ret; + nxt_conn_t *c; + nxt_h1proto_t *h1p; + nxt_socket_conf_t *skcf; + nxt_http_request_t *r; + nxt_socket_conf_joint_t *joint; -static void -nxt_h1p_conn_request_init(nxt_task_t *task, void *obj, void *data) -{ - nxt_int_t ret; - nxt_conn_t *c; - nxt_h1proto_t *h1p; - nxt_socket_conf_t *skcf; - nxt_http_request_t *r; - nxt_socket_conf_joint_t *joint; + c = obj; + h1p = data; - c = obj; - h1p = data; + nxt_debug(task, "h1p conn request init"); - nxt_debug(task, "h1p conn request init"); + nxt_conn_active(task->thread->engine, c); - nxt_conn_active(task->thread->engine, c); + r = nxt_http_request_create(task); - r = nxt_http_request_create(task); - - if (nxt_fast_path(r != NULL)) { - h1p->request = r; - r->proto.h1 = h1p; + if (nxt_fast_path(r != NULL)) { + h1p->request = r; + r->proto.h1 = h1p; - /* r->protocol = NXT_HTTP_PROTO_H1 is done by zeroing. */ - r->remote = c->remote; + /* r->protocol = NXT_HTTP_PROTO_H1 is done by zeroing. */ + r->remote = c->remote; #if (NXT_TLS) - r->tls = (c->u.tls != NULL); + r->tls = (c->u.tls != NULL); #endif - r->task = c->task; - task = &r->task; - c->socket.task = task; - c->read_timer.task = task; - c->write_timer.task = task; - - ret = nxt_http_parse_request_init(&h1p->parser, r->mem_pool); + r->task = c->task; + task = &r->task; + c->socket.task = task; + c->read_timer.task = task; + c->write_timer.task = task; - if (nxt_fast_path(ret == NXT_OK)) { - joint = c->listen->socket.data; - joint->count++; + ret = nxt_http_parse_request_init(&h1p->parser, r->mem_pool); - r->conf = joint; - skcf = joint->socket_conf; - r->log_route = skcf->log_route; + if (nxt_fast_path(ret == NXT_OK)) { + joint = c->listen->socket.data; + joint->count++; - if (c->local == NULL) { - c->local = skcf->sockaddr; - } + r->conf = joint; + skcf = joint->socket_conf; + r->log_route = skcf->log_route; - h1p->parser.discard_unsafe_fields = skcf->discard_unsafe_fields; + if (c->local == NULL) { + c->local = skcf->sockaddr; + } - nxt_h1p_conn_request_header_parse(task, c, h1p); - return; - } + h1p->parser.discard_unsafe_fields = skcf->discard_unsafe_fields; - /* - * The request is very incomplete here, - * so "internal server error" useless here. - */ - nxt_mp_release(r->mem_pool); + nxt_h1p_conn_request_header_parse(task, c, h1p); + return; } - nxt_h1p_closing(task, c); -} + /* + * The request is very incomplete here, + * so "internal server error" useless here. + */ + nxt_mp_release(r->mem_pool); + } + nxt_h1p_closing(task, c); +} -static const nxt_conn_state_t nxt_h1p_header_parse_state - nxt_aligned(64) = -{ +static const nxt_conn_state_t nxt_h1p_header_parse_state nxt_aligned(64) = { .ready_handler = nxt_h1p_conn_request_header_parse, .close_handler = nxt_h1p_conn_request_error, .error_handler = nxt_h1p_conn_request_error, @@ -544,531 +512,494 @@ static const nxt_conn_state_t nxt_h1p_header_parse_state .timer_data = offsetof(nxt_socket_conf_t, header_read_timeout), }; +static void nxt_h1p_conn_request_header_parse(nxt_task_t *task, void *obj, + void *data) { + nxt_int_t ret; + nxt_conn_t *c; + nxt_h1proto_t *h1p; + nxt_http_status_t status; + nxt_http_request_t *r; -static void -nxt_h1p_conn_request_header_parse(nxt_task_t *task, void *obj, void *data) -{ - nxt_int_t ret; - nxt_conn_t *c; - nxt_h1proto_t *h1p; - nxt_http_status_t status; - nxt_http_request_t *r; - - c = obj; - h1p = data; + c = obj; + h1p = data; - nxt_debug(task, "h1p conn header parse"); + nxt_debug(task, "h1p conn header parse"); - ret = nxt_http_parse_request(&h1p->parser, &c->read->mem); + ret = nxt_http_parse_request(&h1p->parser, &c->read->mem); - ret = nxt_expect(NXT_DONE, ret); + ret = nxt_expect(NXT_DONE, ret); - if (ret != NXT_AGAIN) { - nxt_timer_disable(task->thread->engine, &c->read_timer); - } + if (ret != NXT_AGAIN) { + nxt_timer_disable(task->thread->engine, &c->read_timer); + } - r = h1p->request; + r = h1p->request; - switch (ret) { + switch (ret) { - case NXT_DONE: - /* - * By default the keepalive mode is disabled in HTTP/1.0 and - * enabled in HTTP/1.1. The mode can be overridden later by - * the "Connection" field processed in nxt_h1p_connection(). - */ - h1p->keepalive = (h1p->parser.version.s.minor != '0'); + case NXT_DONE: + /* + * By default the keepalive mode is disabled in HTTP/1.0 and + * enabled in HTTP/1.1. The mode can be overridden later by + * the "Connection" field processed in nxt_h1p_connection(). + */ + h1p->keepalive = (h1p->parser.version.s.minor != '0'); - r->request_line.start = h1p->parser.method.start; - r->request_line.length = h1p->parser.request_line_end - - r->request_line.start; + r->request_line.start = h1p->parser.method.start; + r->request_line.length = + h1p->parser.request_line_end - r->request_line.start; - if (nxt_slow_path(r->log_route)) { - nxt_log(task, NXT_LOG_NOTICE, "http request line \"%V\"", - &r->request_line); - } + if (nxt_slow_path(r->log_route)) { + nxt_log(task, NXT_LOG_NOTICE, "http request line \"%V\"", + &r->request_line); + } - ret = nxt_h1p_header_process(task, h1p, r); + ret = nxt_h1p_header_process(task, h1p, r); - if (nxt_fast_path(ret == NXT_OK)) { + if (nxt_fast_path(ret == NXT_OK)) { #if (NXT_TLS) - if (c->u.tls == NULL && r->conf->socket_conf->tls != NULL) { - status = NXT_HTTP_TO_HTTPS; - goto error; - } + if (c->u.tls == NULL && r->conf->socket_conf->tls != NULL) { + status = NXT_HTTP_TO_HTTPS; + goto error; + } #endif - r->state->ready_handler(task, r, NULL); - return; - } + r->state->ready_handler(task, r, NULL); + return; + } - status = ret; - goto error; + status = ret; + goto error; - case NXT_AGAIN: - status = nxt_h1p_header_buffer_test(task, h1p, c, r->conf->socket_conf); + case NXT_AGAIN: + status = nxt_h1p_header_buffer_test(task, h1p, c, r->conf->socket_conf); - if (nxt_fast_path(status == NXT_OK)) { - c->read_state = &nxt_h1p_header_parse_state; + if (nxt_fast_path(status == NXT_OK)) { + c->read_state = &nxt_h1p_header_parse_state; - nxt_conn_read(task->thread->engine, c); - return; - } + nxt_conn_read(task->thread->engine, c); + return; + } - break; + break; - case NXT_HTTP_PARSE_INVALID: - status = NXT_HTTP_BAD_REQUEST; - break; + case NXT_HTTP_PARSE_INVALID: + status = NXT_HTTP_BAD_REQUEST; + break; - case NXT_HTTP_PARSE_UNSUPPORTED_VERSION: - status = NXT_HTTP_VERSION_NOT_SUPPORTED; - break; + case NXT_HTTP_PARSE_UNSUPPORTED_VERSION: + status = NXT_HTTP_VERSION_NOT_SUPPORTED; + break; - case NXT_HTTP_PARSE_TOO_LARGE_FIELD: - status = NXT_HTTP_REQUEST_HEADER_FIELDS_TOO_LARGE; - break; + case NXT_HTTP_PARSE_TOO_LARGE_FIELD: + status = NXT_HTTP_REQUEST_HEADER_FIELDS_TOO_LARGE; + break; - default: - case NXT_ERROR: - status = NXT_HTTP_INTERNAL_SERVER_ERROR; - break; - } + default: + case NXT_ERROR: + status = NXT_HTTP_INTERNAL_SERVER_ERROR; + break; + } - (void) nxt_h1p_header_process(task, h1p, r); + (void)nxt_h1p_header_process(task, h1p, r); error: - h1p->keepalive = 0; + h1p->keepalive = 0; - nxt_http_request_error(task, r, status); + nxt_http_request_error(task, r, status); } +static nxt_int_t nxt_h1p_header_process(nxt_task_t *task, nxt_h1proto_t *h1p, + nxt_http_request_t *r) { + u_char *m; + nxt_int_t ret; -static nxt_int_t -nxt_h1p_header_process(nxt_task_t *task, nxt_h1proto_t *h1p, - nxt_http_request_t *r) -{ - u_char *m; - nxt_int_t ret; - - r->target.start = h1p->parser.target_start; - r->target.length = h1p->parser.target_end - h1p->parser.target_start; - - r->quoted_target = h1p->parser.quoted_target; + r->target.start = h1p->parser.target_start; + r->target.length = h1p->parser.target_end - h1p->parser.target_start; - if (h1p->parser.version.ui64 != 0) { - r->version.start = h1p->parser.version.str; - r->version.length = sizeof(h1p->parser.version.str); - } + r->quoted_target = h1p->parser.quoted_target; - r->method = &h1p->parser.method; - r->path = &h1p->parser.path; - r->args = &h1p->parser.args; + if (h1p->parser.version.ui64 != 0) { + r->version.start = h1p->parser.version.str; + r->version.length = sizeof(h1p->parser.version.str); + } - r->fields = h1p->parser.fields; + r->method = &h1p->parser.method; + r->path = &h1p->parser.path; + r->args = &h1p->parser.args; - ret = nxt_http_fields_process(r->fields, &nxt_h1p_fields_hash, r); - if (nxt_slow_path(ret != NXT_OK)) { - return ret; - } + r->fields = h1p->parser.fields; - if (h1p->connection_upgrade && h1p->upgrade_websocket) { - m = h1p->parser.method.start; + ret = nxt_http_fields_process(r->fields, &nxt_h1p_fields_hash, r); + if (nxt_slow_path(ret != NXT_OK)) { + return ret; + } - if (nxt_slow_path(h1p->parser.method.length != 3 - || m[0] != 'G' - || m[1] != 'E' - || m[2] != 'T')) - { - nxt_log(task, NXT_LOG_INFO, "h1p upgrade: bad method"); + if (h1p->connection_upgrade && h1p->upgrade_websocket) { + m = h1p->parser.method.start; - return NXT_HTTP_BAD_REQUEST; - } + if (nxt_slow_path(h1p->parser.method.length != 3 || m[0] != 'G' || + m[1] != 'E' || m[2] != 'T')) { + nxt_log(task, NXT_LOG_INFO, "h1p upgrade: bad method"); - if (nxt_slow_path(h1p->parser.version.s.minor != '1')) { - nxt_log(task, NXT_LOG_INFO, "h1p upgrade: bad protocol version"); + return NXT_HTTP_BAD_REQUEST; + } - return NXT_HTTP_BAD_REQUEST; - } + if (nxt_slow_path(h1p->parser.version.s.minor != '1')) { + nxt_log(task, NXT_LOG_INFO, "h1p upgrade: bad protocol version"); - if (nxt_slow_path(h1p->websocket_key == NULL)) { - nxt_log(task, NXT_LOG_INFO, - "h1p upgrade: bad or absent websocket key"); + return NXT_HTTP_BAD_REQUEST; + } - return NXT_HTTP_BAD_REQUEST; - } + if (nxt_slow_path(h1p->websocket_key == NULL)) { + nxt_log(task, NXT_LOG_INFO, "h1p upgrade: bad or absent websocket key"); - if (nxt_slow_path(h1p->websocket_version_ok == 0)) { - nxt_log(task, NXT_LOG_INFO, - "h1p upgrade: bad or absent websocket version"); + return NXT_HTTP_BAD_REQUEST; + } - return NXT_HTTP_UPGRADE_REQUIRED; - } + if (nxt_slow_path(h1p->websocket_version_ok == 0)) { + nxt_log(task, NXT_LOG_INFO, + "h1p upgrade: bad or absent websocket version"); - r->websocket_handshake = 1; + return NXT_HTTP_UPGRADE_REQUIRED; } - return ret; -} + r->websocket_handshake = 1; + } + return ret; +} -static nxt_int_t -nxt_h1p_header_buffer_test(nxt_task_t *task, nxt_h1proto_t *h1p, nxt_conn_t *c, - nxt_socket_conf_t *skcf) -{ - size_t size, used; - nxt_buf_t *in, *b; +static nxt_int_t nxt_h1p_header_buffer_test(nxt_task_t *task, + nxt_h1proto_t *h1p, nxt_conn_t *c, + nxt_socket_conf_t *skcf) { + size_t size, used; + nxt_buf_t *in, *b; - in = c->read; + in = c->read; - if (nxt_buf_mem_free_size(&in->mem) == 0) { - size = skcf->large_header_buffer_size; - used = nxt_buf_mem_used_size(&in->mem); + if (nxt_buf_mem_free_size(&in->mem) == 0) { + size = skcf->large_header_buffer_size; + used = nxt_buf_mem_used_size(&in->mem); - if (size <= used || h1p->nbuffers >= skcf->large_header_buffers) { - return NXT_HTTP_REQUEST_HEADER_FIELDS_TOO_LARGE; - } + if (size <= used || h1p->nbuffers >= skcf->large_header_buffers) { + return NXT_HTTP_REQUEST_HEADER_FIELDS_TOO_LARGE; + } - b = nxt_buf_mem_alloc(c->mem_pool, size, 0); - if (nxt_slow_path(b == NULL)) { - return NXT_HTTP_INTERNAL_SERVER_ERROR; - } + b = nxt_buf_mem_alloc(c->mem_pool, size, 0); + if (nxt_slow_path(b == NULL)) { + return NXT_HTTP_INTERNAL_SERVER_ERROR; + } - b->mem.free = nxt_cpymem(b->mem.pos, in->mem.pos, used); + b->mem.free = nxt_cpymem(b->mem.pos, in->mem.pos, used); - in->next = h1p->buffers; - h1p->buffers = in; - h1p->nbuffers++; + in->next = h1p->buffers; + h1p->buffers = in; + h1p->nbuffers++; - c->read = b; - } + c->read = b; + } - return NXT_OK; + return NXT_OK; } +static nxt_int_t nxt_h1p_connection(void *ctx, nxt_http_field_t *field, + uintptr_t data) { + nxt_http_request_t *r; -static nxt_int_t -nxt_h1p_connection(void *ctx, nxt_http_field_t *field, uintptr_t data) -{ - nxt_http_request_t *r; - - r = ctx; - field->hopbyhop = 1; + r = ctx; + field->hopbyhop = 1; - if (field->value_length == 5 - && nxt_memcasecmp(field->value, "close", 5) == 0) - { - r->proto.h1->keepalive = 0; + if (field->value_length == 5 && + nxt_memcasecmp(field->value, "close", 5) == 0) { + r->proto.h1->keepalive = 0; - } else if (field->value_length == 10 - && nxt_memcasecmp(field->value, "keep-alive", 10) == 0) - { - r->proto.h1->keepalive = 1; + } else if (field->value_length == 10 && + nxt_memcasecmp(field->value, "keep-alive", 10) == 0) { + r->proto.h1->keepalive = 1; - } else if (field->value_length == 7 - && nxt_memcasecmp(field->value, "upgrade", 7) == 0) - { - r->proto.h1->connection_upgrade = 1; - } + } else if (field->value_length == 7 && + nxt_memcasecmp(field->value, "upgrade", 7) == 0) { + r->proto.h1->connection_upgrade = 1; + } - return NXT_OK; + return NXT_OK; } +static nxt_int_t nxt_h1p_upgrade(void *ctx, nxt_http_field_t *field, + uintptr_t data) { + nxt_http_request_t *r; -static nxt_int_t -nxt_h1p_upgrade(void *ctx, nxt_http_field_t *field, uintptr_t data) -{ - nxt_http_request_t *r; - - r = ctx; + r = ctx; - if (field->value_length == 9 - && nxt_memcasecmp(field->value, "websocket", 9) == 0) - { - r->proto.h1->upgrade_websocket = 1; - } + if (field->value_length == 9 && + nxt_memcasecmp(field->value, "websocket", 9) == 0) { + r->proto.h1->upgrade_websocket = 1; + } - return NXT_OK; + return NXT_OK; } +static nxt_int_t nxt_h1p_websocket_key(void *ctx, nxt_http_field_t *field, + uintptr_t data) { + nxt_http_request_t *r; -static nxt_int_t -nxt_h1p_websocket_key(void *ctx, nxt_http_field_t *field, uintptr_t data) -{ - nxt_http_request_t *r; - - r = ctx; + r = ctx; - if (field->value_length == 24) { - r->proto.h1->websocket_key = field; - } + if (field->value_length == 24) { + r->proto.h1->websocket_key = field; + } - return NXT_OK; + return NXT_OK; } +static nxt_int_t nxt_h1p_websocket_version(void *ctx, nxt_http_field_t *field, + uintptr_t data) { + nxt_http_request_t *r; -static nxt_int_t -nxt_h1p_websocket_version(void *ctx, nxt_http_field_t *field, uintptr_t data) -{ - nxt_http_request_t *r; - - r = ctx; + r = ctx; - if (field->value_length == 2 - && field->value[0] == '1' && field->value[1] == '3') - { - r->proto.h1->websocket_version_ok = 1; - } + if (field->value_length == 2 && field->value[0] == '1' && + field->value[1] == '3') { + r->proto.h1->websocket_version_ok = 1; + } - return NXT_OK; + return NXT_OK; } +static nxt_int_t nxt_h1p_transfer_encoding(void *ctx, nxt_http_field_t *field, + uintptr_t data) { + nxt_http_te_t te; + nxt_http_request_t *r; -static nxt_int_t -nxt_h1p_transfer_encoding(void *ctx, nxt_http_field_t *field, uintptr_t data) -{ - nxt_http_te_t te; - nxt_http_request_t *r; - - r = ctx; - field->skip = 1; - field->hopbyhop = 1; + r = ctx; + field->skip = 1; + field->hopbyhop = 1; - if (field->value_length == 7 - && memcmp(field->value, "chunked", 7) == 0) - { - if (r->chunked_field != NULL) { - return NXT_HTTP_BAD_REQUEST; - } + if (field->value_length == 7 && memcmp(field->value, "chunked", 7) == 0) { + if (r->chunked_field != NULL) { + return NXT_HTTP_BAD_REQUEST; + } - te = NXT_HTTP_TE_CHUNKED; - r->chunked_field = field; + te = NXT_HTTP_TE_CHUNKED; + r->chunked_field = field; - } else { - te = NXT_HTTP_TE_UNSUPPORTED; - } + } else { + te = NXT_HTTP_TE_UNSUPPORTED; + } - r->proto.h1->transfer_encoding = te; + r->proto.h1->transfer_encoding = te; - return NXT_OK; + return NXT_OK; } +static void nxt_h1p_request_body_read(nxt_task_t *task, nxt_http_request_t *r) { + size_t size, body_length, body_buffer_size, body_rest; + ssize_t res; + nxt_buf_t *in, *b, *out, *chunk; + nxt_conn_t *c; + nxt_h1proto_t *h1p; + nxt_socket_conf_t *skcf; + nxt_http_status_t status; -static void -nxt_h1p_request_body_read(nxt_task_t *task, nxt_http_request_t *r) -{ - size_t size, body_length, body_buffer_size, body_rest; - ssize_t res; - nxt_buf_t *in, *b, *out, *chunk; - nxt_conn_t *c; - nxt_h1proto_t *h1p; - nxt_socket_conf_t *skcf; - nxt_http_status_t status; - - static const nxt_str_t tmp_name_pattern = nxt_string("/req-XXXXXXXX"); + static const nxt_str_t tmp_name_pattern = nxt_string("/req-XXXXXXXX"); - h1p = r->proto.h1; - skcf = r->conf->socket_conf; + h1p = r->proto.h1; + skcf = r->conf->socket_conf; - nxt_debug(task, "h1p request body read %O te:%d", - r->content_length_n, h1p->transfer_encoding); + nxt_debug(task, "h1p request body read %O te:%d", r->content_length_n, + h1p->transfer_encoding); - switch (h1p->transfer_encoding) { + switch (h1p->transfer_encoding) { - case NXT_HTTP_TE_CHUNKED: - if (!skcf->chunked_transform) { - status = NXT_HTTP_LENGTH_REQUIRED; - goto error; - } + case NXT_HTTP_TE_CHUNKED: + if (!skcf->chunked_transform) { + status = NXT_HTTP_LENGTH_REQUIRED; + goto error; + } - if (r->content_length != NULL || !nxt_h1p_is_http11(h1p)) { - status = NXT_HTTP_BAD_REQUEST; - goto error; - } + if (r->content_length != NULL || !nxt_h1p_is_http11(h1p)) { + status = NXT_HTTP_BAD_REQUEST; + goto error; + } - r->chunked = 1; - h1p->chunked_parse.mem_pool = r->mem_pool; - break; + r->chunked = 1; + h1p->chunked_parse.mem_pool = r->mem_pool; + break; - case NXT_HTTP_TE_UNSUPPORTED: - status = NXT_HTTP_NOT_IMPLEMENTED; - goto error; + case NXT_HTTP_TE_UNSUPPORTED: + status = NXT_HTTP_NOT_IMPLEMENTED; + goto error; - default: - case NXT_HTTP_TE_NONE: - break; - } + default: + case NXT_HTTP_TE_NONE: + break; + } - if (!r->chunked && - (r->content_length_n == -1 || r->content_length_n == 0)) - { - goto ready; - } + if (!r->chunked && (r->content_length_n == -1 || r->content_length_n == 0)) { + goto ready; + } - body_length = (size_t) r->content_length_n; + body_length = (size_t)r->content_length_n; - body_buffer_size = nxt_min(skcf->body_buffer_size, body_length); + body_buffer_size = nxt_min(skcf->body_buffer_size, body_length); - if (body_length > body_buffer_size) { - nxt_str_t *tmp_path, tmp_name; + if (body_length > body_buffer_size) { + nxt_str_t *tmp_path, tmp_name; - tmp_path = &skcf->body_temp_path; + tmp_path = &skcf->body_temp_path; - tmp_name.length = tmp_path->length + tmp_name_pattern.length; + tmp_name.length = tmp_path->length + tmp_name_pattern.length; - b = nxt_buf_file_alloc(r->mem_pool, - body_buffer_size + sizeof(nxt_file_t) - + tmp_name.length + 1, 0); - if (nxt_slow_path(b == NULL)) { - status = NXT_HTTP_INTERNAL_SERVER_ERROR; - goto error; - } + b = nxt_buf_file_alloc( + r->mem_pool, + body_buffer_size + sizeof(nxt_file_t) + tmp_name.length + 1, 0); + if (nxt_slow_path(b == NULL)) { + status = NXT_HTTP_INTERNAL_SERVER_ERROR; + goto error; + } - tmp_name.start = nxt_pointer_to(b->mem.start, sizeof(nxt_file_t)); + tmp_name.start = nxt_pointer_to(b->mem.start, sizeof(nxt_file_t)); - memcpy(tmp_name.start, tmp_path->start, tmp_path->length); - memcpy(tmp_name.start + tmp_path->length, tmp_name_pattern.start, - tmp_name_pattern.length); - tmp_name.start[tmp_name.length] = '\0'; + memcpy(tmp_name.start, tmp_path->start, tmp_path->length); + memcpy(tmp_name.start + tmp_path->length, tmp_name_pattern.start, + tmp_name_pattern.length); + tmp_name.start[tmp_name.length] = '\0'; - b->file = (nxt_file_t *) b->mem.start; - nxt_memzero(b->file, sizeof(nxt_file_t)); - b->file->fd = -1; - b->file->size = body_length; + b->file = (nxt_file_t *)b->mem.start; + nxt_memzero(b->file, sizeof(nxt_file_t)); + b->file->fd = -1; + b->file->size = body_length; - b->mem.start += sizeof(nxt_file_t) + tmp_name.length + 1; - b->mem.pos = b->mem.start; - b->mem.free = b->mem.start; + b->mem.start += sizeof(nxt_file_t) + tmp_name.length + 1; + b->mem.pos = b->mem.start; + b->mem.free = b->mem.start; - b->file->fd = mkstemp((char *) tmp_name.start); - if (nxt_slow_path(b->file->fd == -1)) { - nxt_alert(task, "mkstemp(%s) failed %E", tmp_name.start, nxt_errno); + b->file->fd = mkstemp((char *)tmp_name.start); + if (nxt_slow_path(b->file->fd == -1)) { + nxt_alert(task, "mkstemp(%s) failed %E", tmp_name.start, nxt_errno); - status = NXT_HTTP_INTERNAL_SERVER_ERROR; - goto error; - } + status = NXT_HTTP_INTERNAL_SERVER_ERROR; + goto error; + } - nxt_debug(task, "create body tmp file \"%V\", %d", - &tmp_name, b->file->fd); + nxt_debug(task, "create body tmp file \"%V\", %d", &tmp_name, b->file->fd); - unlink((char *) tmp_name.start); + unlink((char *)tmp_name.start); - } else { - b = nxt_buf_mem_alloc(r->mem_pool, body_buffer_size, 0); - if (nxt_slow_path(b == NULL)) { - status = NXT_HTTP_INTERNAL_SERVER_ERROR; - goto error; - } + } else { + b = nxt_buf_mem_alloc(r->mem_pool, body_buffer_size, 0); + if (nxt_slow_path(b == NULL)) { + status = NXT_HTTP_INTERNAL_SERVER_ERROR; + goto error; } + } - r->body = b; + r->body = b; - body_rest = r->chunked ? 1 : body_length; + body_rest = r->chunked ? 1 : body_length; - in = h1p->conn->read; + in = h1p->conn->read; - size = nxt_buf_mem_used_size(&in->mem); + size = nxt_buf_mem_used_size(&in->mem); - if (size != 0) { - if (nxt_buf_is_file(b)) { - if (r->chunked) { - out = nxt_http_chunk_parse(task, &h1p->chunked_parse, in); + if (size != 0) { + if (nxt_buf_is_file(b)) { + if (r->chunked) { + out = nxt_http_chunk_parse(task, &h1p->chunked_parse, in); - if (h1p->chunked_parse.error) { - status = NXT_HTTP_INTERNAL_SERVER_ERROR; - goto error; - } + if (h1p->chunked_parse.error) { + status = NXT_HTTP_INTERNAL_SERVER_ERROR; + goto error; + } - if (h1p->chunked_parse.chunk_error) { - status = NXT_HTTP_BAD_REQUEST; - goto error; - } + if (h1p->chunked_parse.chunk_error) { + status = NXT_HTTP_BAD_REQUEST; + goto error; + } - for (chunk = out; chunk != NULL; chunk = chunk->next) { - size = nxt_buf_mem_used_size(&chunk->mem); + for (chunk = out; chunk != NULL; chunk = chunk->next) { + size = nxt_buf_mem_used_size(&chunk->mem); - res = nxt_fd_write(b->file->fd, chunk->mem.pos, size); - if (nxt_slow_path(res < (ssize_t) size)) { - status = NXT_HTTP_INTERNAL_SERVER_ERROR; - goto error; - } + res = nxt_fd_write(b->file->fd, chunk->mem.pos, size); + if (nxt_slow_path(res < (ssize_t)size)) { + status = NXT_HTTP_INTERNAL_SERVER_ERROR; + goto error; + } - b->file_end += size; + b->file_end += size; - if ((size_t) b->file_end > skcf->max_body_size) { - status = NXT_HTTP_PAYLOAD_TOO_LARGE; - goto error; - } - } + if ((size_t)b->file_end > skcf->max_body_size) { + status = NXT_HTTP_PAYLOAD_TOO_LARGE; + goto error; + } + } - if (h1p->chunked_parse.last) { - body_rest = 0; - } + if (h1p->chunked_parse.last) { + body_rest = 0; + } - } else { - size = nxt_min(size, body_length); - res = nxt_fd_write(b->file->fd, in->mem.pos, size); - if (nxt_slow_path(res < (ssize_t) size)) { - status = NXT_HTTP_INTERNAL_SERVER_ERROR; - goto error; - } + } else { + size = nxt_min(size, body_length); + res = nxt_fd_write(b->file->fd, in->mem.pos, size); + if (nxt_slow_path(res < (ssize_t)size)) { + status = NXT_HTTP_INTERNAL_SERVER_ERROR; + goto error; + } - b->file_end += size; + b->file_end += size; - in->mem.pos += size; - body_rest -= size; - } + in->mem.pos += size; + body_rest -= size; + } - } else { - size = nxt_min(body_buffer_size, size); - b->mem.free = nxt_cpymem(b->mem.free, in->mem.pos, size); + } else { + size = nxt_min(body_buffer_size, size); + b->mem.free = nxt_cpymem(b->mem.free, in->mem.pos, size); - in->mem.pos += size; - body_rest -= size; - } + in->mem.pos += size; + body_rest -= size; } + } - nxt_debug(task, "h1p body rest: %uz", body_rest); + nxt_debug(task, "h1p body rest: %uz", body_rest); - if (body_rest != 0) { - in->next = h1p->buffers; - h1p->buffers = in; - h1p->nbuffers++; + if (body_rest != 0) { + in->next = h1p->buffers; + h1p->buffers = in; + h1p->nbuffers++; - c = h1p->conn; - c->read = b; - c->read_state = &nxt_h1p_read_body_state; + c = h1p->conn; + c->read = b; + c->read_state = &nxt_h1p_read_body_state; - nxt_conn_read(task->thread->engine, c); - return; - } + nxt_conn_read(task->thread->engine, c); + return; + } - if (nxt_buf_is_file(b)) { - b->mem.start = NULL; - b->mem.end = NULL; - b->mem.pos = NULL; - b->mem.free = NULL; - } + if (nxt_buf_is_file(b)) { + b->mem.start = NULL; + b->mem.end = NULL; + b->mem.pos = NULL; + b->mem.free = NULL; + } ready: - r->state->ready_handler(task, r, NULL); + r->state->ready_handler(task, r, NULL); - return; + return; error: - h1p->keepalive = 0; + h1p->keepalive = 0; - nxt_http_request_error(task, r, status); + nxt_http_request_error(task, r, status); } - -static const nxt_conn_state_t nxt_h1p_read_body_state - nxt_aligned(64) = -{ +static const nxt_conn_state_t nxt_h1p_read_body_state nxt_aligned(64) = { .ready_handler = nxt_h1p_conn_request_body_read, .close_handler = nxt_h1p_conn_request_error, .error_handler = nxt_h1p_conn_request_error, @@ -1079,142 +1010,135 @@ static const nxt_conn_state_t nxt_h1p_read_body_state .timer_autoreset = 1, }; +static void nxt_h1p_conn_request_body_read(nxt_task_t *task, void *obj, + void *data) { + size_t size, body_rest; + ssize_t res; + nxt_buf_t *b, *out, *chunk; + nxt_conn_t *c; + nxt_h1proto_t *h1p; + nxt_socket_conf_t *skcf; + nxt_http_request_t *r; + nxt_event_engine_t *engine; -static void -nxt_h1p_conn_request_body_read(nxt_task_t *task, void *obj, void *data) -{ - size_t size, body_rest; - ssize_t res; - nxt_buf_t *b, *out, *chunk; - nxt_conn_t *c; - nxt_h1proto_t *h1p; - nxt_socket_conf_t *skcf; - nxt_http_request_t *r; - nxt_event_engine_t *engine; - - c = obj; - h1p = data; - - nxt_debug(task, "h1p conn request body read"); - - r = h1p->request; - skcf = r->conf->socket_conf; + c = obj; + h1p = data; - engine = task->thread->engine; + nxt_debug(task, "h1p conn request body read"); - b = c->read; + r = h1p->request; + skcf = r->conf->socket_conf; - if (nxt_buf_is_file(b)) { + engine = task->thread->engine; - if (r->chunked) { - body_rest = 1; + b = c->read; - out = nxt_http_chunk_parse(task, &h1p->chunked_parse, b); + if (nxt_buf_is_file(b)) { - if (h1p->chunked_parse.error) { - nxt_h1p_request_error(task, h1p, r); - return; - } + if (r->chunked) { + body_rest = 1; - if (h1p->chunked_parse.chunk_error) { - nxt_http_request_error(task, r, NXT_HTTP_BAD_REQUEST); - return; - } + out = nxt_http_chunk_parse(task, &h1p->chunked_parse, b); - for (chunk = out; chunk != NULL; chunk = chunk->next) { - size = nxt_buf_mem_used_size(&chunk->mem); - res = nxt_fd_write(b->file->fd, chunk->mem.pos, size); - if (nxt_slow_path(res < (ssize_t) size)) { - nxt_h1p_request_error(task, h1p, r); - return; - } + if (h1p->chunked_parse.error) { + nxt_h1p_request_error(task, h1p, r); + return; + } - b->file_end += size; + if (h1p->chunked_parse.chunk_error) { + nxt_http_request_error(task, r, NXT_HTTP_BAD_REQUEST); + return; + } + + for (chunk = out; chunk != NULL; chunk = chunk->next) { + size = nxt_buf_mem_used_size(&chunk->mem); + res = nxt_fd_write(b->file->fd, chunk->mem.pos, size); + if (nxt_slow_path(res < (ssize_t)size)) { + nxt_h1p_request_error(task, h1p, r); + return; + } - if ((size_t) b->file_end > skcf->max_body_size) { - nxt_h1p_request_error(task, h1p, r); - return; - } - } + b->file_end += size; - if (h1p->chunked_parse.last) { - body_rest = 0; - } + if ((size_t)b->file_end > skcf->max_body_size) { + nxt_h1p_request_error(task, h1p, r); + return; + } + } - } else { - body_rest = b->file->size - b->file_end; + if (h1p->chunked_parse.last) { + body_rest = 0; + } - size = nxt_buf_mem_used_size(&b->mem); - size = nxt_min(size, body_rest); + } else { + body_rest = b->file->size - b->file_end; - res = nxt_fd_write(b->file->fd, b->mem.pos, size); - if (nxt_slow_path(res < (ssize_t) size)) { - nxt_h1p_request_error(task, h1p, r); - return; - } + size = nxt_buf_mem_used_size(&b->mem); + size = nxt_min(size, body_rest); - b->file_end += size; - body_rest -= res; + res = nxt_fd_write(b->file->fd, b->mem.pos, size); + if (nxt_slow_path(res < (ssize_t)size)) { + nxt_h1p_request_error(task, h1p, r); + return; + } - b->mem.pos += size; + b->file_end += size; + body_rest -= res; - if (b->mem.pos == b->mem.free) { - if (body_rest >= (size_t) nxt_buf_mem_size(&b->mem)) { - b->mem.free = b->mem.start; + b->mem.pos += size; - } else { - /* This required to avoid reading next request. */ - b->mem.free = b->mem.end - body_rest; - } + if (b->mem.pos == b->mem.free) { + if (body_rest >= (size_t)nxt_buf_mem_size(&b->mem)) { + b->mem.free = b->mem.start; - b->mem.pos = b->mem.free; - } + } else { + /* This required to avoid reading next request. */ + b->mem.free = b->mem.end - body_rest; } - } else { - body_rest = nxt_buf_mem_free_size(&c->read->mem); + b->mem.pos = b->mem.free; + } } - nxt_debug(task, "h1p body rest: %uz", body_rest); + } else { + body_rest = nxt_buf_mem_free_size(&c->read->mem); + } - if (body_rest != 0) { - nxt_conn_read(engine, c); - - } else { - if (nxt_buf_is_file(b)) { - b->mem.start = NULL; - b->mem.end = NULL; - b->mem.pos = NULL; - b->mem.free = NULL; - } + nxt_debug(task, "h1p body rest: %uz", body_rest); - c->read = NULL; + if (body_rest != 0) { + nxt_conn_read(engine, c); - r->state->ready_handler(task, r, NULL); + } else { + if (nxt_buf_is_file(b)) { + b->mem.start = NULL; + b->mem.end = NULL; + b->mem.pos = NULL; + b->mem.free = NULL; } -} + c->read = NULL; -static void -nxt_h1p_request_local_addr(nxt_task_t *task, nxt_http_request_t *r) -{ - r->local = nxt_conn_local_addr(task, r->proto.h1->conn); + r->state->ready_handler(task, r, NULL); + } } +static void nxt_h1p_request_local_addr(nxt_task_t *task, + nxt_http_request_t *r) { + r->local = nxt_conn_local_addr(task, r->proto.h1->conn); +} -#define NXT_HTTP_LAST_INFORMATIONAL \ - (NXT_HTTP_CONTINUE + nxt_nitems(nxt_http_informational) - 1) +#define NXT_HTTP_LAST_INFORMATIONAL \ + (NXT_HTTP_CONTINUE + nxt_nitems(nxt_http_informational) - 1) -static const nxt_str_t nxt_http_informational[] = { +static const nxt_str_t nxt_http_informational[] = { nxt_string("HTTP/1.1 100 Continue\r\n"), nxt_string("HTTP/1.1 101 Switching Protocols\r\n"), }; +#define NXT_HTTP_LAST_SUCCESS (NXT_HTTP_OK + nxt_nitems(nxt_http_success) - 1) -#define NXT_HTTP_LAST_SUCCESS \ - (NXT_HTTP_OK + nxt_nitems(nxt_http_success) - 1) - -static const nxt_str_t nxt_http_success[] = { +static const nxt_str_t nxt_http_success[] = { nxt_string("HTTP/1.1 200 OK\r\n"), nxt_string("HTTP/1.1 201 Created\r\n"), nxt_string("HTTP/1.1 202 Accepted\r\n"), @@ -1224,11 +1148,10 @@ static const nxt_str_t nxt_http_success[] = { nxt_string("HTTP/1.1 206 Partial Content\r\n"), }; +#define NXT_HTTP_LAST_REDIRECTION \ + (NXT_HTTP_MULTIPLE_CHOICES + nxt_nitems(nxt_http_redirection) - 1) -#define NXT_HTTP_LAST_REDIRECTION \ - (NXT_HTTP_MULTIPLE_CHOICES + nxt_nitems(nxt_http_redirection) - 1) - -static const nxt_str_t nxt_http_redirection[] = { +static const nxt_str_t nxt_http_redirection[] = { nxt_string("HTTP/1.1 300 Multiple Choices\r\n"), nxt_string("HTTP/1.1 301 Moved Permanently\r\n"), nxt_string("HTTP/1.1 302 Found\r\n"), @@ -1238,11 +1161,10 @@ static const nxt_str_t nxt_http_redirection[] = { nxt_string("HTTP/1.1 308 Permanent Redirect\r\n"), }; +#define NXT_HTTP_LAST_CLIENT_ERROR \ + (NXT_HTTP_BAD_REQUEST + nxt_nitems(nxt_http_client_error) - 1) -#define NXT_HTTP_LAST_CLIENT_ERROR \ - (NXT_HTTP_BAD_REQUEST + nxt_nitems(nxt_http_client_error) - 1) - -static const nxt_str_t nxt_http_client_error[] = { +static const nxt_str_t nxt_http_client_error[] = { nxt_string("HTTP/1.1 400 Bad Request\r\n"), nxt_string("HTTP/1.1 401 Unauthorized\r\n"), nxt_string("HTTP/1.1 402 Payment Required\r\n"), @@ -1277,20 +1199,18 @@ static const nxt_str_t nxt_http_client_error[] = { nxt_string("HTTP/1.1 431 Request Header Fields Too Large\r\n"), }; +#define NXT_HTTP_LAST_NGINX_ERROR \ + (NXT_HTTP_TO_HTTPS + nxt_nitems(nxt_http_nginx_error) - 1) -#define NXT_HTTP_LAST_NGINX_ERROR \ - (NXT_HTTP_TO_HTTPS + nxt_nitems(nxt_http_nginx_error) - 1) - -static const nxt_str_t nxt_http_nginx_error[] = { +static const nxt_str_t nxt_http_nginx_error[] = { nxt_string("HTTP/1.1 400 " "The plain HTTP request was sent to HTTPS port\r\n"), }; +#define NXT_HTTP_LAST_SERVER_ERROR \ + (NXT_HTTP_INTERNAL_SERVER_ERROR + nxt_nitems(nxt_http_server_error) - 1) -#define NXT_HTTP_LAST_SERVER_ERROR \ - (NXT_HTTP_INTERNAL_SERVER_ERROR + nxt_nitems(nxt_http_server_error) - 1) - -static const nxt_str_t nxt_http_server_error[] = { +static const nxt_str_t nxt_http_server_error[] = { nxt_string("HTTP/1.1 500 Internal Server Error\r\n"), nxt_string("HTTP/1.1 501 Not Implemented\r\n"), nxt_string("HTTP/1.1 502 Bad Gateway\r\n"), @@ -1299,257 +1219,248 @@ static const nxt_str_t nxt_http_server_error[] = { nxt_string("HTTP/1.1 505 HTTP Version Not Supported\r\n"), }; +#define UNKNOWN_STATUS_LENGTH nxt_length("HTTP/1.1 999 \r\n") -#define UNKNOWN_STATUS_LENGTH nxt_length("HTTP/1.1 999 \r\n") - -static void -nxt_h1p_request_header_send(nxt_task_t *task, nxt_http_request_t *r, - nxt_work_handler_t body_handler, void *data) -{ - u_char *p; - size_t size; - nxt_buf_t *header; - nxt_str_t unknown_status; - nxt_int_t conn; - nxt_uint_t n; - nxt_bool_t http11; - nxt_conn_t *c; - nxt_h1proto_t *h1p; - const nxt_str_t *status; - nxt_http_field_t *field; - u_char buf[UNKNOWN_STATUS_LENGTH]; - - static const char chunked[] = "Transfer-Encoding: chunked\r\n"; - static const char websocket_version[] = "Sec-WebSocket-Version: 13\r\n"; - - static const nxt_str_t connection[3] = { - nxt_string("Connection: close\r\n"), - nxt_string("Connection: keep-alive\r\n"), - nxt_string("Upgrade: websocket\r\n" - "Connection: Upgrade\r\n" - "Sec-WebSocket-Accept: "), - }; - - nxt_debug(task, "h1p request header send"); - - r->header_sent = 1; - h1p = r->proto.h1; - n = r->status; - - if (n >= NXT_HTTP_CONTINUE && n <= NXT_HTTP_LAST_INFORMATIONAL) { - status = &nxt_http_informational[n - NXT_HTTP_CONTINUE]; - - } else if (n >= NXT_HTTP_OK && n <= NXT_HTTP_LAST_SUCCESS) { - status = &nxt_http_success[n - NXT_HTTP_OK]; - - } else if (n >= NXT_HTTP_MULTIPLE_CHOICES - && n <= NXT_HTTP_LAST_REDIRECTION) - { - status = &nxt_http_redirection[n - NXT_HTTP_MULTIPLE_CHOICES]; - - } else if (n >= NXT_HTTP_BAD_REQUEST && n <= NXT_HTTP_LAST_CLIENT_ERROR) { - status = &nxt_http_client_error[n - NXT_HTTP_BAD_REQUEST]; +static void nxt_h1p_request_header_send(nxt_task_t *task, nxt_http_request_t *r, + nxt_work_handler_t body_handler, + void *data) { + u_char *p; + size_t size; + nxt_buf_t *header; + nxt_str_t unknown_status; + nxt_int_t conn; + nxt_uint_t n; + nxt_bool_t http11; + nxt_conn_t *c; + nxt_h1proto_t *h1p; + const nxt_str_t *status; + nxt_http_field_t *field; + u_char buf[UNKNOWN_STATUS_LENGTH]; - } else if (n >= NXT_HTTP_TO_HTTPS && n <= NXT_HTTP_LAST_NGINX_ERROR) { - status = &nxt_http_nginx_error[n - NXT_HTTP_TO_HTTPS]; + static const char chunked[] = "Transfer-Encoding: chunked\r\n"; + static const char websocket_version[] = "Sec-WebSocket-Version: 13\r\n"; - } else if (n >= NXT_HTTP_INTERNAL_SERVER_ERROR - && n <= NXT_HTTP_LAST_SERVER_ERROR) - { - status = &nxt_http_server_error[n - NXT_HTTP_INTERNAL_SERVER_ERROR]; + static const nxt_str_t connection[3] = { + nxt_string("Connection: close\r\n"), + nxt_string("Connection: keep-alive\r\n"), + nxt_string("Upgrade: websocket\r\n" + "Connection: Upgrade\r\n" + "Sec-WebSocket-Accept: "), + }; - } else if (n <= NXT_HTTP_STATUS_MAX) { - (void) nxt_sprintf(buf, buf + UNKNOWN_STATUS_LENGTH, - "HTTP/1.1 %03d \r\n", n); + nxt_debug(task, "h1p request header send"); - unknown_status.length = UNKNOWN_STATUS_LENGTH; - unknown_status.start = buf; - status = &unknown_status; + r->header_sent = 1; + h1p = r->proto.h1; + n = r->status; - } else { - status = &nxt_http_server_error[0]; - } + if (n >= NXT_HTTP_CONTINUE && n <= NXT_HTTP_LAST_INFORMATIONAL) { + status = &nxt_http_informational[n - NXT_HTTP_CONTINUE]; - size = status->length; - /* Trailing CRLF at the end of header. */ - size += nxt_length("\r\n"); + } else if (n >= NXT_HTTP_OK && n <= NXT_HTTP_LAST_SUCCESS) { + status = &nxt_http_success[n - NXT_HTTP_OK]; - conn = -1; + } else if (n >= NXT_HTTP_MULTIPLE_CHOICES && n <= NXT_HTTP_LAST_REDIRECTION) { + status = &nxt_http_redirection[n - NXT_HTTP_MULTIPLE_CHOICES]; - if (r->websocket_handshake && n == NXT_HTTP_SWITCHING_PROTOCOLS) { - h1p->websocket = 1; - h1p->keepalive = 0; - conn = 2; - size += NXT_WEBSOCKET_ACCEPT_SIZE + 2; + } else if (n >= NXT_HTTP_BAD_REQUEST && n <= NXT_HTTP_LAST_CLIENT_ERROR) { + status = &nxt_http_client_error[n - NXT_HTTP_BAD_REQUEST]; - } else { - http11 = nxt_h1p_is_http11(h1p); - - if (r->resp.content_length == NULL || r->resp.content_length->skip) { - - if (http11) { - if (n != NXT_HTTP_NOT_MODIFIED - && n != NXT_HTTP_NO_CONTENT - && body_handler != NULL - && !h1p->websocket) - { - h1p->chunked = 1; - size += nxt_length(chunked); - /* Trailing CRLF will be added by the first chunk header. */ - size -= nxt_length("\r\n"); - } - - } else { - h1p->keepalive = 0; - } - } + } else if (n >= NXT_HTTP_TO_HTTPS && n <= NXT_HTTP_LAST_NGINX_ERROR) { + status = &nxt_http_nginx_error[n - NXT_HTTP_TO_HTTPS]; - if (http11 ^ h1p->keepalive) { - conn = h1p->keepalive; - } - } + } else if (n >= NXT_HTTP_INTERNAL_SERVER_ERROR && + n <= NXT_HTTP_LAST_SERVER_ERROR) { + status = &nxt_http_server_error[n - NXT_HTTP_INTERNAL_SERVER_ERROR]; - if (conn >= 0) { - size += connection[conn].length; - } + } else if (n <= NXT_HTTP_STATUS_MAX) { + (void)nxt_sprintf(buf, buf + UNKNOWN_STATUS_LENGTH, "HTTP/1.1 %03d \r\n", + n); - nxt_list_each(field, r->resp.fields) { + unknown_status.length = UNKNOWN_STATUS_LENGTH; + unknown_status.start = buf; + status = &unknown_status; - if (!field->skip) { - size += field->name_length + field->value_length; - size += nxt_length(": \r\n"); - } + } else { + status = &nxt_http_server_error[0]; + } - } nxt_list_loop; + size = status->length; + /* Trailing CRLF at the end of header. */ + size += nxt_length("\r\n"); - if (nxt_slow_path(n == NXT_HTTP_UPGRADE_REQUIRED)) { - size += nxt_length(websocket_version); - } + conn = -1; - header = nxt_http_buf_mem(task, r, size); - if (nxt_slow_path(header == NULL)) { - nxt_h1p_request_error(task, h1p, r); - return; - } + if (r->websocket_handshake && n == NXT_HTTP_SWITCHING_PROTOCOLS) { + h1p->websocket = 1; + h1p->keepalive = 0; + conn = 2; + size += NXT_WEBSOCKET_ACCEPT_SIZE + 2; - p = nxt_cpymem(header->mem.free, status->start, status->length); + } else { + http11 = nxt_h1p_is_http11(h1p); - nxt_list_each(field, r->resp.fields) { + if (r->resp.content_length == NULL || r->resp.content_length->skip) { - if (!field->skip) { - p = nxt_cpymem(p, field->name, field->name_length); - *p++ = ':'; *p++ = ' '; - p = nxt_cpymem(p, field->value, field->value_length); - *p++ = '\r'; *p++ = '\n'; + if (http11) { + if (n != NXT_HTTP_NOT_MODIFIED && n != NXT_HTTP_NO_CONTENT && + body_handler != NULL && !h1p->websocket) { + h1p->chunked = 1; + size += nxt_length(chunked); + /* Trailing CRLF will be added by the first chunk header. */ + size -= nxt_length("\r\n"); } - } nxt_list_loop; + } else { + h1p->keepalive = 0; + } + } - if (conn >= 0) { - p = nxt_cpymem(p, connection[conn].start, connection[conn].length); + if (http11 ^ h1p->keepalive) { + conn = h1p->keepalive; } + } - if (h1p->websocket) { - nxt_websocket_accept(p, h1p->websocket_key->value); - p += NXT_WEBSOCKET_ACCEPT_SIZE; + if (conn >= 0) { + size += connection[conn].length; + } - *p++ = '\r'; *p++ = '\n'; - } + nxt_list_each(field, r->resp.fields) { - if (nxt_slow_path(n == NXT_HTTP_UPGRADE_REQUIRED)) { - p = nxt_cpymem(p, websocket_version, nxt_length(websocket_version)); + if (!field->skip) { + size += field->name_length + field->value_length; + size += nxt_length(": \r\n"); } + } + nxt_list_loop; - if (h1p->chunked) { - p = nxt_cpymem(p, chunked, nxt_length(chunked)); - /* Trailing CRLF will be added by the first chunk header. */ + if (nxt_slow_path(n == NXT_HTTP_UPGRADE_REQUIRED)) { + size += nxt_length(websocket_version); + } - } else { - *p++ = '\r'; *p++ = '\n'; + header = nxt_http_buf_mem(task, r, size); + if (nxt_slow_path(header == NULL)) { + nxt_h1p_request_error(task, h1p, r); + return; + } + + p = nxt_cpymem(header->mem.free, status->start, status->length); + + nxt_list_each(field, r->resp.fields) { + + if (!field->skip) { + p = nxt_cpymem(p, field->name, field->name_length); + *p++ = ':'; + *p++ = ' '; + p = nxt_cpymem(p, field->value, field->value_length); + *p++ = '\r'; + *p++ = '\n'; } + } + nxt_list_loop; - header->mem.free = p; + if (conn >= 0) { + p = nxt_cpymem(p, connection[conn].start, connection[conn].length); + } - h1p->header_size = nxt_buf_mem_used_size(&header->mem); + if (h1p->websocket) { + nxt_websocket_accept(p, h1p->websocket_key->value); + p += NXT_WEBSOCKET_ACCEPT_SIZE; - c = h1p->conn; + *p++ = '\r'; + *p++ = '\n'; + } - c->write = header; - h1p->conn_write_tail = &header->next; - c->write_state = &nxt_h1p_request_send_state; + if (nxt_slow_path(n == NXT_HTTP_UPGRADE_REQUIRED)) { + p = nxt_cpymem(p, websocket_version, nxt_length(websocket_version)); + } - if (body_handler != NULL) { - /* - * The body handler will run before c->io->write() handler, - * because the latter was inqueued by nxt_conn_write() - * in engine->write_work_queue. - */ - nxt_work_queue_add(&task->thread->engine->fast_work_queue, - body_handler, task, r, data); + if (h1p->chunked) { + p = nxt_cpymem(p, chunked, nxt_length(chunked)); + /* Trailing CRLF will be added by the first chunk header. */ - } else { - header->next = nxt_http_buf_last(r); - } + } else { + *p++ = '\r'; + *p++ = '\n'; + } - nxt_conn_write(task->thread->engine, c); + header->mem.free = p; - if (h1p->websocket) { - nxt_h1p_websocket_first_frame_start(task, r, c->read); - } -} + h1p->header_size = nxt_buf_mem_used_size(&header->mem); + c = h1p->conn; -void -nxt_h1p_complete_buffers(nxt_task_t *task, nxt_h1proto_t *h1p, nxt_bool_t all) -{ - size_t size; - nxt_buf_t *b, *in, *next; - nxt_conn_t *c; + c->write = header; + h1p->conn_write_tail = &header->next; + c->write_state = &nxt_h1p_request_send_state; - nxt_debug(task, "h1p complete buffers"); + if (body_handler != NULL) { + /* + * The body handler will run before c->io->write() handler, + * because the latter was inqueued by nxt_conn_write() + * in engine->write_work_queue. + */ + nxt_work_queue_add(&task->thread->engine->fast_work_queue, body_handler, + task, r, data); - b = h1p->buffers; - c = h1p->conn; - in = c->read; + } else { + header->next = nxt_http_buf_last(r); + } - if (b != NULL) { - if (in == NULL) { - /* A request with large body. */ - in = b; - c->read = in; + nxt_conn_write(task->thread->engine, c); - b = in->next; - in->next = NULL; - } + if (h1p->websocket) { + nxt_h1p_websocket_first_frame_start(task, r, c->read); + } +} - while (b != NULL) { - next = b->next; - b->next = NULL; +void nxt_h1p_complete_buffers(nxt_task_t *task, nxt_h1proto_t *h1p, + nxt_bool_t all) { + size_t size; + nxt_buf_t *b, *in, *next; + nxt_conn_t *c; - b->completion_handler(task, b, b->parent); + nxt_debug(task, "h1p complete buffers"); - b = next; - } + b = h1p->buffers; + c = h1p->conn; + in = c->read; - h1p->buffers = NULL; - h1p->nbuffers = 0; + if (b != NULL) { + if (in == NULL) { + /* A request with large body. */ + in = b; + c->read = in; + + b = in->next; + in->next = NULL; } - if (in != NULL) { - size = nxt_buf_mem_used_size(&in->mem); + while (b != NULL) { + next = b->next; + b->next = NULL; - if (size == 0 || all) { - in->completion_handler(task, in, in->parent); + b->completion_handler(task, b, b->parent); - c->read = NULL; - } + b = next; } -} + h1p->buffers = NULL; + h1p->nbuffers = 0; + } + + if (in != NULL) { + size = nxt_buf_mem_used_size(&in->mem); + + if (size == 0 || all) { + in->completion_handler(task, in, in->parent); + + c->read = NULL; + } + } +} -static const nxt_conn_state_t nxt_h1p_request_send_state - nxt_aligned(64) = -{ +static const nxt_conn_state_t nxt_h1p_request_send_state nxt_aligned(64) = { .ready_handler = nxt_h1p_conn_sent, .error_handler = nxt_h1p_conn_request_error, @@ -1559,383 +1470,342 @@ static const nxt_conn_state_t nxt_h1p_request_send_state .timer_autoreset = 1, }; +static void nxt_h1p_request_send(nxt_task_t *task, nxt_http_request_t *r, + nxt_buf_t *out) { + nxt_conn_t *c; + nxt_h1proto_t *h1p; -static void -nxt_h1p_request_send(nxt_task_t *task, nxt_http_request_t *r, nxt_buf_t *out) -{ - nxt_conn_t *c; - nxt_h1proto_t *h1p; - - nxt_debug(task, "h1p request send"); + nxt_debug(task, "h1p request send"); - h1p = r->proto.h1; - c = h1p->conn; + h1p = r->proto.h1; + c = h1p->conn; - if (h1p->chunked) { - out = nxt_h1p_chunk_create(task, r, out); - if (nxt_slow_path(out == NULL)) { - nxt_h1p_request_error(task, h1p, r); - return; - } + if (h1p->chunked) { + out = nxt_h1p_chunk_create(task, r, out); + if (nxt_slow_path(out == NULL)) { + nxt_h1p_request_error(task, h1p, r); + return; } + } - if (c->write == NULL) { - c->write = out; - c->write_state = &nxt_h1p_request_send_state; + if (c->write == NULL) { + c->write = out; + c->write_state = &nxt_h1p_request_send_state; - nxt_conn_write(task->thread->engine, c); + nxt_conn_write(task->thread->engine, c); - } else { - *h1p->conn_write_tail = out; - } + } else { + *h1p->conn_write_tail = out; + } - while (out->next != NULL) { - out = out->next; - } + while (out->next != NULL) { + out = out->next; + } - h1p->conn_write_tail = &out->next; + h1p->conn_write_tail = &out->next; } +static nxt_buf_t *nxt_h1p_chunk_create(nxt_task_t *task, nxt_http_request_t *r, + nxt_buf_t *out) { + nxt_off_t size; + nxt_buf_t *b, **prev, *header, *tail; -static nxt_buf_t * -nxt_h1p_chunk_create(nxt_task_t *task, nxt_http_request_t *r, nxt_buf_t *out) -{ - nxt_off_t size; - nxt_buf_t *b, **prev, *header, *tail; - - const size_t chunk_size = 2 * nxt_length("\r\n") + NXT_OFF_T_HEXLEN; - static const char tail_chunk[] = "\r\n0\r\n\r\n"; - - size = 0; - prev = &out; + const size_t chunk_size = 2 * nxt_length("\r\n") + NXT_OFF_T_HEXLEN; + static const char tail_chunk[] = "\r\n0\r\n\r\n"; - for (b = out; b != NULL; b = b->next) { + size = 0; + prev = &out; - if (nxt_buf_is_last(b)) { - tail = nxt_http_buf_mem(task, r, sizeof(tail_chunk)); - if (nxt_slow_path(tail == NULL)) { - return NULL; - } + for (b = out; b != NULL; b = b->next) { - *prev = tail; - tail->next = b; - /* - * The tail_chunk size with trailing zero is 8 bytes, so - * memcpy may be inlined with just single 8 byte move operation. - */ - nxt_memcpy(tail->mem.free, tail_chunk, sizeof(tail_chunk)); - tail->mem.free += nxt_length(tail_chunk); + if (nxt_buf_is_last(b)) { + tail = nxt_http_buf_mem(task, r, sizeof(tail_chunk)); + if (nxt_slow_path(tail == NULL)) { + return NULL; + } - break; - } + *prev = tail; + tail->next = b; + /* + * The tail_chunk size with trailing zero is 8 bytes, so + * memcpy may be inlined with just single 8 byte move operation. + */ + nxt_memcpy(tail->mem.free, tail_chunk, sizeof(tail_chunk)); + tail->mem.free += nxt_length(tail_chunk); - size += nxt_buf_used_size(b); - prev = &b->next; + break; } - if (size == 0) { - return out; - } + size += nxt_buf_used_size(b); + prev = &b->next; + } - header = nxt_http_buf_mem(task, r, chunk_size); - if (nxt_slow_path(header == NULL)) { - return NULL; - } + if (size == 0) { + return out; + } - header->next = out; - header->mem.free = nxt_sprintf(header->mem.free, header->mem.end, - "\r\n%xO\r\n", size); - return header; -} + header = nxt_http_buf_mem(task, r, chunk_size); + if (nxt_slow_path(header == NULL)) { + return NULL; + } + header->next = out; + header->mem.free = + nxt_sprintf(header->mem.free, header->mem.end, "\r\n%xO\r\n", size); + return header; +} -static nxt_off_t -nxt_h1p_request_body_bytes_sent(nxt_task_t *task, nxt_http_proto_t proto) -{ - nxt_off_t sent; - nxt_h1proto_t *h1p; +static nxt_off_t nxt_h1p_request_body_bytes_sent(nxt_task_t *task, + nxt_http_proto_t proto) { + nxt_off_t sent; + nxt_h1proto_t *h1p; - h1p = proto.h1; + h1p = proto.h1; - sent = h1p->conn->sent - h1p->header_size; + sent = h1p->conn->sent - h1p->header_size; - return (sent > 0) ? sent : 0; + return (sent > 0) ? sent : 0; } +static void nxt_h1p_request_discard(nxt_task_t *task, nxt_http_request_t *r, + nxt_buf_t *last) { + nxt_buf_t *b; + nxt_conn_t *c; + nxt_h1proto_t *h1p; + nxt_work_queue_t *wq; -static void -nxt_h1p_request_discard(nxt_task_t *task, nxt_http_request_t *r, - nxt_buf_t *last) -{ - nxt_buf_t *b; - nxt_conn_t *c; - nxt_h1proto_t *h1p; - nxt_work_queue_t *wq; - - nxt_debug(task, "h1p request discard"); + nxt_debug(task, "h1p request discard"); - h1p = r->proto.h1; - h1p->keepalive = 0; + h1p = r->proto.h1; + h1p->keepalive = 0; - c = h1p->conn; - b = c->write; - c->write = NULL; + c = h1p->conn; + b = c->write; + c->write = NULL; - wq = &task->thread->engine->fast_work_queue; + wq = &task->thread->engine->fast_work_queue; - nxt_sendbuf_drain(task, wq, b); - nxt_sendbuf_drain(task, wq, last); + nxt_sendbuf_drain(task, wq, b); + nxt_sendbuf_drain(task, wq, last); } +static void nxt_h1p_conn_request_error(nxt_task_t *task, void *obj, + void *data) { + nxt_h1proto_t *h1p; + nxt_http_request_t *r; -static void -nxt_h1p_conn_request_error(nxt_task_t *task, void *obj, void *data) -{ - nxt_h1proto_t *h1p; - nxt_http_request_t *r; - - h1p = data; + h1p = data; - nxt_debug(task, "h1p conn request error"); + nxt_debug(task, "h1p conn request error"); - r = h1p->request; + r = h1p->request; - if (nxt_slow_path(r == NULL)) { - nxt_h1p_shutdown(task, h1p->conn); - return; - } + if (nxt_slow_path(r == NULL)) { + nxt_h1p_shutdown(task, h1p->conn); + return; + } - if (r->fields == NULL) { - (void) nxt_h1p_header_process(task, h1p, r); - } + if (r->fields == NULL) { + (void)nxt_h1p_header_process(task, h1p, r); + } - if (r->status == 0) { - r->status = NXT_HTTP_BAD_REQUEST; - } + if (r->status == 0) { + r->status = NXT_HTTP_BAD_REQUEST; + } - nxt_h1p_request_error(task, h1p, r); + nxt_h1p_request_error(task, h1p, r); } +static void nxt_h1p_conn_request_timeout(nxt_task_t *task, void *obj, + void *data) { + nxt_conn_t *c; + nxt_timer_t *timer; + nxt_h1proto_t *h1p; + nxt_http_request_t *r; -static void -nxt_h1p_conn_request_timeout(nxt_task_t *task, void *obj, void *data) -{ - nxt_conn_t *c; - nxt_timer_t *timer; - nxt_h1proto_t *h1p; - nxt_http_request_t *r; - - timer = obj; + timer = obj; - nxt_debug(task, "h1p conn request timeout"); + nxt_debug(task, "h1p conn request timeout"); - c = nxt_read_timer_conn(timer); - c->block_read = 1; - /* - * Disable SO_LINGER off during socket closing - * to send "408 Request Timeout" error response. - */ - c->socket.timedout = 0; + c = nxt_read_timer_conn(timer); + c->block_read = 1; + /* + * Disable SO_LINGER off during socket closing + * to send "408 Request Timeout" error response. + */ + c->socket.timedout = 0; - h1p = c->socket.data; - h1p->keepalive = 0; - r = h1p->request; + h1p = c->socket.data; + h1p->keepalive = 0; + r = h1p->request; - if (r->fields == NULL) { - (void) nxt_h1p_header_process(task, h1p, r); - } + if (r->fields == NULL) { + (void)nxt_h1p_header_process(task, h1p, r); + } - nxt_http_request_error(task, r, NXT_HTTP_REQUEST_TIMEOUT); + nxt_http_request_error(task, r, NXT_HTTP_REQUEST_TIMEOUT); } +static void nxt_h1p_conn_request_send_timeout(nxt_task_t *task, void *obj, + void *data) { + nxt_conn_t *c; + nxt_timer_t *timer; + nxt_h1proto_t *h1p; -static void -nxt_h1p_conn_request_send_timeout(nxt_task_t *task, void *obj, void *data) -{ - nxt_conn_t *c; - nxt_timer_t *timer; - nxt_h1proto_t *h1p; - - timer = obj; + timer = obj; - nxt_debug(task, "h1p conn request send timeout"); + nxt_debug(task, "h1p conn request send timeout"); - c = nxt_write_timer_conn(timer); - c->block_write = 1; - h1p = c->socket.data; + c = nxt_write_timer_conn(timer); + c->block_write = 1; + h1p = c->socket.data; - nxt_h1p_request_error(task, h1p, h1p->request); + nxt_h1p_request_error(task, h1p, h1p->request); } +nxt_msec_t nxt_h1p_conn_request_timer_value(nxt_conn_t *c, uintptr_t data) { + nxt_h1proto_t *h1p; -nxt_msec_t -nxt_h1p_conn_request_timer_value(nxt_conn_t *c, uintptr_t data) -{ - nxt_h1proto_t *h1p; - - h1p = c->socket.data; + h1p = c->socket.data; - return nxt_value_at(nxt_msec_t, h1p->request->conf->socket_conf, data); + return nxt_value_at(nxt_msec_t, h1p->request->conf->socket_conf, data); } +nxt_inline void nxt_h1p_request_error(nxt_task_t *task, nxt_h1proto_t *h1p, + nxt_http_request_t *r) { + h1p->keepalive = 0; -nxt_inline void -nxt_h1p_request_error(nxt_task_t *task, nxt_h1proto_t *h1p, - nxt_http_request_t *r) -{ - h1p->keepalive = 0; - - r->state->error_handler(task, r, h1p); + r->state->error_handler(task, r, h1p); } +static void nxt_h1p_request_close(nxt_task_t *task, nxt_http_proto_t proto, + nxt_socket_conf_joint_t *joint) { + nxt_conn_t *c; + nxt_h1proto_t *h1p; -static void -nxt_h1p_request_close(nxt_task_t *task, nxt_http_proto_t proto, - nxt_socket_conf_joint_t *joint) -{ - nxt_conn_t *c; - nxt_h1proto_t *h1p; + nxt_debug(task, "h1p request close"); - nxt_debug(task, "h1p request close"); + h1p = proto.h1; + h1p->keepalive &= !h1p->request->inconsistent; + h1p->request = NULL; - h1p = proto.h1; - h1p->keepalive &= !h1p->request->inconsistent; - h1p->request = NULL; + nxt_router_conf_release(task, joint); - nxt_router_conf_release(task, joint); + c = h1p->conn; + task = &c->task; + c->socket.task = task; + c->read_timer.task = task; + c->write_timer.task = task; - c = h1p->conn; - task = &c->task; - c->socket.task = task; - c->read_timer.task = task; - c->write_timer.task = task; - - if (h1p->keepalive) { - nxt_h1p_keepalive(task, h1p, c); + if (h1p->keepalive) { + nxt_h1p_keepalive(task, h1p, c); - } else { - nxt_h1p_shutdown(task, c); - } + } else { + nxt_h1p_shutdown(task, c); + } } +static void nxt_h1p_conn_sent(nxt_task_t *task, void *obj, void *data) { + nxt_conn_t *c; + nxt_event_engine_t *engine; -static void -nxt_h1p_conn_sent(nxt_task_t *task, void *obj, void *data) -{ - nxt_conn_t *c; - nxt_event_engine_t *engine; + c = obj; - c = obj; + nxt_debug(task, "h1p conn sent"); - nxt_debug(task, "h1p conn sent"); + engine = task->thread->engine; - engine = task->thread->engine; - - c->write = nxt_sendbuf_completion(task, &engine->fast_work_queue, c->write); + c->write = nxt_sendbuf_completion(task, &engine->fast_work_queue, c->write); - if (c->write != NULL) { - nxt_conn_write(engine, c); - } + if (c->write != NULL) { + nxt_conn_write(engine, c); + } } +static void nxt_h1p_conn_close(nxt_task_t *task, void *obj, void *data) { + nxt_conn_t *c; -static void -nxt_h1p_conn_close(nxt_task_t *task, void *obj, void *data) -{ - nxt_conn_t *c; + c = obj; - c = obj; + nxt_debug(task, "h1p conn close"); - nxt_debug(task, "h1p conn close"); + nxt_conn_active(task->thread->engine, c); - nxt_conn_active(task->thread->engine, c); - - nxt_h1p_shutdown(task, c); + nxt_h1p_shutdown(task, c); } +static void nxt_h1p_conn_error(nxt_task_t *task, void *obj, void *data) { + nxt_conn_t *c; -static void -nxt_h1p_conn_error(nxt_task_t *task, void *obj, void *data) -{ - nxt_conn_t *c; + c = obj; - c = obj; + nxt_debug(task, "h1p conn error"); - nxt_debug(task, "h1p conn error"); + nxt_conn_active(task->thread->engine, c); - nxt_conn_active(task->thread->engine, c); - - nxt_h1p_shutdown(task, c); + nxt_h1p_shutdown(task, c); } +static nxt_msec_t nxt_h1p_conn_timer_value(nxt_conn_t *c, uintptr_t data) { + nxt_socket_conf_joint_t *joint; -static nxt_msec_t -nxt_h1p_conn_timer_value(nxt_conn_t *c, uintptr_t data) -{ - nxt_socket_conf_joint_t *joint; + joint = c->listen->socket.data; - joint = c->listen->socket.data; + if (nxt_fast_path(joint != NULL)) { + return nxt_value_at(nxt_msec_t, joint->socket_conf, data); + } - if (nxt_fast_path(joint != NULL)) { - return nxt_value_at(nxt_msec_t, joint->socket_conf, data); - } - - /* - * Listening socket had been closed while - * connection was in keep-alive state. - */ - return 1; + /* + * Listening socket had been closed while + * connection was in keep-alive state. + */ + return 1; } +static void nxt_h1p_keepalive(nxt_task_t *task, nxt_h1proto_t *h1p, + nxt_conn_t *c) { + size_t size; + nxt_buf_t *in; + nxt_event_engine_t *engine; -static void -nxt_h1p_keepalive(nxt_task_t *task, nxt_h1proto_t *h1p, nxt_conn_t *c) -{ - size_t size; - nxt_buf_t *in; - nxt_event_engine_t *engine; - - nxt_debug(task, "h1p keepalive"); + nxt_debug(task, "h1p keepalive"); - if (!c->tcp_nodelay) { - nxt_conn_tcp_nodelay_on(task, c); - } + if (!c->tcp_nodelay) { + nxt_conn_tcp_nodelay_on(task, c); + } - nxt_h1p_complete_buffers(task, h1p, 0); + nxt_h1p_complete_buffers(task, h1p, 0); - in = c->read; + in = c->read; - nxt_memzero(h1p, offsetof(nxt_h1proto_t, conn)); + nxt_memzero(h1p, offsetof(nxt_h1proto_t, conn)); - c->sent = 0; + c->sent = 0; - engine = task->thread->engine; + engine = task->thread->engine; - nxt_conn_idle(engine, c); + nxt_conn_idle(engine, c); - if (in == NULL) { - c->read_state = &nxt_h1p_keepalive_state; + if (in == NULL) { + c->read_state = &nxt_h1p_keepalive_state; - nxt_conn_read(engine, c); + nxt_conn_read(engine, c); - } else { - size = nxt_buf_mem_used_size(&in->mem); + } else { + size = nxt_buf_mem_used_size(&in->mem); - nxt_debug(task, "h1p pipelining"); + nxt_debug(task, "h1p pipelining"); - nxt_memmove(in->mem.start, in->mem.pos, size); + nxt_memmove(in->mem.start, in->mem.pos, size); - in->mem.pos = in->mem.start; - in->mem.free = in->mem.start + size; + in->mem.pos = in->mem.start; + in->mem.free = in->mem.start + size; - nxt_h1p_conn_request_init(task, c, c->socket.data); - } + nxt_h1p_conn_request_init(task, c, c->socket.data); + } } - -static const nxt_conn_state_t nxt_h1p_keepalive_state - nxt_aligned(64) = -{ +static const nxt_conn_state_t nxt_h1p_keepalive_state nxt_aligned(64) = { .ready_handler = nxt_h1p_conn_request_init, .close_handler = nxt_h1p_conn_close, .error_handler = nxt_h1p_conn_error, @@ -1948,106 +1818,89 @@ static const nxt_conn_state_t nxt_h1p_keepalive_state .timer_autoreset = 1, }; - -const nxt_conn_state_t nxt_h1p_idle_close_state - nxt_aligned(64) = -{ +const nxt_conn_state_t nxt_h1p_idle_close_state nxt_aligned(64) = { .close_handler = nxt_h1p_idle_close, }; +static void nxt_h1p_idle_close(nxt_task_t *task, void *obj, void *data) { + nxt_conn_t *c; -static void -nxt_h1p_idle_close(nxt_task_t *task, void *obj, void *data) -{ - nxt_conn_t *c; - - c = obj; + c = obj; - nxt_debug(task, "h1p idle close"); + nxt_debug(task, "h1p idle close"); - nxt_conn_active(task->thread->engine, c); + nxt_conn_active(task->thread->engine, c); - nxt_h1p_idle_response(task, c); + nxt_h1p_idle_response(task, c); } +static void nxt_h1p_idle_timeout(nxt_task_t *task, void *obj, void *data) { + nxt_conn_t *c; + nxt_timer_t *timer; -static void -nxt_h1p_idle_timeout(nxt_task_t *task, void *obj, void *data) -{ - nxt_conn_t *c; - nxt_timer_t *timer; + timer = obj; - timer = obj; + nxt_debug(task, "h1p idle timeout"); - nxt_debug(task, "h1p idle timeout"); + c = nxt_read_timer_conn(timer); + c->block_read = 1; - c = nxt_read_timer_conn(timer); - c->block_read = 1; + nxt_conn_active(task->thread->engine, c); - nxt_conn_active(task->thread->engine, c); - - nxt_h1p_idle_response(task, c); + nxt_h1p_idle_response(task, c); } +#define NXT_H1P_IDLE_TIMEOUT \ + "HTTP/1.1 408 Request Timeout\r\n" \ + "Server: " NXT_SERVER "\r\n" \ + "Connection: close\r\n" \ + "Content-Length: 0\r\n" \ + "Date: " -#define NXT_H1P_IDLE_TIMEOUT \ - "HTTP/1.1 408 Request Timeout\r\n" \ - "Server: " NXT_SERVER "\r\n" \ - "Connection: close\r\n" \ - "Content-Length: 0\r\n" \ - "Date: " - - -static void -nxt_h1p_idle_response(nxt_task_t *task, nxt_conn_t *c) -{ - u_char *p; - size_t size; - nxt_buf_t *out, *last; +static void nxt_h1p_idle_response(nxt_task_t *task, nxt_conn_t *c) { + u_char *p; + size_t size; + nxt_buf_t *out, *last; - size = nxt_length(NXT_H1P_IDLE_TIMEOUT) - + nxt_http_date_cache.size - + nxt_length("\r\n\r\n"); + size = nxt_length(NXT_H1P_IDLE_TIMEOUT) + nxt_http_date_cache.size + + nxt_length("\r\n\r\n"); - out = nxt_buf_mem_alloc(c->mem_pool, size, 0); - if (nxt_slow_path(out == NULL)) { - goto fail; - } + out = nxt_buf_mem_alloc(c->mem_pool, size, 0); + if (nxt_slow_path(out == NULL)) { + goto fail; + } - p = nxt_cpymem(out->mem.free, NXT_H1P_IDLE_TIMEOUT, - nxt_length(NXT_H1P_IDLE_TIMEOUT)); + p = nxt_cpymem(out->mem.free, NXT_H1P_IDLE_TIMEOUT, + nxt_length(NXT_H1P_IDLE_TIMEOUT)); - p = nxt_thread_time_string(task->thread, &nxt_http_date_cache, p); + p = nxt_thread_time_string(task->thread, &nxt_http_date_cache, p); - out->mem.free = nxt_cpymem(p, "\r\n\r\n", 4); + out->mem.free = nxt_cpymem(p, "\r\n\r\n", 4); - last = nxt_mp_zget(c->mem_pool, NXT_BUF_SYNC_SIZE); - if (nxt_slow_path(last == NULL)) { - goto fail; - } + last = nxt_mp_zget(c->mem_pool, NXT_BUF_SYNC_SIZE); + if (nxt_slow_path(last == NULL)) { + goto fail; + } - out->next = last; - nxt_buf_set_sync(last); - nxt_buf_set_last(last); + out->next = last; + nxt_buf_set_sync(last); + nxt_buf_set_last(last); - last->completion_handler = nxt_h1p_idle_response_sent; - last->parent = c; + last->completion_handler = nxt_h1p_idle_response_sent; + last->parent = c; - c->write = out; - c->write_state = &nxt_h1p_timeout_response_state; + c->write = out; + c->write_state = &nxt_h1p_timeout_response_state; - nxt_conn_write(task->thread->engine, c); - return; + nxt_conn_write(task->thread->engine, c); + return; fail: - nxt_h1p_shutdown(task, c); + nxt_h1p_shutdown(task, c); } - -static const nxt_conn_state_t nxt_h1p_timeout_response_state - nxt_aligned(64) = -{ +static const nxt_conn_state_t nxt_h1p_timeout_response_state nxt_aligned(64) = { .ready_handler = nxt_h1p_conn_sent, .error_handler = nxt_h1p_idle_response_error, @@ -2055,131 +1908,111 @@ static const nxt_conn_state_t nxt_h1p_timeout_response_state .timer_value = nxt_h1p_idle_response_timer_value, }; +static void nxt_h1p_idle_response_sent(nxt_task_t *task, void *obj, + void *data) { + nxt_conn_t *c; -static void -nxt_h1p_idle_response_sent(nxt_task_t *task, void *obj, void *data) -{ - nxt_conn_t *c; - - c = data; + c = data; - nxt_debug(task, "h1p idle timeout response sent"); + nxt_debug(task, "h1p idle timeout response sent"); - nxt_h1p_shutdown(task, c); + nxt_h1p_shutdown(task, c); } +static void nxt_h1p_idle_response_error(nxt_task_t *task, void *obj, + void *data) { + nxt_conn_t *c; -static void -nxt_h1p_idle_response_error(nxt_task_t *task, void *obj, void *data) -{ - nxt_conn_t *c; - - c = obj; + c = obj; - nxt_debug(task, "h1p response error"); + nxt_debug(task, "h1p response error"); - nxt_h1p_shutdown(task, c); + nxt_h1p_shutdown(task, c); } +static void nxt_h1p_idle_response_timeout(nxt_task_t *task, void *obj, + void *data) { + nxt_conn_t *c; + nxt_timer_t *timer; -static void -nxt_h1p_idle_response_timeout(nxt_task_t *task, void *obj, void *data) -{ - nxt_conn_t *c; - nxt_timer_t *timer; - - timer = obj; + timer = obj; - nxt_debug(task, "h1p idle timeout response timeout"); + nxt_debug(task, "h1p idle timeout response timeout"); - c = nxt_read_timer_conn(timer); - c->block_write = 1; + c = nxt_read_timer_conn(timer); + c->block_write = 1; - nxt_h1p_shutdown(task, c); + nxt_h1p_shutdown(task, c); } - -static nxt_msec_t -nxt_h1p_idle_response_timer_value(nxt_conn_t *c, uintptr_t data) -{ - return 10 * 1000; +static nxt_msec_t nxt_h1p_idle_response_timer_value(nxt_conn_t *c, + uintptr_t data) { + return 10 * 1000; } +static void nxt_h1p_shutdown(nxt_task_t *task, nxt_conn_t *c) { + nxt_timer_t *timer; + nxt_h1proto_t *h1p; -static void -nxt_h1p_shutdown(nxt_task_t *task, nxt_conn_t *c) -{ - nxt_timer_t *timer; - nxt_h1proto_t *h1p; - - nxt_debug(task, "h1p shutdown"); + nxt_debug(task, "h1p shutdown"); - h1p = c->socket.data; + h1p = c->socket.data; - if (h1p != NULL) { - nxt_h1p_complete_buffers(task, h1p, 1); + if (h1p != NULL) { + nxt_h1p_complete_buffers(task, h1p, 1); - if (nxt_slow_path(h1p->websocket_timer != NULL)) { - timer = &h1p->websocket_timer->timer; + if (nxt_slow_path(h1p->websocket_timer != NULL)) { + timer = &h1p->websocket_timer->timer; - if (timer->handler != nxt_h1p_conn_ws_shutdown) { - timer->handler = nxt_h1p_conn_ws_shutdown; - nxt_timer_add(task->thread->engine, timer, 0); + if (timer->handler != nxt_h1p_conn_ws_shutdown) { + timer->handler = nxt_h1p_conn_ws_shutdown; + nxt_timer_add(task->thread->engine, timer, 0); - } else { - nxt_debug(task, "h1p already scheduled ws shutdown"); - } + } else { + nxt_debug(task, "h1p already scheduled ws shutdown"); + } - return; - } + return; } + } - nxt_h1p_closing(task, c); + nxt_h1p_closing(task, c); } +static void nxt_h1p_conn_ws_shutdown(nxt_task_t *task, void *obj, void *data) { + nxt_timer_t *timer; + nxt_h1p_websocket_timer_t *ws_timer; -static void -nxt_h1p_conn_ws_shutdown(nxt_task_t *task, void *obj, void *data) -{ - nxt_timer_t *timer; - nxt_h1p_websocket_timer_t *ws_timer; - - nxt_debug(task, "h1p conn ws shutdown"); + nxt_debug(task, "h1p conn ws shutdown"); - timer = obj; - ws_timer = nxt_timer_data(timer, nxt_h1p_websocket_timer_t, timer); + timer = obj; + ws_timer = nxt_timer_data(timer, nxt_h1p_websocket_timer_t, timer); - nxt_h1p_closing(task, ws_timer->h1p->conn); + nxt_h1p_closing(task, ws_timer->h1p->conn); } +static void nxt_h1p_closing(nxt_task_t *task, nxt_conn_t *c) { + nxt_debug(task, "h1p closing"); -static void -nxt_h1p_closing(nxt_task_t *task, nxt_conn_t *c) -{ - nxt_debug(task, "h1p closing"); - - c->socket.data = NULL; + c->socket.data = NULL; #if (NXT_TLS) - if (c->u.tls != NULL) { - c->write_state = &nxt_h1p_shutdown_state; + if (c->u.tls != NULL) { + c->write_state = &nxt_h1p_shutdown_state; - c->io->shutdown(task, c, NULL); - return; - } + c->io->shutdown(task, c, NULL); + return; + } #endif - nxt_h1p_conn_closing(task, c, NULL); + nxt_h1p_conn_closing(task, c, NULL); } - #if (NXT_TLS) -static const nxt_conn_state_t nxt_h1p_shutdown_state - nxt_aligned(64) = -{ +static const nxt_conn_state_t nxt_h1p_shutdown_state nxt_aligned(64) = { .ready_handler = nxt_h1p_conn_closing, .close_handler = nxt_h1p_conn_closing, .error_handler = nxt_h1p_conn_closing, @@ -2187,133 +2020,118 @@ static const nxt_conn_state_t nxt_h1p_shutdown_state #endif +static void nxt_h1p_conn_closing(nxt_task_t *task, void *obj, void *data) { + nxt_conn_t *c; -static void -nxt_h1p_conn_closing(nxt_task_t *task, void *obj, void *data) -{ - nxt_conn_t *c; + c = obj; - c = obj; + nxt_debug(task, "h1p conn closing"); - nxt_debug(task, "h1p conn closing"); + c->write_state = &nxt_h1p_close_state; - c->write_state = &nxt_h1p_close_state; - - nxt_conn_close(task->thread->engine, c); + nxt_conn_close(task->thread->engine, c); } - -static const nxt_conn_state_t nxt_h1p_close_state - nxt_aligned(64) = -{ +static const nxt_conn_state_t nxt_h1p_close_state nxt_aligned(64) = { .ready_handler = nxt_h1p_conn_free, }; +static void nxt_h1p_conn_free(nxt_task_t *task, void *obj, void *data) { + nxt_conn_t *c; + nxt_listen_event_t *lev; + nxt_event_engine_t *engine; -static void -nxt_h1p_conn_free(nxt_task_t *task, void *obj, void *data) -{ - nxt_conn_t *c; - nxt_listen_event_t *lev; - nxt_event_engine_t *engine; + c = obj; - c = obj; + nxt_debug(task, "h1p conn free"); - nxt_debug(task, "h1p conn free"); - - engine = task->thread->engine; + engine = task->thread->engine; - nxt_sockaddr_cache_free(engine, c); + nxt_sockaddr_cache_free(engine, c); - lev = c->listen; + lev = c->listen; - nxt_conn_free(task, c); + nxt_conn_free(task, c); - nxt_router_listen_event_release(&engine->task, lev, NULL); + nxt_router_listen_event_release(&engine->task, lev, NULL); } +static void nxt_h1p_peer_connect(nxt_task_t *task, nxt_http_peer_t *peer) { + nxt_mp_t *mp; + nxt_int_t ret; + nxt_conn_t *c, *client; + nxt_h1proto_t *h1p; + nxt_fd_event_t *socket; + nxt_work_queue_t *wq; + nxt_http_request_t *r; -static void -nxt_h1p_peer_connect(nxt_task_t *task, nxt_http_peer_t *peer) -{ - nxt_mp_t *mp; - nxt_int_t ret; - nxt_conn_t *c, *client; - nxt_h1proto_t *h1p; - nxt_fd_event_t *socket; - nxt_work_queue_t *wq; - nxt_http_request_t *r; + nxt_debug(task, "h1p peer connect"); - nxt_debug(task, "h1p peer connect"); + peer->status = NXT_HTTP_UNSET; + r = peer->request; - peer->status = NXT_HTTP_UNSET; - r = peer->request; + mp = nxt_mp_create(1024, 128, 256, 32); - mp = nxt_mp_create(1024, 128, 256, 32); + if (nxt_slow_path(mp == NULL)) { + goto fail; + } - if (nxt_slow_path(mp == NULL)) { - goto fail; - } + h1p = nxt_mp_zalloc(mp, sizeof(nxt_h1proto_t)); + if (nxt_slow_path(h1p == NULL)) { + goto fail; + } - h1p = nxt_mp_zalloc(mp, sizeof(nxt_h1proto_t)); - if (nxt_slow_path(h1p == NULL)) { - goto fail; - } + ret = nxt_http_parse_request_init(&h1p->parser, r->mem_pool); + if (nxt_slow_path(ret != NXT_OK)) { + goto fail; + } - ret = nxt_http_parse_request_init(&h1p->parser, r->mem_pool); - if (nxt_slow_path(ret != NXT_OK)) { - goto fail; - } + c = nxt_conn_create(mp, task); + if (nxt_slow_path(c == NULL)) { + goto fail; + } - c = nxt_conn_create(mp, task); - if (nxt_slow_path(c == NULL)) { - goto fail; - } + c->mem_pool = mp; + h1p->conn = c; - c->mem_pool = mp; - h1p->conn = c; + peer->proto.h1 = h1p; + h1p->request = r; - peer->proto.h1 = h1p; - h1p->request = r; + c->socket.data = peer; + c->remote = peer->server->sockaddr; - c->socket.data = peer; - c->remote = peer->server->sockaddr; + c->socket.write_ready = 1; + c->write_state = &nxt_h1p_peer_connect_state; - c->socket.write_ready = 1; - c->write_state = &nxt_h1p_peer_connect_state; + /* + * TODO: queues should be implemented via client proto interface. + */ + client = r->proto.h1->conn; - /* - * TODO: queues should be implemented via client proto interface. - */ - client = r->proto.h1->conn; + socket = &client->socket; + wq = socket->read_work_queue; + c->read_work_queue = wq; + c->socket.read_work_queue = wq; + c->read_timer.work_queue = wq; - socket = &client->socket; - wq = socket->read_work_queue; - c->read_work_queue = wq; - c->socket.read_work_queue = wq; - c->read_timer.work_queue = wq; + wq = socket->write_work_queue; + c->write_work_queue = wq; + c->socket.write_work_queue = wq; + c->write_timer.work_queue = wq; + /* TODO END */ - wq = socket->write_work_queue; - c->write_work_queue = wq; - c->socket.write_work_queue = wq; - c->write_timer.work_queue = wq; - /* TODO END */ + nxt_conn_connect(task->thread->engine, c); - nxt_conn_connect(task->thread->engine, c); - - return; + return; fail: - peer->status = NXT_HTTP_INTERNAL_SERVER_ERROR; + peer->status = NXT_HTTP_INTERNAL_SERVER_ERROR; - r->state->error_handler(task, r, peer); + r->state->error_handler(task, r, peer); } - -static const nxt_conn_state_t nxt_h1p_peer_connect_state - nxt_aligned(64) = -{ +static const nxt_conn_state_t nxt_h1p_peer_connect_state nxt_aligned(64) = { .ready_handler = nxt_h1p_peer_connected, .close_handler = nxt_h1p_peer_refused, .error_handler = nxt_h1p_peer_error, @@ -2323,201 +2141,188 @@ static const nxt_conn_state_t nxt_h1p_peer_connect_state .timer_data = offsetof(nxt_socket_conf_t, proxy_timeout), }; +static void nxt_h1p_peer_connected(nxt_task_t *task, void *obj, void *data) { + nxt_http_peer_t *peer; + nxt_http_request_t *r; -static void -nxt_h1p_peer_connected(nxt_task_t *task, void *obj, void *data) -{ - nxt_http_peer_t *peer; - nxt_http_request_t *r; - - peer = data; + peer = data; - nxt_debug(task, "h1p peer connected"); + nxt_debug(task, "h1p peer connected"); - r = peer->request; - r->state->ready_handler(task, r, peer); + r = peer->request; + r->state->ready_handler(task, r, peer); } +static void nxt_h1p_peer_refused(nxt_task_t *task, void *obj, void *data) { + nxt_http_peer_t *peer; + nxt_http_request_t *r; -static void -nxt_h1p_peer_refused(nxt_task_t *task, void *obj, void *data) -{ - nxt_http_peer_t *peer; - nxt_http_request_t *r; - - peer = data; + peer = data; - nxt_debug(task, "h1p peer refused"); + nxt_debug(task, "h1p peer refused"); - //peer->status = NXT_HTTP_SERVICE_UNAVAILABLE; - peer->status = NXT_HTTP_BAD_GATEWAY; + // peer->status = NXT_HTTP_SERVICE_UNAVAILABLE; + peer->status = NXT_HTTP_BAD_GATEWAY; - r = peer->request; - r->state->error_handler(task, r, peer); + r = peer->request; + r->state->error_handler(task, r, peer); } +static void nxt_h1p_peer_header_send(nxt_task_t *task, nxt_http_peer_t *peer) { + u_char *p; + size_t size; + nxt_int_t ret; + nxt_str_t target; + nxt_buf_t *header, *body; + nxt_conn_t *c; + nxt_http_field_t *field; + nxt_http_request_t *r; -static void -nxt_h1p_peer_header_send(nxt_task_t *task, nxt_http_peer_t *peer) -{ - u_char *p; - size_t size; - nxt_int_t ret; - nxt_str_t target; - nxt_buf_t *header, *body; - nxt_conn_t *c; - nxt_http_field_t *field; - nxt_http_request_t *r; - - nxt_debug(task, "h1p peer header send"); + nxt_debug(task, "h1p peer header send"); - r = peer->request; + r = peer->request; - ret = nxt_h1p_peer_request_target(r, &target); - if (nxt_slow_path(ret != NXT_OK)) { - goto fail; - } - - size = r->method->length + sizeof(" ") + target.length - + sizeof(" HTTP/1.1\r\n") - + sizeof("Connection: close\r\n") - + sizeof("\r\n"); + ret = nxt_h1p_peer_request_target(r, &target); + if (nxt_slow_path(ret != NXT_OK)) { + goto fail; + } - nxt_list_each(field, r->fields) { - - if (!field->hopbyhop) { - size += field->name_length + field->value_length; - size += nxt_length(": \r\n"); - } + size = r->method->length + sizeof(" ") + target.length + + sizeof(" HTTP/1.1\r\n") + sizeof("Connection: close\r\n") + + sizeof("\r\n"); - } nxt_list_loop; + nxt_list_each(field, r->fields) { - header = nxt_http_buf_mem(task, r, size); - if (nxt_slow_path(header == NULL)) { - goto fail; + if (!field->hopbyhop) { + size += field->name_length + field->value_length; + size += nxt_length(": \r\n"); } + } + nxt_list_loop; - p = header->mem.free; + header = nxt_http_buf_mem(task, r, size); + if (nxt_slow_path(header == NULL)) { + goto fail; + } - p = nxt_cpymem(p, r->method->start, r->method->length); - *p++ = ' '; - p = nxt_cpymem(p, target.start, target.length); - p = nxt_cpymem(p, " HTTP/1.1\r\n", 11); - p = nxt_cpymem(p, "Connection: close\r\n", 19); + p = header->mem.free; - nxt_list_each(field, r->fields) { + p = nxt_cpymem(p, r->method->start, r->method->length); + *p++ = ' '; + p = nxt_cpymem(p, target.start, target.length); + p = nxt_cpymem(p, " HTTP/1.1\r\n", 11); + p = nxt_cpymem(p, "Connection: close\r\n", 19); - if (!field->hopbyhop) { - p = nxt_cpymem(p, field->name, field->name_length); - *p++ = ':'; *p++ = ' '; - p = nxt_cpymem(p, field->value, field->value_length); - *p++ = '\r'; *p++ = '\n'; - } + nxt_list_each(field, r->fields) { - } nxt_list_loop; + if (!field->hopbyhop) { + p = nxt_cpymem(p, field->name, field->name_length); + *p++ = ':'; + *p++ = ' '; + p = nxt_cpymem(p, field->value, field->value_length); + *p++ = '\r'; + *p++ = '\n'; + } + } + nxt_list_loop; - *p++ = '\r'; *p++ = '\n'; - header->mem.free = p; - size = p - header->mem.pos; + *p++ = '\r'; + *p++ = '\n'; + header->mem.free = p; + size = p - header->mem.pos; - c = peer->proto.h1->conn; - c->write = header; - c->write_state = &nxt_h1p_peer_header_send_state; + c = peer->proto.h1->conn; + c->write = header; + c->write_state = &nxt_h1p_peer_header_send_state; - if (r->body != NULL) { - if (nxt_buf_is_file(r->body)) { - body = nxt_buf_file_alloc(r->mem_pool, 0, 0); + if (r->body != NULL) { + if (nxt_buf_is_file(r->body)) { + body = nxt_buf_file_alloc(r->mem_pool, 0, 0); - } else { - body = nxt_buf_mem_alloc(r->mem_pool, 0, 0); - } + } else { + body = nxt_buf_mem_alloc(r->mem_pool, 0, 0); + } - if (nxt_slow_path(body == NULL)) { - goto fail; - } + if (nxt_slow_path(body == NULL)) { + goto fail; + } - header->next = body; + header->next = body; - if (nxt_buf_is_file(r->body)) { - body->file = r->body->file; - body->file_end = r->body->file_end; + if (nxt_buf_is_file(r->body)) { + body->file = r->body->file; + body->file_end = r->body->file_end; - } else { - body->mem = r->body->mem; - } + } else { + body->mem = r->body->mem; + } - size += nxt_buf_used_size(body); + size += nxt_buf_used_size(body); -// nxt_mp_retain(r->mem_pool); - } + // nxt_mp_retain(r->mem_pool); + } - if (size > 16384) { - /* Use proxy_send_timeout instead of proxy_timeout. */ - c->write_state = &nxt_h1p_peer_header_body_send_state; - } + if (size > 16384) { + /* Use proxy_send_timeout instead of proxy_timeout. */ + c->write_state = &nxt_h1p_peer_header_body_send_state; + } - nxt_conn_write(task->thread->engine, c); + nxt_conn_write(task->thread->engine, c); - return; + return; fail: - r->state->error_handler(task, r, peer); + r->state->error_handler(task, r, peer); } +static nxt_int_t nxt_h1p_peer_request_target(nxt_http_request_t *r, + nxt_str_t *target) { + u_char *p; + size_t size, encode; -static nxt_int_t -nxt_h1p_peer_request_target(nxt_http_request_t *r, nxt_str_t *target) -{ - u_char *p; - size_t size, encode; - - if (!r->uri_changed) { - *target = r->target; - return NXT_OK; - } + if (!r->uri_changed) { + *target = r->target; + return NXT_OK; + } - if (!r->quoted_target && r->args->length == 0) { - *target = *r->path; - return NXT_OK; - } + if (!r->quoted_target && r->args->length == 0) { + *target = *r->path; + return NXT_OK; + } - if (r->quoted_target) { - encode = nxt_encode_complex_uri(NULL, r->path->start, - r->path->length); - } else { - encode = 0; - } + if (r->quoted_target) { + encode = nxt_encode_complex_uri(NULL, r->path->start, r->path->length); + } else { + encode = 0; + } - size = r->path->length + encode * 2 + 1 + r->args->length; + size = r->path->length + encode * 2 + 1 + r->args->length; - target->start = nxt_mp_nget(r->mem_pool, size); - if (target->start == NULL) { - return NXT_ERROR; - } + target->start = nxt_mp_nget(r->mem_pool, size); + if (target->start == NULL) { + return NXT_ERROR; + } - if (r->quoted_target) { - p = (u_char *) nxt_encode_complex_uri(target->start, r->path->start, - r->path->length); + if (r->quoted_target) { + p = (u_char *)nxt_encode_complex_uri(target->start, r->path->start, + r->path->length); - } else { - p = nxt_cpymem(target->start, r->path->start, r->path->length); - } + } else { + p = nxt_cpymem(target->start, r->path->start, r->path->length); + } - if (r->args->length > 0) { - *p++ = '?'; - p = nxt_cpymem(p, r->args->start, r->args->length); - } + if (r->args->length > 0) { + *p++ = '?'; + p = nxt_cpymem(p, r->args->start, r->args->length); + } - target->length = p - target->start; + target->length = p - target->start; - return NXT_OK; + return NXT_OK; } - -static const nxt_conn_state_t nxt_h1p_peer_header_send_state - nxt_aligned(64) = -{ +static const nxt_conn_state_t nxt_h1p_peer_header_send_state nxt_aligned(64) = { .ready_handler = nxt_h1p_peer_header_sent, .error_handler = nxt_h1p_peer_error, @@ -2526,70 +2331,59 @@ static const nxt_conn_state_t nxt_h1p_peer_header_send_state .timer_data = offsetof(nxt_socket_conf_t, proxy_timeout), }; +static const nxt_conn_state_t + nxt_h1p_peer_header_body_send_state nxt_aligned(64) = { + .ready_handler = nxt_h1p_peer_header_sent, + .error_handler = nxt_h1p_peer_error, -static const nxt_conn_state_t nxt_h1p_peer_header_body_send_state - nxt_aligned(64) = -{ - .ready_handler = nxt_h1p_peer_header_sent, - .error_handler = nxt_h1p_peer_error, - - .timer_handler = nxt_h1p_peer_send_timeout, - .timer_value = nxt_h1p_peer_timer_value, - .timer_data = offsetof(nxt_socket_conf_t, proxy_send_timeout), - .timer_autoreset = 1, + .timer_handler = nxt_h1p_peer_send_timeout, + .timer_value = nxt_h1p_peer_timer_value, + .timer_data = offsetof(nxt_socket_conf_t, proxy_send_timeout), + .timer_autoreset = 1, }; +static void nxt_h1p_peer_header_sent(nxt_task_t *task, void *obj, void *data) { + nxt_conn_t *c; + nxt_http_peer_t *peer; + nxt_http_request_t *r; + nxt_event_engine_t *engine; -static void -nxt_h1p_peer_header_sent(nxt_task_t *task, void *obj, void *data) -{ - nxt_conn_t *c; - nxt_http_peer_t *peer; - nxt_http_request_t *r; - nxt_event_engine_t *engine; + c = obj; + peer = data; - c = obj; - peer = data; + nxt_debug(task, "h1p peer header sent"); - nxt_debug(task, "h1p peer header sent"); + engine = task->thread->engine; - engine = task->thread->engine; + c->write = nxt_sendbuf_completion(task, &engine->fast_work_queue, c->write); - c->write = nxt_sendbuf_completion(task, &engine->fast_work_queue, c->write); - - if (c->write != NULL) { - nxt_conn_write(engine, c); - return; - } + if (c->write != NULL) { + nxt_conn_write(engine, c); + return; + } - r = peer->request; - r->state->ready_handler(task, r, peer); + r = peer->request; + r->state->ready_handler(task, r, peer); } +static void nxt_h1p_peer_header_read(nxt_task_t *task, nxt_http_peer_t *peer) { + nxt_conn_t *c; -static void -nxt_h1p_peer_header_read(nxt_task_t *task, nxt_http_peer_t *peer) -{ - nxt_conn_t *c; + nxt_debug(task, "h1p peer header read"); - nxt_debug(task, "h1p peer header read"); + c = peer->proto.h1->conn; - c = peer->proto.h1->conn; + if (c->write_timer.enabled) { + c->read_state = &nxt_h1p_peer_header_read_state; - if (c->write_timer.enabled) { - c->read_state = &nxt_h1p_peer_header_read_state; - - } else { - c->read_state = &nxt_h1p_peer_header_read_timer_state; - } + } else { + c->read_state = &nxt_h1p_peer_header_read_timer_state; + } - nxt_conn_read(task->thread->engine, c); + nxt_conn_read(task->thread->engine, c); } - -static const nxt_conn_state_t nxt_h1p_peer_header_read_state - nxt_aligned(64) = -{ +static const nxt_conn_state_t nxt_h1p_peer_header_read_state nxt_aligned(64) = { .ready_handler = nxt_h1p_peer_header_read_done, .close_handler = nxt_h1p_peer_closed, .error_handler = nxt_h1p_peer_error, @@ -2597,218 +2391,201 @@ static const nxt_conn_state_t nxt_h1p_peer_header_read_state .io_read_handler = nxt_h1p_peer_io_read_handler, }; +static const nxt_conn_state_t + nxt_h1p_peer_header_read_timer_state nxt_aligned(64) = { + .ready_handler = nxt_h1p_peer_header_read_done, + .close_handler = nxt_h1p_peer_closed, + .error_handler = nxt_h1p_peer_error, -static const nxt_conn_state_t nxt_h1p_peer_header_read_timer_state - nxt_aligned(64) = -{ - .ready_handler = nxt_h1p_peer_header_read_done, - .close_handler = nxt_h1p_peer_closed, - .error_handler = nxt_h1p_peer_error, - - .io_read_handler = nxt_h1p_peer_io_read_handler, + .io_read_handler = nxt_h1p_peer_io_read_handler, - .timer_handler = nxt_h1p_peer_read_timeout, - .timer_value = nxt_h1p_peer_timer_value, - .timer_data = offsetof(nxt_socket_conf_t, proxy_timeout), + .timer_handler = nxt_h1p_peer_read_timeout, + .timer_value = nxt_h1p_peer_timer_value, + .timer_data = offsetof(nxt_socket_conf_t, proxy_timeout), }; +static ssize_t nxt_h1p_peer_io_read_handler(nxt_task_t *task, nxt_conn_t *c) { + size_t size; + ssize_t n; + nxt_buf_t *b; + nxt_http_peer_t *peer; + nxt_socket_conf_t *skcf; + nxt_http_request_t *r; -static ssize_t -nxt_h1p_peer_io_read_handler(nxt_task_t *task, nxt_conn_t *c) -{ - size_t size; - ssize_t n; - nxt_buf_t *b; - nxt_http_peer_t *peer; - nxt_socket_conf_t *skcf; - nxt_http_request_t *r; - - peer = c->socket.data; - r = peer->request; - b = c->read; + peer = c->socket.data; + r = peer->request; + b = c->read; - if (b == NULL) { - skcf = r->conf->socket_conf; + if (b == NULL) { + skcf = r->conf->socket_conf; - size = (peer->header_received) ? skcf->proxy_buffer_size - : skcf->proxy_header_buffer_size; + size = (peer->header_received) ? skcf->proxy_buffer_size + : skcf->proxy_header_buffer_size; - nxt_debug(task, "h1p peer io read: %z", size); + nxt_debug(task, "h1p peer io read: %z", size); - b = nxt_http_proxy_buf_mem_alloc(task, r, size); - if (nxt_slow_path(b == NULL)) { - c->socket.error = NXT_ENOMEM; - return NXT_ERROR; - } + b = nxt_http_proxy_buf_mem_alloc(task, r, size); + if (nxt_slow_path(b == NULL)) { + c->socket.error = NXT_ENOMEM; + return NXT_ERROR; } + } - n = c->io->recvbuf(c, b); + n = c->io->recvbuf(c, b); - if (n > 0) { - c->read = b; + if (n > 0) { + c->read = b; - } else { - c->read = NULL; - nxt_http_proxy_buf_mem_free(task, r, b); - } + } else { + c->read = NULL; + nxt_http_proxy_buf_mem_free(task, r, b); + } - return n; + return n; } +static void nxt_h1p_peer_header_read_done(nxt_task_t *task, void *obj, + void *data) { + nxt_int_t ret; + nxt_buf_t *b; + nxt_conn_t *c; + nxt_h1proto_t *h1p; + nxt_http_peer_t *peer; + nxt_http_request_t *r; + nxt_event_engine_t *engine; -static void -nxt_h1p_peer_header_read_done(nxt_task_t *task, void *obj, void *data) -{ - nxt_int_t ret; - nxt_buf_t *b; - nxt_conn_t *c; - nxt_h1proto_t *h1p; - nxt_http_peer_t *peer; - nxt_http_request_t *r; - nxt_event_engine_t *engine; - - c = obj; - peer = data; - - nxt_debug(task, "h1p peer header read done"); - - b = c->read; + c = obj; + peer = data; - ret = nxt_h1p_peer_header_parse(peer, &b->mem); + nxt_debug(task, "h1p peer header read done"); - r = peer->request; + b = c->read; - ret = nxt_expect(NXT_DONE, ret); + ret = nxt_h1p_peer_header_parse(peer, &b->mem); - if (ret != NXT_AGAIN) { - engine = task->thread->engine; - nxt_timer_disable(engine, &c->write_timer); - nxt_timer_disable(engine, &c->read_timer); - } + r = peer->request; - switch (ret) { + ret = nxt_expect(NXT_DONE, ret); - case NXT_DONE: - peer->fields = peer->proto.h1->parser.fields; + if (ret != NXT_AGAIN) { + engine = task->thread->engine; + nxt_timer_disable(engine, &c->write_timer); + nxt_timer_disable(engine, &c->read_timer); + } - ret = nxt_http_fields_process(peer->fields, - &nxt_h1p_peer_fields_hash, r); - if (nxt_slow_path(ret != NXT_OK)) { - peer->status = NXT_HTTP_INTERNAL_SERVER_ERROR; - break; - } + switch (ret) { - c->read = NULL; + case NXT_DONE: + peer->fields = peer->proto.h1->parser.fields; - peer->header_received = 1; + ret = nxt_http_fields_process(peer->fields, &nxt_h1p_peer_fields_hash, r); + if (nxt_slow_path(ret != NXT_OK)) { + peer->status = NXT_HTTP_INTERNAL_SERVER_ERROR; + break; + } - h1p = peer->proto.h1; + c->read = NULL; - if (h1p->chunked) { - if (r->resp.content_length != NULL) { - peer->status = NXT_HTTP_BAD_GATEWAY; - break; - } + peer->header_received = 1; - h1p->chunked_parse.mem_pool = c->mem_pool; + h1p = peer->proto.h1; - } else if (r->resp.content_length_n > 0) { - h1p->remainder = r->resp.content_length_n; - } + if (h1p->chunked) { + if (r->resp.content_length != NULL) { + peer->status = NXT_HTTP_BAD_GATEWAY; + break; + } - if (nxt_buf_mem_used_size(&b->mem) != 0) { - nxt_h1p_peer_body_process(task, peer, b); - return; - } + h1p->chunked_parse.mem_pool = c->mem_pool; - r->state->ready_handler(task, r, peer); - return; + } else if (r->resp.content_length_n > 0) { + h1p->remainder = r->resp.content_length_n; + } - case NXT_AGAIN: - if (nxt_buf_mem_free_size(&b->mem) != 0) { - nxt_conn_read(task->thread->engine, c); - return; - } + if (nxt_buf_mem_used_size(&b->mem) != 0) { + nxt_h1p_peer_body_process(task, peer, b); + return; + } - /* Fall through. */ + r->state->ready_handler(task, r, peer); + return; - default: - case NXT_ERROR: - case NXT_HTTP_PARSE_INVALID: - case NXT_HTTP_PARSE_UNSUPPORTED_VERSION: - case NXT_HTTP_PARSE_TOO_LARGE_FIELD: - peer->status = NXT_HTTP_BAD_GATEWAY; - break; + case NXT_AGAIN: + if (nxt_buf_mem_free_size(&b->mem) != 0) { + nxt_conn_read(task->thread->engine, c); + return; } - nxt_http_proxy_buf_mem_free(task, r, b); + /* Fall through. */ - r->state->error_handler(task, r, peer); -} + default: + case NXT_ERROR: + case NXT_HTTP_PARSE_INVALID: + case NXT_HTTP_PARSE_UNSUPPORTED_VERSION: + case NXT_HTTP_PARSE_TOO_LARGE_FIELD: + peer->status = NXT_HTTP_BAD_GATEWAY; + break; + } + nxt_http_proxy_buf_mem_free(task, r, b); -static nxt_int_t -nxt_h1p_peer_header_parse(nxt_http_peer_t *peer, nxt_buf_mem_t *bm) -{ - u_char *p; - size_t length; - nxt_int_t status; + r->state->error_handler(task, r, peer); +} - if (peer->status < 0) { - length = nxt_buf_mem_used_size(bm); +static nxt_int_t nxt_h1p_peer_header_parse(nxt_http_peer_t *peer, + nxt_buf_mem_t *bm) { + u_char *p; + size_t length; + nxt_int_t status; - if (nxt_slow_path(length < 12)) { - return NXT_AGAIN; - } + if (peer->status < 0) { + length = nxt_buf_mem_used_size(bm); - p = bm->pos; + if (nxt_slow_path(length < 12)) { + return NXT_AGAIN; + } - if (nxt_slow_path(memcmp(p, "HTTP/1.", 7) != 0 - || (p[7] != '0' && p[7] != '1'))) - { - return NXT_ERROR; - } + p = bm->pos; - status = nxt_int_parse(&p[9], 3); + if (nxt_slow_path(memcmp(p, "HTTP/1.", 7) != 0 || + (p[7] != '0' && p[7] != '1'))) { + return NXT_ERROR; + } - if (nxt_slow_path(status < 0)) { - return NXT_ERROR; - } + status = nxt_int_parse(&p[9], 3); - p += 12; - length -= 12; + if (nxt_slow_path(status < 0)) { + return NXT_ERROR; + } - p = memchr(p, '\n', length); + p += 12; + length -= 12; - if (nxt_slow_path(p == NULL)) { - return NXT_AGAIN; - } + p = memchr(p, '\n', length); - bm->pos = p + 1; - peer->status = status; + if (nxt_slow_path(p == NULL)) { + return NXT_AGAIN; } - return nxt_http_parse_fields(&peer->proto.h1->parser, bm); -} + bm->pos = p + 1; + peer->status = status; + } + return nxt_http_parse_fields(&peer->proto.h1->parser, bm); +} -static void -nxt_h1p_peer_read(nxt_task_t *task, nxt_http_peer_t *peer) -{ - nxt_conn_t *c; +static void nxt_h1p_peer_read(nxt_task_t *task, nxt_http_peer_t *peer) { + nxt_conn_t *c; - nxt_debug(task, "h1p peer read"); + nxt_debug(task, "h1p peer read"); - c = peer->proto.h1->conn; - c->read_state = &nxt_h1p_peer_read_state; + c = peer->proto.h1->conn; + c->read_state = &nxt_h1p_peer_read_state; - nxt_conn_read(task->thread->engine, c); + nxt_conn_read(task->thread->engine, c); } - -static const nxt_conn_state_t nxt_h1p_peer_read_state - nxt_aligned(64) = -{ +static const nxt_conn_state_t nxt_h1p_peer_read_state nxt_aligned(64) = { .ready_handler = nxt_h1p_peer_read_done, .close_handler = nxt_h1p_peer_closed, .error_handler = nxt_h1p_peer_error, @@ -2821,231 +2598,197 @@ static const nxt_conn_state_t nxt_h1p_peer_read_state .timer_autoreset = 1, }; +static void nxt_h1p_peer_read_done(nxt_task_t *task, void *obj, void *data) { + nxt_buf_t *out; + nxt_conn_t *c; + nxt_http_peer_t *peer; -static void -nxt_h1p_peer_read_done(nxt_task_t *task, void *obj, void *data) -{ - nxt_buf_t *out; - nxt_conn_t *c; - nxt_http_peer_t *peer; - - c = obj; - peer = data; + c = obj; + peer = data; - nxt_debug(task, "h1p peer read done"); + nxt_debug(task, "h1p peer read done"); - out = c->read; - c->read = NULL; + out = c->read; + c->read = NULL; - nxt_h1p_peer_body_process(task, peer, out); + nxt_h1p_peer_body_process(task, peer, out); } +static void nxt_h1p_peer_body_process(nxt_task_t *task, nxt_http_peer_t *peer, + nxt_buf_t *out) { + size_t length; + nxt_h1proto_t *h1p; + nxt_http_request_t *r; -static void -nxt_h1p_peer_body_process(nxt_task_t *task, nxt_http_peer_t *peer, - nxt_buf_t *out) -{ - size_t length; - nxt_h1proto_t *h1p; - nxt_http_request_t *r; + h1p = peer->proto.h1; - h1p = peer->proto.h1; + if (h1p->chunked) { + out = nxt_http_chunk_parse(task, &h1p->chunked_parse, out); - if (h1p->chunked) { - out = nxt_http_chunk_parse(task, &h1p->chunked_parse, out); - - if (h1p->chunked_parse.chunk_error || h1p->chunked_parse.error) { - peer->status = NXT_HTTP_BAD_GATEWAY; - r = peer->request; - r->state->error_handler(task, r, peer); - return; - } + if (h1p->chunked_parse.chunk_error || h1p->chunked_parse.error) { + peer->status = NXT_HTTP_BAD_GATEWAY; + r = peer->request; + r->state->error_handler(task, r, peer); + return; + } - if (h1p->chunked_parse.last) { - nxt_buf_chain_add(&out, nxt_http_buf_last(peer->request)); - peer->closed = 1; - } + if (h1p->chunked_parse.last) { + nxt_buf_chain_add(&out, nxt_http_buf_last(peer->request)); + peer->closed = 1; + } - } else if (h1p->remainder > 0) { - length = nxt_buf_chain_length(out); - h1p->remainder -= length; + } else if (h1p->remainder > 0) { + length = nxt_buf_chain_length(out); + h1p->remainder -= length; - if (h1p->remainder == 0) { - nxt_buf_chain_add(&out, nxt_http_buf_last(peer->request)); - peer->closed = 1; - } + if (h1p->remainder == 0) { + nxt_buf_chain_add(&out, nxt_http_buf_last(peer->request)); + peer->closed = 1; } + } - peer->body = out; + peer->body = out; - r = peer->request; - r->state->ready_handler(task, r, peer); + r = peer->request; + r->state->ready_handler(task, r, peer); } +static void nxt_h1p_peer_closed(nxt_task_t *task, void *obj, void *data) { + nxt_http_peer_t *peer; + nxt_http_request_t *r; -static void -nxt_h1p_peer_closed(nxt_task_t *task, void *obj, void *data) -{ - nxt_http_peer_t *peer; - nxt_http_request_t *r; + peer = data; - peer = data; + nxt_debug(task, "h1p peer closed"); - nxt_debug(task, "h1p peer closed"); + r = peer->request; - r = peer->request; - - if (peer->header_received) { - peer->body = nxt_http_buf_last(r); - peer->closed = 1; - r->inconsistent = (peer->proto.h1->remainder != 0); + if (peer->header_received) { + peer->body = nxt_http_buf_last(r); + peer->closed = 1; + r->inconsistent = (peer->proto.h1->remainder != 0); - r->state->ready_handler(task, r, peer); + r->state->ready_handler(task, r, peer); - } else { - peer->status = NXT_HTTP_BAD_GATEWAY; + } else { + peer->status = NXT_HTTP_BAD_GATEWAY; - r->state->error_handler(task, r, peer); - } + r->state->error_handler(task, r, peer); + } } +static void nxt_h1p_peer_error(nxt_task_t *task, void *obj, void *data) { + nxt_http_peer_t *peer; + nxt_http_request_t *r; -static void -nxt_h1p_peer_error(nxt_task_t *task, void *obj, void *data) -{ - nxt_http_peer_t *peer; - nxt_http_request_t *r; - - peer = data; + peer = data; - nxt_debug(task, "h1p peer error"); + nxt_debug(task, "h1p peer error"); - peer->status = NXT_HTTP_BAD_GATEWAY; + peer->status = NXT_HTTP_BAD_GATEWAY; - r = peer->request; - r->state->error_handler(task, r, peer); + r = peer->request; + r->state->error_handler(task, r, peer); } +static void nxt_h1p_peer_send_timeout(nxt_task_t *task, void *obj, void *data) { + nxt_conn_t *c; + nxt_timer_t *timer; + nxt_http_peer_t *peer; + nxt_http_request_t *r; -static void -nxt_h1p_peer_send_timeout(nxt_task_t *task, void *obj, void *data) -{ - nxt_conn_t *c; - nxt_timer_t *timer; - nxt_http_peer_t *peer; - nxt_http_request_t *r; - - timer = obj; + timer = obj; - nxt_debug(task, "h1p peer send timeout"); + nxt_debug(task, "h1p peer send timeout"); - c = nxt_write_timer_conn(timer); - c->block_write = 1; - c->block_read = 1; + c = nxt_write_timer_conn(timer); + c->block_write = 1; + c->block_read = 1; - peer = c->socket.data; - peer->status = NXT_HTTP_GATEWAY_TIMEOUT; + peer = c->socket.data; + peer->status = NXT_HTTP_GATEWAY_TIMEOUT; - r = peer->request; - r->state->error_handler(task, r, peer); + r = peer->request; + r->state->error_handler(task, r, peer); } +static void nxt_h1p_peer_read_timeout(nxt_task_t *task, void *obj, void *data) { + nxt_conn_t *c; + nxt_timer_t *timer; + nxt_http_peer_t *peer; + nxt_http_request_t *r; -static void -nxt_h1p_peer_read_timeout(nxt_task_t *task, void *obj, void *data) -{ - nxt_conn_t *c; - nxt_timer_t *timer; - nxt_http_peer_t *peer; - nxt_http_request_t *r; - - timer = obj; + timer = obj; - nxt_debug(task, "h1p peer read timeout"); + nxt_debug(task, "h1p peer read timeout"); - c = nxt_read_timer_conn(timer); - c->block_write = 1; - c->block_read = 1; + c = nxt_read_timer_conn(timer); + c->block_write = 1; + c->block_read = 1; - peer = c->socket.data; - peer->status = NXT_HTTP_GATEWAY_TIMEOUT; + peer = c->socket.data; + peer->status = NXT_HTTP_GATEWAY_TIMEOUT; - r = peer->request; - r->state->error_handler(task, r, peer); + r = peer->request; + r->state->error_handler(task, r, peer); } +static nxt_msec_t nxt_h1p_peer_timer_value(nxt_conn_t *c, uintptr_t data) { + nxt_http_peer_t *peer; -static nxt_msec_t -nxt_h1p_peer_timer_value(nxt_conn_t *c, uintptr_t data) -{ - nxt_http_peer_t *peer; + peer = c->socket.data; - peer = c->socket.data; - - return nxt_value_at(nxt_msec_t, peer->request->conf->socket_conf, data); + return nxt_value_at(nxt_msec_t, peer->request->conf->socket_conf, data); } +static void nxt_h1p_peer_close(nxt_task_t *task, nxt_http_peer_t *peer) { + nxt_conn_t *c; -static void -nxt_h1p_peer_close(nxt_task_t *task, nxt_http_peer_t *peer) -{ - nxt_conn_t *c; - - nxt_debug(task, "h1p peer close"); + nxt_debug(task, "h1p peer close"); - peer->closed = 1; + peer->closed = 1; - c = peer->proto.h1->conn; - task = &c->task; - c->socket.task = task; - c->read_timer.task = task; - c->write_timer.task = task; + c = peer->proto.h1->conn; + task = &c->task; + c->socket.task = task; + c->read_timer.task = task; + c->write_timer.task = task; - if (c->socket.fd != -1) { - c->write_state = &nxt_h1p_peer_close_state; + if (c->socket.fd != -1) { + c->write_state = &nxt_h1p_peer_close_state; - nxt_conn_close(task->thread->engine, c); + nxt_conn_close(task->thread->engine, c); - } else { - nxt_h1p_peer_free(task, c, NULL); - } + } else { + nxt_h1p_peer_free(task, c, NULL); + } } - -static const nxt_conn_state_t nxt_h1p_peer_close_state - nxt_aligned(64) = -{ +static const nxt_conn_state_t nxt_h1p_peer_close_state nxt_aligned(64) = { .ready_handler = nxt_h1p_peer_free, }; +static void nxt_h1p_peer_free(nxt_task_t *task, void *obj, void *data) { + nxt_conn_t *c; -static void -nxt_h1p_peer_free(nxt_task_t *task, void *obj, void *data) -{ - nxt_conn_t *c; + c = obj; - c = obj; + nxt_debug(task, "h1p peer free"); - nxt_debug(task, "h1p peer free"); - - nxt_conn_free(task, c); + nxt_conn_free(task, c); } +static nxt_int_t nxt_h1p_peer_transfer_encoding(void *ctx, + nxt_http_field_t *field, + uintptr_t data) { + nxt_http_request_t *r; -static nxt_int_t -nxt_h1p_peer_transfer_encoding(void *ctx, nxt_http_field_t *field, - uintptr_t data) -{ - nxt_http_request_t *r; - - r = ctx; - field->skip = 1; + r = ctx; + field->skip = 1; - if (field->value_length == 7 - && memcmp(field->value, "chunked", 7) == 0) - { - r->peer->proto.h1->chunked = 1; - } + if (field->value_length == 7 && memcmp(field->value, "chunked", 7) == 0) { + r->peer->proto.h1->chunked = 1; + } - return NXT_OK; + return NXT_OK; } diff --git a/src/nxt_h1proto.h b/src/nxt_h1proto.h index b324db8d1..75e99895e 100644 --- a/src/nxt_h1proto.h +++ b/src/nxt_h1proto.h @@ -6,52 +6,48 @@ #ifndef _NXT_H1PROTO_H_INCLUDED_ #define _NXT_H1PROTO_H_INCLUDED_ - #include #include #include #include - typedef struct nxt_h1p_websocket_timer_s nxt_h1p_websocket_timer_t; - struct nxt_h1proto_s { - nxt_http_request_parse_t parser; - nxt_http_chunk_parse_t chunked_parse; - nxt_off_t remainder; - - uint8_t nbuffers; - uint8_t header_buffer_slot; - uint8_t large_buffer_slot; - uint8_t keepalive; /* 1 bit */ - uint8_t chunked; /* 1 bit */ - uint8_t websocket; /* 1 bit */ - uint8_t connection_upgrade; /* 1 bit */ - uint8_t upgrade_websocket; /* 1 bit */ - uint8_t websocket_version_ok; /* 1 bit */ - nxt_http_te_t transfer_encoding:8; /* 2 bits */ - - uint8_t websocket_cont_expected; /* 1 bit */ - uint8_t websocket_closed; /* 1 bit */ - - uint32_t header_size; - - nxt_http_field_t *websocket_key; - nxt_h1p_websocket_timer_t *websocket_timer; - - nxt_http_request_t *request; - nxt_buf_t *buffers; - - nxt_buf_t **conn_write_tail; - /* - * All fields before the conn field will - * be zeroed in a keep-alive connection. - */ - nxt_conn_t *conn; + nxt_http_request_parse_t parser; + nxt_http_chunk_parse_t chunked_parse; + nxt_off_t remainder; + + uint8_t nbuffers; + uint8_t header_buffer_slot; + uint8_t large_buffer_slot; + uint8_t keepalive; /* 1 bit */ + uint8_t chunked; /* 1 bit */ + uint8_t websocket; /* 1 bit */ + uint8_t connection_upgrade; /* 1 bit */ + uint8_t upgrade_websocket; /* 1 bit */ + uint8_t websocket_version_ok; /* 1 bit */ + nxt_http_te_t transfer_encoding : 8; /* 2 bits */ + + uint8_t websocket_cont_expected; /* 1 bit */ + uint8_t websocket_closed; /* 1 bit */ + + uint32_t header_size; + + nxt_http_field_t *websocket_key; + nxt_h1p_websocket_timer_t *websocket_timer; + + nxt_http_request_t *request; + nxt_buf_t *buffers; + + nxt_buf_t **conn_write_tail; + /* + * All fields before the conn field will + * be zeroed in a keep-alive connection. + */ + nxt_conn_t *conn; }; -#define nxt_h1p_is_http11(h1p) \ - ((h1p)->parser.version.s.minor != '0') +#define nxt_h1p_is_http11(h1p) ((h1p)->parser.version.s.minor != '0') -#endif /* _NXT_H1PROTO_H_INCLUDED_ */ +#endif /* _NXT_H1PROTO_H_INCLUDED_ */ diff --git a/src/nxt_h1proto_websocket.c b/src/nxt_h1proto_websocket.c index 7be190f6c..558f24a58 100644 --- a/src/nxt_h1proto_websocket.c +++ b/src/nxt_h1proto_websocket.c @@ -11,692 +11,640 @@ #include typedef struct { - uint16_t code; - uint8_t args; - nxt_str_t desc; + uint16_t code; + uint8_t args; + nxt_str_t desc; } nxt_ws_error_t; static void nxt_h1p_conn_ws_keepalive(nxt_task_t *task, void *obj, void *data); static void nxt_h1p_conn_ws_frame_header_read(nxt_task_t *task, void *obj, - void *data); + void *data); static void nxt_h1p_conn_ws_keepalive_disable(nxt_task_t *task, - nxt_h1proto_t *h1p); + nxt_h1proto_t *h1p); static void nxt_h1p_conn_ws_keepalive_enable(nxt_task_t *task, - nxt_h1proto_t *h1p); + nxt_h1proto_t *h1p); static void nxt_h1p_conn_ws_frame_process(nxt_task_t *task, nxt_conn_t *c, - nxt_h1proto_t *h1p, nxt_websocket_header_t *wsh); + nxt_h1proto_t *h1p, + nxt_websocket_header_t *wsh); static void nxt_h1p_conn_ws_error(nxt_task_t *task, void *obj, void *data); static ssize_t nxt_h1p_ws_io_read_handler(nxt_task_t *task, nxt_conn_t *c); static void nxt_h1p_conn_ws_timeout(nxt_task_t *task, void *obj, void *data); static void nxt_h1p_conn_ws_frame_payload_read(nxt_task_t *task, void *obj, - void *data); + void *data); static void hxt_h1p_send_ws_error(nxt_task_t *task, nxt_http_request_t *r, - const nxt_ws_error_t *err, ...); + const nxt_ws_error_t *err, ...); static void nxt_h1p_conn_ws_error_sent(nxt_task_t *task, void *obj, void *data); static void nxt_h1p_conn_ws_pong(nxt_task_t *task, void *obj, void *data); -static const nxt_conn_state_t nxt_h1p_read_ws_frame_header_state; -static const nxt_conn_state_t nxt_h1p_read_ws_frame_payload_state; - -static const nxt_ws_error_t nxt_ws_err_out_of_memory = { - NXT_WEBSOCKET_CR_INTERNAL_SERVER_ERROR, - 0, nxt_string("Out of memory") }; -static const nxt_ws_error_t nxt_ws_err_too_big = { - NXT_WEBSOCKET_CR_MESSAGE_TOO_BIG, - 1, nxt_string("Message too big: %uL bytes") }; -static const nxt_ws_error_t nxt_ws_err_invalid_close_code = { - NXT_WEBSOCKET_CR_PROTOCOL_ERROR, - 1, nxt_string("Close code %ud is not valid") }; -static const nxt_ws_error_t nxt_ws_err_going_away = { - NXT_WEBSOCKET_CR_GOING_AWAY, - 0, nxt_string("Remote peer is going away") }; -static const nxt_ws_error_t nxt_ws_err_not_masked = { - NXT_WEBSOCKET_CR_PROTOCOL_ERROR, - 0, nxt_string("Not masked client frame") }; -static const nxt_ws_error_t nxt_ws_err_ctrl_fragmented = { - NXT_WEBSOCKET_CR_PROTOCOL_ERROR, - 0, nxt_string("Fragmented control frame") }; -static const nxt_ws_error_t nxt_ws_err_ctrl_too_big = { - NXT_WEBSOCKET_CR_PROTOCOL_ERROR, - 1, nxt_string("Control frame too big: %uL bytes") }; -static const nxt_ws_error_t nxt_ws_err_invalid_close_len = { - NXT_WEBSOCKET_CR_PROTOCOL_ERROR, - 0, nxt_string("Close frame payload length cannot be 1") }; -static const nxt_ws_error_t nxt_ws_err_invalid_opcode = { - NXT_WEBSOCKET_CR_PROTOCOL_ERROR, - 1, nxt_string("Unrecognized opcode %ud") }; -static const nxt_ws_error_t nxt_ws_err_cont_expected = { - NXT_WEBSOCKET_CR_PROTOCOL_ERROR, - 1, nxt_string("Continuation expected, but %ud opcode received") }; - -void -nxt_h1p_websocket_first_frame_start(nxt_task_t *task, nxt_http_request_t *r, - nxt_buf_t *ws_frame) -{ - nxt_conn_t *c; - nxt_timer_t *timer; - nxt_h1proto_t *h1p; - nxt_websocket_conf_t *websocket_conf; - - nxt_debug(task, "h1p ws first frame start"); - - h1p = r->proto.h1; - c = h1p->conn; - - if (!c->tcp_nodelay) { - nxt_conn_tcp_nodelay_on(task, c); +static const nxt_conn_state_t nxt_h1p_read_ws_frame_header_state; +static const nxt_conn_state_t nxt_h1p_read_ws_frame_payload_state; + +static const nxt_ws_error_t nxt_ws_err_out_of_memory = { + NXT_WEBSOCKET_CR_INTERNAL_SERVER_ERROR, 0, nxt_string("Out of memory")}; +static const nxt_ws_error_t nxt_ws_err_too_big = { + NXT_WEBSOCKET_CR_MESSAGE_TOO_BIG, 1, + nxt_string("Message too big: %uL bytes")}; +static const nxt_ws_error_t nxt_ws_err_invalid_close_code = { + NXT_WEBSOCKET_CR_PROTOCOL_ERROR, 1, + nxt_string("Close code %ud is not valid")}; +static const nxt_ws_error_t nxt_ws_err_going_away = { + NXT_WEBSOCKET_CR_GOING_AWAY, 0, nxt_string("Remote peer is going away")}; +static const nxt_ws_error_t nxt_ws_err_not_masked = { + NXT_WEBSOCKET_CR_PROTOCOL_ERROR, 0, nxt_string("Not masked client frame")}; +static const nxt_ws_error_t nxt_ws_err_ctrl_fragmented = { + NXT_WEBSOCKET_CR_PROTOCOL_ERROR, 0, nxt_string("Fragmented control frame")}; +static const nxt_ws_error_t nxt_ws_err_ctrl_too_big = { + NXT_WEBSOCKET_CR_PROTOCOL_ERROR, 1, + nxt_string("Control frame too big: %uL bytes")}; +static const nxt_ws_error_t nxt_ws_err_invalid_close_len = { + NXT_WEBSOCKET_CR_PROTOCOL_ERROR, 0, + nxt_string("Close frame payload length cannot be 1")}; +static const nxt_ws_error_t nxt_ws_err_invalid_opcode = { + NXT_WEBSOCKET_CR_PROTOCOL_ERROR, 1, nxt_string("Unrecognized opcode %ud")}; +static const nxt_ws_error_t nxt_ws_err_cont_expected = { + NXT_WEBSOCKET_CR_PROTOCOL_ERROR, 1, + nxt_string("Continuation expected, but %ud opcode received")}; + +void nxt_h1p_websocket_first_frame_start(nxt_task_t *task, + nxt_http_request_t *r, + nxt_buf_t *ws_frame) { + nxt_conn_t *c; + nxt_timer_t *timer; + nxt_h1proto_t *h1p; + nxt_websocket_conf_t *websocket_conf; + + nxt_debug(task, "h1p ws first frame start"); + + h1p = r->proto.h1; + c = h1p->conn; + + if (!c->tcp_nodelay) { + nxt_conn_tcp_nodelay_on(task, c); + } + + websocket_conf = &r->conf->socket_conf->websocket_conf; + + if (nxt_slow_path(websocket_conf->keepalive_interval != 0)) { + h1p->websocket_timer = + nxt_mp_zget(c->mem_pool, sizeof(nxt_h1p_websocket_timer_t)); + if (nxt_slow_path(h1p->websocket_timer == NULL)) { + hxt_h1p_send_ws_error(task, r, &nxt_ws_err_out_of_memory); + return; } - websocket_conf = &r->conf->socket_conf->websocket_conf; - - if (nxt_slow_path(websocket_conf->keepalive_interval != 0)) { - h1p->websocket_timer = nxt_mp_zget(c->mem_pool, - sizeof(nxt_h1p_websocket_timer_t)); - if (nxt_slow_path(h1p->websocket_timer == NULL)) { - hxt_h1p_send_ws_error(task, r, &nxt_ws_err_out_of_memory); - return; - } - - h1p->websocket_timer->keepalive_interval = - websocket_conf->keepalive_interval; - h1p->websocket_timer->h1p = h1p; - - timer = &h1p->websocket_timer->timer; - timer->task = &c->task; - timer->work_queue = &task->thread->engine->fast_work_queue; - timer->log = &c->log; - timer->bias = NXT_TIMER_DEFAULT_BIAS; - timer->handler = nxt_h1p_conn_ws_keepalive; - } + h1p->websocket_timer->keepalive_interval = + websocket_conf->keepalive_interval; + h1p->websocket_timer->h1p = h1p; - nxt_h1p_websocket_frame_start(task, r, ws_frame); + timer = &h1p->websocket_timer->timer; + timer->task = &c->task; + timer->work_queue = &task->thread->engine->fast_work_queue; + timer->log = &c->log; + timer->bias = NXT_TIMER_DEFAULT_BIAS; + timer->handler = nxt_h1p_conn_ws_keepalive; + } + + nxt_h1p_websocket_frame_start(task, r, ws_frame); } +void nxt_h1p_websocket_frame_start(nxt_task_t *task, nxt_http_request_t *r, + nxt_buf_t *ws_frame) { + size_t size; + nxt_buf_t *in; + nxt_conn_t *c; + nxt_h1proto_t *h1p; -void -nxt_h1p_websocket_frame_start(nxt_task_t *task, nxt_http_request_t *r, - nxt_buf_t *ws_frame) -{ - size_t size; - nxt_buf_t *in; - nxt_conn_t *c; - nxt_h1proto_t *h1p; + nxt_debug(task, "h1p ws frame start"); - nxt_debug(task, "h1p ws frame start"); + h1p = r->proto.h1; - h1p = r->proto.h1; + if (nxt_slow_path(h1p->websocket_closed)) { + return; + } - if (nxt_slow_path(h1p->websocket_closed)) { - return; - } + c = h1p->conn; + c->read = ws_frame; - c = h1p->conn; - c->read = ws_frame; + nxt_h1p_complete_buffers(task, h1p, 0); - nxt_h1p_complete_buffers(task, h1p, 0); + in = c->read; + c->read_state = &nxt_h1p_read_ws_frame_header_state; - in = c->read; - c->read_state = &nxt_h1p_read_ws_frame_header_state; - - if (in == NULL) { - nxt_conn_read(task->thread->engine, c); - nxt_h1p_conn_ws_keepalive_enable(task, h1p); + if (in == NULL) { + nxt_conn_read(task->thread->engine, c); + nxt_h1p_conn_ws_keepalive_enable(task, h1p); - } else { - size = nxt_buf_mem_used_size(&in->mem); + } else { + size = nxt_buf_mem_used_size(&in->mem); - nxt_debug(task, "h1p read client ws frame"); + nxt_debug(task, "h1p read client ws frame"); - nxt_memmove(in->mem.start, in->mem.pos, size); + nxt_memmove(in->mem.start, in->mem.pos, size); - in->mem.pos = in->mem.start; - in->mem.free = in->mem.start + size; + in->mem.pos = in->mem.start; + in->mem.free = in->mem.start + size; - nxt_h1p_conn_ws_frame_header_read(task, c, h1p); - } + nxt_h1p_conn_ws_frame_header_read(task, c, h1p); + } } +static void nxt_h1p_conn_ws_keepalive(nxt_task_t *task, void *obj, void *data) { + nxt_buf_t *out; + nxt_timer_t *timer; + nxt_h1proto_t *h1p; + nxt_http_request_t *r; + nxt_websocket_header_t *wsh; + nxt_h1p_websocket_timer_t *ws_timer; -static void -nxt_h1p_conn_ws_keepalive(nxt_task_t *task, void *obj, void *data) -{ - nxt_buf_t *out; - nxt_timer_t *timer; - nxt_h1proto_t *h1p; - nxt_http_request_t *r; - nxt_websocket_header_t *wsh; - nxt_h1p_websocket_timer_t *ws_timer; + nxt_debug(task, "h1p conn ws keepalive"); - nxt_debug(task, "h1p conn ws keepalive"); + timer = obj; + ws_timer = nxt_timer_data(timer, nxt_h1p_websocket_timer_t, timer); + h1p = ws_timer->h1p; - timer = obj; - ws_timer = nxt_timer_data(timer, nxt_h1p_websocket_timer_t, timer); - h1p = ws_timer->h1p; + r = h1p->request; + if (nxt_slow_path(r == NULL)) { + return; + } - r = h1p->request; - if (nxt_slow_path(r == NULL)) { - return; - } + out = nxt_http_buf_mem(task, r, 2); + if (nxt_slow_path(out == NULL)) { + nxt_http_request_error_handler(task, r, r->proto.any); + return; + } - out = nxt_http_buf_mem(task, r, 2); - if (nxt_slow_path(out == NULL)) { - nxt_http_request_error_handler(task, r, r->proto.any); - return; - } - - out->mem.start[0] = 0; - out->mem.start[1] = 0; + out->mem.start[0] = 0; + out->mem.start[1] = 0; - wsh = (nxt_websocket_header_t *) out->mem.start; - out->mem.free = nxt_websocket_frame_init(wsh, 0); + wsh = (nxt_websocket_header_t *)out->mem.start; + out->mem.free = nxt_websocket_frame_init(wsh, 0); - wsh->fin = 1; - wsh->opcode = NXT_WEBSOCKET_OP_PING; + wsh->fin = 1; + wsh->opcode = NXT_WEBSOCKET_OP_PING; - nxt_http_request_send(task, r, out); + nxt_http_request_send(task, r, out); } +static const nxt_conn_state_t + nxt_h1p_read_ws_frame_header_state nxt_aligned(64) = { + .ready_handler = nxt_h1p_conn_ws_frame_header_read, + .close_handler = nxt_h1p_conn_ws_error, + .error_handler = nxt_h1p_conn_ws_error, -static const nxt_conn_state_t nxt_h1p_read_ws_frame_header_state - nxt_aligned(64) = -{ - .ready_handler = nxt_h1p_conn_ws_frame_header_read, - .close_handler = nxt_h1p_conn_ws_error, - .error_handler = nxt_h1p_conn_ws_error, - - .io_read_handler = nxt_h1p_ws_io_read_handler, + .io_read_handler = nxt_h1p_ws_io_read_handler, - .timer_handler = nxt_h1p_conn_ws_timeout, - .timer_value = nxt_h1p_conn_request_timer_value, - .timer_data = offsetof(nxt_socket_conf_t, websocket_conf.read_timeout), - .timer_autoreset = 1, + .timer_handler = nxt_h1p_conn_ws_timeout, + .timer_value = nxt_h1p_conn_request_timer_value, + .timer_data = offsetof(nxt_socket_conf_t, websocket_conf.read_timeout), + .timer_autoreset = 1, }; +static void nxt_h1p_conn_ws_frame_header_read(nxt_task_t *task, void *obj, + void *data) { + size_t size, hsize, frame_size, max_frame_size; + uint64_t payload_len; + nxt_conn_t *c; + nxt_h1proto_t *h1p; + nxt_http_request_t *r; + nxt_event_engine_t *engine; + nxt_websocket_header_t *wsh; -static void -nxt_h1p_conn_ws_frame_header_read(nxt_task_t *task, void *obj, void *data) -{ - size_t size, hsize, frame_size, max_frame_size; - uint64_t payload_len; - nxt_conn_t *c; - nxt_h1proto_t *h1p; - nxt_http_request_t *r; - nxt_event_engine_t *engine; - nxt_websocket_header_t *wsh; + c = obj; + h1p = data; - c = obj; - h1p = data; + nxt_h1p_conn_ws_keepalive_disable(task, h1p); - nxt_h1p_conn_ws_keepalive_disable(task, h1p); + size = nxt_buf_mem_used_size(&c->read->mem); - size = nxt_buf_mem_used_size(&c->read->mem); + engine = task->thread->engine; - engine = task->thread->engine; + if (size < 2) { + nxt_debug(task, "h1p conn ws frame header read %z", size); - if (size < 2) { - nxt_debug(task, "h1p conn ws frame header read %z", size); + nxt_conn_read(engine, c); + nxt_h1p_conn_ws_keepalive_enable(task, h1p); - nxt_conn_read(engine, c); - nxt_h1p_conn_ws_keepalive_enable(task, h1p); + return; + } - return; - } + wsh = (nxt_websocket_header_t *)c->read->mem.pos; - wsh = (nxt_websocket_header_t *) c->read->mem.pos; + hsize = nxt_websocket_frame_header_size(wsh); - hsize = nxt_websocket_frame_header_size(wsh); + if (size < hsize) { + nxt_debug(task, "h1p conn ws frame header read %z < %z", size, hsize); - if (size < hsize) { - nxt_debug(task, "h1p conn ws frame header read %z < %z", size, hsize); + nxt_conn_read(engine, c); + nxt_h1p_conn_ws_keepalive_enable(task, h1p); - nxt_conn_read(engine, c); - nxt_h1p_conn_ws_keepalive_enable(task, h1p); + return; + } - return; - } + r = h1p->request; + if (nxt_slow_path(r == NULL)) { + return; + } - r = h1p->request; - if (nxt_slow_path(r == NULL)) { - return; - } + r->ws_frame = c->read; - r->ws_frame = c->read; + if (nxt_slow_path(wsh->mask == 0)) { + hxt_h1p_send_ws_error(task, r, &nxt_ws_err_not_masked); + return; + } - if (nxt_slow_path(wsh->mask == 0)) { - hxt_h1p_send_ws_error(task, r, &nxt_ws_err_not_masked); - return; + if ((wsh->opcode & NXT_WEBSOCKET_OP_CTRL) != 0) { + if (nxt_slow_path(wsh->fin == 0)) { + hxt_h1p_send_ws_error(task, r, &nxt_ws_err_ctrl_fragmented); + return; } - if ((wsh->opcode & NXT_WEBSOCKET_OP_CTRL) != 0) { - if (nxt_slow_path(wsh->fin == 0)) { - hxt_h1p_send_ws_error(task, r, &nxt_ws_err_ctrl_fragmented); - return; - } - - if (nxt_slow_path(wsh->opcode != NXT_WEBSOCKET_OP_PING - && wsh->opcode != NXT_WEBSOCKET_OP_PONG - && wsh->opcode != NXT_WEBSOCKET_OP_CLOSE)) - { - hxt_h1p_send_ws_error(task, r, &nxt_ws_err_invalid_opcode, - wsh->opcode); - return; - } - - if (nxt_slow_path(wsh->payload_len > 125)) { - hxt_h1p_send_ws_error(task, r, &nxt_ws_err_ctrl_too_big, - nxt_websocket_frame_payload_len(wsh)); - return; - } - - if (nxt_slow_path(wsh->opcode == NXT_WEBSOCKET_OP_CLOSE - && wsh->payload_len == 1)) - { - hxt_h1p_send_ws_error(task, r, &nxt_ws_err_invalid_close_len); - return; - } + if (nxt_slow_path(wsh->opcode != NXT_WEBSOCKET_OP_PING && + wsh->opcode != NXT_WEBSOCKET_OP_PONG && + wsh->opcode != NXT_WEBSOCKET_OP_CLOSE)) { + hxt_h1p_send_ws_error(task, r, &nxt_ws_err_invalid_opcode, wsh->opcode); + return; + } - } else { - if (h1p->websocket_cont_expected) { - if (nxt_slow_path(wsh->opcode != NXT_WEBSOCKET_OP_CONT)) { - hxt_h1p_send_ws_error(task, r, &nxt_ws_err_cont_expected, - wsh->opcode); - return; - } - - } else { - if (nxt_slow_path(wsh->opcode != NXT_WEBSOCKET_OP_BINARY - && wsh->opcode != NXT_WEBSOCKET_OP_TEXT)) - { - hxt_h1p_send_ws_error(task, r, &nxt_ws_err_invalid_opcode, - wsh->opcode); - return; - } - } - - h1p->websocket_cont_expected = !wsh->fin; + if (nxt_slow_path(wsh->payload_len > 125)) { + hxt_h1p_send_ws_error(task, r, &nxt_ws_err_ctrl_too_big, + nxt_websocket_frame_payload_len(wsh)); + return; } - max_frame_size = r->conf->socket_conf->websocket_conf.max_frame_size; + if (nxt_slow_path(wsh->opcode == NXT_WEBSOCKET_OP_CLOSE && + wsh->payload_len == 1)) { + hxt_h1p_send_ws_error(task, r, &nxt_ws_err_invalid_close_len); + return; + } - payload_len = nxt_websocket_frame_payload_len(wsh); + } else { + if (h1p->websocket_cont_expected) { + if (nxt_slow_path(wsh->opcode != NXT_WEBSOCKET_OP_CONT)) { + hxt_h1p_send_ws_error(task, r, &nxt_ws_err_cont_expected, wsh->opcode); + return; + } - if (nxt_slow_path(hsize > max_frame_size - || payload_len > (max_frame_size - hsize))) - { - hxt_h1p_send_ws_error(task, r, &nxt_ws_err_too_big, payload_len); + } else { + if (nxt_slow_path(wsh->opcode != NXT_WEBSOCKET_OP_BINARY && + wsh->opcode != NXT_WEBSOCKET_OP_TEXT)) { + hxt_h1p_send_ws_error(task, r, &nxt_ws_err_invalid_opcode, wsh->opcode); return; + } } - c->read_state = &nxt_h1p_read_ws_frame_payload_state; - - frame_size = payload_len + hsize; - - nxt_debug(task, "h1p conn ws frame header read: %z, %z", size, frame_size); + h1p->websocket_cont_expected = !wsh->fin; + } - if (frame_size <= size) { - nxt_h1p_conn_ws_frame_process(task, c, h1p, wsh); + max_frame_size = r->conf->socket_conf->websocket_conf.max_frame_size; - return; - } + payload_len = nxt_websocket_frame_payload_len(wsh); - if (frame_size < (size_t) nxt_buf_mem_size(&c->read->mem)) { - c->read->mem.end = c->read->mem.start + frame_size; + if (nxt_slow_path(hsize > max_frame_size || + payload_len > (max_frame_size - hsize))) { + hxt_h1p_send_ws_error(task, r, &nxt_ws_err_too_big, payload_len); + return; + } - } else { - nxt_buf_t *b = nxt_buf_mem_alloc(c->mem_pool, frame_size - size, 0); + c->read_state = &nxt_h1p_read_ws_frame_payload_state; - c->read->next = b; - c->read = b; - } + frame_size = payload_len + hsize; - nxt_conn_read(engine, c); - nxt_h1p_conn_ws_keepalive_enable(task, h1p); -} + nxt_debug(task, "h1p conn ws frame header read: %z, %z", size, frame_size); + if (frame_size <= size) { + nxt_h1p_conn_ws_frame_process(task, c, h1p, wsh); -static void -nxt_h1p_conn_ws_keepalive_disable(nxt_task_t *task, nxt_h1proto_t *h1p) -{ - nxt_timer_t *timer; + return; + } - if (h1p->websocket_timer == NULL) { - return; - } + if (frame_size < (size_t)nxt_buf_mem_size(&c->read->mem)) { + c->read->mem.end = c->read->mem.start + frame_size; - timer = &h1p->websocket_timer->timer; + } else { + nxt_buf_t *b = nxt_buf_mem_alloc(c->mem_pool, frame_size - size, 0); - if (nxt_slow_path(timer->handler != nxt_h1p_conn_ws_keepalive)) { - nxt_debug(task, "h1p ws keepalive disable: scheduled ws shutdown"); - return; - } + c->read->next = b; + c->read = b; + } - nxt_timer_disable(task->thread->engine, timer); + nxt_conn_read(engine, c); + nxt_h1p_conn_ws_keepalive_enable(task, h1p); } +static void nxt_h1p_conn_ws_keepalive_disable(nxt_task_t *task, + nxt_h1proto_t *h1p) { + nxt_timer_t *timer; -static void -nxt_h1p_conn_ws_keepalive_enable(nxt_task_t *task, nxt_h1proto_t *h1p) -{ - nxt_timer_t *timer; + if (h1p->websocket_timer == NULL) { + return; + } - if (h1p->websocket_timer == NULL) { - return; - } + timer = &h1p->websocket_timer->timer; - timer = &h1p->websocket_timer->timer; - - if (nxt_slow_path(timer->handler != nxt_h1p_conn_ws_keepalive)) { - nxt_debug(task, "h1p ws keepalive enable: scheduled ws shutdown"); - return; - } + if (nxt_slow_path(timer->handler != nxt_h1p_conn_ws_keepalive)) { + nxt_debug(task, "h1p ws keepalive disable: scheduled ws shutdown"); + return; + } - nxt_timer_add(task->thread->engine, timer, - h1p->websocket_timer->keepalive_interval); + nxt_timer_disable(task->thread->engine, timer); } +static void nxt_h1p_conn_ws_keepalive_enable(nxt_task_t *task, + nxt_h1proto_t *h1p) { + nxt_timer_t *timer; -static void -nxt_h1p_conn_ws_frame_process(nxt_task_t *task, nxt_conn_t *c, - nxt_h1proto_t *h1p, nxt_websocket_header_t *wsh) -{ - size_t hsize; - uint8_t *p, *mask; - uint16_t code; - nxt_http_request_t *r; + if (h1p->websocket_timer == NULL) { + return; + } - r = h1p->request; + timer = &h1p->websocket_timer->timer; - c->read = NULL; + if (nxt_slow_path(timer->handler != nxt_h1p_conn_ws_keepalive)) { + nxt_debug(task, "h1p ws keepalive enable: scheduled ws shutdown"); + return; + } - if (nxt_slow_path(wsh->opcode == NXT_WEBSOCKET_OP_PING)) { - nxt_h1p_conn_ws_pong(task, r, NULL); + nxt_timer_add(task->thread->engine, timer, + h1p->websocket_timer->keepalive_interval); +} + +static void nxt_h1p_conn_ws_frame_process(nxt_task_t *task, nxt_conn_t *c, + nxt_h1proto_t *h1p, + nxt_websocket_header_t *wsh) { + size_t hsize; + uint8_t *p, *mask; + uint16_t code; + nxt_http_request_t *r; + + r = h1p->request; + + c->read = NULL; + + if (nxt_slow_path(wsh->opcode == NXT_WEBSOCKET_OP_PING)) { + nxt_h1p_conn_ws_pong(task, r, NULL); + return; + } + + if (nxt_slow_path(wsh->opcode == NXT_WEBSOCKET_OP_CLOSE)) { + if (wsh->payload_len >= 2) { + hsize = nxt_websocket_frame_header_size(wsh); + mask = nxt_pointer_to(wsh, hsize - 4); + p = nxt_pointer_to(wsh, hsize); + + code = ((p[0] ^ mask[0]) << 8) + (p[1] ^ mask[1]); + + if (nxt_slow_path(code < 1000 || code >= 5000 || + (code > 1003 && code < 1007) || + (code > 1014 && code < 3000))) { + hxt_h1p_send_ws_error(task, r, &nxt_ws_err_invalid_close_code, code); return; + } } - if (nxt_slow_path(wsh->opcode == NXT_WEBSOCKET_OP_CLOSE)) { - if (wsh->payload_len >= 2) { - hsize = nxt_websocket_frame_header_size(wsh); - mask = nxt_pointer_to(wsh, hsize - 4); - p = nxt_pointer_to(wsh, hsize); - - code = ((p[0] ^ mask[0]) << 8) + (p[1] ^ mask[1]); - - if (nxt_slow_path(code < 1000 || code >= 5000 - || (code > 1003 && code < 1007) - || (code > 1014 && code < 3000))) - { - hxt_h1p_send_ws_error(task, r, &nxt_ws_err_invalid_close_code, - code); - return; - } - } - - h1p->websocket_closed = 1; - } + h1p->websocket_closed = 1; + } - r->state->ready_handler(task, r, NULL); + r->state->ready_handler(task, r, NULL); } +static void nxt_h1p_conn_ws_error(nxt_task_t *task, void *obj, void *data) { + nxt_h1proto_t *h1p; + nxt_http_request_t *r; -static void -nxt_h1p_conn_ws_error(nxt_task_t *task, void *obj, void *data) -{ - nxt_h1proto_t *h1p; - nxt_http_request_t *r; - - h1p = data; + h1p = data; - nxt_debug(task, "h1p conn ws error"); + nxt_debug(task, "h1p conn ws error"); - r = h1p->request; + r = h1p->request; - h1p->keepalive = 0; + h1p->keepalive = 0; - if (nxt_fast_path(r != NULL)) { - r->state->error_handler(task, r, h1p); - } + if (nxt_fast_path(r != NULL)) { + r->state->error_handler(task, r, h1p); + } } +static ssize_t nxt_h1p_ws_io_read_handler(nxt_task_t *task, nxt_conn_t *c) { + size_t size; + ssize_t n; + nxt_buf_t *b; -static ssize_t -nxt_h1p_ws_io_read_handler(nxt_task_t *task, nxt_conn_t *c) -{ - size_t size; - ssize_t n; - nxt_buf_t *b; - - b = c->read; + b = c->read; - if (b == NULL) { - /* Enough for control frame. */ - size = 10 + 125; + if (b == NULL) { + /* Enough for control frame. */ + size = 10 + 125; - b = nxt_buf_mem_alloc(c->mem_pool, size, 0); - if (nxt_slow_path(b == NULL)) { - c->socket.error = NXT_ENOMEM; - return NXT_ERROR; - } + b = nxt_buf_mem_alloc(c->mem_pool, size, 0); + if (nxt_slow_path(b == NULL)) { + c->socket.error = NXT_ENOMEM; + return NXT_ERROR; } + } - n = c->io->recvbuf(c, b); + n = c->io->recvbuf(c, b); - if (n > 0) { - c->read = b; + if (n > 0) { + c->read = b; - } else { - c->read = NULL; - nxt_mp_free(c->mem_pool, b); - } + } else { + c->read = NULL; + nxt_mp_free(c->mem_pool, b); + } - return n; + return n; } +static void nxt_h1p_conn_ws_timeout(nxt_task_t *task, void *obj, void *data) { + nxt_conn_t *c; + nxt_timer_t *timer; + nxt_h1proto_t *h1p; + nxt_http_request_t *r; -static void -nxt_h1p_conn_ws_timeout(nxt_task_t *task, void *obj, void *data) -{ - nxt_conn_t *c; - nxt_timer_t *timer; - nxt_h1proto_t *h1p; - nxt_http_request_t *r; + timer = obj; - timer = obj; + nxt_debug(task, "h1p conn ws timeout"); - nxt_debug(task, "h1p conn ws timeout"); + c = nxt_read_timer_conn(timer); + c->block_read = 1; + /* + * Disable SO_LINGER off during socket closing + * to send "408 Request Timeout" error response. + */ + c->socket.timedout = 0; - c = nxt_read_timer_conn(timer); - c->block_read = 1; - /* - * Disable SO_LINGER off during socket closing - * to send "408 Request Timeout" error response. - */ - c->socket.timedout = 0; + h1p = c->socket.data; + h1p->keepalive = 0; - h1p = c->socket.data; - h1p->keepalive = 0; + r = h1p->request; + if (nxt_slow_path(r == NULL)) { + return; + } - r = h1p->request; - if (nxt_slow_path(r == NULL)) { - return; - } - - hxt_h1p_send_ws_error(task, r, &nxt_ws_err_going_away); + hxt_h1p_send_ws_error(task, r, &nxt_ws_err_going_away); } +static const nxt_conn_state_t + nxt_h1p_read_ws_frame_payload_state nxt_aligned(64) = { + .ready_handler = nxt_h1p_conn_ws_frame_payload_read, + .close_handler = nxt_h1p_conn_ws_error, + .error_handler = nxt_h1p_conn_ws_error, -static const nxt_conn_state_t nxt_h1p_read_ws_frame_payload_state - nxt_aligned(64) = -{ - .ready_handler = nxt_h1p_conn_ws_frame_payload_read, - .close_handler = nxt_h1p_conn_ws_error, - .error_handler = nxt_h1p_conn_ws_error, - - .timer_handler = nxt_h1p_conn_ws_timeout, - .timer_value = nxt_h1p_conn_request_timer_value, - .timer_data = offsetof(nxt_socket_conf_t, websocket_conf.read_timeout), - .timer_autoreset = 1, + .timer_handler = nxt_h1p_conn_ws_timeout, + .timer_value = nxt_h1p_conn_request_timer_value, + .timer_data = offsetof(nxt_socket_conf_t, websocket_conf.read_timeout), + .timer_autoreset = 1, }; +static void nxt_h1p_conn_ws_frame_payload_read(nxt_task_t *task, void *obj, + void *data) { + nxt_conn_t *c; + nxt_h1proto_t *h1p; + nxt_http_request_t *r; + nxt_event_engine_t *engine; + nxt_websocket_header_t *wsh; -static void -nxt_h1p_conn_ws_frame_payload_read(nxt_task_t *task, void *obj, void *data) -{ - nxt_conn_t *c; - nxt_h1proto_t *h1p; - nxt_http_request_t *r; - nxt_event_engine_t *engine; - nxt_websocket_header_t *wsh; - - c = obj; - h1p = data; + c = obj; + h1p = data; - nxt_h1p_conn_ws_keepalive_disable(task, h1p); + nxt_h1p_conn_ws_keepalive_disable(task, h1p); - nxt_debug(task, "h1p conn ws frame read"); + nxt_debug(task, "h1p conn ws frame read"); - if (nxt_buf_mem_free_size(&c->read->mem) == 0) { - r = h1p->request; - if (nxt_slow_path(r == NULL)) { - return; - } + if (nxt_buf_mem_free_size(&c->read->mem) == 0) { + r = h1p->request; + if (nxt_slow_path(r == NULL)) { + return; + } - wsh = (nxt_websocket_header_t *) r->ws_frame->mem.pos; + wsh = (nxt_websocket_header_t *)r->ws_frame->mem.pos; - nxt_h1p_conn_ws_frame_process(task, c, h1p, wsh); + nxt_h1p_conn_ws_frame_process(task, c, h1p, wsh); - return; - } + return; + } - engine = task->thread->engine; + engine = task->thread->engine; - nxt_conn_read(engine, c); - nxt_h1p_conn_ws_keepalive_enable(task, h1p); + nxt_conn_read(engine, c); + nxt_h1p_conn_ws_keepalive_enable(task, h1p); } +static void hxt_h1p_send_ws_error(nxt_task_t *task, nxt_http_request_t *r, + const nxt_ws_error_t *err, ...) { + u_char *p; + va_list args; + nxt_buf_t *out; + nxt_str_t desc; + nxt_websocket_header_t *wsh; + u_char buf[125]; -static void -hxt_h1p_send_ws_error(nxt_task_t *task, nxt_http_request_t *r, - const nxt_ws_error_t *err, ...) -{ - u_char *p; - va_list args; - nxt_buf_t *out; - nxt_str_t desc; - nxt_websocket_header_t *wsh; - u_char buf[125]; - - if (nxt_slow_path(err->args)) { - va_start(args, err); - p = nxt_vsprintf(buf, buf + sizeof(buf), (char *) err->desc.start, - args); - va_end(args); + if (nxt_slow_path(err->args)) { + va_start(args, err); + p = nxt_vsprintf(buf, buf + sizeof(buf), (char *)err->desc.start, args); + va_end(args); - desc.start = buf; - desc.length = p - buf; + desc.start = buf; + desc.length = p - buf; - } else { - desc = err->desc; - } + } else { + desc = err->desc; + } - nxt_log(task, NXT_LOG_INFO, "websocket error %d: %V", err->code, &desc); + nxt_log(task, NXT_LOG_INFO, "websocket error %d: %V", err->code, &desc); - out = nxt_http_buf_mem(task, r, 2 + sizeof(err->code) + desc.length); - if (nxt_slow_path(out == NULL)) { - nxt_http_request_error_handler(task, r, r->proto.any); - return; - } + out = nxt_http_buf_mem(task, r, 2 + sizeof(err->code) + desc.length); + if (nxt_slow_path(out == NULL)) { + nxt_http_request_error_handler(task, r, r->proto.any); + return; + } - out->mem.start[0] = 0; - out->mem.start[1] = 0; + out->mem.start[0] = 0; + out->mem.start[1] = 0; - wsh = (nxt_websocket_header_t *) out->mem.start; - p = nxt_websocket_frame_init(wsh, sizeof(err->code) + desc.length); + wsh = (nxt_websocket_header_t *)out->mem.start; + p = nxt_websocket_frame_init(wsh, sizeof(err->code) + desc.length); - wsh->fin = 1; - wsh->opcode = NXT_WEBSOCKET_OP_CLOSE; + wsh->fin = 1; + wsh->opcode = NXT_WEBSOCKET_OP_CLOSE; - *p++ = (err->code >> 8) & 0xFF; - *p++ = err->code & 0xFF; + *p++ = (err->code >> 8) & 0xFF; + *p++ = err->code & 0xFF; - out->mem.free = nxt_cpymem(p, desc.start, desc.length); - out->next = nxt_http_buf_last(r); + out->mem.free = nxt_cpymem(p, desc.start, desc.length); + out->next = nxt_http_buf_last(r); - if (out->next != NULL) { - out->next->completion_handler = nxt_h1p_conn_ws_error_sent; - } + if (out->next != NULL) { + out->next->completion_handler = nxt_h1p_conn_ws_error_sent; + } - nxt_http_request_send(task, r, out); + nxt_http_request_send(task, r, out); } +static void nxt_h1p_conn_ws_error_sent(nxt_task_t *task, void *obj, + void *data) { + nxt_http_request_t *r; -static void -nxt_h1p_conn_ws_error_sent(nxt_task_t *task, void *obj, void *data) -{ - nxt_http_request_t *r; + r = data; - r = data; + nxt_debug(task, "h1p conn ws error sent"); - nxt_debug(task, "h1p conn ws error sent"); - - r->state->error_handler(task, r, r->proto.any); + r->state->error_handler(task, r, r->proto.any); } +static void nxt_h1p_conn_ws_pong(nxt_task_t *task, void *obj, void *data) { + uint8_t payload_len, i; + nxt_buf_t *b, *out, *next; + nxt_http_request_t *r; + nxt_websocket_header_t *wsh; + uint8_t mask[4]; -static void -nxt_h1p_conn_ws_pong(nxt_task_t *task, void *obj, void *data) -{ - uint8_t payload_len, i; - nxt_buf_t *b, *out, *next; - nxt_http_request_t *r; - nxt_websocket_header_t *wsh; - uint8_t mask[4]; - - nxt_debug(task, "h1p conn ws pong"); - - r = obj; - b = r->ws_frame; + nxt_debug(task, "h1p conn ws pong"); - wsh = (nxt_websocket_header_t *) b->mem.pos; - payload_len = wsh->payload_len; + r = obj; + b = r->ws_frame; - b->mem.pos += 2; + wsh = (nxt_websocket_header_t *)b->mem.pos; + payload_len = wsh->payload_len; - nxt_memcpy(mask, b->mem.pos, 4); + b->mem.pos += 2; - b->mem.pos += 4; + nxt_memcpy(mask, b->mem.pos, 4); - out = nxt_http_buf_mem(task, r, 2 + payload_len); - if (nxt_slow_path(out == NULL)) { - nxt_http_request_error_handler(task, r, r->proto.any); - return; - } + b->mem.pos += 4; - out->mem.start[0] = 0; - out->mem.start[1] = 0; + out = nxt_http_buf_mem(task, r, 2 + payload_len); + if (nxt_slow_path(out == NULL)) { + nxt_http_request_error_handler(task, r, r->proto.any); + return; + } - wsh = (nxt_websocket_header_t *) out->mem.start; - out->mem.free = nxt_websocket_frame_init(wsh, payload_len); + out->mem.start[0] = 0; + out->mem.start[1] = 0; - wsh->fin = 1; - wsh->opcode = NXT_WEBSOCKET_OP_PONG; + wsh = (nxt_websocket_header_t *)out->mem.start; + out->mem.free = nxt_websocket_frame_init(wsh, payload_len); - for (i = 0; i < payload_len; i++) { - while (nxt_buf_mem_used_size(&b->mem) == 0) { - next = b->next; - b->next = NULL; + wsh->fin = 1; + wsh->opcode = NXT_WEBSOCKET_OP_PONG; - nxt_work_queue_add(&task->thread->engine->fast_work_queue, - b->completion_handler, task, b, b->parent); + for (i = 0; i < payload_len; i++) { + while (nxt_buf_mem_used_size(&b->mem) == 0) { + next = b->next; + b->next = NULL; - b = next; - } + nxt_work_queue_add(&task->thread->engine->fast_work_queue, + b->completion_handler, task, b, b->parent); - *out->mem.free++ = *b->mem.pos++ ^ mask[i % 4]; + b = next; } - r->ws_frame = b; + *out->mem.free++ = *b->mem.pos++ ^ mask[i % 4]; + } + + r->ws_frame = b; - nxt_http_request_send(task, r, out); + nxt_http_request_send(task, r, out); - nxt_http_request_ws_frame_start(task, r, r->ws_frame); + nxt_http_request_ws_frame_start(task, r, r->ws_frame); } diff --git a/src/nxt_hash.h b/src/nxt_hash.h index 01c727d24..dfa3ecfeb 100644 --- a/src/nxt_hash.h +++ b/src/nxt_hash.h @@ -7,41 +7,30 @@ #ifndef _NXT_HASH_H_INCLUDED_ #define _NXT_HASH_H_INCLUDED_ - typedef struct { - nxt_lvlhsh_t lvlhsh; - const nxt_lvlhsh_proto_t *proto; - void *pool; + nxt_lvlhsh_t lvlhsh; + const nxt_lvlhsh_proto_t *proto; + void *pool; } nxt_hash_t; +nxt_inline nxt_int_t nxt_hash_find(nxt_hash_t *h, nxt_lvlhsh_query_t *lhq) { + lhq->proto = h->proto; -nxt_inline nxt_int_t -nxt_hash_find(nxt_hash_t *h, nxt_lvlhsh_query_t *lhq) -{ - lhq->proto = h->proto; - - return nxt_lvlhsh_find(&h->lvlhsh, lhq); + return nxt_lvlhsh_find(&h->lvlhsh, lhq); } +nxt_inline nxt_int_t nxt_hash_insert(nxt_hash_t *h, nxt_lvlhsh_query_t *lhq) { + lhq->proto = h->proto; + lhq->pool = h->pool; -nxt_inline nxt_int_t -nxt_hash_insert(nxt_hash_t *h, nxt_lvlhsh_query_t *lhq) -{ - lhq->proto = h->proto; - lhq->pool = h->pool; - - return nxt_lvlhsh_insert(&h->lvlhsh, lhq); + return nxt_lvlhsh_insert(&h->lvlhsh, lhq); } +nxt_inline nxt_int_t nxt_hash_delete(nxt_hash_t *h, nxt_lvlhsh_query_t *lhq) { + lhq->proto = h->proto; + lhq->pool = h->pool; -nxt_inline nxt_int_t -nxt_hash_delete(nxt_hash_t *h, nxt_lvlhsh_query_t *lhq) -{ - lhq->proto = h->proto; - lhq->pool = h->pool; - - return nxt_lvlhsh_delete(&h->lvlhsh, lhq); + return nxt_lvlhsh_delete(&h->lvlhsh, lhq); } - #endif /* _NXT_HASH_H_INCLUDED_ */ diff --git a/src/nxt_hpux_sendfile.c b/src/nxt_hpux_sendfile.c index df200b64c..6f72a8559 100644 --- a/src/nxt_hpux_sendfile.c +++ b/src/nxt_hpux_sendfile.c @@ -6,16 +6,14 @@ #include - #ifdef NXT_TEST_BUILD_HPUX_SENDFILE ssize_t nxt_hpux_event_conn_io_sendfile(nxt_event_conn_t *c, nxt_buf_t *b, - size_t limit); + size_t limit); static ssize_t nxt_sys_sendfile(int s, int fd, off_t offset, size_t nbytes, - const struct iovec *hdtrl, int flags) -{ - return -1; + const struct iovec *hdtrl, int flags) { + return -1; } #else @@ -23,115 +21,111 @@ static ssize_t nxt_sys_sendfile(int s, int fd, off_t offset, size_t nbytes, /* sendfile() is not declared if _XOPEN_SOURCE_EXTENDED is defined. */ sbsize_t sendfile(int s, int fd, off_t offset, bsize_t nbytes, - const struct iovec *hdtrl, int flags); + const struct iovec *hdtrl, int flags); -#define nxt_sys_sendfile sendfile +#define nxt_sys_sendfile sendfile #endif +ssize_t nxt_hpux_event_conn_io_sendfile(nxt_event_conn_t *c, nxt_buf_t *b, + size_t limit) { + size_t file_size; + ssize_t n; + nxt_buf_t *fb; + nxt_err_t err; + nxt_uint_t nhd, ntr; + struct iovec iov[NXT_IOBUF_MAX], *hdtrl; + nxt_sendbuf_coalesce_t sb; -ssize_t -nxt_hpux_event_conn_io_sendfile(nxt_event_conn_t *c, nxt_buf_t *b, size_t limit) -{ - size_t file_size; - ssize_t n; - nxt_buf_t *fb; - nxt_err_t err; - nxt_uint_t nhd, ntr; - struct iovec iov[NXT_IOBUF_MAX], *hdtrl; - nxt_sendbuf_coalesce_t sb; - - sb.buf = b; - sb.iobuf = iov; - sb.nmax = NXT_IOBUF_MAX; - sb.sync = 0; - sb.size = 0; - sb.limit = limit; - - nhd = nxt_sendbuf_mem_coalesce(c->socket.task, &sb); - - if (nhd == 0 && sb.sync) { - return 0; - } + sb.buf = b; + sb.iobuf = iov; + sb.nmax = NXT_IOBUF_MAX; + sb.sync = 0; + sb.size = 0; + sb.limit = limit; - if (nhd > 1 || sb.buf == NULL || !nxt_buf_is_file(sb.buf)) { - return nxt_event_conn_io_writev(c, iov, nhd); - } + nhd = nxt_sendbuf_mem_coalesce(c->socket.task, &sb); - fb = sb.buf; + if (nhd == 0 && sb.sync) { + return 0; + } - file_size = nxt_sendbuf_file_coalesce(&sb); + if (nhd > 1 || sb.buf == NULL || !nxt_buf_is_file(sb.buf)) { + return nxt_event_conn_io_writev(c, iov, nhd); + } - if (file_size == 0) { - return nxt_event_conn_io_writev(c, iov, nhd); - } + fb = sb.buf; - sb.iobuf = &iov[1]; - sb.nmax = 1; + file_size = nxt_sendbuf_file_coalesce(&sb); - ntr = nxt_sendbuf_mem_coalesce(c->socket.task, &sb); + if (file_size == 0) { + return nxt_event_conn_io_writev(c, iov, nhd); + } - /* - * Disposal of surplus kernel operations - * if there are no headers and trailers. - */ + sb.iobuf = &iov[1]; + sb.nmax = 1; - if (nhd == 0) { - hdtrl = NULL; - iov[0].iov_base = NULL; - iov[0].iov_len = 0; + ntr = nxt_sendbuf_mem_coalesce(c->socket.task, &sb); - } else { - hdtrl = iov; - } + /* + * Disposal of surplus kernel operations + * if there are no headers and trailers. + */ - if (ntr == 0) { - iov[1].iov_base = NULL; - iov[1].iov_len = 0; + if (nhd == 0) { + hdtrl = NULL; + iov[0].iov_base = NULL; + iov[0].iov_len = 0; - } else { - hdtrl = iov; - } + } else { + hdtrl = iov; + } - nxt_debug(c->socket.task, "sendfile(%d, %FD, @%O, %uz) hd:%ui tr:%ui", - c->socket.fd, fb->file->fd, fb->file_pos, file_size, - nhd, ntr); + if (ntr == 0) { + iov[1].iov_base = NULL; + iov[1].iov_len = 0; - n = nxt_sys_sendfile(c->socket.fd, fb->file->fd, fb->file_pos, - file_size, hdtrl, 0); + } else { + hdtrl = iov; + } - err = (n == -1) ? nxt_errno : 0; + nxt_debug(c->socket.task, "sendfile(%d, %FD, @%O, %uz) hd:%ui tr:%ui", + c->socket.fd, fb->file->fd, fb->file_pos, file_size, nhd, ntr); - nxt_debug(c->socket.task, "sendfile(): %uz", n); + n = nxt_sys_sendfile(c->socket.fd, fb->file->fd, fb->file_pos, file_size, + hdtrl, 0); - if (n == -1) { - switch (err) { + err = (n == -1) ? nxt_errno : 0; - case NXT_EAGAIN: - c->socket.write_ready = 0; - break; + nxt_debug(c->socket.task, "sendfile(): %uz", n); - case NXT_EINTR: - break; + if (n == -1) { + switch (err) { - default: - c->socket.error = err; - nxt_log(c->socket.task, nxt_socket_error_level(err), - "sendfile(%d, %FD, @%O, %uz) failed \"%FN\" hd:%ui tr:%ui", - c->socket.fd, fb->file_pos, file_size, &fb->file->name, - nhd, ntr); + case NXT_EAGAIN: + c->socket.write_ready = 0; + break; - return NXT_ERROR; - } + case NXT_EINTR: + break; - nxt_debug(c->socket.task, "sendfile() %E", err); + default: + c->socket.error = err; + nxt_log(c->socket.task, nxt_socket_error_level(err), + "sendfile(%d, %FD, @%O, %uz) failed \"%FN\" hd:%ui tr:%ui", + c->socket.fd, fb->file_pos, file_size, &fb->file->name, nhd, ntr); - return 0; + return NXT_ERROR; } - if (n < (ssize_t) sb.size) { - c->socket.write_ready = 0; - } + nxt_debug(c->socket.task, "sendfile() %E", err); + + return 0; + } + + if (n < (ssize_t)sb.size) { + c->socket.write_ready = 0; + } - return n; + return n; } diff --git a/src/nxt_http.h b/src/nxt_http.h index 5369c8e16..717042de3 100644 --- a/src/nxt_http.h +++ b/src/nxt_http.h @@ -9,319 +9,293 @@ #include - typedef enum { - NXT_HTTP_UNSET = -1, - NXT_HTTP_INVALID = 0, - - NXT_HTTP_CONTINUE = 100, - NXT_HTTP_SWITCHING_PROTOCOLS = 101, - - NXT_HTTP_OK = 200, - NXT_HTTP_NO_CONTENT = 204, - - NXT_HTTP_MULTIPLE_CHOICES = 300, - NXT_HTTP_MOVED_PERMANENTLY = 301, - NXT_HTTP_FOUND = 302, - NXT_HTTP_SEE_OTHER = 303, - NXT_HTTP_NOT_MODIFIED = 304, - NXT_HTTP_TEMPORARY_REDIRECT = 307, - NXT_HTTP_PERMANENT_REDIRECT = 308, - - NXT_HTTP_BAD_REQUEST = 400, - NXT_HTTP_FORBIDDEN = 403, - NXT_HTTP_NOT_FOUND = 404, - NXT_HTTP_METHOD_NOT_ALLOWED = 405, - NXT_HTTP_REQUEST_TIMEOUT = 408, - NXT_HTTP_LENGTH_REQUIRED = 411, - NXT_HTTP_PAYLOAD_TOO_LARGE = 413, - NXT_HTTP_URI_TOO_LONG = 414, - NXT_HTTP_UPGRADE_REQUIRED = 426, - NXT_HTTP_REQUEST_HEADER_FIELDS_TOO_LARGE = 431, - - NXT_HTTP_TO_HTTPS = 497, - - NXT_HTTP_INTERNAL_SERVER_ERROR = 500, - NXT_HTTP_NOT_IMPLEMENTED = 501, - NXT_HTTP_BAD_GATEWAY = 502, - NXT_HTTP_SERVICE_UNAVAILABLE = 503, - NXT_HTTP_GATEWAY_TIMEOUT = 504, - NXT_HTTP_VERSION_NOT_SUPPORTED = 505, - NXT_HTTP_SERVER_ERROR_MAX = 599, - - NXT_HTTP_STATUS_MAX = 999, + NXT_HTTP_UNSET = -1, + NXT_HTTP_INVALID = 0, + + NXT_HTTP_CONTINUE = 100, + NXT_HTTP_SWITCHING_PROTOCOLS = 101, + + NXT_HTTP_OK = 200, + NXT_HTTP_NO_CONTENT = 204, + + NXT_HTTP_MULTIPLE_CHOICES = 300, + NXT_HTTP_MOVED_PERMANENTLY = 301, + NXT_HTTP_FOUND = 302, + NXT_HTTP_SEE_OTHER = 303, + NXT_HTTP_NOT_MODIFIED = 304, + NXT_HTTP_TEMPORARY_REDIRECT = 307, + NXT_HTTP_PERMANENT_REDIRECT = 308, + + NXT_HTTP_BAD_REQUEST = 400, + NXT_HTTP_FORBIDDEN = 403, + NXT_HTTP_NOT_FOUND = 404, + NXT_HTTP_METHOD_NOT_ALLOWED = 405, + NXT_HTTP_REQUEST_TIMEOUT = 408, + NXT_HTTP_LENGTH_REQUIRED = 411, + NXT_HTTP_PAYLOAD_TOO_LARGE = 413, + NXT_HTTP_URI_TOO_LONG = 414, + NXT_HTTP_UPGRADE_REQUIRED = 426, + NXT_HTTP_REQUEST_HEADER_FIELDS_TOO_LARGE = 431, + + NXT_HTTP_TO_HTTPS = 497, + + NXT_HTTP_INTERNAL_SERVER_ERROR = 500, + NXT_HTTP_NOT_IMPLEMENTED = 501, + NXT_HTTP_BAD_GATEWAY = 502, + NXT_HTTP_SERVICE_UNAVAILABLE = 503, + NXT_HTTP_GATEWAY_TIMEOUT = 504, + NXT_HTTP_VERSION_NOT_SUPPORTED = 505, + NXT_HTTP_SERVER_ERROR_MAX = 599, + + NXT_HTTP_STATUS_MAX = 999, } nxt_http_status_t; - typedef enum { - NXT_HTTP_TE_NONE = 0, - NXT_HTTP_TE_CHUNKED = 1, - NXT_HTTP_TE_UNSUPPORTED = 2, + NXT_HTTP_TE_NONE = 0, + NXT_HTTP_TE_CHUNKED = 1, + NXT_HTTP_TE_UNSUPPORTED = 2, } nxt_http_te_t; - typedef enum { - NXT_HTTP_PROTO_H1 = 0, - NXT_HTTP_PROTO_H2, - NXT_HTTP_PROTO_DEVNULL, + NXT_HTTP_PROTO_H1 = 0, + NXT_HTTP_PROTO_H2, + NXT_HTTP_PROTO_DEVNULL, } nxt_http_protocol_t; - typedef struct { - nxt_work_handler_t ready_handler; - nxt_work_handler_t error_handler; + nxt_work_handler_t ready_handler; + nxt_work_handler_t error_handler; } nxt_http_request_state_t; - -typedef struct nxt_h1proto_s nxt_h1proto_t; +typedef struct nxt_h1proto_s nxt_h1proto_t; struct nxt_h1p_websocket_timer_s { - nxt_timer_t timer; - nxt_h1proto_t *h1p; - nxt_msec_t keepalive_interval; + nxt_timer_t timer; + nxt_h1proto_t *h1p; + nxt_msec_t keepalive_interval; }; - typedef union { - void *any; - nxt_h1proto_t *h1; + void *any; + nxt_h1proto_t *h1; } nxt_http_proto_t; +#define nxt_http_field_name_set(_field, _name) \ + do { \ + (_field)->name_length = nxt_length(_name); \ + (_field)->name = (u_char *)_name; \ + } while (0) -#define nxt_http_field_name_set(_field, _name) \ - do { \ - (_field)->name_length = nxt_length(_name); \ - (_field)->name = (u_char *) _name; \ - } while (0) - - -#define nxt_http_field_set(_field, _name, _value) \ - do { \ - (_field)->name_length = nxt_length(_name); \ - (_field)->value_length = nxt_length(_value); \ - (_field)->name = (u_char *) _name; \ - (_field)->value = (u_char *) _value; \ - } while (0) - +#define nxt_http_field_set(_field, _name, _value) \ + do { \ + (_field)->name_length = nxt_length(_name); \ + (_field)->value_length = nxt_length(_value); \ + (_field)->name = (u_char *)_name; \ + (_field)->value = (u_char *)_value; \ + } while (0) typedef struct { - nxt_list_t *fields; - nxt_http_field_t *date; - nxt_http_field_t *content_type; - nxt_http_field_t *content_length; - nxt_off_t content_length_n; + nxt_list_t *fields; + nxt_http_field_t *date; + nxt_http_field_t *content_type; + nxt_http_field_t *content_length; + nxt_off_t content_length_n; } nxt_http_response_t; - -typedef struct nxt_upstream_server_s nxt_upstream_server_t; +typedef struct nxt_upstream_server_s nxt_upstream_server_t; typedef struct { - nxt_http_proto_t proto; - nxt_http_request_t *request; - nxt_upstream_server_t *server; - nxt_list_t *fields; - nxt_buf_t *body; - - nxt_http_status_t status:16; - nxt_http_protocol_t protocol:8; /* 2 bits */ - uint8_t header_received; /* 1 bit */ - uint8_t closed; /* 1 bit */ + nxt_http_proto_t proto; + nxt_http_request_t *request; + nxt_upstream_server_t *server; + nxt_list_t *fields; + nxt_buf_t *body; + + nxt_http_status_t status : 16; + nxt_http_protocol_t protocol : 8; /* 2 bits */ + uint8_t header_received; /* 1 bit */ + uint8_t closed; /* 1 bit */ } nxt_http_peer_t; - struct nxt_http_request_s { - nxt_http_proto_t proto; - nxt_socket_conf_joint_t *conf; - - nxt_mp_t *mem_pool; - - nxt_buf_t *body; - nxt_buf_t *ws_frame; - nxt_buf_t *out; - const nxt_http_request_state_t *state; - - nxt_nsec_t start_time; - - nxt_str_t host; - nxt_str_t server_name; - nxt_str_t request_line; - nxt_str_t target; - nxt_str_t version; - nxt_str_t *method; - nxt_str_t *path; - nxt_str_t *args; - - nxt_str_t args_decoded; - nxt_array_t *arguments; /* of nxt_http_name_value_t */ - nxt_array_t *cookies; /* of nxt_http_name_value_t */ - nxt_list_t *fields; - nxt_http_field_t *content_type; - nxt_http_field_t *content_length; - nxt_http_field_t *chunked_field; - nxt_http_field_t *cookie; - nxt_http_field_t *referer; - nxt_http_field_t *user_agent; - nxt_http_field_t *authorization; - nxt_off_t content_length_n; - - nxt_sockaddr_t *remote; - nxt_sockaddr_t *local; - nxt_task_t task; - - nxt_timer_t timer; - void *timer_data; - - nxt_tstr_query_t *tstr_query; - nxt_tstr_cache_t tstr_cache; - - nxt_http_action_t *action; - void *req_rpc_data; + nxt_http_proto_t proto; + nxt_socket_conf_joint_t *conf; + + nxt_mp_t *mem_pool; + + nxt_buf_t *body; + nxt_buf_t *ws_frame; + nxt_buf_t *out; + const nxt_http_request_state_t *state; + + nxt_nsec_t start_time; + + nxt_str_t host; + nxt_str_t server_name; + nxt_str_t request_line; + nxt_str_t target; + nxt_str_t version; + nxt_str_t *method; + nxt_str_t *path; + nxt_str_t *args; + + nxt_str_t args_decoded; + nxt_array_t *arguments; /* of nxt_http_name_value_t */ + nxt_array_t *cookies; /* of nxt_http_name_value_t */ + nxt_list_t *fields; + nxt_http_field_t *content_type; + nxt_http_field_t *content_length; + nxt_http_field_t *chunked_field; + nxt_http_field_t *cookie; + nxt_http_field_t *referer; + nxt_http_field_t *user_agent; + nxt_http_field_t *authorization; + nxt_off_t content_length_n; + + nxt_sockaddr_t *remote; + nxt_sockaddr_t *local; + nxt_task_t task; + + nxt_timer_t timer; + void *timer_data; + + nxt_tstr_query_t *tstr_query; + nxt_tstr_cache_t tstr_cache; + + nxt_http_action_t *action; + void *req_rpc_data; #if (NXT_HAVE_REGEX) - nxt_regex_match_t *regex_match; + nxt_regex_match_t *regex_match; #endif - nxt_http_peer_t *peer; - nxt_buf_t *last; + nxt_http_peer_t *peer; + nxt_buf_t *last; - nxt_queue_link_t app_link; /* nxt_app_t.ack_waiting_req */ - nxt_event_engine_t *engine; - nxt_work_t err_work; + nxt_queue_link_t app_link; /* nxt_app_t.ack_waiting_req */ + nxt_event_engine_t *engine; + nxt_work_t err_work; - nxt_http_response_t resp; + nxt_http_response_t resp; - nxt_http_status_t status:16; + nxt_http_status_t status : 16; - uint8_t log_route; /* 1 bit */ - uint8_t quoted_target; /* 1 bit */ - uint8_t uri_changed; /* 1 bit */ + uint8_t log_route; /* 1 bit */ + uint8_t quoted_target; /* 1 bit */ + uint8_t uri_changed; /* 1 bit */ - uint8_t pass_count; /* 8 bits */ - uint8_t app_target; - nxt_http_protocol_t protocol:8; /* 2 bits */ - uint8_t tls; /* 1 bit */ - uint8_t logged; /* 1 bit */ - uint8_t header_sent; /* 1 bit */ - uint8_t inconsistent; /* 1 bit */ - uint8_t error; /* 1 bit */ - uint8_t websocket_handshake; /* 1 bit */ - uint8_t chunked; /* 1 bit */ + uint8_t pass_count; /* 8 bits */ + uint8_t app_target; + nxt_http_protocol_t protocol : 8; /* 2 bits */ + uint8_t tls; /* 1 bit */ + uint8_t logged; /* 1 bit */ + uint8_t header_sent; /* 1 bit */ + uint8_t inconsistent; /* 1 bit */ + uint8_t error; /* 1 bit */ + uint8_t websocket_handshake; /* 1 bit */ + uint8_t chunked; /* 1 bit */ }; - typedef struct { - uint16_t hash; - uint16_t name_length; - uint32_t value_length; - u_char *name; - u_char *value; + uint16_t hash; + uint16_t name_length; + uint32_t value_length; + u_char *name; + u_char *value; } nxt_http_name_value_t; - typedef enum { - NXT_HTTP_URI_ENCODING_NONE = 0, - NXT_HTTP_URI_ENCODING, - NXT_HTTP_URI_ENCODING_PLUS + NXT_HTTP_URI_ENCODING_NONE = 0, + NXT_HTTP_URI_ENCODING, + NXT_HTTP_URI_ENCODING_PLUS } nxt_http_uri_encoding_t; - -typedef struct nxt_http_route_s nxt_http_route_t; -typedef struct nxt_http_route_rule_s nxt_http_route_rule_t; -typedef struct nxt_http_route_addr_rule_s nxt_http_route_addr_rule_t; - +typedef struct nxt_http_route_s nxt_http_route_t; +typedef struct nxt_http_route_rule_s nxt_http_route_rule_t; +typedef struct nxt_http_route_addr_rule_s nxt_http_route_addr_rule_t; typedef struct { - nxt_conf_value_t *rewrite; - nxt_conf_value_t *set_headers; - nxt_conf_value_t *pass; - nxt_conf_value_t *ret; - nxt_conf_value_t *location; - nxt_conf_value_t *proxy; - nxt_conf_value_t *share; - nxt_conf_value_t *index; - nxt_str_t chroot; - nxt_conf_value_t *follow_symlinks; - nxt_conf_value_t *traverse_mounts; - nxt_conf_value_t *types; - nxt_conf_value_t *fallback; + nxt_conf_value_t *rewrite; + nxt_conf_value_t *set_headers; + nxt_conf_value_t *pass; + nxt_conf_value_t *ret; + nxt_conf_value_t *location; + nxt_conf_value_t *proxy; + nxt_conf_value_t *share; + nxt_conf_value_t *index; + nxt_str_t chroot; + nxt_conf_value_t *follow_symlinks; + nxt_conf_value_t *traverse_mounts; + nxt_conf_value_t *types; + nxt_conf_value_t *fallback; } nxt_http_action_conf_t; - struct nxt_http_action_s { - nxt_http_action_t *(*handler)(nxt_task_t *task, - nxt_http_request_t *r, - nxt_http_action_t *action); - union { - void *conf; - nxt_http_route_t *route; - nxt_upstream_t *upstream; - uint32_t upstream_number; - nxt_tstr_t *tstr; - nxt_str_t *pass; - } u; - - nxt_tstr_t *rewrite; - nxt_array_t *set_headers; /* of nxt_http_field_t */ - nxt_http_action_t *fallback; + nxt_http_action_t *(*handler)(nxt_task_t *task, nxt_http_request_t *r, + nxt_http_action_t *action); + union { + void *conf; + nxt_http_route_t *route; + nxt_upstream_t *upstream; + uint32_t upstream_number; + nxt_tstr_t *tstr; + nxt_str_t *pass; + } u; + + nxt_tstr_t *rewrite; + nxt_array_t *set_headers; /* of nxt_http_field_t */ + nxt_http_action_t *fallback; }; - typedef struct { - void (*body_read)(nxt_task_t *task, nxt_http_request_t *r); - void (*local_addr)(nxt_task_t *task, nxt_http_request_t *r); - void (*header_send)(nxt_task_t *task, nxt_http_request_t *r, - nxt_work_handler_t body_handler, void *data); - void (*send)(nxt_task_t *task, nxt_http_request_t *r, nxt_buf_t *out); - nxt_off_t (*body_bytes_sent)(nxt_task_t *task, nxt_http_proto_t proto); - void (*discard)(nxt_task_t *task, nxt_http_request_t *r, nxt_buf_t *last); - void (*close)(nxt_task_t *task, nxt_http_proto_t proto, - nxt_socket_conf_joint_t *joint); - - void (*peer_connect)(nxt_task_t *task, nxt_http_peer_t *peer); - void (*peer_header_send)(nxt_task_t *task, nxt_http_peer_t *peer); - void (*peer_header_read)(nxt_task_t *task, nxt_http_peer_t *peer); - void (*peer_read)(nxt_task_t *task, nxt_http_peer_t *peer); - void (*peer_close)(nxt_task_t *task, nxt_http_peer_t *peer); - - void (*ws_frame_start)(nxt_task_t *task, nxt_http_request_t *r, - nxt_buf_t *ws_frame); + void (*body_read)(nxt_task_t *task, nxt_http_request_t *r); + void (*local_addr)(nxt_task_t *task, nxt_http_request_t *r); + void (*header_send)(nxt_task_t *task, nxt_http_request_t *r, + nxt_work_handler_t body_handler, void *data); + void (*send)(nxt_task_t *task, nxt_http_request_t *r, nxt_buf_t *out); + nxt_off_t (*body_bytes_sent)(nxt_task_t *task, nxt_http_proto_t proto); + void (*discard)(nxt_task_t *task, nxt_http_request_t *r, nxt_buf_t *last); + void (*close)(nxt_task_t *task, nxt_http_proto_t proto, + nxt_socket_conf_joint_t *joint); + + void (*peer_connect)(nxt_task_t *task, nxt_http_peer_t *peer); + void (*peer_header_send)(nxt_task_t *task, nxt_http_peer_t *peer); + void (*peer_header_read)(nxt_task_t *task, nxt_http_peer_t *peer); + void (*peer_read)(nxt_task_t *task, nxt_http_peer_t *peer); + void (*peer_close)(nxt_task_t *task, nxt_http_peer_t *peer); + + void (*ws_frame_start)(nxt_task_t *task, nxt_http_request_t *r, + nxt_buf_t *ws_frame); } nxt_http_proto_table_t; - typedef struct { - nxt_str_t *header; - uint32_t header_hash; + nxt_str_t *header; + uint32_t header_hash; } nxt_http_forward_header_t; - struct nxt_http_forward_s { - nxt_http_forward_header_t client_ip; - nxt_http_forward_header_t protocol; - nxt_http_route_addr_rule_t *source; - uint8_t recursive; /* 1 bit */ + nxt_http_forward_header_t client_ip; + nxt_http_forward_header_t protocol; + nxt_http_route_addr_rule_t *source; + uint8_t recursive; /* 1 bit */ }; +#define NXT_HTTP_DATE_LEN nxt_length("Wed, 31 Dec 1986 16:40:00 GMT") -#define NXT_HTTP_DATE_LEN nxt_length("Wed, 31 Dec 1986 16:40:00 GMT") +nxt_inline u_char *nxt_http_date(u_char *buf, struct tm *tm) { + static const char *const week[] = {"Sun", "Mon", "Tue", "Wed", + "Thu", "Fri", "Sat"}; -nxt_inline u_char * -nxt_http_date(u_char *buf, struct tm *tm) -{ - static const char * const week[] = { "Sun", "Mon", "Tue", "Wed", "Thu", - "Fri", "Sat" }; + static const char *const month[] = {"Jan", "Feb", "Mar", "Apr", "May", "Jun", + "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"}; - static const char * const month[] = { "Jan", "Feb", "Mar", "Apr", "May", - "Jun", "Jul", "Aug", "Sep", "Oct", - "Nov", "Dec" }; - - return nxt_sprintf(buf, buf + NXT_HTTP_DATE_LEN, - "%s, %02d %s %4d %02d:%02d:%02d GMT", - week[tm->tm_wday], tm->tm_mday, - month[tm->tm_mon], tm->tm_year + 1900, - tm->tm_hour, tm->tm_min, tm->tm_sec); + return nxt_sprintf(buf, buf + NXT_HTTP_DATE_LEN, + "%s, %02d %s %4d %02d:%02d:%02d GMT", week[tm->tm_wday], + tm->tm_mday, month[tm->tm_mon], tm->tm_year + 1900, + tm->tm_hour, tm->tm_min, tm->tm_sec); } - nxt_int_t nxt_http_init(nxt_task_t *task); nxt_int_t nxt_h1p_init(nxt_task_t *task); nxt_int_t nxt_http_response_hash_init(nxt_task_t *task); @@ -329,121 +303,136 @@ nxt_int_t nxt_http_response_hash_init(nxt_task_t *task); void nxt_http_conn_init(nxt_task_t *task, void *obj, void *data); nxt_http_request_t *nxt_http_request_create(nxt_task_t *task); void nxt_http_request_error(nxt_task_t *task, nxt_http_request_t *r, - nxt_http_status_t status); + nxt_http_status_t status); void nxt_http_request_read_body(nxt_task_t *task, nxt_http_request_t *r); void nxt_http_request_header_send(nxt_task_t *task, nxt_http_request_t *r, - nxt_work_handler_t body_handler, void *data); + nxt_work_handler_t body_handler, void *data); void nxt_http_request_ws_frame_start(nxt_task_t *task, nxt_http_request_t *r, - nxt_buf_t *ws_frame); + nxt_buf_t *ws_frame); void nxt_http_request_send(nxt_task_t *task, nxt_http_request_t *r, - nxt_buf_t *out); + nxt_buf_t *out); nxt_buf_t *nxt_http_buf_mem(nxt_task_t *task, nxt_http_request_t *r, - size_t size); + size_t size); nxt_buf_t *nxt_http_buf_last(nxt_http_request_t *r); void nxt_http_request_error_handler(nxt_task_t *task, void *obj, void *data); void nxt_http_request_close_handler(nxt_task_t *task, void *obj, void *data); nxt_int_t nxt_http_request_host(void *ctx, nxt_http_field_t *field, - uintptr_t data); + uintptr_t data); nxt_int_t nxt_http_request_field(void *ctx, nxt_http_field_t *field, - uintptr_t offset); + uintptr_t offset); nxt_int_t nxt_http_request_content_length(void *ctx, nxt_http_field_t *field, - uintptr_t data); + uintptr_t data); nxt_array_t *nxt_http_arguments_parse(nxt_http_request_t *r); nxt_array_t *nxt_http_cookies_parse(nxt_http_request_t *r); int64_t nxt_http_field_hash(nxt_mp_t *mp, nxt_str_t *name, - nxt_bool_t case_sensitive, uint8_t encoding); + nxt_bool_t case_sensitive, uint8_t encoding); int64_t nxt_http_argument_hash(nxt_mp_t *mp, nxt_str_t *name); int64_t nxt_http_header_hash(nxt_mp_t *mp, nxt_str_t *name); int64_t nxt_http_cookie_hash(nxt_mp_t *mp, nxt_str_t *name); nxt_http_routes_t *nxt_http_routes_create(nxt_task_t *task, - nxt_router_temp_conf_t *tmcf, nxt_conf_value_t *routes_conf); + nxt_router_temp_conf_t *tmcf, + nxt_conf_value_t *routes_conf); nxt_http_action_t *nxt_http_action_create(nxt_task_t *task, - nxt_router_temp_conf_t *tmcf, nxt_str_t *pass); + nxt_router_temp_conf_t *tmcf, + nxt_str_t *pass); nxt_int_t nxt_http_routes_resolve(nxt_task_t *task, - nxt_router_temp_conf_t *tmcf); + nxt_router_temp_conf_t *tmcf); nxt_int_t nxt_http_pass_segments(nxt_mp_t *mp, nxt_str_t *pass, - nxt_str_t *segments, nxt_uint_t n); + nxt_str_t *segments, nxt_uint_t n); nxt_http_action_t *nxt_http_pass_application(nxt_task_t *task, - nxt_router_conf_t *rtcf, nxt_str_t *name); -nxt_http_route_addr_rule_t *nxt_http_route_addr_rule_create( - nxt_task_t *task, nxt_mp_t *mp, nxt_conf_value_t *cv); + nxt_router_conf_t *rtcf, + nxt_str_t *name); +nxt_http_route_addr_rule_t * +nxt_http_route_addr_rule_create(nxt_task_t *task, nxt_mp_t *mp, + nxt_conf_value_t *cv); nxt_int_t nxt_http_route_addr_rule(nxt_http_request_t *r, - nxt_http_route_addr_rule_t *addr_rule, nxt_sockaddr_t *sockaddr); -nxt_http_route_rule_t *nxt_http_route_types_rule_create(nxt_task_t *task, - nxt_mp_t *mp, nxt_conf_value_t *types); + nxt_http_route_addr_rule_t *addr_rule, + nxt_sockaddr_t *sockaddr); +nxt_http_route_rule_t * +nxt_http_route_types_rule_create(nxt_task_t *task, nxt_mp_t *mp, + nxt_conf_value_t *types); nxt_int_t nxt_http_route_test_rule(nxt_http_request_t *r, - nxt_http_route_rule_t *rule, u_char *start, size_t length); + nxt_http_route_rule_t *rule, u_char *start, + size_t length); nxt_int_t nxt_http_action_init(nxt_task_t *task, nxt_router_temp_conf_t *tmcf, - nxt_conf_value_t *cv, nxt_http_action_t *action); + nxt_conf_value_t *cv, nxt_http_action_t *action); void nxt_http_request_action(nxt_task_t *task, nxt_http_request_t *r, - nxt_http_action_t *action); + nxt_http_action_t *action); nxt_int_t nxt_upstreams_create(nxt_task_t *task, nxt_router_temp_conf_t *tmcf, - nxt_conf_value_t *conf); + nxt_conf_value_t *conf); nxt_int_t nxt_upstreams_joint_create(nxt_router_temp_conf_t *tmcf, - nxt_upstream_t ***upstream_joint); + nxt_upstream_t ***upstream_joint); nxt_int_t nxt_http_rewrite_init(nxt_router_conf_t *rtcf, - nxt_http_action_t *action, nxt_http_action_conf_t *acf); + nxt_http_action_t *action, + nxt_http_action_conf_t *acf); nxt_int_t nxt_http_rewrite(nxt_task_t *task, nxt_http_request_t *r); nxt_int_t nxt_http_set_headers_init(nxt_router_conf_t *rtcf, - nxt_http_action_t *action, nxt_http_action_conf_t *acf); + nxt_http_action_t *action, + nxt_http_action_conf_t *acf); nxt_int_t nxt_http_set_headers(nxt_http_request_t *r); nxt_int_t nxt_http_return_init(nxt_router_conf_t *rtcf, - nxt_http_action_t *action, nxt_http_action_conf_t *acf); + nxt_http_action_t *action, + nxt_http_action_conf_t *acf); nxt_int_t nxt_http_static_init(nxt_task_t *task, nxt_router_temp_conf_t *tmcf, - nxt_http_action_t *action, nxt_http_action_conf_t *acf); + nxt_http_action_t *action, + nxt_http_action_conf_t *acf); nxt_int_t nxt_http_static_mtypes_init(nxt_mp_t *mp, nxt_lvlhsh_t *hash); nxt_int_t nxt_http_static_mtypes_hash_add(nxt_mp_t *mp, nxt_lvlhsh_t *hash, - const nxt_str_t *exten, nxt_str_t *type); + const nxt_str_t *exten, + nxt_str_t *type); nxt_str_t *nxt_http_static_mtype_get(nxt_lvlhsh_t *hash, - const nxt_str_t *exten); + const nxt_str_t *exten); nxt_http_action_t *nxt_http_application_handler(nxt_task_t *task, - nxt_http_request_t *r, nxt_http_action_t *action); + nxt_http_request_t *r, + nxt_http_action_t *action); nxt_int_t nxt_upstream_find(nxt_upstreams_t *upstreams, nxt_str_t *name, - nxt_http_action_t *action); + nxt_http_action_t *action); nxt_http_action_t *nxt_upstream_proxy_handler(nxt_task_t *task, - nxt_http_request_t *r, nxt_upstream_t *upstream); + nxt_http_request_t *r, + nxt_upstream_t *upstream); nxt_int_t nxt_http_proxy_init(nxt_mp_t *mp, nxt_http_action_t *action, - nxt_http_action_conf_t *acf); + nxt_http_action_conf_t *acf); nxt_int_t nxt_http_proxy_date(void *ctx, nxt_http_field_t *field, - uintptr_t data); + uintptr_t data); nxt_int_t nxt_http_proxy_content_length(void *ctx, nxt_http_field_t *field, - uintptr_t data); + uintptr_t data); nxt_int_t nxt_http_proxy_skip(void *ctx, nxt_http_field_t *field, - uintptr_t data); + uintptr_t data); nxt_buf_t *nxt_http_proxy_buf_mem_alloc(nxt_task_t *task, nxt_http_request_t *r, - size_t size); + size_t size); void nxt_http_proxy_buf_mem_free(nxt_task_t *task, nxt_http_request_t *r, - nxt_buf_t *b); + nxt_buf_t *b); -extern nxt_time_string_t nxt_http_date_cache; +extern nxt_time_string_t nxt_http_date_cache; -extern nxt_lvlhsh_t nxt_response_fields_hash; +extern nxt_lvlhsh_t nxt_response_fields_hash; -extern const nxt_http_proto_table_t nxt_http_proto[]; +extern const nxt_http_proto_table_t nxt_http_proto[]; void nxt_h1p_websocket_first_frame_start(nxt_task_t *task, - nxt_http_request_t *r, nxt_buf_t *ws_frame); + nxt_http_request_t *r, + nxt_buf_t *ws_frame); void nxt_h1p_websocket_frame_start(nxt_task_t *task, nxt_http_request_t *r, - nxt_buf_t *ws_frame); + nxt_buf_t *ws_frame); void nxt_h1p_complete_buffers(nxt_task_t *task, nxt_h1proto_t *h1p, - nxt_bool_t all); + nxt_bool_t all); nxt_msec_t nxt_h1p_conn_request_timer_value(nxt_conn_t *c, uintptr_t data); int nxt_http_cond_value(nxt_task_t *task, nxt_http_request_t *r, - nxt_tstr_cond_t *cond); + nxt_tstr_cond_t *cond); -extern const nxt_conn_state_t nxt_h1p_idle_close_state; +extern const nxt_conn_state_t nxt_h1p_idle_close_state; -#endif /* _NXT_HTTP_H_INCLUDED_ */ +#endif /* _NXT_HTTP_H_INCLUDED_ */ diff --git a/src/nxt_http_chunk_parse.c b/src/nxt_http_chunk_parse.c index a43ce75b8..dd5692527 100644 --- a/src/nxt_http_chunk_parse.c +++ b/src/nxt_http_chunk_parse.c @@ -6,265 +6,252 @@ #include +#define NXT_HTTP_CHUNK_MIDDLE 0 +#define NXT_HTTP_CHUNK_END_ON_BORDER 1 +#define NXT_HTTP_CHUNK_END 2 -#define NXT_HTTP_CHUNK_MIDDLE 0 -#define NXT_HTTP_CHUNK_END_ON_BORDER 1 -#define NXT_HTTP_CHUNK_END 2 - - -#define nxt_size_is_sufficient(cs) \ - (cs < ((__typeof__(cs)) 1 << (sizeof(cs) * 8 - 4))) - +#define nxt_size_is_sufficient(cs) \ + (cs < ((__typeof__(cs))1 << (sizeof(cs) * 8 - 4))) static nxt_int_t nxt_http_chunk_buffer(nxt_http_chunk_parse_t *hcp, - nxt_buf_t ***tail, nxt_buf_t *in); - + nxt_buf_t ***tail, nxt_buf_t *in); static void nxt_http_chunk_buf_completion(nxt_task_t *task, void *obj, - void *data); - - -nxt_buf_t * -nxt_http_chunk_parse(nxt_task_t *task, nxt_http_chunk_parse_t *hcp, - nxt_buf_t *in) -{ - u_char c, ch; - nxt_int_t ret; - nxt_buf_t *b, *out, *next, **tail; - enum { - sw_start = 0, - sw_chunk_size, - sw_chunk_size_linefeed, - sw_chunk_end_newline, - sw_chunk_end_linefeed, - sw_chunk, - } state; - - next = NULL; - out = NULL; - tail = &out; - - state = hcp->state; - - for (b = in; b != NULL; b = next) { - - while (b->mem.pos < b->mem.free) { - /* - * The sw_chunk state is tested outside the switch - * to preserve hcp->pos and to not touch memory. - */ - if (state == sw_chunk) { - ret = nxt_http_chunk_buffer(hcp, &tail, b); - - if (ret == NXT_HTTP_CHUNK_MIDDLE) { - goto next; - } - - if (nxt_slow_path(ret == NXT_ERROR)) { - hcp->error = 1; - return out; - } - - state = sw_chunk_end_newline; + void *data); + +nxt_buf_t *nxt_http_chunk_parse(nxt_task_t *task, nxt_http_chunk_parse_t *hcp, + nxt_buf_t *in) { + u_char c, ch; + nxt_int_t ret; + nxt_buf_t *b, *out, *next, **tail; + enum { + sw_start = 0, + sw_chunk_size, + sw_chunk_size_linefeed, + sw_chunk_end_newline, + sw_chunk_end_linefeed, + sw_chunk, + } state; + + next = NULL; + out = NULL; + tail = &out; + + state = hcp->state; + + for (b = in; b != NULL; b = next) { + + while (b->mem.pos < b->mem.free) { + /* + * The sw_chunk state is tested outside the switch + * to preserve hcp->pos and to not touch memory. + */ + if (state == sw_chunk) { + ret = nxt_http_chunk_buffer(hcp, &tail, b); + + if (ret == NXT_HTTP_CHUNK_MIDDLE) { + goto next; + } - if (ret == NXT_HTTP_CHUNK_END_ON_BORDER) { - goto next; - } + if (nxt_slow_path(ret == NXT_ERROR)) { + hcp->error = 1; + return out; + } - /* ret == NXT_HTTP_CHUNK_END */ - } + state = sw_chunk_end_newline; - ch = *b->mem.pos++; + if (ret == NXT_HTTP_CHUNK_END_ON_BORDER) { + goto next; + } - switch (state) { + /* ret == NXT_HTTP_CHUNK_END */ + } - case sw_start: - state = sw_chunk_size; + ch = *b->mem.pos++; - c = ch - '0'; + switch (state) { - if (c <= 9) { - hcp->chunk_size = c; - continue; - } + case sw_start: + state = sw_chunk_size; - c = (ch | 0x20) - 'a'; + c = ch - '0'; - if (c <= 5) { - hcp->chunk_size = 0x0A + c; - continue; - } + if (c <= 9) { + hcp->chunk_size = c; + continue; + } - goto chunk_error; + c = (ch | 0x20) - 'a'; - case sw_chunk_size: + if (c <= 5) { + hcp->chunk_size = 0x0A + c; + continue; + } - c = ch - '0'; + goto chunk_error; - if (c > 9) { - c = (ch | 0x20) - 'a'; + case sw_chunk_size: - if (nxt_fast_path(c <= 5)) { - c += 0x0A; + c = ch - '0'; - } else if (nxt_fast_path(ch == '\r')) { - state = sw_chunk_size_linefeed; - continue; + if (c > 9) { + c = (ch | 0x20) - 'a'; - } else { - goto chunk_error; - } - } + if (nxt_fast_path(c <= 5)) { + c += 0x0A; - if (nxt_fast_path(nxt_size_is_sufficient(hcp->chunk_size))) { - hcp->chunk_size = (hcp->chunk_size << 4) + c; - continue; - } + } else if (nxt_fast_path(ch == '\r')) { + state = sw_chunk_size_linefeed; + continue; - goto chunk_error; + } else { + goto chunk_error; + } + } - case sw_chunk_size_linefeed: - if (nxt_fast_path(ch == '\n')) { + if (nxt_fast_path(nxt_size_is_sufficient(hcp->chunk_size))) { + hcp->chunk_size = (hcp->chunk_size << 4) + c; + continue; + } - if (hcp->chunk_size != 0) { - state = sw_chunk; - continue; - } + goto chunk_error; - hcp->last = 1; - state = sw_chunk_end_newline; - continue; - } + case sw_chunk_size_linefeed: + if (nxt_fast_path(ch == '\n')) { - goto chunk_error; + if (hcp->chunk_size != 0) { + state = sw_chunk; + continue; + } - case sw_chunk_end_newline: - if (nxt_fast_path(ch == '\r')) { - state = sw_chunk_end_linefeed; - continue; - } + hcp->last = 1; + state = sw_chunk_end_newline; + continue; + } - goto chunk_error; + goto chunk_error; - case sw_chunk_end_linefeed: - if (nxt_fast_path(ch == '\n')) { + case sw_chunk_end_newline: + if (nxt_fast_path(ch == '\r')) { + state = sw_chunk_end_linefeed; + continue; + } - if (!hcp->last) { - state = sw_start; - continue; - } + goto chunk_error; - return out; - } + case sw_chunk_end_linefeed: + if (nxt_fast_path(ch == '\n')) { - goto chunk_error; + if (!hcp->last) { + state = sw_start; + continue; + } - case sw_chunk: - /* - * This state is processed before the switch. - * It added here just to suppress a warning. - */ - continue; - } + return out; } - if (b->retain == 0) { - /* No chunk data was found in a buffer. */ - nxt_work_queue_add(&task->thread->engine->fast_work_queue, - b->completion_handler, task, b, b->parent); + goto chunk_error; - } - - next: + case sw_chunk: + /* + * This state is processed before the switch. + * It added here just to suppress a warning. + */ + continue; + } + } - next = b->next; - b->next = NULL; + if (b->retain == 0) { + /* No chunk data was found in a buffer. */ + nxt_work_queue_add(&task->thread->engine->fast_work_queue, + b->completion_handler, task, b, b->parent); } - hcp->state = state; + next: + + next = b->next; + b->next = NULL; + } - return out; + hcp->state = state; + + return out; chunk_error: - hcp->chunk_error = 1; + hcp->chunk_error = 1; - return out; + return out; } +static nxt_int_t nxt_http_chunk_buffer(nxt_http_chunk_parse_t *hcp, + nxt_buf_t ***tail, nxt_buf_t *in) { + u_char *p; + size_t size; + nxt_buf_t *b; -static nxt_int_t -nxt_http_chunk_buffer(nxt_http_chunk_parse_t *hcp, nxt_buf_t ***tail, - nxt_buf_t *in) -{ - u_char *p; - size_t size; - nxt_buf_t *b; - - p = in->mem.pos; - size = in->mem.free - p; + p = in->mem.pos; + size = in->mem.free - p; - b = nxt_buf_mem_alloc(hcp->mem_pool, 0, 0); - if (nxt_slow_path(b == NULL)) { - return NXT_ERROR; - } + b = nxt_buf_mem_alloc(hcp->mem_pool, 0, 0); + if (nxt_slow_path(b == NULL)) { + return NXT_ERROR; + } - **tail = b; - *tail = &b->next; + **tail = b; + *tail = &b->next; - nxt_mp_retain(hcp->mem_pool); - b->completion_handler = nxt_http_chunk_buf_completion; + nxt_mp_retain(hcp->mem_pool); + b->completion_handler = nxt_http_chunk_buf_completion; - b->parent = in; - in->retain++; - b->mem.pos = p; - b->mem.start = p; + b->parent = in; + in->retain++; + b->mem.pos = p; + b->mem.start = p; - if (hcp->chunk_size < size) { - p += hcp->chunk_size; - in->mem.pos = p; + if (hcp->chunk_size < size) { + p += hcp->chunk_size; + in->mem.pos = p; - b->mem.free = p; - b->mem.end = p; + b->mem.free = p; + b->mem.end = p; - return NXT_HTTP_CHUNK_END; - } + return NXT_HTTP_CHUNK_END; + } - b->mem.free = in->mem.free; - b->mem.end = in->mem.free; + b->mem.free = in->mem.free; + b->mem.end = in->mem.free; - hcp->chunk_size -= size; + hcp->chunk_size -= size; - if (hcp->chunk_size == 0) { - return NXT_HTTP_CHUNK_END_ON_BORDER; - } + if (hcp->chunk_size == 0) { + return NXT_HTTP_CHUNK_END_ON_BORDER; + } - return NXT_HTTP_CHUNK_MIDDLE; + return NXT_HTTP_CHUNK_MIDDLE; } +static void nxt_http_chunk_buf_completion(nxt_task_t *task, void *obj, + void *data) { + nxt_mp_t *mp; + nxt_buf_t *b, *next, *parent; -static void -nxt_http_chunk_buf_completion(nxt_task_t *task, void *obj, void *data) -{ - nxt_mp_t *mp; - nxt_buf_t *b, *next, *parent; - - b = obj; + b = obj; - nxt_debug(task, "buf completion: %p %p", b, b->mem.start); + nxt_debug(task, "buf completion: %p %p", b, b->mem.start); - nxt_assert(data == b->parent); + nxt_assert(data == b->parent); - do { - next = b->next; - parent = b->parent; - mp = b->data; + do { + next = b->next; + parent = b->parent; + mp = b->data; - nxt_mp_free(mp, b); - nxt_mp_release(mp); + nxt_mp_free(mp, b); + nxt_mp_release(mp); - nxt_buf_parent_completion(task, parent); + nxt_buf_parent_completion(task, parent); - b = next; - } while (b != NULL); + b = next; + } while (b != NULL); } diff --git a/src/nxt_http_error.c b/src/nxt_http_error.c index 370b12dbc..e9bb596bc 100644 --- a/src/nxt_http_error.c +++ b/src/nxt_http_error.c @@ -7,98 +7,86 @@ #include #include - static void nxt_http_request_send_error_body(nxt_task_t *task, void *r, - void *data); - - -static const nxt_http_request_state_t nxt_http_request_send_error_body_state; + void *data); +static const nxt_http_request_state_t nxt_http_request_send_error_body_state; -static const char error[] = - "" - "Error %03d" - "

Error %03d.\r\n"; +static const char error[] = "" + "Error %03d" + "

Error %03d.\r\n"; /* Two %03d (4 chars) patterns are replaced by status code (3 chars). */ -#define NXT_HTTP_ERROR_LEN (nxt_length(error) - 2) +#define NXT_HTTP_ERROR_LEN (nxt_length(error) - 2) +void nxt_http_request_error(nxt_task_t *task, nxt_http_request_t *r, + nxt_http_status_t status) { + nxt_http_field_t *content_type; -void -nxt_http_request_error(nxt_task_t *task, nxt_http_request_t *r, - nxt_http_status_t status) -{ - nxt_http_field_t *content_type; + nxt_debug(task, "http request error: %d", status); - nxt_debug(task, "http request error: %d", status); + if (r->header_sent || r->error) { + goto fail; + } - if (r->header_sent || r->error) { - goto fail; - } + r->error = (status == NXT_HTTP_INTERNAL_SERVER_ERROR); - r->error = (status == NXT_HTTP_INTERNAL_SERVER_ERROR); + r->status = status; - r->status = status; + r->resp.fields = nxt_list_create(r->mem_pool, 8, sizeof(nxt_http_field_t)); + if (nxt_slow_path(r->resp.fields == NULL)) { + goto fail; + } - r->resp.fields = nxt_list_create(r->mem_pool, 8, sizeof(nxt_http_field_t)); - if (nxt_slow_path(r->resp.fields == NULL)) { - goto fail; - } + content_type = nxt_list_zero_add(r->resp.fields); + if (nxt_slow_path(content_type == NULL)) { + goto fail; + } - content_type = nxt_list_zero_add(r->resp.fields); - if (nxt_slow_path(content_type == NULL)) { - goto fail; - } + nxt_http_field_set(content_type, "Content-Type", "text/html"); - nxt_http_field_set(content_type, "Content-Type", "text/html"); + r->resp.content_length = NULL; + r->resp.content_length_n = NXT_HTTP_ERROR_LEN; - r->resp.content_length = NULL; - r->resp.content_length_n = NXT_HTTP_ERROR_LEN; + r->state = &nxt_http_request_send_error_body_state; - r->state = &nxt_http_request_send_error_body_state; - - nxt_http_request_header_send(task, r, - nxt_http_request_send_error_body, NULL); - return; + nxt_http_request_header_send(task, r, nxt_http_request_send_error_body, NULL); + return; fail: - nxt_http_request_error_handler(task, r, r->proto.any); + nxt_http_request_error_handler(task, r, r->proto.any); } - -static const nxt_http_request_state_t nxt_http_request_send_error_body_state - nxt_aligned(64) = -{ - .error_handler = nxt_http_request_error_handler, +static const nxt_http_request_state_t + nxt_http_request_send_error_body_state nxt_aligned(64) = { + .error_handler = nxt_http_request_error_handler, }; +static void nxt_http_request_send_error_body(nxt_task_t *task, void *obj, + void *data) { + nxt_buf_t *out; + nxt_http_request_t *r; -static void -nxt_http_request_send_error_body(nxt_task_t *task, void *obj, void *data) -{ - nxt_buf_t *out; - nxt_http_request_t *r; - - r = obj; + r = obj; - nxt_debug(task, "http request send error body"); + nxt_debug(task, "http request send error body"); - out = nxt_http_buf_mem(task, r, NXT_HTTP_ERROR_LEN); - if (nxt_slow_path(out == NULL)) { - goto fail; - } + out = nxt_http_buf_mem(task, r, NXT_HTTP_ERROR_LEN); + if (nxt_slow_path(out == NULL)) { + goto fail; + } - out->mem.free = nxt_sprintf(out->mem.pos, out->mem.end, error, - r->status, r->status); + out->mem.free = + nxt_sprintf(out->mem.pos, out->mem.end, error, r->status, r->status); - out->next = nxt_http_buf_last(r); + out->next = nxt_http_buf_last(r); - nxt_http_request_send(task, r, out); + nxt_http_request_send(task, r, out); - return; + return; fail: - nxt_http_request_error_handler(task, r, r->proto.any); + nxt_http_request_error_handler(task, r, r->proto.any); } diff --git a/src/nxt_http_js.c b/src/nxt_http_js.c index 34689fba1..775670a0b 100644 --- a/src/nxt_http_js.c +++ b/src/nxt_http_js.c @@ -7,386 +7,370 @@ #include #include - static njs_int_t nxt_http_js_ext_uri(njs_vm_t *vm, njs_object_prop_t *prop, - njs_value_t *value, njs_value_t *setval, njs_value_t *retval); + njs_value_t *value, njs_value_t *setval, + njs_value_t *retval); static njs_int_t nxt_http_js_ext_host(njs_vm_t *vm, njs_object_prop_t *prop, - njs_value_t *value, njs_value_t *setval, njs_value_t *retval); + njs_value_t *value, njs_value_t *setval, + njs_value_t *retval); static njs_int_t nxt_http_js_ext_remote_addr(njs_vm_t *vm, - njs_object_prop_t *prop, njs_value_t *value, njs_value_t *setval, - njs_value_t *retval); -static njs_int_t nxt_http_js_ext_get_args(njs_vm_t *vm, - njs_object_prop_t *prop, njs_value_t *value, njs_value_t *setval, - njs_value_t *retval); + njs_object_prop_t *prop, + njs_value_t *value, + njs_value_t *setval, + njs_value_t *retval); +static njs_int_t nxt_http_js_ext_get_args(njs_vm_t *vm, njs_object_prop_t *prop, + njs_value_t *value, + njs_value_t *setval, + njs_value_t *retval); static njs_int_t nxt_http_js_ext_get_header(njs_vm_t *vm, - njs_object_prop_t *prop, njs_value_t *value, njs_value_t *setval, - njs_value_t *retval); -static njs_int_t nxt_http_js_ext_keys_header(njs_vm_t *vm, - njs_value_t *value, njs_value_t *keys); + njs_object_prop_t *prop, + njs_value_t *value, + njs_value_t *setval, + njs_value_t *retval); +static njs_int_t nxt_http_js_ext_keys_header(njs_vm_t *vm, njs_value_t *value, + njs_value_t *keys); static njs_int_t nxt_http_js_ext_get_cookie(njs_vm_t *vm, - njs_object_prop_t *prop, njs_value_t *value, njs_value_t *setval, - njs_value_t *retval); + njs_object_prop_t *prop, + njs_value_t *value, + njs_value_t *setval, + njs_value_t *retval); static njs_int_t nxt_http_js_ext_keys_cookie(njs_vm_t *vm, njs_value_t *value, - njs_value_t *keys); + njs_value_t *keys); static njs_int_t nxt_http_js_ext_get_var(njs_vm_t *vm, njs_object_prop_t *prop, - njs_value_t *value, njs_value_t *setval, njs_value_t *retval); - - -static njs_external_t nxt_http_js_proto[] = { - { - .flags = NJS_EXTERN_PROPERTY, - .name.string = njs_str("uri"), - .enumerable = 1, - .u.property = { - .handler = nxt_http_js_ext_uri, - } - }, - - { - .flags = NJS_EXTERN_PROPERTY, - .name.string = njs_str("host"), - .enumerable = 1, - .u.property = { - .handler = nxt_http_js_ext_host, - } - }, - - { - .flags = NJS_EXTERN_PROPERTY, - .name.string = njs_str("remoteAddr"), - .enumerable = 1, - .u.property = { - .handler = nxt_http_js_ext_remote_addr, - } - }, - - { - .flags = NJS_EXTERN_PROPERTY, - .name.string = njs_str("args"), - .enumerable = 1, - .u.property = { - .handler = nxt_http_js_ext_get_args, - } - }, - - { - .flags = NJS_EXTERN_OBJECT, - .name.string = njs_str("headers"), - .enumerable = 1, - .u.object = { - .enumerable = 1, - .prop_handler = nxt_http_js_ext_get_header, - .keys = nxt_http_js_ext_keys_header, - } - }, - - { - .flags = NJS_EXTERN_OBJECT, - .name.string = njs_str("cookies"), - .enumerable = 1, - .u.object = { - .enumerable = 1, - .prop_handler = nxt_http_js_ext_get_cookie, - .keys = nxt_http_js_ext_keys_cookie, - } - }, - - { - .flags = NJS_EXTERN_OBJECT, - .name.string = njs_str("vars"), - .u.object = { - .prop_handler = nxt_http_js_ext_get_var, - } - }, + njs_value_t *value, + njs_value_t *setval, + njs_value_t *retval); + +static njs_external_t nxt_http_js_proto[] = { + {.flags = NJS_EXTERN_PROPERTY, + .name.string = njs_str("uri"), + .enumerable = 1, + .u.property = + { + .handler = nxt_http_js_ext_uri, + }}, + + {.flags = NJS_EXTERN_PROPERTY, + .name.string = njs_str("host"), + .enumerable = 1, + .u.property = + { + .handler = nxt_http_js_ext_host, + }}, + + {.flags = NJS_EXTERN_PROPERTY, + .name.string = njs_str("remoteAddr"), + .enumerable = 1, + .u.property = + { + .handler = nxt_http_js_ext_remote_addr, + }}, + + {.flags = NJS_EXTERN_PROPERTY, + .name.string = njs_str("args"), + .enumerable = 1, + .u.property = + { + .handler = nxt_http_js_ext_get_args, + }}, + + {.flags = NJS_EXTERN_OBJECT, + .name.string = njs_str("headers"), + .enumerable = 1, + .u.object = + { + .enumerable = 1, + .prop_handler = nxt_http_js_ext_get_header, + .keys = nxt_http_js_ext_keys_header, + }}, + + {.flags = NJS_EXTERN_OBJECT, + .name.string = njs_str("cookies"), + .enumerable = 1, + .u.object = + { + .enumerable = 1, + .prop_handler = nxt_http_js_ext_get_cookie, + .keys = nxt_http_js_ext_keys_cookie, + }}, + + {.flags = NJS_EXTERN_OBJECT, + .name.string = njs_str("vars"), + .u.object = + { + .prop_handler = nxt_http_js_ext_get_var, + }}, }; - -void -nxt_http_register_js_proto(nxt_js_conf_t *jcf) -{ - nxt_js_set_proto(jcf, nxt_http_js_proto, njs_nitems(nxt_http_js_proto)); +void nxt_http_register_js_proto(nxt_js_conf_t *jcf) { + nxt_js_set_proto(jcf, nxt_http_js_proto, njs_nitems(nxt_http_js_proto)); } +static njs_int_t nxt_http_js_ext_uri(njs_vm_t *vm, njs_object_prop_t *prop, + njs_value_t *value, njs_value_t *setval, + njs_value_t *retval) { + nxt_http_request_t *r; -static njs_int_t -nxt_http_js_ext_uri(njs_vm_t *vm, njs_object_prop_t *prop, - njs_value_t *value, njs_value_t *setval, njs_value_t *retval) -{ - nxt_http_request_t *r; - - r = njs_vm_external(vm, nxt_js_proto_id, value); - if (r == NULL) { - njs_value_undefined_set(retval); - return NJS_DECLINED; - } + r = njs_vm_external(vm, nxt_js_proto_id, value); + if (r == NULL) { + njs_value_undefined_set(retval); + return NJS_DECLINED; + } - return njs_vm_value_string_create(vm, retval, r->path->start, - r->path->length); + return njs_vm_value_string_create(vm, retval, r->path->start, + r->path->length); } +static njs_int_t nxt_http_js_ext_host(njs_vm_t *vm, njs_object_prop_t *prop, + njs_value_t *value, njs_value_t *setval, + njs_value_t *retval) { + nxt_http_request_t *r; -static njs_int_t -nxt_http_js_ext_host(njs_vm_t *vm, njs_object_prop_t *prop, - njs_value_t *value, njs_value_t *setval, njs_value_t *retval) -{ - nxt_http_request_t *r; - - r = njs_vm_external(vm, nxt_js_proto_id, value); - if (r == NULL) { - njs_value_undefined_set(retval); - return NJS_DECLINED; - } + r = njs_vm_external(vm, nxt_js_proto_id, value); + if (r == NULL) { + njs_value_undefined_set(retval); + return NJS_DECLINED; + } - return njs_vm_value_string_create(vm, retval, r->host.start, - r->host.length); + return njs_vm_value_string_create(vm, retval, r->host.start, r->host.length); } +static njs_int_t nxt_http_js_ext_remote_addr(njs_vm_t *vm, + njs_object_prop_t *prop, + njs_value_t *value, + njs_value_t *setval, + njs_value_t *retval) { + nxt_http_request_t *r; + + r = njs_vm_external(vm, nxt_js_proto_id, value); + if (r == NULL) { + njs_value_undefined_set(retval); + return NJS_DECLINED; + } -static njs_int_t -nxt_http_js_ext_remote_addr(njs_vm_t *vm, njs_object_prop_t *prop, - njs_value_t *value, njs_value_t *setval, njs_value_t *retval) -{ - nxt_http_request_t *r; - - r = njs_vm_external(vm, nxt_js_proto_id, value); - if (r == NULL) { - njs_value_undefined_set(retval); - return NJS_DECLINED; - } - - return njs_vm_value_string_create(vm, retval, - nxt_sockaddr_address(r->remote), - r->remote->address_length); + return njs_vm_value_string_create(vm, retval, nxt_sockaddr_address(r->remote), + r->remote->address_length); } +static njs_int_t nxt_http_js_ext_get_args(njs_vm_t *vm, njs_object_prop_t *prop, + njs_value_t *value, + njs_value_t *setval, + njs_value_t *retval) { + u_char *start; + njs_int_t ret; + njs_value_t *args; + njs_opaque_value_t val; + nxt_http_request_t *r; + + r = njs_vm_external(vm, nxt_js_proto_id, value); + if (r == NULL) { + njs_value_undefined_set(retval); + return NJS_DECLINED; + } -static njs_int_t -nxt_http_js_ext_get_args(njs_vm_t *vm, njs_object_prop_t *prop, - njs_value_t *value, njs_value_t *setval, njs_value_t *retval) -{ - u_char *start; - njs_int_t ret; - njs_value_t *args; - njs_opaque_value_t val; - nxt_http_request_t *r; - - r = njs_vm_external(vm, nxt_js_proto_id, value); - if (r == NULL) { - njs_value_undefined_set(retval); - return NJS_DECLINED; - } - - args = njs_value_arg(&val); + args = njs_value_arg(&val); - start = (r->args->start != NULL) ? r->args->start : (u_char *) ""; - ret = njs_vm_query_string_parse(vm, start, start + r->args->length, args); + start = (r->args->start != NULL) ? r->args->start : (u_char *)""; + ret = njs_vm_query_string_parse(vm, start, start + r->args->length, args); - if (ret == NJS_ERROR) { - return NJS_ERROR; - } + if (ret == NJS_ERROR) { + return NJS_ERROR; + } - njs_value_assign(retval, args); + njs_value_assign(retval, args); - return NJS_OK; + return NJS_OK; } - -static njs_int_t -nxt_http_js_ext_get_header(njs_vm_t *vm, njs_object_prop_t *prop, - njs_value_t *value, njs_value_t *setval, njs_value_t *retval) -{ - njs_int_t rc; - njs_str_t key; - nxt_http_field_t *f; - nxt_http_request_t *r; - - r = njs_vm_external(vm, nxt_js_proto_id, value); - if (r == NULL) { - njs_value_undefined_set(retval); - return NJS_DECLINED; - } - - rc = njs_vm_prop_name(vm, prop, &key); - if (rc != NJS_OK) { - njs_value_undefined_set(retval); - return NJS_DECLINED; - } - - nxt_list_each(f, r->fields) { - - if (key.length == f->name_length - && memcmp(key.start, f->name, f->name_length) == 0) - { - return njs_vm_value_string_create(vm, retval, f->value, - f->value_length); - } - - } nxt_list_loop; - +static njs_int_t nxt_http_js_ext_get_header(njs_vm_t *vm, + njs_object_prop_t *prop, + njs_value_t *value, + njs_value_t *setval, + njs_value_t *retval) { + njs_int_t rc; + njs_str_t key; + nxt_http_field_t *f; + nxt_http_request_t *r; + + r = njs_vm_external(vm, nxt_js_proto_id, value); + if (r == NULL) { njs_value_undefined_set(retval); - return NJS_DECLINED; -} - + } -static njs_int_t -nxt_http_js_ext_keys_header(njs_vm_t *vm, njs_value_t *value, njs_value_t *keys) -{ - njs_int_t rc; - nxt_http_field_t *f; - nxt_http_request_t *r; + rc = njs_vm_prop_name(vm, prop, &key); + if (rc != NJS_OK) { + njs_value_undefined_set(retval); + return NJS_DECLINED; + } - rc = njs_vm_array_alloc(vm, keys, 4); - if (rc != NJS_OK) { - return NJS_ERROR; - } + nxt_list_each(f, r->fields) { - r = njs_vm_external(vm, nxt_js_proto_id, value); - if (r == NULL) { - return NJS_OK; + if (key.length == f->name_length && + memcmp(key.start, f->name, f->name_length) == 0) { + return njs_vm_value_string_create(vm, retval, f->value, f->value_length); } + } + nxt_list_loop; - nxt_list_each(f, r->fields) { + njs_value_undefined_set(retval); - value = njs_vm_array_push(vm, keys); - if (value == NULL) { - return NJS_ERROR; - } + return NJS_DECLINED; +} - rc = njs_vm_value_string_create(vm, value, f->name, f->name_length); - if (rc != NJS_OK) { - return NJS_ERROR; - } +static njs_int_t nxt_http_js_ext_keys_header(njs_vm_t *vm, njs_value_t *value, + njs_value_t *keys) { + njs_int_t rc; + nxt_http_field_t *f; + nxt_http_request_t *r; - } nxt_list_loop; + rc = njs_vm_array_alloc(vm, keys, 4); + if (rc != NJS_OK) { + return NJS_ERROR; + } + r = njs_vm_external(vm, nxt_js_proto_id, value); + if (r == NULL) { return NJS_OK; -} + } + nxt_list_each(f, r->fields) { -static njs_int_t -nxt_http_js_ext_get_cookie(njs_vm_t *vm, njs_object_prop_t *prop, - njs_value_t *value, njs_value_t *setval, njs_value_t *retval) -{ - njs_int_t rc; - njs_str_t key; - nxt_array_t *cookies; - nxt_http_request_t *r; - nxt_http_name_value_t *nv, *start, *end; - - r = njs_vm_external(vm, nxt_js_proto_id, value); - if (r == NULL) { - njs_value_undefined_set(retval); - return NJS_DECLINED; + value = njs_vm_array_push(vm, keys); + if (value == NULL) { + return NJS_ERROR; } - rc = njs_vm_prop_name(vm, prop, &key); + rc = njs_vm_value_string_create(vm, value, f->name, f->name_length); if (rc != NJS_OK) { - njs_value_undefined_set(retval); - return NJS_DECLINED; - } - - cookies = nxt_http_cookies_parse(r); - if (nxt_slow_path(cookies == NULL)) { - return NJS_ERROR; + return NJS_ERROR; } + } + nxt_list_loop; - start = cookies->elts; - end = start + cookies->nelts; - - for (nv = start; nv < end; nv++) { - - if (key.length == nv->name_length - && memcmp(key.start, nv->name, nv->name_length) == 0) - { - return njs_vm_value_string_create(vm, retval, nv->value, - nv->value_length); - } - } + return NJS_OK; +} +static njs_int_t nxt_http_js_ext_get_cookie(njs_vm_t *vm, + njs_object_prop_t *prop, + njs_value_t *value, + njs_value_t *setval, + njs_value_t *retval) { + njs_int_t rc; + njs_str_t key; + nxt_array_t *cookies; + nxt_http_request_t *r; + nxt_http_name_value_t *nv, *start, *end; + + r = njs_vm_external(vm, nxt_js_proto_id, value); + if (r == NULL) { njs_value_undefined_set(retval); - return NJS_DECLINED; -} + } + rc = njs_vm_prop_name(vm, prop, &key); + if (rc != NJS_OK) { + njs_value_undefined_set(retval); + return NJS_DECLINED; + } -static njs_int_t -nxt_http_js_ext_keys_cookie(njs_vm_t *vm, njs_value_t *value, njs_value_t *keys) -{ - njs_int_t rc; - nxt_array_t *cookies; - nxt_http_request_t *r; - nxt_http_name_value_t *nv, *start, *end; + cookies = nxt_http_cookies_parse(r); + if (nxt_slow_path(cookies == NULL)) { + return NJS_ERROR; + } - rc = njs_vm_array_alloc(vm, keys, 4); - if (rc != NJS_OK) { - return NJS_ERROR; - } + start = cookies->elts; + end = start + cookies->nelts; - r = njs_vm_external(vm, nxt_js_proto_id, value); - if (r == NULL) { - return NJS_OK; - } + for (nv = start; nv < end; nv++) { - cookies = nxt_http_cookies_parse(r); - if (nxt_slow_path(cookies == NULL)) { - return NJS_ERROR; + if (key.length == nv->name_length && + memcmp(key.start, nv->name, nv->name_length) == 0) { + return njs_vm_value_string_create(vm, retval, nv->value, + nv->value_length); } + } - start = cookies->elts; - end = start + cookies->nelts; + njs_value_undefined_set(retval); - for (nv = start; nv < end; nv++) { + return NJS_DECLINED; +} - value = njs_vm_array_push(vm, keys); - if (value == NULL) { - return NJS_ERROR; - } +static njs_int_t nxt_http_js_ext_keys_cookie(njs_vm_t *vm, njs_value_t *value, + njs_value_t *keys) { + njs_int_t rc; + nxt_array_t *cookies; + nxt_http_request_t *r; + nxt_http_name_value_t *nv, *start, *end; + + rc = njs_vm_array_alloc(vm, keys, 4); + if (rc != NJS_OK) { + return NJS_ERROR; + } + + r = njs_vm_external(vm, nxt_js_proto_id, value); + if (r == NULL) { + return NJS_OK; + } - rc = njs_vm_value_string_create(vm, value, nv->name, nv->name_length); - if (rc != NJS_OK) { - return NJS_ERROR; - } - } + cookies = nxt_http_cookies_parse(r); + if (nxt_slow_path(cookies == NULL)) { + return NJS_ERROR; + } - return NJS_OK; -} + start = cookies->elts; + end = start + cookies->nelts; + for (nv = start; nv < end; nv++) { -static njs_int_t -nxt_http_js_ext_get_var(njs_vm_t *vm, njs_object_prop_t *prop, - njs_value_t *value, njs_value_t *setval, njs_value_t *retval) -{ - njs_int_t rc; - njs_str_t key; - nxt_str_t name, *vv; - nxt_router_conf_t *rtcf; - nxt_http_request_t *r; - - r = njs_vm_external(vm, nxt_js_proto_id, value); - if (r == NULL) { - njs_value_undefined_set(retval); - return NJS_DECLINED; + value = njs_vm_array_push(vm, keys); + if (value == NULL) { + return NJS_ERROR; } - rc = njs_vm_prop_name(vm, prop, &key); + rc = njs_vm_value_string_create(vm, value, nv->name, nv->name_length); if (rc != NJS_OK) { - njs_value_undefined_set(retval); - return NJS_DECLINED; + return NJS_ERROR; } + } - rtcf = r->conf->socket_conf->router_conf; + return NJS_OK; +} - name.start = key.start; - name.length = key.length; +static njs_int_t nxt_http_js_ext_get_var(njs_vm_t *vm, njs_object_prop_t *prop, + njs_value_t *value, + njs_value_t *setval, + njs_value_t *retval) { + njs_int_t rc; + njs_str_t key; + nxt_str_t name, *vv; + nxt_router_conf_t *rtcf; + nxt_http_request_t *r; + + r = njs_vm_external(vm, nxt_js_proto_id, value); + if (r == NULL) { + njs_value_undefined_set(retval); + return NJS_DECLINED; + } - vv = nxt_var_get(&r->task, rtcf->tstr_state, &r->tstr_cache.var, &name, r); + rc = njs_vm_prop_name(vm, prop, &key); + if (rc != NJS_OK) { + njs_value_undefined_set(retval); + return NJS_DECLINED; + } - if (vv != NULL) { - return njs_vm_value_string_create(vm, retval, vv->start, vv->length); - } + rtcf = r->conf->socket_conf->router_conf; - njs_value_undefined_set(retval); + name.start = key.start; + name.length = key.length; - return NJS_DECLINED; + vv = nxt_var_get(&r->task, rtcf->tstr_state, &r->tstr_cache.var, &name, r); + + if (vv != NULL) { + return njs_vm_value_string_create(vm, retval, vv->start, vv->length); + } + + njs_value_undefined_set(retval); + + return NJS_DECLINED; } diff --git a/src/nxt_http_parse.c b/src/nxt_http_parse.c index dd490e729..484df0417 100644 --- a/src/nxt_http_parse.c +++ b/src/nxt_http_parse.c @@ -6,1264 +6,1289 @@ #include - static nxt_int_t nxt_http_parse_unusual_target(nxt_http_request_parse_t *rp, - u_char **pos, const u_char *end); + u_char **pos, const u_char *end); static nxt_int_t nxt_http_parse_request_line(nxt_http_request_parse_t *rp, - u_char **pos, const u_char *end); + u_char **pos, const u_char *end); static nxt_int_t nxt_http_parse_field_name(nxt_http_request_parse_t *rp, - u_char **pos, const u_char *end); + u_char **pos, const u_char *end); static nxt_int_t nxt_http_parse_field_value(nxt_http_request_parse_t *rp, - u_char **pos, const u_char *end); + u_char **pos, const u_char *end); static u_char *nxt_http_lookup_field_end(u_char *p, const u_char *end); static nxt_int_t nxt_http_parse_field_end(nxt_http_request_parse_t *rp, - u_char **pos, const u_char *end); + u_char **pos, const u_char *end); static nxt_int_t nxt_http_field_hash_test(nxt_lvlhsh_query_t *lhq, void *data); static nxt_int_t nxt_http_field_hash_collision(nxt_lvlhsh_query_t *lhq, - void *data); - + void *data); -#define NXT_HTTP_MAX_FIELD_NAME 0xFF -#define NXT_HTTP_MAX_FIELD_VALUE NXT_INT32_T_MAX - -#define NXT_HTTP_FIELD_LVLHSH_SHIFT 5 +#define NXT_HTTP_MAX_FIELD_NAME 0xFF +#define NXT_HTTP_MAX_FIELD_VALUE NXT_INT32_T_MAX +#define NXT_HTTP_FIELD_LVLHSH_SHIFT 5 typedef enum { - NXT_HTTP_TARGET_SPACE = 1, /* \s */ - NXT_HTTP_TARGET_HASH, /* # */ - NXT_HTTP_TARGET_AGAIN, - NXT_HTTP_TARGET_BAD, /* \0\r\n */ + NXT_HTTP_TARGET_SPACE = 1, /* \s */ + NXT_HTTP_TARGET_HASH, /* # */ + NXT_HTTP_TARGET_AGAIN, + NXT_HTTP_TARGET_BAD, /* \0\r\n */ - /* traps below are used for extended check only */ + /* traps below are used for extended check only */ - NXT_HTTP_TARGET_SLASH = 5, /* / */ - NXT_HTTP_TARGET_DOT, /* . */ - NXT_HTTP_TARGET_ARGS_MARK, /* ? */ - NXT_HTTP_TARGET_QUOTE_MARK, /* % */ + NXT_HTTP_TARGET_SLASH = 5, /* / */ + NXT_HTTP_TARGET_DOT, /* . */ + NXT_HTTP_TARGET_ARGS_MARK, /* ? */ + NXT_HTTP_TARGET_QUOTE_MARK, /* % */ } nxt_http_target_traps_e; - -static const uint8_t nxt_http_target_chars[256] nxt_aligned(64) = { +static const uint8_t nxt_http_target_chars[256] nxt_aligned(64) = { /* \0 \n \r */ - 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 4, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 4, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 4, + 0, + 0, + 4, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, /* \s ! " # $ % & ' ( ) * + , - . / */ - 1, 0, 0, 2, 0, 8, 0, 0, 0, 0, 0, 0, 0, 0, 6, 5, + 1, + 0, + 0, + 2, + 0, + 8, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 6, + 5, /* 0 1 2 3 4 5 6 7 8 9 : ; < = > ? */ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 7, }; +nxt_inline nxt_http_target_traps_e nxt_http_parse_target(u_char **pos, + const u_char *end) { + u_char *p; + nxt_uint_t trap; -nxt_inline nxt_http_target_traps_e -nxt_http_parse_target(u_char **pos, const u_char *end) -{ - u_char *p; - nxt_uint_t trap; + p = *pos; - p = *pos; + while (nxt_fast_path(end - p >= 10)) { - while (nxt_fast_path(end - p >= 10)) { +#define nxt_target_test_char(ch) \ + \ + trap = nxt_http_target_chars[ch]; \ + \ + if (nxt_slow_path(trap != 0)) { \ + *pos = &(ch); \ + return trap; \ + } -#define nxt_target_test_char(ch) \ - \ - trap = nxt_http_target_chars[ch]; \ - \ - if (nxt_slow_path(trap != 0)) { \ - *pos = &(ch); \ - return trap; \ - } - -/* enddef */ + /* enddef */ - nxt_target_test_char(p[0]); - nxt_target_test_char(p[1]); - nxt_target_test_char(p[2]); - nxt_target_test_char(p[3]); + nxt_target_test_char(p[0]); + nxt_target_test_char(p[1]); + nxt_target_test_char(p[2]); + nxt_target_test_char(p[3]); - nxt_target_test_char(p[4]); - nxt_target_test_char(p[5]); - nxt_target_test_char(p[6]); - nxt_target_test_char(p[7]); + nxt_target_test_char(p[4]); + nxt_target_test_char(p[5]); + nxt_target_test_char(p[6]); + nxt_target_test_char(p[7]); - nxt_target_test_char(p[8]); - nxt_target_test_char(p[9]); + nxt_target_test_char(p[8]); + nxt_target_test_char(p[9]); - p += 10; - } + p += 10; + } - while (p != end) { - nxt_target_test_char(*p); p++; - } + while (p != end) { + nxt_target_test_char(*p); + p++; + } - return NXT_HTTP_TARGET_AGAIN; + return NXT_HTTP_TARGET_AGAIN; } +nxt_int_t nxt_http_parse_request_init(nxt_http_request_parse_t *rp, + nxt_mp_t *mp) { + rp->mem_pool = mp; -nxt_int_t -nxt_http_parse_request_init(nxt_http_request_parse_t *rp, nxt_mp_t *mp) -{ - rp->mem_pool = mp; - - rp->fields = nxt_list_create(mp, 8, sizeof(nxt_http_field_t)); - if (nxt_slow_path(rp->fields == NULL)) { - return NXT_ERROR; - } + rp->fields = nxt_list_create(mp, 8, sizeof(nxt_http_field_t)); + if (nxt_slow_path(rp->fields == NULL)) { + return NXT_ERROR; + } - rp->field_hash = NXT_HTTP_FIELD_HASH_INIT; + rp->field_hash = NXT_HTTP_FIELD_HASH_INIT; - return NXT_OK; + return NXT_OK; } +nxt_int_t nxt_http_parse_request(nxt_http_request_parse_t *rp, + nxt_buf_mem_t *b) { + nxt_int_t rc; -nxt_int_t -nxt_http_parse_request(nxt_http_request_parse_t *rp, nxt_buf_mem_t *b) -{ - nxt_int_t rc; - - if (rp->handler == NULL) { - rp->handler = &nxt_http_parse_request_line; - } + if (rp->handler == NULL) { + rp->handler = &nxt_http_parse_request_line; + } - do { - rc = rp->handler(rp, &b->pos, b->free); - } while (rc == NXT_OK); + do { + rc = rp->handler(rp, &b->pos, b->free); + } while (rc == NXT_OK); - return rc; + return rc; } +nxt_int_t nxt_http_parse_fields(nxt_http_request_parse_t *rp, + nxt_buf_mem_t *b) { + nxt_int_t rc; -nxt_int_t -nxt_http_parse_fields(nxt_http_request_parse_t *rp, nxt_buf_mem_t *b) -{ - nxt_int_t rc; - - if (rp->handler == NULL) { - rp->handler = &nxt_http_parse_field_name; - } + if (rp->handler == NULL) { + rp->handler = &nxt_http_parse_field_name; + } - do { - rc = rp->handler(rp, &b->pos, b->free); - } while (rc == NXT_OK); + do { + rc = rp->handler(rp, &b->pos, b->free); + } while (rc == NXT_OK); - return rc; + return rc; } +static nxt_int_t nxt_http_parse_request_line(nxt_http_request_parse_t *rp, + u_char **pos, const u_char *end) { + u_char *p, ch, *after_slash, *args; + nxt_int_t rc; + nxt_bool_t rest; + nxt_http_ver_t ver; + nxt_http_target_traps_e trap; -static nxt_int_t -nxt_http_parse_request_line(nxt_http_request_parse_t *rp, u_char **pos, - const u_char *end) -{ - u_char *p, ch, *after_slash, *args; - nxt_int_t rc; - nxt_bool_t rest; - nxt_http_ver_t ver; - nxt_http_target_traps_e trap; - - static const nxt_http_ver_t http11 = { "HTTP/1.1" }; - static const nxt_http_ver_t http10 = { "HTTP/1.0" }; + static const nxt_http_ver_t http11 = {"HTTP/1.1"}; + static const nxt_http_ver_t http10 = {"HTTP/1.0"}; - p = *pos; + p = *pos; - rp->method.start = p; + rp->method.start = p; - for ( ;; ) { + for (;;) { - while (nxt_fast_path(end - p >= 8)) { + while (nxt_fast_path(end - p >= 8)) { -#define nxt_method_test_char(ch) \ - \ - if (nxt_slow_path((ch) < 'A' || (ch) > 'Z')) { \ - p = &(ch); \ - goto method_unusual_char; \ - } +#define nxt_method_test_char(ch) \ + \ + if (nxt_slow_path((ch) < 'A' || (ch) > 'Z')) { \ + p = &(ch); \ + goto method_unusual_char; \ + } -/* enddef */ + /* enddef */ - nxt_method_test_char(p[0]); - nxt_method_test_char(p[1]); - nxt_method_test_char(p[2]); - nxt_method_test_char(p[3]); + nxt_method_test_char(p[0]); + nxt_method_test_char(p[1]); + nxt_method_test_char(p[2]); + nxt_method_test_char(p[3]); - nxt_method_test_char(p[4]); - nxt_method_test_char(p[5]); - nxt_method_test_char(p[6]); - nxt_method_test_char(p[7]); + nxt_method_test_char(p[4]); + nxt_method_test_char(p[5]); + nxt_method_test_char(p[6]); + nxt_method_test_char(p[7]); - p += 8; - } + p += 8; + } - while (p != end) { - nxt_method_test_char(*p); p++; - } + while (p != end) { + nxt_method_test_char(*p); + p++; + } - rp->method.length = p - rp->method.start; + rp->method.length = p - rp->method.start; - return NXT_AGAIN; + return NXT_AGAIN; - method_unusual_char: + method_unusual_char: - ch = *p; + ch = *p; - if (nxt_fast_path(ch == ' ')) { - rp->method.length = p - rp->method.start; - break; - } + if (nxt_fast_path(ch == ' ')) { + rp->method.length = p - rp->method.start; + break; + } - if (ch == '_' || ch == '-') { - p++; - continue; - } + if (ch == '_' || ch == '-') { + p++; + continue; + } - if (rp->method.start == p && (ch == '\r' || ch == '\n')) { - rp->method.start++; - p++; - continue; - } + if (rp->method.start == p && (ch == '\r' || ch == '\n')) { + rp->method.start++; + p++; + continue; + } - rp->method.length = p - rp->method.start; + rp->method.length = p - rp->method.start; - return NXT_HTTP_PARSE_INVALID; - } + return NXT_HTTP_PARSE_INVALID; + } - p++; + p++; - if (nxt_slow_path(p == end)) { - return NXT_AGAIN; - } + if (nxt_slow_path(p == end)) { + return NXT_AGAIN; + } - /* target */ + /* target */ - ch = *p; + ch = *p; - if (nxt_slow_path(ch != '/')) { - rc = nxt_http_parse_unusual_target(rp, &p, end); + if (nxt_slow_path(ch != '/')) { + rc = nxt_http_parse_unusual_target(rp, &p, end); - if (nxt_slow_path(rc != NXT_OK)) { - return rc; - } + if (nxt_slow_path(rc != NXT_OK)) { + return rc; } + } - rp->target_start = p; + rp->target_start = p; - after_slash = p + 1; - args = NULL; - rest = 0; + after_slash = p + 1; + args = NULL; + rest = 0; continue_target: - for ( ;; ) { - p++; - - trap = nxt_http_parse_target(&p, end); + for (;;) { + p++; - switch (trap) { - case NXT_HTTP_TARGET_SLASH: - if (nxt_slow_path(after_slash == p)) { - rp->complex_target = 1; - goto rest_of_target; - } + trap = nxt_http_parse_target(&p, end); - after_slash = p + 1; - continue; + switch (trap) { + case NXT_HTTP_TARGET_SLASH: + if (nxt_slow_path(after_slash == p)) { + rp->complex_target = 1; + goto rest_of_target; + } - case NXT_HTTP_TARGET_DOT: - if (nxt_slow_path(after_slash == p)) { - rp->complex_target = 1; - goto rest_of_target; - } + after_slash = p + 1; + continue; - continue; + case NXT_HTTP_TARGET_DOT: + if (nxt_slow_path(after_slash == p)) { + rp->complex_target = 1; + goto rest_of_target; + } - case NXT_HTTP_TARGET_ARGS_MARK: - args = p + 1; - goto rest_of_target; + continue; - case NXT_HTTP_TARGET_SPACE: - rp->target_end = p; - goto space_after_target; + case NXT_HTTP_TARGET_ARGS_MARK: + args = p + 1; + goto rest_of_target; - case NXT_HTTP_TARGET_QUOTE_MARK: - rp->quoted_target = 1; - goto rest_of_target; + case NXT_HTTP_TARGET_SPACE: + rp->target_end = p; + goto space_after_target; - case NXT_HTTP_TARGET_HASH: - rp->complex_target = 1; - goto rest_of_target; + case NXT_HTTP_TARGET_QUOTE_MARK: + rp->quoted_target = 1; + goto rest_of_target; - case NXT_HTTP_TARGET_AGAIN: - rp->target_end = p; - return NXT_AGAIN; + case NXT_HTTP_TARGET_HASH: + rp->complex_target = 1; + goto rest_of_target; - case NXT_HTTP_TARGET_BAD: - rp->target_end = p; - return NXT_HTTP_PARSE_INVALID; - } + case NXT_HTTP_TARGET_AGAIN: + rp->target_end = p; + return NXT_AGAIN; - nxt_unreachable(); + case NXT_HTTP_TARGET_BAD: + rp->target_end = p; + return NXT_HTTP_PARSE_INVALID; } + nxt_unreachable(); + } + rest_of_target: - rest = 1; + rest = 1; - for ( ;; ) { - p++; + for (;;) { + p++; - trap = nxt_http_parse_target(&p, end); + trap = nxt_http_parse_target(&p, end); - switch (trap) { - case NXT_HTTP_TARGET_SPACE: - rp->target_end = p; - goto space_after_target; + switch (trap) { + case NXT_HTTP_TARGET_SPACE: + rp->target_end = p; + goto space_after_target; - case NXT_HTTP_TARGET_HASH: - rp->complex_target = 1; - continue; + case NXT_HTTP_TARGET_HASH: + rp->complex_target = 1; + continue; - case NXT_HTTP_TARGET_AGAIN: - rp->target_end = p; - return NXT_AGAIN; + case NXT_HTTP_TARGET_AGAIN: + rp->target_end = p; + return NXT_AGAIN; - case NXT_HTTP_TARGET_BAD: - rp->target_end = p; - return NXT_HTTP_PARSE_INVALID; + case NXT_HTTP_TARGET_BAD: + rp->target_end = p; + return NXT_HTTP_PARSE_INVALID; - default: - continue; - } - - nxt_unreachable(); + default: + continue; } -space_after_target: + nxt_unreachable(); + } - if (nxt_slow_path(end - p < 10)) { - - do { - p++; - - if (p == end) { - return NXT_AGAIN; - } - - } while (*p == ' '); - - if (memcmp(p, "HTTP/", nxt_min(end - p, 5)) == 0) { - - switch (end - p) { - case 8: - if (p[7] < '0' || p[7] > '9') { - break; - } - /* Fall through. */ - case 7: - if (p[6] != '.') { - break; - } - /* Fall through. */ - case 6: - if (p[5] < '0' || p[5] > '9') { - break; - } - /* Fall through. */ - default: - return NXT_AGAIN; - } - } +space_after_target: - //rp->space_in_target = 1; + if (nxt_slow_path(end - p < 10)) { - if (rest) { - goto rest_of_target; - } + do { + p++; - goto continue_target; - } + if (p == end) { + return NXT_AGAIN; + } - /* " HTTP/1.1\r\n" or " HTTP/1.1\n" */ + } while (*p == ' '); - if (nxt_slow_path(p[9] != '\r' && p[9] != '\n')) { + if (memcmp(p, "HTTP/", nxt_min(end - p, 5)) == 0) { - if (p[1] == ' ') { - /* surplus space after tartet */ - p++; - goto space_after_target; + switch (end - p) { + case 8: + if (p[7] < '0' || p[7] > '9') { + break; } - - //rp->space_in_target = 1; - - if (rest) { - goto rest_of_target; + /* Fall through. */ + case 7: + if (p[6] != '.') { + break; } - - goto continue_target; + /* Fall through. */ + case 6: + if (p[5] < '0' || p[5] > '9') { + break; + } + /* Fall through. */ + default: + return NXT_AGAIN; + } } - nxt_memcpy(ver.str, &p[1], 8); - - if (nxt_fast_path(ver.ui64 == http11.ui64 - || ver.ui64 == http10.ui64 - || (memcmp(ver.str, "HTTP/1.", 7) == 0 - && ver.s.minor >= '0' && ver.s.minor <= '9'))) - { - rp->version.ui64 = ver.ui64; + // rp->space_in_target = 1; - p += 9; - if (nxt_fast_path(*p == '\r')) { + if (rest) { + goto rest_of_target; + } - if (nxt_slow_path(p + 1 == end)) { - return NXT_AGAIN; - } + goto continue_target; + } - if (nxt_slow_path(p[1] != '\n')) { - return NXT_HTTP_PARSE_INVALID; - } + /* " HTTP/1.1\r\n" or " HTTP/1.1\n" */ - *pos = p + 2; + if (nxt_slow_path(p[9] != '\r' && p[9] != '\n')) { - } else { - *pos = p + 1; - } + if (p[1] == ' ') { + /* surplus space after tartet */ + p++; + goto space_after_target; + } - rp->request_line_end = p; + // rp->space_in_target = 1; - if (rp->complex_target || rp->quoted_target) { - rc = nxt_http_parse_complex_target(rp); + if (rest) { + goto rest_of_target; + } - if (nxt_slow_path(rc != NXT_OK)) { - return rc; - } + goto continue_target; + } - return nxt_http_parse_field_name(rp, pos, end); - } + nxt_memcpy(ver.str, &p[1], 8); - rp->path.start = rp->target_start; + if (nxt_fast_path(ver.ui64 == http11.ui64 || ver.ui64 == http10.ui64 || + (memcmp(ver.str, "HTTP/1.", 7) == 0 && ver.s.minor >= '0' && + ver.s.minor <= '9'))) { + rp->version.ui64 = ver.ui64; - if (args != NULL) { - rp->path.length = args - rp->target_start - 1; + p += 9; + if (nxt_fast_path(*p == '\r')) { - rp->args.length = rp->target_end - args; - rp->args.start = args; + if (nxt_slow_path(p + 1 == end)) { + return NXT_AGAIN; + } - } else { - rp->path.length = rp->target_end - rp->target_start; - } + if (nxt_slow_path(p[1] != '\n')) { + return NXT_HTTP_PARSE_INVALID; + } - return nxt_http_parse_field_name(rp, pos, end); - } + *pos = p + 2; - if (memcmp(ver.s.prefix, "HTTP/", 5) == 0 - && ver.s.major >= '0' && ver.s.major <= '9' - && ver.s.point == '.' - && ver.s.minor >= '0' && ver.s.minor <= '9') - { - rp->version.ui64 = ver.ui64; - return NXT_HTTP_PARSE_UNSUPPORTED_VERSION; + } else { + *pos = p + 1; } - return NXT_HTTP_PARSE_INVALID; -} + rp->request_line_end = p; + if (rp->complex_target || rp->quoted_target) { + rc = nxt_http_parse_complex_target(rp); -static nxt_int_t -nxt_http_parse_unusual_target(nxt_http_request_parse_t *rp, u_char **pos, - const u_char *end) -{ - u_char *p, ch; - - p = *pos; - - ch = *p; + if (nxt_slow_path(rc != NXT_OK)) { + return rc; + } - if (ch == ' ') { - /* skip surplus spaces before target */ - - do { - p++; + return nxt_http_parse_field_name(rp, pos, end); + } - if (nxt_slow_path(p == end)) { - return NXT_AGAIN; - } + rp->path.start = rp->target_start; - ch = *p; + if (args != NULL) { + rp->path.length = args - rp->target_start - 1; - } while (ch == ' '); + rp->args.length = rp->target_end - args; + rp->args.start = args; - if (ch == '/') { - *pos = p; - return NXT_OK; - } + } else { + rp->path.length = rp->target_end - rp->target_start; } - /* absolute path or '*' */ + return nxt_http_parse_field_name(rp, pos, end); + } - /* TODO */ + if (memcmp(ver.s.prefix, "HTTP/", 5) == 0 && ver.s.major >= '0' && + ver.s.major <= '9' && ver.s.point == '.' && ver.s.minor >= '0' && + ver.s.minor <= '9') { + rp->version.ui64 = ver.ui64; + return NXT_HTTP_PARSE_UNSUPPORTED_VERSION; + } - return NXT_HTTP_PARSE_INVALID; + return NXT_HTTP_PARSE_INVALID; } +static nxt_int_t nxt_http_parse_unusual_target(nxt_http_request_parse_t *rp, + u_char **pos, + const u_char *end) { + u_char *p, ch; -static nxt_int_t -nxt_http_parse_field_name(nxt_http_request_parse_t *rp, u_char **pos, - const u_char *end) -{ - u_char *p, c; - size_t len; - uint32_t hash; + p = *pos; - static const u_char normal[256] nxt_aligned(64) = - "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" - /* \s ! " # $ % & ' ( ) * + , . / : ; < = > ? */ - "\0\1\0\1\1\1\1\1\0\0\1\1\0" "-" "\1\0" "0123456789" "\0\0\0\0\0\0" + ch = *p; - /* @ [ \ ] ^ _ */ - "\0" "abcdefghijklmnopqrstuvwxyz" "\0\0\0\1\1" - /* ` { | } ~ */ - "\1" "abcdefghijklmnopqrstuvwxyz" "\0\1\0\1\0" + if (ch == ' ') { + /* skip surplus spaces before target */ - "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" - "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" - "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" - "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"; + do { + p++; - p = *pos + rp->field_name.length; - hash = rp->field_hash; + if (nxt_slow_path(p == end)) { + return NXT_AGAIN; + } - while (nxt_fast_path(end - p >= 8)) { + ch = *p; -#define nxt_field_name_test_char(ch) \ - \ - c = normal[ch]; \ - \ - if (nxt_slow_path(c <= '\1')) { \ - if (c == '\0') { \ - p = &(ch); \ - goto name_end; \ - } \ - \ - rp->skip_field = rp->discard_unsafe_fields; \ - c = ch; \ - } \ - \ - hash = nxt_http_field_hash_char(hash, c); - -/* enddef */ - - nxt_field_name_test_char(p[0]); - nxt_field_name_test_char(p[1]); - nxt_field_name_test_char(p[2]); - nxt_field_name_test_char(p[3]); - - nxt_field_name_test_char(p[4]); - nxt_field_name_test_char(p[5]); - nxt_field_name_test_char(p[6]); - nxt_field_name_test_char(p[7]); - - p += 8; - } + } while (ch == ' '); - while (nxt_fast_path(p != end)) { - nxt_field_name_test_char(*p); p++; + if (ch == '/') { + *pos = p; + return NXT_OK; } + } - len = p - *pos; + /* absolute path or '*' */ - if (nxt_slow_path(len > NXT_HTTP_MAX_FIELD_NAME)) { - return NXT_HTTP_PARSE_TOO_LARGE_FIELD; - } + /* TODO */ - rp->field_hash = hash; - rp->field_name.length = len; + return NXT_HTTP_PARSE_INVALID; +} - rp->handler = &nxt_http_parse_field_name; +static nxt_int_t nxt_http_parse_field_name(nxt_http_request_parse_t *rp, + u_char **pos, const u_char *end) { + u_char *p, c; + size_t len; + uint32_t hash; + + static const u_char normal[256] nxt_aligned(64) = + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + /* \s ! " # $ % & ' ( ) * + , . / : ; < = > ? */ + "\0\1\0\1\1\1\1\1\0\0\1\1\0" + "-" + "\1\0" + "0123456789" + "\0\0\0\0\0\0" + + /* @ [ \ ] ^ _ */ + "\0" + "abcdefghijklmnopqrstuvwxyz" + "\0\0\0\1\1" + /* ` { | } ~ */ + "\1" + "abcdefghijklmnopqrstuvwxyz" + "\0\1\0\1\0" + + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"; + + p = *pos + rp->field_name.length; + hash = rp->field_hash; + + while (nxt_fast_path(end - p >= 8)) { + +#define nxt_field_name_test_char(ch) \ + \ + c = normal[ch]; \ + \ + if (nxt_slow_path(c <= '\1')) { \ + if (c == '\0') { \ + p = &(ch); \ + goto name_end; \ + } \ + \ + rp->skip_field = rp->discard_unsafe_fields; \ + c = ch; \ + } \ + \ + hash = nxt_http_field_hash_char(hash, c); + + /* enddef */ + + nxt_field_name_test_char(p[0]); + nxt_field_name_test_char(p[1]); + nxt_field_name_test_char(p[2]); + nxt_field_name_test_char(p[3]); + + nxt_field_name_test_char(p[4]); + nxt_field_name_test_char(p[5]); + nxt_field_name_test_char(p[6]); + nxt_field_name_test_char(p[7]); + + p += 8; + } + + while (nxt_fast_path(p != end)) { + nxt_field_name_test_char(*p); + p++; + } - return NXT_AGAIN; + len = p - *pos; -name_end: + if (nxt_slow_path(len > NXT_HTTP_MAX_FIELD_NAME)) { + return NXT_HTTP_PARSE_TOO_LARGE_FIELD; + } - if (nxt_fast_path(*p == ':')) { - if (nxt_slow_path(p == *pos)) { - return NXT_HTTP_PARSE_INVALID; - } + rp->field_hash = hash; + rp->field_name.length = len; - len = p - *pos; + rp->handler = &nxt_http_parse_field_name; - if (nxt_slow_path(len > NXT_HTTP_MAX_FIELD_NAME)) { - return NXT_HTTP_PARSE_TOO_LARGE_FIELD; - } + return NXT_AGAIN; - rp->field_hash = hash; +name_end: - rp->field_name.length = len; - rp->field_name.start = *pos; + if (nxt_fast_path(*p == ':')) { + if (nxt_slow_path(p == *pos)) { + return NXT_HTTP_PARSE_INVALID; + } - *pos = p + 1; + len = p - *pos; - return nxt_http_parse_field_value(rp, pos, end); + if (nxt_slow_path(len > NXT_HTTP_MAX_FIELD_NAME)) { + return NXT_HTTP_PARSE_TOO_LARGE_FIELD; } - if (nxt_slow_path(p != *pos)) { - return NXT_HTTP_PARSE_INVALID; - } + rp->field_hash = hash; - return nxt_http_parse_field_end(rp, pos, end); -} + rp->field_name.length = len; + rp->field_name.start = *pos; + *pos = p + 1; -static nxt_int_t -nxt_http_parse_field_value(nxt_http_request_parse_t *rp, u_char **pos, - const u_char *end) -{ - u_char *p, *start, ch; - size_t len; + return nxt_http_parse_field_value(rp, pos, end); + } - p = *pos; + if (nxt_slow_path(p != *pos)) { + return NXT_HTTP_PARSE_INVALID; + } - for ( ;; ) { - if (nxt_slow_path(p == end)) { - *pos = p; - rp->handler = &nxt_http_parse_field_value; - return NXT_AGAIN; - } + return nxt_http_parse_field_end(rp, pos, end); +} - ch = *p; +static nxt_int_t nxt_http_parse_field_value(nxt_http_request_parse_t *rp, + u_char **pos, const u_char *end) { + u_char *p, *start, ch; + size_t len; - if (ch != ' ' && ch != '\t') { - break; - } + p = *pos; - p++; + for (;;) { + if (nxt_slow_path(p == end)) { + *pos = p; + rp->handler = &nxt_http_parse_field_value; + return NXT_AGAIN; } - start = p; - - p += rp->field_value.length; + ch = *p; - for ( ;; ) { - p = nxt_http_lookup_field_end(p, end); + if (ch != ' ' && ch != '\t') { + break; + } - if (nxt_slow_path(p == end)) { - *pos = start; + p++; + } - len = p - start; + start = p; - if (nxt_slow_path(len > NXT_HTTP_MAX_FIELD_VALUE)) { - return NXT_HTTP_PARSE_TOO_LARGE_FIELD; - } + p += rp->field_value.length; - rp->field_value.length = len; - rp->handler = &nxt_http_parse_field_value; - return NXT_AGAIN; - } + for (;;) { + p = nxt_http_lookup_field_end(p, end); - ch = *p; + if (nxt_slow_path(p == end)) { + *pos = start; - if (nxt_fast_path(ch == '\r' || ch == '\n')) { - break; - } + len = p - start; - if (ch != '\t') { - return NXT_HTTP_PARSE_INVALID; - } + if (nxt_slow_path(len > NXT_HTTP_MAX_FIELD_VALUE)) { + return NXT_HTTP_PARSE_TOO_LARGE_FIELD; + } - p++; + rp->field_value.length = len; + rp->handler = &nxt_http_parse_field_value; + return NXT_AGAIN; } - *pos = p; - - if (nxt_fast_path(p != start)) { + ch = *p; - while (p[-1] == ' ' || p[-1] == '\t') { - p--; - } + if (nxt_fast_path(ch == '\r' || ch == '\n')) { + break; } - len = p - start; - - if (nxt_slow_path(len > NXT_HTTP_MAX_FIELD_VALUE)) { - return NXT_HTTP_PARSE_TOO_LARGE_FIELD; + if (ch != '\t') { + return NXT_HTTP_PARSE_INVALID; } - rp->field_value.length = len; - rp->field_value.start = start; - - return nxt_http_parse_field_end(rp, pos, end); -} - - -static u_char * -nxt_http_lookup_field_end(u_char *p, const u_char *end) -{ - while (nxt_fast_path(end - p >= 16)) { - -#define nxt_field_end_test_char(ch) \ - \ - if (nxt_slow_path((ch) < 0x20)) { \ - return &(ch); \ - } - -/* enddef */ - - nxt_field_end_test_char(p[0]); - nxt_field_end_test_char(p[1]); - nxt_field_end_test_char(p[2]); - nxt_field_end_test_char(p[3]); - - nxt_field_end_test_char(p[4]); - nxt_field_end_test_char(p[5]); - nxt_field_end_test_char(p[6]); - nxt_field_end_test_char(p[7]); + p++; + } - nxt_field_end_test_char(p[8]); - nxt_field_end_test_char(p[9]); - nxt_field_end_test_char(p[10]); - nxt_field_end_test_char(p[11]); + *pos = p; - nxt_field_end_test_char(p[12]); - nxt_field_end_test_char(p[13]); - nxt_field_end_test_char(p[14]); - nxt_field_end_test_char(p[15]); + if (nxt_fast_path(p != start)) { - p += 16; + while (p[-1] == ' ' || p[-1] == '\t') { + p--; } + } - while (nxt_fast_path(end - p >= 4)) { + len = p - start; - nxt_field_end_test_char(p[0]); - nxt_field_end_test_char(p[1]); - nxt_field_end_test_char(p[2]); - nxt_field_end_test_char(p[3]); + if (nxt_slow_path(len > NXT_HTTP_MAX_FIELD_VALUE)) { + return NXT_HTTP_PARSE_TOO_LARGE_FIELD; + } - p += 4; - } + rp->field_value.length = len; + rp->field_value.start = start; - switch (end - p) { - case 3: - nxt_field_end_test_char(*p); p++; - /* Fall through. */ - case 2: - nxt_field_end_test_char(*p); p++; - /* Fall through. */ - case 1: - nxt_field_end_test_char(*p); p++; - /* Fall through. */ - case 0: - break; - default: - nxt_unreachable(); - } - - return p; + return nxt_http_parse_field_end(rp, pos, end); } +static u_char *nxt_http_lookup_field_end(u_char *p, const u_char *end) { + while (nxt_fast_path(end - p >= 16)) { -static nxt_int_t -nxt_http_parse_field_end(nxt_http_request_parse_t *rp, u_char **pos, - const u_char *end) -{ - u_char *p; - nxt_http_field_t *field; - - p = *pos; - - if (nxt_fast_path(*p == '\r')) { - p++; - - if (nxt_slow_path(p == end)) { - rp->handler = &nxt_http_parse_field_end; - return NXT_AGAIN; - } - } - - if (nxt_fast_path(*p == '\n')) { - *pos = p + 1; +#define nxt_field_end_test_char(ch) \ + \ + if (nxt_slow_path((ch) < 0x20)) { \ + return &(ch); \ + } - if (rp->field_name.length != 0) { - if (rp->skip_field) { - rp->skip_field = 0; + /* enddef */ - } else { - field = nxt_list_add(rp->fields); + nxt_field_end_test_char(p[0]); + nxt_field_end_test_char(p[1]); + nxt_field_end_test_char(p[2]); + nxt_field_end_test_char(p[3]); - if (nxt_slow_path(field == NULL)) { - return NXT_ERROR; - } + nxt_field_end_test_char(p[4]); + nxt_field_end_test_char(p[5]); + nxt_field_end_test_char(p[6]); + nxt_field_end_test_char(p[7]); - field->hash = nxt_http_field_hash_end(rp->field_hash); - field->skip = 0; - field->hopbyhop = 0; + nxt_field_end_test_char(p[8]); + nxt_field_end_test_char(p[9]); + nxt_field_end_test_char(p[10]); + nxt_field_end_test_char(p[11]); - field->name_length = rp->field_name.length; - field->value_length = rp->field_value.length; - field->name = rp->field_name.start; - field->value = rp->field_value.start; - } + nxt_field_end_test_char(p[12]); + nxt_field_end_test_char(p[13]); + nxt_field_end_test_char(p[14]); + nxt_field_end_test_char(p[15]); - rp->field_hash = NXT_HTTP_FIELD_HASH_INIT; + p += 16; + } - rp->field_name.length = 0; - rp->field_value.length = 0; + while (nxt_fast_path(end - p >= 4)) { - rp->handler = &nxt_http_parse_field_name; - return NXT_OK; - } + nxt_field_end_test_char(p[0]); + nxt_field_end_test_char(p[1]); + nxt_field_end_test_char(p[2]); + nxt_field_end_test_char(p[3]); - return NXT_DONE; - } + p += 4; + } - return NXT_HTTP_PARSE_INVALID; + switch (end - p) { + case 3: + nxt_field_end_test_char(*p); + p++; + /* Fall through. */ + case 2: + nxt_field_end_test_char(*p); + p++; + /* Fall through. */ + case 1: + nxt_field_end_test_char(*p); + p++; + /* Fall through. */ + case 0: + break; + default: + nxt_unreachable(); + } + + return p; } +static nxt_int_t nxt_http_parse_field_end(nxt_http_request_parse_t *rp, + u_char **pos, const u_char *end) { + u_char *p; + nxt_http_field_t *field; -#define nxt_http_is_normal(c) \ - (nxt_fast_path((nxt_http_normal[c / 8] & (1 << (c & 7))) != 0)) - - -static const uint8_t nxt_http_normal[32] nxt_aligned(32) = { + p = *pos; - /* \0 \r \n */ - 0xFE, 0xDB, 0xFF, 0xFF, /* 1111 1110 1101 1011 1111 1111 1111 1111 */ + if (nxt_fast_path(*p == '\r')) { + p++; - /* '&%$ #"! /.-, |*)( 7654 3210 ?>=< ;:98 */ - 0xD6, 0x37, 0xFF, 0x7F, /* 1101 0110 0011 0111 1111 1111 0111 1111 */ + if (nxt_slow_path(p == end)) { + rp->handler = &nxt_http_parse_field_end; + return NXT_AGAIN; + } + } - /* GFED CBA@ ONML KJIH WVUT SRQP _^]\ [ZYX */ - 0xFF, 0xFF, 0xFF, 0xFF, /* 1111 1111 1111 1111 1111 1111 1111 1111 */ + if (nxt_fast_path(*p == '\n')) { + *pos = p + 1; - /* gfed cba` onml kjih wvut srqp ~}| {zyx */ - 0xFF, 0xFF, 0xFF, 0xFF, /* 1111 1111 1111 1111 1111 1111 1111 1111 */ + if (rp->field_name.length != 0) { + if (rp->skip_field) { + rp->skip_field = 0; - 0xFF, 0xFF, 0xFF, 0xFF, /* 1111 1111 1111 1111 1111 1111 1111 1111 */ - 0xFF, 0xFF, 0xFF, 0xFF, /* 1111 1111 1111 1111 1111 1111 1111 1111 */ - 0xFF, 0xFF, 0xFF, 0xFF, /* 1111 1111 1111 1111 1111 1111 1111 1111 */ - 0xFF, 0xFF, 0xFF, 0xFF, /* 1111 1111 1111 1111 1111 1111 1111 1111 */ -}; + } else { + field = nxt_list_add(rp->fields); + if (nxt_slow_path(field == NULL)) { + return NXT_ERROR; + } -nxt_int_t -nxt_http_parse_complex_target(nxt_http_request_parse_t *rp) -{ - u_char *p, *u, c, ch, high, *args; + field->hash = nxt_http_field_hash_end(rp->field_hash); + field->skip = 0; + field->hopbyhop = 0; - enum { - sw_normal = 0, - sw_slash, - sw_dot, - sw_dot_dot, - sw_quoted, - sw_quoted_second, - } state, saved_state; + field->name_length = rp->field_name.length; + field->value_length = rp->field_value.length; + field->name = rp->field_name.start; + field->value = rp->field_value.start; + } - nxt_prefetch(nxt_http_normal); + rp->field_hash = NXT_HTTP_FIELD_HASH_INIT; - state = sw_normal; - saved_state = sw_normal; - p = rp->target_start; + rp->field_name.length = 0; + rp->field_value.length = 0; - u = nxt_mp_alloc(rp->mem_pool, rp->target_end - p + 1); - if (nxt_slow_path(u == NULL)) { - return NXT_ERROR; + rp->handler = &nxt_http_parse_field_name; + return NXT_OK; } - rp->path.length = 0; - rp->path.start = u; + return NXT_DONE; + } - high = '\0'; - args = NULL; - - while (p < rp->target_end) { + return NXT_HTTP_PARSE_INVALID; +} - ch = *p++; +#define nxt_http_is_normal(c) \ + (nxt_fast_path((nxt_http_normal[c / 8] & (1 << (c & 7))) != 0)) - again: +static const uint8_t nxt_http_normal[32] nxt_aligned(32) = { - switch (state) { + /* \0 \r \n */ + 0xFE, 0xDB, 0xFF, 0xFF, /* 1111 1110 1101 1011 1111 1111 1111 1111 */ - case sw_normal: + /* '&%$ #"! /.-, |*)( 7654 3210 ?>=< ;:98 */ + 0xD6, 0x37, 0xFF, 0x7F, /* 1101 0110 0011 0111 1111 1111 0111 1111 */ - if (nxt_http_is_normal(ch)) { - *u++ = ch; - continue; - } + /* GFED CBA@ ONML KJIH WVUT SRQP _^]\ [ZYX */ + 0xFF, 0xFF, 0xFF, 0xFF, /* 1111 1111 1111 1111 1111 1111 1111 1111 */ - switch (ch) { - case '/': - state = sw_slash; - *u++ = ch; - continue; - case '%': - saved_state = state; - state = sw_quoted; - continue; - case '?': - args = p; - goto args; - case '#': - goto done; - default: - *u++ = ch; - continue; - } + /* gfed cba` onml kjih wvut srqp ~}| {zyx */ + 0xFF, 0xFF, 0xFF, 0xFF, /* 1111 1111 1111 1111 1111 1111 1111 1111 */ - break; + 0xFF, 0xFF, 0xFF, 0xFF, /* 1111 1111 1111 1111 1111 1111 1111 1111 */ + 0xFF, 0xFF, 0xFF, 0xFF, /* 1111 1111 1111 1111 1111 1111 1111 1111 */ + 0xFF, 0xFF, 0xFF, 0xFF, /* 1111 1111 1111 1111 1111 1111 1111 1111 */ + 0xFF, 0xFF, 0xFF, 0xFF, /* 1111 1111 1111 1111 1111 1111 1111 1111 */ +}; - case sw_slash: - - if (nxt_http_is_normal(ch)) { - state = sw_normal; - *u++ = ch; - continue; - } - - switch (ch) { - case '/': - continue; - case '.': - state = sw_dot; - *u++ = ch; - continue; - case '%': - saved_state = state; - state = sw_quoted; - continue; - case '?': - args = p; - goto args; - case '#': - goto done; - default: - state = sw_normal; - *u++ = ch; - continue; - } +nxt_int_t nxt_http_parse_complex_target(nxt_http_request_parse_t *rp) { + u_char *p, *u, c, ch, high, *args; + + enum { + sw_normal = 0, + sw_slash, + sw_dot, + sw_dot_dot, + sw_quoted, + sw_quoted_second, + } state, + saved_state; + + nxt_prefetch(nxt_http_normal); + + state = sw_normal; + saved_state = sw_normal; + p = rp->target_start; + + u = nxt_mp_alloc(rp->mem_pool, rp->target_end - p + 1); + if (nxt_slow_path(u == NULL)) { + return NXT_ERROR; + } + + rp->path.length = 0; + rp->path.start = u; + + high = '\0'; + args = NULL; + + while (p < rp->target_end) { + + ch = *p++; + + again: + + switch (state) { + + case sw_normal: + + if (nxt_http_is_normal(ch)) { + *u++ = ch; + continue; + } + + switch (ch) { + case '/': + state = sw_slash; + *u++ = ch; + continue; + case '%': + saved_state = state; + state = sw_quoted; + continue; + case '?': + args = p; + goto args; + case '#': + goto done; + default: + *u++ = ch; + continue; + } + + break; + + case sw_slash: + + if (nxt_http_is_normal(ch)) { + state = sw_normal; + *u++ = ch; + continue; + } + + switch (ch) { + case '/': + continue; + case '.': + state = sw_dot; + *u++ = ch; + continue; + case '%': + saved_state = state; + state = sw_quoted; + continue; + case '?': + args = p; + goto args; + case '#': + goto done; + default: + state = sw_normal; + *u++ = ch; + continue; + } + + break; + + case sw_dot: + + if (nxt_http_is_normal(ch)) { + state = sw_normal; + *u++ = ch; + continue; + } + + switch (ch) { + case '/': + state = sw_slash; + u--; + continue; + case '.': + state = sw_dot_dot; + *u++ = ch; + continue; + case '%': + saved_state = state; + state = sw_quoted; + continue; + case '?': + u--; + args = p; + goto args; + case '#': + u--; + goto done; + default: + state = sw_normal; + *u++ = ch; + continue; + } + + break; + + case sw_dot_dot: + + if (nxt_http_is_normal(ch)) { + state = sw_normal; + *u++ = ch; + continue; + } + + switch (ch) { + + case '/': + case '?': + case '#': + u -= 5; + + for (;;) { + if (u < rp->path.start) { + return NXT_HTTP_PARSE_INVALID; + } + if (*u == '/') { + u++; break; + } - case sw_dot: - - if (nxt_http_is_normal(ch)) { - state = sw_normal; - *u++ = ch; - continue; - } - - switch (ch) { - case '/': - state = sw_slash; - u--; - continue; - case '.': - state = sw_dot_dot; - *u++ = ch; - continue; - case '%': - saved_state = state; - state = sw_quoted; - continue; - case '?': - u--; - args = p; - goto args; - case '#': - u--; - goto done; - default: - state = sw_normal; - *u++ = ch; - continue; - } - - break; + u--; + } - case sw_dot_dot: + if (ch == '?') { + args = p; + goto args; + } - if (nxt_http_is_normal(ch)) { - state = sw_normal; - *u++ = ch; - continue; - } + if (ch == '#') { + goto done; + } - switch (ch) { + state = sw_slash; + break; - case '/': - case '?': - case '#': - u -= 5; + case '%': + saved_state = state; + state = sw_quoted; + continue; - for ( ;; ) { - if (u < rp->path.start) { - return NXT_HTTP_PARSE_INVALID; - } + default: + state = sw_normal; + *u++ = ch; + continue; + } - if (*u == '/') { - u++; - break; - } + break; - u--; - } + case sw_quoted: + rp->quoted_target = 1; - if (ch == '?') { - args = p; - goto args; - } + if (ch >= '0' && ch <= '9') { + high = (u_char)(ch - '0'); + state = sw_quoted_second; + continue; + } - if (ch == '#') { - goto done; - } + c = (u_char)(ch | 0x20); + if (c >= 'a' && c <= 'f') { + high = (u_char)(c - 'a' + 10); + state = sw_quoted_second; + continue; + } - state = sw_slash; - break; + return NXT_HTTP_PARSE_INVALID; - case '%': - saved_state = state; - state = sw_quoted; - continue; + case sw_quoted_second: + if (ch >= '0' && ch <= '9') { + ch = (u_char)((high << 4) + ch - '0'); - default: - state = sw_normal; - *u++ = ch; - continue; - } + if (ch == '%') { + state = sw_normal; + *u++ = '%'; - break; + if (rp->encoded_slashes) { + *u++ = '2'; + *u++ = '5'; + } - case sw_quoted: - rp->quoted_target = 1; + continue; + } - if (ch >= '0' && ch <= '9') { - high = (u_char) (ch - '0'); - state = sw_quoted_second; - continue; - } + if (ch == '#') { + state = sw_normal; + *u++ = '#'; + continue; + } - c = (u_char) (ch | 0x20); - if (c >= 'a' && c <= 'f') { - high = (u_char) (c - 'a' + 10); - state = sw_quoted_second; - continue; - } + if (ch == '\0') { + return NXT_HTTP_PARSE_INVALID; + } - return NXT_HTTP_PARSE_INVALID; + state = saved_state; + goto again; + } - case sw_quoted_second: - if (ch >= '0' && ch <= '9') { - ch = (u_char) ((high << 4) + ch - '0'); - - if (ch == '%') { - state = sw_normal; - *u++ = '%'; - - if (rp->encoded_slashes) { - *u++ = '2'; - *u++ = '5'; - } - - continue; - } - - if (ch == '#') { - state = sw_normal; - *u++ = '#'; - continue; - } - - if (ch == '\0') { - return NXT_HTTP_PARSE_INVALID; - } - - state = saved_state; - goto again; - } - - c = (u_char) (ch | 0x20); - if (c >= 'a' && c <= 'f') { - ch = (u_char) ((high << 4) + c - 'a' + 10); - - if (ch == '?') { - state = sw_normal; - *u++ = ch; - continue; - } - - if (ch == '/' && rp->encoded_slashes) { - state = sw_normal; - *u++ = '%'; - *u++ = '2'; - *u++ = p[-1]; /* 'f' or 'F' */ - continue; - } - - state = saved_state; - goto again; - } + c = (u_char)(ch | 0x20); + if (c >= 'a' && c <= 'f') { + ch = (u_char)((high << 4) + c - 'a' + 10); - return NXT_HTTP_PARSE_INVALID; + if (ch == '?') { + state = sw_normal; + *u++ = ch; + continue; } - } - if (state >= sw_dot) { - if (state >= sw_quoted) { - return NXT_HTTP_PARSE_INVALID; + if (ch == '/' && rp->encoded_slashes) { + state = sw_normal; + *u++ = '%'; + *u++ = '2'; + *u++ = p[-1]; /* 'f' or 'F' */ + continue; } - /* "/." and "/.." must be normalized similar to "/./" and "/../". */ - ch = '/'; + state = saved_state; goto again; + } + + return NXT_HTTP_PARSE_INVALID; } + } + + if (state >= sw_dot) { + if (state >= sw_quoted) { + return NXT_HTTP_PARSE_INVALID; + } + + /* "/." and "/.." must be normalized similar to "/./" and "/../". */ + ch = '/'; + goto again; + } args: - for (/* void */; p < rp->target_end; p++) { - if (*p == '#') { - break; - } + for (/* void */; p < rp->target_end; p++) { + if (*p == '#') { + break; } + } - if (args != NULL) { - rp->args.length = p - args; - rp->args.start = args; - } + if (args != NULL) { + rp->args.length = p - args; + rp->args.start = args; + } done: - rp->path.length = u - rp->path.start; + rp->path.length = u - rp->path.start; - return NXT_OK; + return NXT_OK; } - -const nxt_lvlhsh_proto_t nxt_http_fields_hash_proto nxt_aligned(64) = { +const nxt_lvlhsh_proto_t nxt_http_fields_hash_proto nxt_aligned(64) = { NXT_LVLHSH_BUCKET_SIZE(64), - { NXT_HTTP_FIELD_LVLHSH_SHIFT, 0, 0, 0, 0, 0, 0, 0 }, + {NXT_HTTP_FIELD_LVLHSH_SHIFT, 0, 0, 0, 0, 0, 0, 0}, nxt_http_field_hash_test, nxt_lvlhsh_alloc, nxt_lvlhsh_free, }; +static nxt_int_t nxt_http_field_hash_test(nxt_lvlhsh_query_t *lhq, void *data) { + nxt_http_field_proc_t *field; -static nxt_int_t -nxt_http_field_hash_test(nxt_lvlhsh_query_t *lhq, void *data) -{ - nxt_http_field_proc_t *field; - - field = data; + field = data; - if (nxt_strcasestr_eq(&lhq->key, &field->name)) { - return NXT_OK; - } + if (nxt_strcasestr_eq(&lhq->key, &field->name)) { + return NXT_OK; + } - return NXT_DECLINED; + return NXT_DECLINED; } - -static nxt_int_t -nxt_http_field_hash_collision(nxt_lvlhsh_query_t *lhq, void *data) -{ - return NXT_OK; +static nxt_int_t nxt_http_field_hash_collision(nxt_lvlhsh_query_t *lhq, + void *data) { + return NXT_OK; } +nxt_int_t nxt_http_fields_hash(nxt_lvlhsh_t *hash, + nxt_http_field_proc_t items[], + nxt_uint_t count) { + u_char ch; + uint32_t key; + nxt_str_t *name; + nxt_int_t ret; + nxt_uint_t i, j; + nxt_lvlhsh_query_t lhq; + + lhq.replace = 0; + lhq.proto = &nxt_http_fields_hash_proto; + lhq.pool = NULL; + + for (i = 0; i < count; i++) { + key = NXT_HTTP_FIELD_HASH_INIT; + name = &items[i].name; + + for (j = 0; j < name->length; j++) { + ch = nxt_lowcase(name->start[j]); + key = nxt_http_field_hash_char(key, ch); + } -nxt_int_t -nxt_http_fields_hash(nxt_lvlhsh_t *hash, - nxt_http_field_proc_t items[], nxt_uint_t count) -{ - u_char ch; - uint32_t key; - nxt_str_t *name; - nxt_int_t ret; - nxt_uint_t i, j; - nxt_lvlhsh_query_t lhq; - - lhq.replace = 0; - lhq.proto = &nxt_http_fields_hash_proto; - lhq.pool = NULL; - - for (i = 0; i < count; i++) { - key = NXT_HTTP_FIELD_HASH_INIT; - name = &items[i].name; - - for (j = 0; j < name->length; j++) { - ch = nxt_lowcase(name->start[j]); - key = nxt_http_field_hash_char(key, ch); - } - - lhq.key_hash = nxt_http_field_hash_end(key) & 0xFFFF; - lhq.key = *name; - lhq.value = &items[i]; + lhq.key_hash = nxt_http_field_hash_end(key) & 0xFFFF; + lhq.key = *name; + lhq.value = &items[i]; - ret = nxt_lvlhsh_insert(hash, &lhq); + ret = nxt_lvlhsh_insert(hash, &lhq); - if (nxt_slow_path(ret != NXT_OK)) { - return NXT_ERROR; - } + if (nxt_slow_path(ret != NXT_OK)) { + return NXT_ERROR; } + } - return NXT_OK; + return NXT_OK; } +nxt_uint_t nxt_http_fields_hash_collisions(nxt_lvlhsh_t *hash, + nxt_http_field_proc_t items[], + nxt_uint_t count, nxt_bool_t level) { + u_char ch; + uint32_t key, mask; + nxt_str_t *name; + nxt_uint_t colls, i, j; + nxt_lvlhsh_proto_t proto; + nxt_lvlhsh_query_t lhq; -nxt_uint_t -nxt_http_fields_hash_collisions(nxt_lvlhsh_t *hash, - nxt_http_field_proc_t items[], nxt_uint_t count, nxt_bool_t level) -{ - u_char ch; - uint32_t key, mask; - nxt_str_t *name; - nxt_uint_t colls, i, j; - nxt_lvlhsh_proto_t proto; - nxt_lvlhsh_query_t lhq; - - proto = nxt_http_fields_hash_proto; - proto.test = nxt_http_field_hash_collision; + proto = nxt_http_fields_hash_proto; + proto.test = nxt_http_field_hash_collision; - lhq.replace = 0; - lhq.proto = &proto; + lhq.replace = 0; + lhq.proto = &proto; - mask = level ? (1 << NXT_HTTP_FIELD_LVLHSH_SHIFT) - 1 : 0xFFFF; + mask = level ? (1 << NXT_HTTP_FIELD_LVLHSH_SHIFT) - 1 : 0xFFFF; - colls = 0; + colls = 0; - for (i = 0; i < count; i++) { - key = NXT_HTTP_FIELD_HASH_INIT; - name = &items[i].name; + for (i = 0; i < count; i++) { + key = NXT_HTTP_FIELD_HASH_INIT; + name = &items[i].name; - for (j = 0; j < name->length; j++) { - ch = nxt_lowcase(name->start[j]); - key = nxt_http_field_hash_char(key, ch); - } + for (j = 0; j < name->length; j++) { + ch = nxt_lowcase(name->start[j]); + key = nxt_http_field_hash_char(key, ch); + } - lhq.key_hash = nxt_http_field_hash_end(key) & mask; - lhq.value = &items[i]; + lhq.key_hash = nxt_http_field_hash_end(key) & mask; + lhq.value = &items[i]; - if (nxt_lvlhsh_insert(hash, &lhq) == NXT_DECLINED) { - colls++; - } + if (nxt_lvlhsh_insert(hash, &lhq) == NXT_DECLINED) { + colls++; } + } - return colls; + return colls; } +nxt_int_t nxt_http_fields_process(nxt_list_t *fields, nxt_lvlhsh_t *hash, + void *ctx) { + nxt_int_t ret; + nxt_http_field_t *field; -nxt_int_t -nxt_http_fields_process(nxt_list_t *fields, nxt_lvlhsh_t *hash, void *ctx) -{ - nxt_int_t ret; - nxt_http_field_t *field; + nxt_list_each(field, fields) { - nxt_list_each(field, fields) { - - ret = nxt_http_field_process(field, hash, ctx); - if (nxt_slow_path(ret != NXT_OK)) { - return ret; - } - - } nxt_list_loop; + ret = nxt_http_field_process(field, hash, ctx); + if (nxt_slow_path(ret != NXT_OK)) { + return ret; + } + } + nxt_list_loop; - return NXT_OK; + return NXT_OK; } diff --git a/src/nxt_http_parse.h b/src/nxt_http_parse.h index 9e2f6fabb..18148a183 100644 --- a/src/nxt_http_parse.h +++ b/src/nxt_http_parse.h @@ -7,150 +7,137 @@ #ifndef _NXT_HTTP_PARSER_H_INCLUDED_ #define _NXT_HTTP_PARSER_H_INCLUDED_ - typedef enum { - NXT_HTTP_PARSE_INVALID = 1, - NXT_HTTP_PARSE_UNSUPPORTED_VERSION, - NXT_HTTP_PARSE_TOO_LARGE_FIELD, + NXT_HTTP_PARSE_INVALID = 1, + NXT_HTTP_PARSE_UNSUPPORTED_VERSION, + NXT_HTTP_PARSE_TOO_LARGE_FIELD, } nxt_http_parse_error_t; - -typedef struct nxt_http_request_parse_s nxt_http_request_parse_t; -typedef struct nxt_http_field_s nxt_http_field_t; -typedef struct nxt_http_fields_hash_s nxt_http_fields_hash_t; - +typedef struct nxt_http_request_parse_s nxt_http_request_parse_t; +typedef struct nxt_http_field_s nxt_http_field_t; +typedef struct nxt_http_fields_hash_s nxt_http_fields_hash_t; typedef union { - u_char str[8]; - uint64_t ui64; - - struct { - u_char prefix[5]; - u_char major; - u_char point; - u_char minor; - } s; + u_char str[8]; + uint64_t ui64; + + struct { + u_char prefix[5]; + u_char major; + u_char point; + u_char minor; + } s; } nxt_http_ver_t; - struct nxt_http_request_parse_s { - nxt_int_t (*handler)(nxt_http_request_parse_t *rp, - u_char **pos, const u_char *end); + nxt_int_t (*handler)(nxt_http_request_parse_t *rp, u_char **pos, + const u_char *end); - nxt_str_t method; + nxt_str_t method; - u_char *target_start; - u_char *target_end; - u_char *request_line_end; + u_char *target_start; + u_char *target_end; + u_char *request_line_end; - nxt_str_t path; - nxt_str_t args; + nxt_str_t path; + nxt_str_t args; - nxt_http_ver_t version; + nxt_http_ver_t version; - nxt_list_t *fields; - nxt_mp_t *mem_pool; + nxt_list_t *fields; + nxt_mp_t *mem_pool; - nxt_str_t field_name; - nxt_str_t field_value; + nxt_str_t field_name; + nxt_str_t field_value; - uint32_t field_hash; + uint32_t field_hash; - uint8_t skip_field; /* 1 bit */ - uint8_t discard_unsafe_fields; /* 1 bit */ + uint8_t skip_field; /* 1 bit */ + uint8_t discard_unsafe_fields; /* 1 bit */ - /* target with "/." */ - uint8_t complex_target; /* 1 bit */ - /* target with "%" */ - uint8_t quoted_target; /* 1 bit */ + /* target with "/." */ + uint8_t complex_target; /* 1 bit */ + /* target with "%" */ + uint8_t quoted_target; /* 1 bit */ #if 0 /* target with " " */ uint8_t space_in_target; /* 1 bit */ #endif - /* Preserve encoded '/' (%2F) and '%' (%25). */ - uint8_t encoded_slashes; /* 1 bit */ + /* Preserve encoded '/' (%2F) and '%' (%25). */ + uint8_t encoded_slashes; /* 1 bit */ }; - typedef nxt_int_t (*nxt_http_field_handler_t)(void *ctx, nxt_http_field_t *field, uintptr_t data); - typedef struct { - nxt_str_t name; - nxt_http_field_handler_t handler; - uintptr_t data; + nxt_str_t name; + nxt_http_field_handler_t handler; + uintptr_t data; } nxt_http_field_proc_t; - struct nxt_http_field_s { - uint16_t hash; - uint8_t skip:1; - uint8_t hopbyhop:1; - uint8_t name_length; - uint32_t value_length; - u_char *name; - u_char *value; + uint16_t hash; + uint8_t skip : 1; + uint8_t hopbyhop : 1; + uint8_t name_length; + uint32_t value_length; + u_char *name; + u_char *value; }; - typedef struct { - nxt_mp_t *mem_pool; - uint64_t chunk_size; - uint8_t state; - uint8_t last; /* 1 bit */ - uint8_t chunk_error; /* 1 bit */ - uint8_t error; /* 1 bit */ + nxt_mp_t *mem_pool; + uint64_t chunk_size; + uint8_t state; + uint8_t last; /* 1 bit */ + uint8_t chunk_error; /* 1 bit */ + uint8_t error; /* 1 bit */ } nxt_http_chunk_parse_t; - -#define NXT_HTTP_FIELD_HASH_INIT 159406U -#define nxt_http_field_hash_char(h, c) (((h) << 4) + (h) + (c)) -#define nxt_http_field_hash_end(h) (((h) >> 16) ^ (h)) - +#define NXT_HTTP_FIELD_HASH_INIT 159406U +#define nxt_http_field_hash_char(h, c) (((h) << 4) + (h) + (c)) +#define nxt_http_field_hash_end(h) (((h) >> 16) ^ (h)) nxt_int_t nxt_http_parse_request_init(nxt_http_request_parse_t *rp, - nxt_mp_t *mp); + nxt_mp_t *mp); nxt_int_t nxt_http_parse_request(nxt_http_request_parse_t *rp, - nxt_buf_mem_t *b); -nxt_int_t nxt_http_parse_fields(nxt_http_request_parse_t *rp, - nxt_buf_mem_t *b); + nxt_buf_mem_t *b); +nxt_int_t nxt_http_parse_fields(nxt_http_request_parse_t *rp, nxt_buf_mem_t *b); nxt_int_t nxt_http_fields_hash(nxt_lvlhsh_t *hash, - nxt_http_field_proc_t items[], nxt_uint_t count); + nxt_http_field_proc_t items[], nxt_uint_t count); nxt_uint_t nxt_http_fields_hash_collisions(nxt_lvlhsh_t *hash, - nxt_http_field_proc_t items[], nxt_uint_t count, nxt_bool_t level); + nxt_http_field_proc_t items[], + nxt_uint_t count, nxt_bool_t level); nxt_int_t nxt_http_fields_process(nxt_list_t *fields, nxt_lvlhsh_t *hash, - void *ctx); + void *ctx); nxt_int_t nxt_http_parse_complex_target(nxt_http_request_parse_t *rp); nxt_buf_t *nxt_http_chunk_parse(nxt_task_t *task, nxt_http_chunk_parse_t *hcp, - nxt_buf_t *in); - + nxt_buf_t *in); -extern const nxt_lvlhsh_proto_t nxt_http_fields_hash_proto; +extern const nxt_lvlhsh_proto_t nxt_http_fields_hash_proto; -nxt_inline nxt_int_t -nxt_http_field_process(nxt_http_field_t *field, nxt_lvlhsh_t *hash, void *ctx) -{ - nxt_lvlhsh_query_t lhq; - nxt_http_field_proc_t *proc; +nxt_inline nxt_int_t nxt_http_field_process(nxt_http_field_t *field, + nxt_lvlhsh_t *hash, void *ctx) { + nxt_lvlhsh_query_t lhq; + nxt_http_field_proc_t *proc; - lhq.proto = &nxt_http_fields_hash_proto; + lhq.proto = &nxt_http_fields_hash_proto; - lhq.key_hash = field->hash; - lhq.key.length = field->name_length; - lhq.key.start = field->name; + lhq.key_hash = field->hash; + lhq.key.length = field->name_length; + lhq.key.start = field->name; - if (nxt_lvlhsh_find(hash, &lhq) != NXT_OK) { - return NXT_OK; - } + if (nxt_lvlhsh_find(hash, &lhq) != NXT_OK) { + return NXT_OK; + } - proc = lhq.value; + proc = lhq.value; - return proc->handler(ctx, field, proc->data); + return proc->handler(ctx, field, proc->data); } - #endif /* _NXT_HTTP_PARSER_H_INCLUDED_ */ diff --git a/src/nxt_http_proxy.c b/src/nxt_http_proxy.c index 7f6ad6866..58a2778d1 100644 --- a/src/nxt_http_proxy.c +++ b/src/nxt_http_proxy.c @@ -8,426 +8,374 @@ #include #include - struct nxt_upstream_proxy_s { - nxt_sockaddr_t *sockaddr; - uint8_t protocol; + nxt_sockaddr_t *sockaddr; + uint8_t protocol; }; - static void nxt_http_proxy_server_get(nxt_task_t *task, - nxt_upstream_server_t *us); + nxt_upstream_server_t *us); static void nxt_http_proxy_upstream_ready(nxt_task_t *task, - nxt_upstream_server_t *us); + nxt_upstream_server_t *us); static void nxt_http_proxy_upstream_error(nxt_task_t *task, - nxt_upstream_server_t *us); + nxt_upstream_server_t *us); static nxt_http_action_t *nxt_http_proxy(nxt_task_t *task, - nxt_http_request_t *r, nxt_http_action_t *action); + nxt_http_request_t *r, + nxt_http_action_t *action); static void nxt_http_proxy_header_send(nxt_task_t *task, void *obj, void *data); static void nxt_http_proxy_header_sent(nxt_task_t *task, void *obj, void *data); static void nxt_http_proxy_header_read(nxt_task_t *task, void *obj, void *data); static void nxt_http_proxy_send_body(nxt_task_t *task, void *obj, void *data); static void nxt_http_proxy_buf_mem_completion(nxt_task_t *task, void *obj, - void *data); + void *data); static void nxt_http_proxy_error(nxt_task_t *task, void *obj, void *data); +static const nxt_http_request_state_t nxt_http_proxy_header_send_state; +static const nxt_http_request_state_t nxt_http_proxy_header_sent_state; +static const nxt_http_request_state_t nxt_http_proxy_header_read_state; +static const nxt_http_request_state_t nxt_http_proxy_read_state; -static const nxt_http_request_state_t nxt_http_proxy_header_send_state; -static const nxt_http_request_state_t nxt_http_proxy_header_sent_state; -static const nxt_http_request_state_t nxt_http_proxy_header_read_state; -static const nxt_http_request_state_t nxt_http_proxy_read_state; - - -static const nxt_upstream_server_proto_t nxt_upstream_simple_proto = { +static const nxt_upstream_server_proto_t nxt_upstream_simple_proto = { .get = nxt_http_proxy_server_get, }; - -static const nxt_upstream_peer_state_t nxt_upstream_proxy_state = { +static const nxt_upstream_peer_state_t nxt_upstream_proxy_state = { .ready = nxt_http_proxy_upstream_ready, .error = nxt_http_proxy_upstream_error, }; +nxt_int_t nxt_http_proxy_init(nxt_mp_t *mp, nxt_http_action_t *action, + nxt_http_action_conf_t *acf) { + nxt_str_t name; + nxt_sockaddr_t *sa; + nxt_upstream_t *up; + nxt_upstream_proxy_t *proxy; -nxt_int_t -nxt_http_proxy_init(nxt_mp_t *mp, nxt_http_action_t *action, - nxt_http_action_conf_t *acf) -{ - nxt_str_t name; - nxt_sockaddr_t *sa; - nxt_upstream_t *up; - nxt_upstream_proxy_t *proxy; + sa = NULL; + nxt_conf_get_string(acf->proxy, &name); - sa = NULL; - nxt_conf_get_string(acf->proxy, &name); + if (nxt_str_start(&name, "http://", 7)) { + name.length -= 7; + name.start += 7; - if (nxt_str_start(&name, "http://", 7)) { - name.length -= 7; - name.start += 7; + sa = nxt_sockaddr_parse(mp, &name); + if (nxt_slow_path(sa == NULL)) { + return NXT_ERROR; + } - sa = nxt_sockaddr_parse(mp, &name); - if (nxt_slow_path(sa == NULL)) { - return NXT_ERROR; - } + sa->type = SOCK_STREAM; + } - sa->type = SOCK_STREAM; + if (sa != NULL) { + up = nxt_mp_alloc(mp, sizeof(nxt_upstream_t)); + if (nxt_slow_path(up == NULL)) { + return NXT_ERROR; } - if (sa != NULL) { - up = nxt_mp_alloc(mp, sizeof(nxt_upstream_t)); - if (nxt_slow_path(up == NULL)) { - return NXT_ERROR; - } - - up->name.length = sa->length; - up->name.start = nxt_sockaddr_start(sa); - up->proto = &nxt_upstream_simple_proto; + up->name.length = sa->length; + up->name.start = nxt_sockaddr_start(sa); + up->proto = &nxt_upstream_simple_proto; - proxy = nxt_mp_alloc(mp, sizeof(nxt_upstream_proxy_t)); - if (nxt_slow_path(proxy == NULL)) { - return NXT_ERROR; - } + proxy = nxt_mp_alloc(mp, sizeof(nxt_upstream_proxy_t)); + if (nxt_slow_path(proxy == NULL)) { + return NXT_ERROR; + } - proxy->sockaddr = sa; - proxy->protocol = NXT_HTTP_PROTO_H1; - up->type.proxy = proxy; + proxy->sockaddr = sa; + proxy->protocol = NXT_HTTP_PROTO_H1; + up->type.proxy = proxy; - action->u.upstream = up; - action->handler = nxt_http_proxy; - } + action->u.upstream = up; + action->handler = nxt_http_proxy; + } - return NXT_OK; + return NXT_OK; } +static nxt_http_action_t *nxt_http_proxy(nxt_task_t *task, + nxt_http_request_t *r, + nxt_http_action_t *action) { + nxt_upstream_t *u; -static nxt_http_action_t * -nxt_http_proxy(nxt_task_t *task, nxt_http_request_t *r, - nxt_http_action_t *action) -{ - nxt_upstream_t *u; - - u = action->u.upstream; + u = action->u.upstream; - nxt_debug(task, "http proxy: \"%V\"", &u->name); + nxt_debug(task, "http proxy: \"%V\"", &u->name); - return nxt_upstream_proxy_handler(task, r, u); + return nxt_upstream_proxy_handler(task, r, u); } +nxt_http_action_t *nxt_upstream_proxy_handler(nxt_task_t *task, + nxt_http_request_t *r, + nxt_upstream_t *upstream) { + nxt_http_peer_t *peer; + nxt_upstream_server_t *us; -nxt_http_action_t * -nxt_upstream_proxy_handler(nxt_task_t *task, nxt_http_request_t *r, - nxt_upstream_t *upstream) -{ - nxt_http_peer_t *peer; - nxt_upstream_server_t *us; - - us = nxt_mp_zalloc(r->mem_pool, sizeof(nxt_upstream_server_t)); - if (nxt_slow_path(us == NULL)) { - nxt_http_request_error(task, r, NXT_HTTP_INTERNAL_SERVER_ERROR); - return NULL; - } + us = nxt_mp_zalloc(r->mem_pool, sizeof(nxt_upstream_server_t)); + if (nxt_slow_path(us == NULL)) { + nxt_http_request_error(task, r, NXT_HTTP_INTERNAL_SERVER_ERROR); + return NULL; + } - peer = nxt_mp_zalloc(r->mem_pool, sizeof(nxt_http_peer_t)); - if (nxt_slow_path(peer == NULL)) { - nxt_http_request_error(task, r, NXT_HTTP_INTERNAL_SERVER_ERROR); - return NULL; - } + peer = nxt_mp_zalloc(r->mem_pool, sizeof(nxt_http_peer_t)); + if (nxt_slow_path(peer == NULL)) { + nxt_http_request_error(task, r, NXT_HTTP_INTERNAL_SERVER_ERROR); + return NULL; + } - peer->request = r; - r->peer = peer; + peer->request = r; + r->peer = peer; - nxt_mp_retain(r->mem_pool); + nxt_mp_retain(r->mem_pool); - us->state = &nxt_upstream_proxy_state; - us->peer.http = peer; - peer->server = us; + us->state = &nxt_upstream_proxy_state; + us->peer.http = peer; + peer->server = us; - us->upstream = upstream; - upstream->proto->get(task, us); + us->upstream = upstream; + upstream->proto->get(task, us); - return NULL; + return NULL; } +static void nxt_http_proxy_server_get(nxt_task_t *task, + nxt_upstream_server_t *us) { + nxt_upstream_proxy_t *proxy; -static void -nxt_http_proxy_server_get(nxt_task_t *task, nxt_upstream_server_t *us) -{ - nxt_upstream_proxy_t *proxy; - - proxy = us->upstream->type.proxy; + proxy = us->upstream->type.proxy; - us->sockaddr = proxy->sockaddr; - us->protocol = proxy->protocol; + us->sockaddr = proxy->sockaddr; + us->protocol = proxy->protocol; - us->state->ready(task, us); + us->state->ready(task, us); } +static void nxt_http_proxy_upstream_ready(nxt_task_t *task, + nxt_upstream_server_t *us) { + nxt_http_peer_t *peer; -static void -nxt_http_proxy_upstream_ready(nxt_task_t *task, nxt_upstream_server_t *us) -{ - nxt_http_peer_t *peer; - - peer = us->peer.http; + peer = us->peer.http; - peer->protocol = us->protocol; + peer->protocol = us->protocol; - peer->request->state = &nxt_http_proxy_header_send_state; + peer->request->state = &nxt_http_proxy_header_send_state; - nxt_http_proto[peer->protocol].peer_connect(task, peer); + nxt_http_proto[peer->protocol].peer_connect(task, peer); } +static void nxt_http_proxy_upstream_error(nxt_task_t *task, + nxt_upstream_server_t *us) { + nxt_http_request_t *r; -static void -nxt_http_proxy_upstream_error(nxt_task_t *task, nxt_upstream_server_t *us) -{ - nxt_http_request_t *r; - - r = us->peer.http->request; + r = us->peer.http->request; - nxt_mp_release(r->mem_pool); + nxt_mp_release(r->mem_pool); - nxt_http_request_error(task, r, NXT_HTTP_BAD_GATEWAY); + nxt_http_request_error(task, r, NXT_HTTP_BAD_GATEWAY); } - -static const nxt_http_request_state_t nxt_http_proxy_header_send_state - nxt_aligned(64) = -{ - .ready_handler = nxt_http_proxy_header_send, - .error_handler = nxt_http_proxy_error, +static const nxt_http_request_state_t + nxt_http_proxy_header_send_state nxt_aligned(64) = { + .ready_handler = nxt_http_proxy_header_send, + .error_handler = nxt_http_proxy_error, }; +static void nxt_http_proxy_header_send(nxt_task_t *task, void *obj, + void *data) { + nxt_http_peer_t *peer; + nxt_http_request_t *r; -static void -nxt_http_proxy_header_send(nxt_task_t *task, void *obj, void *data) -{ - nxt_http_peer_t *peer; - nxt_http_request_t *r; - - r = obj; - peer = data; - r->state = &nxt_http_proxy_header_sent_state; + r = obj; + peer = data; + r->state = &nxt_http_proxy_header_sent_state; - nxt_http_proto[peer->protocol].peer_header_send(task, peer); + nxt_http_proto[peer->protocol].peer_header_send(task, peer); } - -static const nxt_http_request_state_t nxt_http_proxy_header_sent_state - nxt_aligned(64) = -{ - .ready_handler = nxt_http_proxy_header_sent, - .error_handler = nxt_http_proxy_error, +static const nxt_http_request_state_t + nxt_http_proxy_header_sent_state nxt_aligned(64) = { + .ready_handler = nxt_http_proxy_header_sent, + .error_handler = nxt_http_proxy_error, }; +static void nxt_http_proxy_header_sent(nxt_task_t *task, void *obj, + void *data) { + nxt_http_peer_t *peer; + nxt_http_request_t *r; -static void -nxt_http_proxy_header_sent(nxt_task_t *task, void *obj, void *data) -{ - nxt_http_peer_t *peer; - nxt_http_request_t *r; - - r = obj; - peer = data; - r->state = &nxt_http_proxy_header_read_state; + r = obj; + peer = data; + r->state = &nxt_http_proxy_header_read_state; - nxt_http_proto[peer->protocol].peer_header_read(task, peer); + nxt_http_proto[peer->protocol].peer_header_read(task, peer); } - -static const nxt_http_request_state_t nxt_http_proxy_header_read_state - nxt_aligned(64) = -{ - .ready_handler = nxt_http_proxy_header_read, - .error_handler = nxt_http_proxy_error, +static const nxt_http_request_state_t + nxt_http_proxy_header_read_state nxt_aligned(64) = { + .ready_handler = nxt_http_proxy_header_read, + .error_handler = nxt_http_proxy_error, }; +static void nxt_http_proxy_header_read(nxt_task_t *task, void *obj, + void *data) { + nxt_http_peer_t *peer; + nxt_http_field_t *f, *field; + nxt_http_request_t *r; -static void -nxt_http_proxy_header_read(nxt_task_t *task, void *obj, void *data) -{ - nxt_http_peer_t *peer; - nxt_http_field_t *f, *field; - nxt_http_request_t *r; - - r = obj; - peer = data; + r = obj; + peer = data; - r->status = peer->status; + r->status = peer->status; - nxt_debug(task, "http proxy status: %d", peer->status); + nxt_debug(task, "http proxy status: %d", peer->status); - nxt_list_each(field, peer->fields) { + nxt_list_each(field, peer->fields) { - nxt_debug(task, "http proxy header: \"%*s: %*s\"", - (size_t) field->name_length, field->name, - (size_t) field->value_length, field->value); + nxt_debug(task, "http proxy header: \"%*s: %*s\"", + (size_t)field->name_length, field->name, + (size_t)field->value_length, field->value); - if (!field->skip) { - f = nxt_list_add(r->resp.fields); - if (nxt_slow_path(f == NULL)) { - nxt_http_proxy_error(task, r, peer); - return; - } + if (!field->skip) { + f = nxt_list_add(r->resp.fields); + if (nxt_slow_path(f == NULL)) { + nxt_http_proxy_error(task, r, peer); + return; + } - *f = *field; - } - - } nxt_list_loop; + *f = *field; + } + } + nxt_list_loop; - r->state = &nxt_http_proxy_read_state; + r->state = &nxt_http_proxy_read_state; - nxt_http_request_header_send(task, r, nxt_http_proxy_send_body, peer); + nxt_http_request_header_send(task, r, nxt_http_proxy_send_body, peer); } - -static const nxt_http_request_state_t nxt_http_proxy_read_state - nxt_aligned(64) = -{ - .ready_handler = nxt_http_proxy_send_body, - .error_handler = nxt_http_proxy_error, +static const nxt_http_request_state_t + nxt_http_proxy_read_state nxt_aligned(64) = { + .ready_handler = nxt_http_proxy_send_body, + .error_handler = nxt_http_proxy_error, }; +static void nxt_http_proxy_send_body(nxt_task_t *task, void *obj, void *data) { + nxt_buf_t *out; + nxt_http_peer_t *peer; + nxt_http_request_t *r; -static void -nxt_http_proxy_send_body(nxt_task_t *task, void *obj, void *data) -{ - nxt_buf_t *out; - nxt_http_peer_t *peer; - nxt_http_request_t *r; + r = obj; + peer = data; + out = peer->body; - r = obj; - peer = data; - out = peer->body; + if (out != NULL) { + peer->body = NULL; + nxt_http_request_send(task, r, out); + } - if (out != NULL) { - peer->body = NULL; - nxt_http_request_send(task, r, out); - } - - if (!peer->closed) { - nxt_http_proto[peer->protocol].peer_read(task, peer); + if (!peer->closed) { + nxt_http_proto[peer->protocol].peer_read(task, peer); - } else { - nxt_http_proto[peer->protocol].peer_close(task, peer); + } else { + nxt_http_proto[peer->protocol].peer_close(task, peer); - nxt_mp_release(r->mem_pool); - } + nxt_mp_release(r->mem_pool); + } } +nxt_buf_t *nxt_http_proxy_buf_mem_alloc(nxt_task_t *task, nxt_http_request_t *r, + size_t size) { + nxt_buf_t *b; -nxt_buf_t * -nxt_http_proxy_buf_mem_alloc(nxt_task_t *task, nxt_http_request_t *r, - size_t size) -{ - nxt_buf_t *b; - - b = nxt_event_engine_buf_mem_alloc(task->thread->engine, size); - if (nxt_fast_path(b != NULL)) { - b->completion_handler = nxt_http_proxy_buf_mem_completion; - b->parent = r; - nxt_mp_retain(r->mem_pool); + b = nxt_event_engine_buf_mem_alloc(task->thread->engine, size); + if (nxt_fast_path(b != NULL)) { + b->completion_handler = nxt_http_proxy_buf_mem_completion; + b->parent = r; + nxt_mp_retain(r->mem_pool); - } else { - nxt_http_request_error(task, r, NXT_HTTP_INTERNAL_SERVER_ERROR); - } + } else { + nxt_http_request_error(task, r, NXT_HTTP_INTERNAL_SERVER_ERROR); + } - return b; + return b; } +static void nxt_http_proxy_buf_mem_completion(nxt_task_t *task, void *obj, + void *data) { + nxt_buf_t *b, *next; + nxt_http_peer_t *peer; + nxt_http_request_t *r; -static void -nxt_http_proxy_buf_mem_completion(nxt_task_t *task, void *obj, void *data) -{ - nxt_buf_t *b, *next; - nxt_http_peer_t *peer; - nxt_http_request_t *r; - - b = obj; - r = data; + b = obj; + r = data; - peer = r->peer; + peer = r->peer; - do { - next = b->next; + do { + next = b->next; - nxt_http_proxy_buf_mem_free(task, r, b); + nxt_http_proxy_buf_mem_free(task, r, b); - b = next; - } while (b != NULL); + b = next; + } while (b != NULL); - if (!peer->closed) { - nxt_http_proto[peer->protocol].peer_read(task, peer); - } + if (!peer->closed) { + nxt_http_proto[peer->protocol].peer_read(task, peer); + } } +void nxt_http_proxy_buf_mem_free(nxt_task_t *task, nxt_http_request_t *r, + nxt_buf_t *b) { + nxt_event_engine_buf_mem_free(task->thread->engine, b); -void -nxt_http_proxy_buf_mem_free(nxt_task_t *task, nxt_http_request_t *r, - nxt_buf_t *b) -{ - nxt_event_engine_buf_mem_free(task->thread->engine, b); - - nxt_mp_release(r->mem_pool); + nxt_mp_release(r->mem_pool); } +static void nxt_http_proxy_error(nxt_task_t *task, void *obj, void *data) { + nxt_http_peer_t *peer; + nxt_http_request_t *r; -static void -nxt_http_proxy_error(nxt_task_t *task, void *obj, void *data) -{ - nxt_http_peer_t *peer; - nxt_http_request_t *r; - - r = obj; - peer = r->peer; + r = obj; + peer = r->peer; - if (!peer->closed) { - nxt_http_proto[peer->protocol].peer_close(task, peer); - nxt_mp_release(r->mem_pool); - } + if (!peer->closed) { + nxt_http_proto[peer->protocol].peer_close(task, peer); + nxt_mp_release(r->mem_pool); + } - nxt_http_request_error(&r->task, r, peer->status); + nxt_http_request_error(&r->task, r, peer->status); } +nxt_int_t nxt_http_proxy_date(void *ctx, nxt_http_field_t *field, + uintptr_t data) { + nxt_http_request_t *r; -nxt_int_t -nxt_http_proxy_date(void *ctx, nxt_http_field_t *field, uintptr_t data) -{ - nxt_http_request_t *r; - - r = ctx; + r = ctx; - r->resp.date = field; + r->resp.date = field; - return NXT_OK; + return NXT_OK; } +nxt_int_t nxt_http_proxy_content_length(void *ctx, nxt_http_field_t *field, + uintptr_t data) { + nxt_off_t n; + nxt_http_request_t *r; -nxt_int_t -nxt_http_proxy_content_length(void *ctx, nxt_http_field_t *field, - uintptr_t data) -{ - nxt_off_t n; - nxt_http_request_t *r; + r = ctx; - r = ctx; + r->resp.content_length = field; - r->resp.content_length = field; + n = nxt_off_t_parse(field->value, field->value_length); - n = nxt_off_t_parse(field->value, field->value_length); + if (nxt_fast_path(n >= 0)) { + r->resp.content_length_n = n; + } - if (nxt_fast_path(n >= 0)) { - r->resp.content_length_n = n; - } - - return NXT_OK; + return NXT_OK; } +nxt_int_t nxt_http_proxy_skip(void *ctx, nxt_http_field_t *field, + uintptr_t data) { + field->skip = 1; -nxt_int_t -nxt_http_proxy_skip(void *ctx, nxt_http_field_t *field, uintptr_t data) -{ - field->skip = 1; - - return NXT_OK; + return NXT_OK; } diff --git a/src/nxt_http_request.c b/src/nxt_http_request.c index a7e9ff69a..cbab31fdd 100644 --- a/src/nxt_http_request.c +++ b/src/nxt_http_request.c @@ -7,1355 +7,1241 @@ #include #include - static nxt_int_t nxt_http_validate_host(nxt_str_t *host, nxt_mp_t *mp); static void nxt_http_request_start(nxt_task_t *task, void *obj, void *data); static nxt_int_t nxt_http_request_forward(nxt_task_t *task, - nxt_http_request_t *r, nxt_http_forward_t *forward); + nxt_http_request_t *r, + nxt_http_forward_t *forward); static void nxt_http_request_forward_client_ip(nxt_http_request_t *r, - nxt_http_forward_t *forward, nxt_array_t *fields); -static nxt_sockaddr_t *nxt_http_request_client_ip_sockaddr( - nxt_http_request_t *r, u_char *start, size_t len); + nxt_http_forward_t *forward, + nxt_array_t *fields); +static nxt_sockaddr_t * +nxt_http_request_client_ip_sockaddr(nxt_http_request_t *r, u_char *start, + size_t len); static void nxt_http_request_forward_protocol(nxt_http_request_t *r, - nxt_http_field_t *field); + nxt_http_field_t *field); static void nxt_http_request_ready(nxt_task_t *task, void *obj, void *data); static void nxt_http_request_proto_info(nxt_task_t *task, - nxt_http_request_t *r); + nxt_http_request_t *r); static void nxt_http_request_mem_buf_completion(nxt_task_t *task, void *obj, - void *data); + void *data); static void nxt_http_request_done(nxt_task_t *task, void *obj, void *data); static u_char *nxt_http_date_cache_handler(u_char *buf, nxt_realtime_t *now, - struct tm *tm, size_t size, const char *format); + struct tm *tm, size_t size, + const char *format); -static nxt_http_name_value_t *nxt_http_argument(nxt_array_t *array, - u_char *name, size_t name_length, uint32_t hash, u_char *start, - const u_char *end); +static nxt_http_name_value_t * +nxt_http_argument(nxt_array_t *array, u_char *name, size_t name_length, + uint32_t hash, u_char *start, const u_char *end); static nxt_int_t nxt_http_cookie_parse(nxt_array_t *cookies, u_char *start, - const u_char *end); + const u_char *end); static nxt_http_name_value_t *nxt_http_cookie(nxt_array_t *array, u_char *name, - size_t name_length, u_char *start, const u_char *end); + size_t name_length, u_char *start, + const u_char *end); + +#define NXT_HTTP_COOKIE_HASH \ + (nxt_http_field_hash_end(nxt_http_field_hash_char( \ + nxt_http_field_hash_char( \ + nxt_http_field_hash_char( \ + nxt_http_field_hash_char( \ + nxt_http_field_hash_char( \ + nxt_http_field_hash_char(NXT_HTTP_FIELD_HASH_INIT, \ + 'c'), \ + 'o'), \ + 'o'), \ + 'k'), \ + 'i'), \ + 'e')) & \ + 0xFFFF) + +static const nxt_http_request_state_t nxt_http_request_init_state; +static const nxt_http_request_state_t nxt_http_request_body_state; + +nxt_time_string_t nxt_http_date_cache = { + (nxt_atomic_uint_t)-1, nxt_http_date_cache_handler, NULL, + NXT_HTTP_DATE_LEN, NXT_THREAD_TIME_GMT, NXT_THREAD_TIME_SEC, +}; +nxt_int_t nxt_http_init(nxt_task_t *task) { + nxt_int_t ret; -#define NXT_HTTP_COOKIE_HASH \ - (nxt_http_field_hash_end( \ - nxt_http_field_hash_char( \ - nxt_http_field_hash_char( \ - nxt_http_field_hash_char( \ - nxt_http_field_hash_char( \ - nxt_http_field_hash_char( \ - nxt_http_field_hash_char(NXT_HTTP_FIELD_HASH_INIT, \ - 'c'), 'o'), 'o'), 'k'), 'i'), 'e')) & 0xFFFF) + ret = nxt_h1p_init(task); + if (ret != NXT_OK) { + return ret; + } -static const nxt_http_request_state_t nxt_http_request_init_state; -static const nxt_http_request_state_t nxt_http_request_body_state; + return nxt_http_response_hash_init(task); +} +nxt_int_t nxt_http_request_host(void *ctx, nxt_http_field_t *field, + uintptr_t data) { + nxt_int_t ret; + nxt_str_t host; + nxt_http_request_t *r; -nxt_time_string_t nxt_http_date_cache = { - (nxt_atomic_uint_t) -1, - nxt_http_date_cache_handler, - NULL, - NXT_HTTP_DATE_LEN, - NXT_THREAD_TIME_GMT, - NXT_THREAD_TIME_SEC, -}; + r = ctx; + if (nxt_slow_path(r->host.start != NULL)) { + return NXT_HTTP_BAD_REQUEST; + } -nxt_int_t -nxt_http_init(nxt_task_t *task) -{ - nxt_int_t ret; + host.length = field->value_length; + host.start = field->value; - ret = nxt_h1p_init(task); + ret = nxt_http_validate_host(&host, r->mem_pool); - if (ret != NXT_OK) { - return ret; - } + if (nxt_fast_path(ret == NXT_OK)) { + r->host = host; + } - return nxt_http_response_hash_init(task); + return ret; } +static nxt_int_t nxt_http_validate_host(nxt_str_t *host, nxt_mp_t *mp) { + u_char *h, ch; + size_t i, dot_pos, host_length; + nxt_bool_t lowcase; -nxt_int_t -nxt_http_request_host(void *ctx, nxt_http_field_t *field, uintptr_t data) -{ - nxt_int_t ret; - nxt_str_t host; - nxt_http_request_t *r; + enum { sw_usual, sw_literal, sw_rest } state; - r = ctx; + dot_pos = host->length; + host_length = host->length; - if (nxt_slow_path(r->host.start != NULL)) { - return NXT_HTTP_BAD_REQUEST; - } + h = host->start; - host.length = field->value_length; - host.start = field->value; + lowcase = 0; + state = sw_usual; - ret = nxt_http_validate_host(&host, r->mem_pool); + for (i = 0; i < host->length; i++) { + ch = h[i]; - if (nxt_fast_path(ret == NXT_OK)) { - r->host = host; + if (ch > ']') { + /* Short path. */ + continue; } - return ret; -} - + switch (ch) { -static nxt_int_t -nxt_http_validate_host(nxt_str_t *host, nxt_mp_t *mp) -{ - u_char *h, ch; - size_t i, dot_pos, host_length; - nxt_bool_t lowcase; + case '.': + if (dot_pos == i - 1) { + return NXT_HTTP_BAD_REQUEST; + } - enum { - sw_usual, - sw_literal, - sw_rest - } state; + dot_pos = i; + break; - dot_pos = host->length; - host_length = host->length; + case ':': + if (state == sw_usual) { + host_length = i; + state = sw_rest; + } - h = host->start; + break; - lowcase = 0; - state = sw_usual; + case '[': + if (i == 0) { + state = sw_literal; + } - for (i = 0; i < host->length; i++) { - ch = h[i]; + break; - if (ch > ']') { - /* Short path. */ - continue; - } + case ']': + if (state == sw_literal) { + host_length = i + 1; + state = sw_rest; + } - switch (ch) { + break; - case '.': - if (dot_pos == i - 1) { - return NXT_HTTP_BAD_REQUEST; - } + case '/': + return NXT_HTTP_BAD_REQUEST; - dot_pos = i; - break; + default: + if (ch >= 'A' && ch <= 'Z') { + lowcase = 1; + } - case ':': - if (state == sw_usual) { - host_length = i; - state = sw_rest; - } + break; + } + } - break; + if (dot_pos == host_length - 1) { + host_length--; + } - case '[': - if (i == 0) { - state = sw_literal; - } + host->length = host_length; - break; + if (lowcase) { + host->start = nxt_mp_nget(mp, host_length); + if (nxt_slow_path(host->start == NULL)) { + return NXT_HTTP_INTERNAL_SERVER_ERROR; + } - case ']': - if (state == sw_literal) { - host_length = i + 1; - state = sw_rest; - } + nxt_memcpy_lowcase(host->start, h, host_length); + } - break; + return NXT_OK; +} - case '/': - return NXT_HTTP_BAD_REQUEST; +nxt_int_t nxt_http_request_field(void *ctx, nxt_http_field_t *field, + uintptr_t offset) { + nxt_http_request_t *r; - default: - if (ch >= 'A' && ch <= 'Z') { - lowcase = 1; - } + r = ctx; - break; - } - } + nxt_value_at(nxt_http_field_t *, r, offset) = field; - if (dot_pos == host_length - 1) { - host_length--; - } + return NXT_OK; +} - host->length = host_length; +nxt_int_t nxt_http_request_content_length(void *ctx, nxt_http_field_t *field, + uintptr_t data) { + nxt_off_t n, max_body_size; + nxt_http_request_t *r; - if (lowcase) { - host->start = nxt_mp_nget(mp, host_length); - if (nxt_slow_path(host->start == NULL)) { - return NXT_HTTP_INTERNAL_SERVER_ERROR; - } + r = ctx; - nxt_memcpy_lowcase(host->start, h, host_length); - } + if (nxt_fast_path(r->content_length == NULL)) { + r->content_length = field; - return NXT_OK; -} + n = nxt_off_t_parse(field->value, field->value_length); + if (nxt_fast_path(n >= 0)) { + r->content_length_n = n; -nxt_int_t -nxt_http_request_field(void *ctx, nxt_http_field_t *field, uintptr_t offset) -{ - nxt_http_request_t *r; + max_body_size = r->conf->socket_conf->max_body_size; - r = ctx; + if (nxt_slow_path(n > max_body_size)) { + return NXT_HTTP_PAYLOAD_TOO_LARGE; + } - nxt_value_at(nxt_http_field_t *, r, offset) = field; + return NXT_OK; + } + } - return NXT_OK; + return NXT_HTTP_BAD_REQUEST; } +nxt_http_request_t *nxt_http_request_create(nxt_task_t *task) { + nxt_mp_t *mp; + nxt_buf_t *last; + nxt_http_request_t *r; -nxt_int_t -nxt_http_request_content_length(void *ctx, nxt_http_field_t *field, - uintptr_t data) -{ - nxt_off_t n, max_body_size; - nxt_http_request_t *r; + mp = nxt_mp_create(4096, 128, 512, 32); + if (nxt_slow_path(mp == NULL)) { + return NULL; + } - r = ctx; + r = nxt_mp_zget(mp, sizeof(nxt_http_request_t)); + if (nxt_slow_path(r == NULL)) { + goto fail; + } - if (nxt_fast_path(r->content_length == NULL)) { - r->content_length = field; + r->resp.fields = nxt_list_create(mp, 8, sizeof(nxt_http_field_t)); + if (nxt_slow_path(r->resp.fields == NULL)) { + goto fail; + } - n = nxt_off_t_parse(field->value, field->value_length); + last = nxt_mp_zget(mp, NXT_BUF_SYNC_SIZE); + if (nxt_slow_path(last == NULL)) { + goto fail; + } - if (nxt_fast_path(n >= 0)) { - r->content_length_n = n; + nxt_buf_set_sync(last); + nxt_buf_set_last(last); + last->completion_handler = nxt_http_request_done; + last->parent = r; + r->last = last; - max_body_size = r->conf->socket_conf->max_body_size; + r->mem_pool = mp; + r->content_length_n = -1; + r->resp.content_length_n = -1; + r->state = &nxt_http_request_init_state; - if (nxt_slow_path(n > max_body_size)) { - return NXT_HTTP_PAYLOAD_TOO_LARGE; - } + r->start_time = nxt_thread_monotonic_time(task->thread); - return NXT_OK; - } - } + task->thread->engine->requests_cnt++; - return NXT_HTTP_BAD_REQUEST; -} + r->tstr_cache.var.pool = mp; + return r; -nxt_http_request_t * -nxt_http_request_create(nxt_task_t *task) -{ - nxt_mp_t *mp; - nxt_buf_t *last; - nxt_http_request_t *r; - - mp = nxt_mp_create(4096, 128, 512, 32); - if (nxt_slow_path(mp == NULL)) { - return NULL; - } +fail: - r = nxt_mp_zget(mp, sizeof(nxt_http_request_t)); - if (nxt_slow_path(r == NULL)) { - goto fail; - } + nxt_mp_release(mp); - r->resp.fields = nxt_list_create(mp, 8, sizeof(nxt_http_field_t)); - if (nxt_slow_path(r->resp.fields == NULL)) { - goto fail; - } + return NULL; +} - last = nxt_mp_zget(mp, NXT_BUF_SYNC_SIZE); - if (nxt_slow_path(last == NULL)) { - goto fail; - } +static const nxt_http_request_state_t + nxt_http_request_init_state nxt_aligned(64) = { + .ready_handler = nxt_http_request_start, + .error_handler = nxt_http_request_close_handler, +}; - nxt_buf_set_sync(last); - nxt_buf_set_last(last); - last->completion_handler = nxt_http_request_done; - last->parent = r; - r->last = last; +static void nxt_http_request_start(nxt_task_t *task, void *obj, void *data) { + nxt_int_t ret; + nxt_socket_conf_t *skcf; + nxt_http_request_t *r; - r->mem_pool = mp; - r->content_length_n = -1; - r->resp.content_length_n = -1; - r->state = &nxt_http_request_init_state; + r = obj; - r->start_time = nxt_thread_monotonic_time(task->thread); + r->state = &nxt_http_request_body_state; - task->thread->engine->requests_cnt++; + skcf = r->conf->socket_conf; - r->tstr_cache.var.pool = mp; + if (skcf->forwarded != NULL) { + ret = nxt_http_request_forward(task, r, skcf->forwarded); + if (nxt_slow_path(ret != NXT_OK)) { + goto fail; + } + } - return r; + if (skcf->client_ip != NULL) { + ret = nxt_http_request_forward(task, r, skcf->client_ip); + if (nxt_slow_path(ret != NXT_OK)) { + goto fail; + } + } -fail: + nxt_http_request_read_body(task, r); - nxt_mp_release(mp); + return; - return NULL; +fail: + nxt_http_request_error(task, r, NXT_HTTP_INTERNAL_SERVER_ERROR); } +static nxt_int_t nxt_http_request_forward(nxt_task_t *task, + nxt_http_request_t *r, + nxt_http_forward_t *forward) { + nxt_int_t ret; + nxt_array_t *client_ip_fields; + nxt_http_field_t *f, **fields, *protocol_field; + nxt_http_forward_header_t *client_ip, *protocol; + + ret = nxt_http_route_addr_rule(r, forward->source, r->remote); + if (ret <= 0) { + return NXT_OK; + } -static const nxt_http_request_state_t nxt_http_request_init_state - nxt_aligned(64) = -{ - .ready_handler = nxt_http_request_start, - .error_handler = nxt_http_request_close_handler, -}; - + client_ip = &forward->client_ip; + protocol = &forward->protocol; -static void -nxt_http_request_start(nxt_task_t *task, void *obj, void *data) -{ - nxt_int_t ret; - nxt_socket_conf_t *skcf; - nxt_http_request_t *r; + if (client_ip->header != NULL) { + client_ip_fields = + nxt_array_create(r->mem_pool, 1, sizeof(nxt_http_field_t *)); + if (nxt_slow_path(client_ip_fields == NULL)) { + return NXT_ERROR; + } - r = obj; + } else { + client_ip_fields = NULL; + } - r->state = &nxt_http_request_body_state; + protocol_field = NULL; - skcf = r->conf->socket_conf; + nxt_list_each(f, r->fields) { + if (client_ip_fields != NULL && f->hash == client_ip->header_hash && + f->value_length > 0 && f->name_length == client_ip->header->length && + nxt_memcasecmp(f->name, client_ip->header->start, + client_ip->header->length) == 0) { + fields = nxt_array_add(client_ip_fields); + if (nxt_slow_path(fields == NULL)) { + return NXT_ERROR; + } - if (skcf->forwarded != NULL) { - ret = nxt_http_request_forward(task, r, skcf->forwarded); - if (nxt_slow_path(ret != NXT_OK)) { - goto fail; - } + *fields = f; } - if (skcf->client_ip != NULL) { - ret = nxt_http_request_forward(task, r, skcf->client_ip); - if (nxt_slow_path(ret != NXT_OK)) { - goto fail; - } + if (protocol->header != NULL && protocol_field == NULL && + f->hash == protocol->header_hash && f->value_length > 0 && + f->name_length == protocol->header->length && + nxt_memcasecmp(f->name, protocol->header->start, + protocol->header->length) == 0) { + protocol_field = f; } + } + nxt_list_loop; - nxt_http_request_read_body(task, r); + if (client_ip_fields != NULL) { + nxt_http_request_forward_client_ip(r, forward, client_ip_fields); + } - return; + if (protocol_field != NULL) { + nxt_http_request_forward_protocol(r, protocol_field); + } -fail: - nxt_http_request_error(task, r, NXT_HTTP_INTERNAL_SERVER_ERROR); + return NXT_OK; } +static void nxt_http_request_forward_client_ip(nxt_http_request_t *r, + nxt_http_forward_t *forward, + nxt_array_t *fields) { + u_char *start, *p; + nxt_int_t ret, i, len; + nxt_sockaddr_t *sa, *prev_sa; + nxt_http_field_t **f; -static nxt_int_t -nxt_http_request_forward(nxt_task_t *task, nxt_http_request_t *r, - nxt_http_forward_t *forward) -{ - nxt_int_t ret; - nxt_array_t *client_ip_fields; - nxt_http_field_t *f, **fields, *protocol_field; - nxt_http_forward_header_t *client_ip, *protocol; + prev_sa = r->remote; + f = (nxt_http_field_t **)fields->elts; - ret = nxt_http_route_addr_rule(r, forward->source, r->remote); - if (ret <= 0) { - return NXT_OK; - } + i = fields->nelts; - client_ip = &forward->client_ip; - protocol = &forward->protocol; + while (i-- > 0) { + start = f[i]->value; + len = f[i]->value_length; - if (client_ip->header != NULL) { - client_ip_fields = nxt_array_create(r->mem_pool, 1, - sizeof(nxt_http_field_t *)); - if (nxt_slow_path(client_ip_fields == NULL)) { - return NXT_ERROR; + do { + for (p = start + len - 1; p > start; p--, len--) { + if (*p != ' ' && *p != ',') { + break; } + } - } else { - client_ip_fields = NULL; - } - - protocol_field = NULL; - - nxt_list_each(f, r->fields) { - if (client_ip_fields != NULL - && f->hash == client_ip->header_hash - && f->value_length > 0 - && f->name_length == client_ip->header->length - && nxt_memcasecmp(f->name, client_ip->header->start, - client_ip->header->length) == 0) - { - fields = nxt_array_add(client_ip_fields); - if (nxt_slow_path(fields == NULL)) { - return NXT_ERROR; - } - - *fields = f; + for (/* void */; p > start; p--) { + if (*p == ' ' || *p == ',') { + p++; + break; } + } - if (protocol->header != NULL - && protocol_field == NULL - && f->hash == protocol->header_hash - && f->value_length > 0 - && f->name_length == protocol->header->length - && nxt_memcasecmp(f->name, protocol->header->start, - protocol->header->length) == 0) - { - protocol_field = f; + sa = nxt_http_request_client_ip_sockaddr(r, p, len - (p - start)); + if (nxt_slow_path(sa == NULL)) { + if (prev_sa != NULL) { + r->remote = prev_sa; } - } nxt_list_loop; - if (client_ip_fields != NULL) { - nxt_http_request_forward_client_ip(r, forward, client_ip_fields); - } + return; + } - if (protocol_field != NULL) { - nxt_http_request_forward_protocol(r, protocol_field); - } + if (!forward->recursive) { + r->remote = sa; + return; + } - return NXT_OK; -} + ret = nxt_http_route_addr_rule(r, forward->source, sa); + if (ret <= 0 || (i == 0 && p == start)) { + r->remote = sa; + return; + } + prev_sa = sa; + len = p - 1 - start; -static void -nxt_http_request_forward_client_ip(nxt_http_request_t *r, - nxt_http_forward_t *forward, nxt_array_t *fields) -{ - u_char *start, *p; - nxt_int_t ret, i, len; - nxt_sockaddr_t *sa, *prev_sa; - nxt_http_field_t **f; - - prev_sa = r->remote; - f = (nxt_http_field_t **) fields->elts; - - i = fields->nelts; - - while (i-- > 0) { - start = f[i]->value; - len = f[i]->value_length; - - do { - for (p = start + len - 1; p > start; p--, len--) { - if (*p != ' ' && *p != ',') { - break; - } - } - - for (/* void */; p > start; p--) { - if (*p == ' ' || *p == ',') { - p++; - break; - } - } - - sa = nxt_http_request_client_ip_sockaddr(r, p, len - (p - start)); - if (nxt_slow_path(sa == NULL)) { - if (prev_sa != NULL) { - r->remote = prev_sa; - } - - return; - } - - if (!forward->recursive) { - r->remote = sa; - return; - } - - ret = nxt_http_route_addr_rule(r, forward->source, sa); - if (ret <= 0 || (i == 0 && p == start)) { - r->remote = sa; - return; - } - - prev_sa = sa; - len = p - 1 - start; - - } while (len > 0); - } + } while (len > 0); + } } - static nxt_sockaddr_t * nxt_http_request_client_ip_sockaddr(nxt_http_request_t *r, u_char *start, - size_t len) -{ - nxt_str_t addr; - nxt_sockaddr_t *sa; + size_t len) { + nxt_str_t addr; + nxt_sockaddr_t *sa; - addr.start = start; - addr.length = len; + addr.start = start; + addr.length = len; - sa = nxt_sockaddr_parse_optport(r->mem_pool, &addr); - if (nxt_slow_path(sa == NULL)) { - return NULL; - } + sa = nxt_sockaddr_parse_optport(r->mem_pool, &addr); + if (nxt_slow_path(sa == NULL)) { + return NULL; + } - switch (sa->u.sockaddr.sa_family) { - case AF_INET: - if (sa->u.sockaddr_in.sin_addr.s_addr == INADDR_ANY) { - return NULL; - } + switch (sa->u.sockaddr.sa_family) { + case AF_INET: + if (sa->u.sockaddr_in.sin_addr.s_addr == INADDR_ANY) { + return NULL; + } - break; + break; #if (NXT_INET6) - case AF_INET6: - if (IN6_IS_ADDR_UNSPECIFIED(&sa->u.sockaddr_in6.sin6_addr)) { - return NULL; - } + case AF_INET6: + if (IN6_IS_ADDR_UNSPECIFIED(&sa->u.sockaddr_in6.sin6_addr)) { + return NULL; + } - break; + break; #endif /* NXT_INET6 */ - default: - return NULL; - } + default: + return NULL; + } - return sa; + return sa; } +static void nxt_http_request_forward_protocol(nxt_http_request_t *r, + nxt_http_field_t *field) { + if (field->value_length == 4) { + if (nxt_memcasecmp(field->value, "http", 4) == 0) { + r->tls = 0; + } -static void -nxt_http_request_forward_protocol(nxt_http_request_t *r, - nxt_http_field_t *field) -{ - if (field->value_length == 4) { - if (nxt_memcasecmp(field->value, "http", 4) == 0) { - r->tls = 0; - } - - } else if (field->value_length == 5) { - if (nxt_memcasecmp(field->value, "https", 5) == 0) { - r->tls = 1; - } + } else if (field->value_length == 5) { + if (nxt_memcasecmp(field->value, "https", 5) == 0) { + r->tls = 1; + } - } else if (field->value_length == 2) { - if (nxt_memcasecmp(field->value, "on", 2) == 0) { - r->tls = 1; - } + } else if (field->value_length == 2) { + if (nxt_memcasecmp(field->value, "on", 2) == 0) { + r->tls = 1; } + } } - -static const nxt_http_request_state_t nxt_http_request_body_state - nxt_aligned(64) = -{ - .ready_handler = nxt_http_request_ready, - .error_handler = nxt_http_request_close_handler, +static const nxt_http_request_state_t + nxt_http_request_body_state nxt_aligned(64) = { + .ready_handler = nxt_http_request_ready, + .error_handler = nxt_http_request_close_handler, }; +static nxt_int_t nxt_http_request_chunked_transform(nxt_http_request_t *r) { + size_t size; + u_char *p, *end; + nxt_http_field_t *f; -static nxt_int_t -nxt_http_request_chunked_transform(nxt_http_request_t *r) -{ - size_t size; - u_char *p, *end; - nxt_http_field_t *f; - - r->chunked_field->skip = 1; + r->chunked_field->skip = 1; - size = r->body->file_end; + size = r->body->file_end; - f = nxt_list_zero_add(r->fields); - if (nxt_slow_path(f == NULL)) { - return NXT_ERROR; - } + f = nxt_list_zero_add(r->fields); + if (nxt_slow_path(f == NULL)) { + return NXT_ERROR; + } - nxt_http_field_name_set(f, "Content-Length"); + nxt_http_field_name_set(f, "Content-Length"); - p = nxt_mp_nget(r->mem_pool, NXT_OFF_T_LEN); - if (nxt_slow_path(p == NULL)) { - return NXT_ERROR; - } + p = nxt_mp_nget(r->mem_pool, NXT_OFF_T_LEN); + if (nxt_slow_path(p == NULL)) { + return NXT_ERROR; + } - f->value = p; - end = nxt_sprintf(p, p + NXT_OFF_T_LEN, "%uz", size); - f->value_length = end - p; + f->value = p; + end = nxt_sprintf(p, p + NXT_OFF_T_LEN, "%uz", size); + f->value_length = end - p; - r->content_length = f; - r->content_length_n = size; + r->content_length = f; + r->content_length_n = size; - return NXT_OK; + return NXT_OK; } +static void nxt_http_request_ready(nxt_task_t *task, void *obj, void *data) { + nxt_int_t ret; + nxt_http_action_t *action; + nxt_http_request_t *r; -static void -nxt_http_request_ready(nxt_task_t *task, void *obj, void *data) -{ - nxt_int_t ret; - nxt_http_action_t *action; - nxt_http_request_t *r; + r = obj; + action = r->conf->socket_conf->action; - r = obj; - action = r->conf->socket_conf->action; - - if (r->chunked) { - ret = nxt_http_request_chunked_transform(r); - if (nxt_slow_path(ret != NXT_OK)) { - nxt_http_request_error(task, r, NXT_HTTP_INTERNAL_SERVER_ERROR); - return; - } + if (r->chunked) { + ret = nxt_http_request_chunked_transform(r); + if (nxt_slow_path(ret != NXT_OK)) { + nxt_http_request_error(task, r, NXT_HTTP_INTERNAL_SERVER_ERROR); + return; } + } - nxt_http_request_action(task, r, action); + nxt_http_request_action(task, r, action); } +void nxt_http_request_action(nxt_task_t *task, nxt_http_request_t *r, + nxt_http_action_t *action) { + nxt_int_t ret; -void -nxt_http_request_action(nxt_task_t *task, nxt_http_request_t *r, - nxt_http_action_t *action) -{ - nxt_int_t ret; - - if (nxt_fast_path(action != NULL)) { + if (nxt_fast_path(action != NULL)) { - do { - ret = nxt_http_rewrite(task, r); - if (nxt_slow_path(ret != NXT_OK)) { - break; - } + do { + ret = nxt_http_rewrite(task, r); + if (nxt_slow_path(ret != NXT_OK)) { + break; + } - action = action->handler(task, r, action); + action = action->handler(task, r, action); - if (action == NULL) { - return; - } + if (action == NULL) { + return; + } - if (action == NXT_HTTP_ACTION_ERROR) { - break; - } + if (action == NXT_HTTP_ACTION_ERROR) { + break; + } - } while (r->pass_count++ < 255); - } + } while (r->pass_count++ < 255); + } - nxt_http_request_error(task, r, NXT_HTTP_INTERNAL_SERVER_ERROR); + nxt_http_request_error(task, r, NXT_HTTP_INTERNAL_SERVER_ERROR); } +nxt_http_action_t *nxt_http_application_handler(nxt_task_t *task, + nxt_http_request_t *r, + nxt_http_action_t *action) { + nxt_debug(task, "http application handler"); -nxt_http_action_t * -nxt_http_application_handler(nxt_task_t *task, nxt_http_request_t *r, - nxt_http_action_t *action) -{ - nxt_debug(task, "http application handler"); + /* + * TODO: need an application flag to get local address + * required by "SERVER_ADDR" in Pyhton and PHP. Not used in Go. + */ + nxt_http_request_proto_info(task, r); - /* - * TODO: need an application flag to get local address - * required by "SERVER_ADDR" in Pyhton and PHP. Not used in Go. - */ - nxt_http_request_proto_info(task, r); + if (r->host.length != 0) { + r->server_name = r->host; - if (r->host.length != 0) { - r->server_name = r->host; + } else { + nxt_str_set(&r->server_name, "localhost"); + } - } else { - nxt_str_set(&r->server_name, "localhost"); - } + nxt_router_process_http_request(task, r, action); - nxt_router_process_http_request(task, r, action); - - return NULL; + return NULL; } - -static void -nxt_http_request_proto_info(nxt_task_t *task, nxt_http_request_t *r) -{ - if (nxt_fast_path(r->proto.any != NULL)) { - nxt_http_proto[r->protocol].local_addr(task, r); - } +static void nxt_http_request_proto_info(nxt_task_t *task, + nxt_http_request_t *r) { + if (nxt_fast_path(r->proto.any != NULL)) { + nxt_http_proto[r->protocol].local_addr(task, r); + } } - -void -nxt_http_request_read_body(nxt_task_t *task, nxt_http_request_t *r) -{ - if (nxt_fast_path(r->proto.any != NULL)) { - nxt_http_proto[r->protocol].body_read(task, r); - } +void nxt_http_request_read_body(nxt_task_t *task, nxt_http_request_t *r) { + if (nxt_fast_path(r->proto.any != NULL)) { + nxt_http_proto[r->protocol].body_read(task, r); + } } - -void -nxt_http_request_header_send(nxt_task_t *task, nxt_http_request_t *r, - nxt_work_handler_t body_handler, void *data) -{ - u_char *p, *end, *server_string; - nxt_int_t ret; - nxt_http_field_t *server, *date, *content_length; - nxt_socket_conf_t *skcf; - - ret = nxt_http_set_headers(r); - if (nxt_slow_path(ret != NXT_OK)) { - goto fail; +void nxt_http_request_header_send(nxt_task_t *task, nxt_http_request_t *r, + nxt_work_handler_t body_handler, void *data) { + u_char *p, *end, *server_string; + nxt_int_t ret; + nxt_http_field_t *server, *date, *content_length; + nxt_socket_conf_t *skcf; + + ret = nxt_http_set_headers(r); + if (nxt_slow_path(ret != NXT_OK)) { + goto fail; + } + + /* + * TODO: "Server", "Date", and "Content-Length" processing should be moved + * to the last header filter. + */ + + server = nxt_list_zero_add(r->resp.fields); + if (nxt_slow_path(server == NULL)) { + goto fail; + } + + skcf = r->conf->socket_conf; + server_string = (u_char *)(skcf->server_version ? NXT_SERVER : NXT_NAME); + + nxt_http_field_name_set(server, "Server"); + server->value = server_string; + server->value_length = nxt_strlen(server_string); + + if (r->resp.date == NULL) { + date = nxt_list_zero_add(r->resp.fields); + if (nxt_slow_path(date == NULL)) { + goto fail; } - /* - * TODO: "Server", "Date", and "Content-Length" processing should be moved - * to the last header filter. - */ + nxt_http_field_name_set(date, "Date"); - server = nxt_list_zero_add(r->resp.fields); - if (nxt_slow_path(server == NULL)) { - goto fail; + p = nxt_mp_nget(r->mem_pool, nxt_http_date_cache.size); + if (nxt_slow_path(p == NULL)) { + goto fail; } - skcf = r->conf->socket_conf; - server_string = (u_char *) (skcf->server_version ? NXT_SERVER : NXT_NAME); - - nxt_http_field_name_set(server, "Server"); - server->value = server_string; - server->value_length = nxt_strlen(server_string); - - if (r->resp.date == NULL) { - date = nxt_list_zero_add(r->resp.fields); - if (nxt_slow_path(date == NULL)) { - goto fail; - } - - nxt_http_field_name_set(date, "Date"); - - p = nxt_mp_nget(r->mem_pool, nxt_http_date_cache.size); - if (nxt_slow_path(p == NULL)) { - goto fail; - } + (void)nxt_thread_time_string(task->thread, &nxt_http_date_cache, p); - (void) nxt_thread_time_string(task->thread, &nxt_http_date_cache, p); + date->value = p; + date->value_length = nxt_http_date_cache.size; - date->value = p; - date->value_length = nxt_http_date_cache.size; + r->resp.date = date; + } - r->resp.date = date; + if (r->resp.content_length_n != -1 && + (r->resp.content_length == NULL || r->resp.content_length->skip)) { + content_length = nxt_list_zero_add(r->resp.fields); + if (nxt_slow_path(content_length == NULL)) { + goto fail; } - if (r->resp.content_length_n != -1 - && (r->resp.content_length == NULL || r->resp.content_length->skip)) - { - content_length = nxt_list_zero_add(r->resp.fields); - if (nxt_slow_path(content_length == NULL)) { - goto fail; - } + nxt_http_field_name_set(content_length, "Content-Length"); - nxt_http_field_name_set(content_length, "Content-Length"); - - p = nxt_mp_nget(r->mem_pool, NXT_OFF_T_LEN); - if (nxt_slow_path(p == NULL)) { - goto fail; - } + p = nxt_mp_nget(r->mem_pool, NXT_OFF_T_LEN); + if (nxt_slow_path(p == NULL)) { + goto fail; + } - content_length->value = p; - end = nxt_sprintf(p, p + NXT_OFF_T_LEN, "%O", r->resp.content_length_n); - content_length->value_length = end - p; + content_length->value = p; + end = nxt_sprintf(p, p + NXT_OFF_T_LEN, "%O", r->resp.content_length_n); + content_length->value_length = end - p; - r->resp.content_length = content_length; - } + r->resp.content_length = content_length; + } - if (nxt_fast_path(r->proto.any != NULL)) { - nxt_http_proto[r->protocol].header_send(task, r, body_handler, data); - } + if (nxt_fast_path(r->proto.any != NULL)) { + nxt_http_proto[r->protocol].header_send(task, r, body_handler, data); + } - return; + return; fail: - nxt_http_request_error(task, r, NXT_HTTP_INTERNAL_SERVER_ERROR); + nxt_http_request_error(task, r, NXT_HTTP_INTERNAL_SERVER_ERROR); } - -void -nxt_http_request_ws_frame_start(nxt_task_t *task, nxt_http_request_t *r, - nxt_buf_t *ws_frame) -{ - if (r->proto.any != NULL) { - nxt_http_proto[r->protocol].ws_frame_start(task, r, ws_frame); - } +void nxt_http_request_ws_frame_start(nxt_task_t *task, nxt_http_request_t *r, + nxt_buf_t *ws_frame) { + if (r->proto.any != NULL) { + nxt_http_proto[r->protocol].ws_frame_start(task, r, ws_frame); + } } - -void -nxt_http_request_send(nxt_task_t *task, nxt_http_request_t *r, nxt_buf_t *out) -{ - if (nxt_fast_path(r->proto.any != NULL)) { - nxt_http_proto[r->protocol].send(task, r, out); - } +void nxt_http_request_send(nxt_task_t *task, nxt_http_request_t *r, + nxt_buf_t *out) { + if (nxt_fast_path(r->proto.any != NULL)) { + nxt_http_proto[r->protocol].send(task, r, out); + } } +nxt_buf_t *nxt_http_buf_mem(nxt_task_t *task, nxt_http_request_t *r, + size_t size) { + nxt_buf_t *b; -nxt_buf_t * -nxt_http_buf_mem(nxt_task_t *task, nxt_http_request_t *r, size_t size) -{ - nxt_buf_t *b; - - b = nxt_buf_mem_alloc(r->mem_pool, size, 0); - if (nxt_fast_path(b != NULL)) { - b->completion_handler = nxt_http_request_mem_buf_completion; - b->parent = r; - nxt_mp_retain(r->mem_pool); + b = nxt_buf_mem_alloc(r->mem_pool, size, 0); + if (nxt_fast_path(b != NULL)) { + b->completion_handler = nxt_http_request_mem_buf_completion; + b->parent = r; + nxt_mp_retain(r->mem_pool); - } else { - nxt_http_request_error(task, r, NXT_HTTP_INTERNAL_SERVER_ERROR); - } + } else { + nxt_http_request_error(task, r, NXT_HTTP_INTERNAL_SERVER_ERROR); + } - return b; + return b; } +static void nxt_http_request_mem_buf_completion(nxt_task_t *task, void *obj, + void *data) { + nxt_buf_t *b, *next; + nxt_http_request_t *r; -static void -nxt_http_request_mem_buf_completion(nxt_task_t *task, void *obj, void *data) -{ - nxt_buf_t *b, *next; - nxt_http_request_t *r; + b = obj; + r = data; - b = obj; - r = data; + do { + next = b->next; - do { - next = b->next; + nxt_mp_free(r->mem_pool, b); + nxt_mp_release(r->mem_pool); - nxt_mp_free(r->mem_pool, b); - nxt_mp_release(r->mem_pool); - - b = next; - } while (b != NULL); + b = next; + } while (b != NULL); } +nxt_buf_t *nxt_http_buf_last(nxt_http_request_t *r) { + nxt_buf_t *last; -nxt_buf_t * -nxt_http_buf_last(nxt_http_request_t *r) -{ - nxt_buf_t *last; - - last = r->last; - r->last = NULL; + last = r->last; + r->last = NULL; - return last; + return last; } +static void nxt_http_request_done(nxt_task_t *task, void *obj, void *data) { + nxt_http_request_t *r; -static void -nxt_http_request_done(nxt_task_t *task, void *obj, void *data) -{ - nxt_http_request_t *r; - - r = data; + r = data; - nxt_debug(task, "http request done"); + nxt_debug(task, "http request done"); - nxt_http_request_close_handler(task, r, r->proto.any); + nxt_http_request_close_handler(task, r, r->proto.any); } +void nxt_http_request_error_handler(nxt_task_t *task, void *obj, void *data) { + nxt_http_proto_t proto; + nxt_http_request_t *r; -void -nxt_http_request_error_handler(nxt_task_t *task, void *obj, void *data) -{ - nxt_http_proto_t proto; - nxt_http_request_t *r; + r = obj; + proto.any = data; - r = obj; - proto.any = data; + nxt_debug(task, "http request error handler"); - nxt_debug(task, "http request error handler"); + r->error = 1; - r->error = 1; - - if (nxt_fast_path(proto.any != NULL)) { - nxt_http_proto[r->protocol].discard(task, r, nxt_http_buf_last(r)); - } + if (nxt_fast_path(proto.any != NULL)) { + nxt_http_proto[r->protocol].discard(task, r, nxt_http_buf_last(r)); + } } +void nxt_http_request_close_handler(nxt_task_t *task, void *obj, void *data) { + nxt_http_proto_t proto; + nxt_router_conf_t *rtcf; + nxt_http_request_t *r; + nxt_http_protocol_t protocol; + nxt_socket_conf_joint_t *conf; + nxt_router_access_log_t *access_log; -void -nxt_http_request_close_handler(nxt_task_t *task, void *obj, void *data) -{ - nxt_http_proto_t proto; - nxt_router_conf_t *rtcf; - nxt_http_request_t *r; - nxt_http_protocol_t protocol; - nxt_socket_conf_joint_t *conf; - nxt_router_access_log_t *access_log; + r = obj; + proto.any = data; - r = obj; - proto.any = data; + conf = r->conf; + rtcf = conf->socket_conf->router_conf; - conf = r->conf; - rtcf = conf->socket_conf->router_conf; + if (!r->logged) { + r->logged = 1; - if (!r->logged) { - r->logged = 1; + if (rtcf->access_log != NULL) { + access_log = rtcf->access_log; - if (rtcf->access_log != NULL) { - access_log = rtcf->access_log; - - if (nxt_http_cond_value(task, r, &rtcf->log_cond)) { - access_log->handler(task, r, access_log, rtcf->log_format); - return; - } - } + if (nxt_http_cond_value(task, r, &rtcf->log_cond)) { + access_log->handler(task, r, access_log, rtcf->log_format); + return; + } } + } - nxt_debug(task, "http request close handler"); + nxt_debug(task, "http request close handler"); - r->proto.any = NULL; + r->proto.any = NULL; - if (r->body != NULL && nxt_buf_is_file(r->body) - && r->body->file->fd != -1) - { - nxt_fd_close(r->body->file->fd); + if (r->body != NULL && nxt_buf_is_file(r->body) && r->body->file->fd != -1) { + nxt_fd_close(r->body->file->fd); - r->body->file->fd = -1; - } + r->body->file->fd = -1; + } - if (r->tstr_query != NULL) { - nxt_tstr_query_release(r->tstr_query); - } + if (r->tstr_query != NULL) { + nxt_tstr_query_release(r->tstr_query); + } - if (nxt_fast_path(proto.any != NULL)) { - protocol = r->protocol; + if (nxt_fast_path(proto.any != NULL)) { + protocol = r->protocol; - nxt_http_proto[protocol].close(task, proto, conf); + nxt_http_proto[protocol].close(task, proto, conf); - nxt_mp_release(r->mem_pool); - } + nxt_mp_release(r->mem_pool); + } } - -static u_char * -nxt_http_date_cache_handler(u_char *buf, nxt_realtime_t *now, struct tm *tm, - size_t size, const char *format) -{ - return nxt_http_date(buf, tm); +static u_char *nxt_http_date_cache_handler(u_char *buf, nxt_realtime_t *now, + struct tm *tm, size_t size, + const char *format) { + return nxt_http_date(buf, tm); } +nxt_array_t *nxt_http_arguments_parse(nxt_http_request_t *r) { + size_t name_length; + u_char *p, *dst, *dst_start, *start, *end, *name; + uint8_t d0, d1; + uint32_t hash; + nxt_array_t *args; + nxt_http_name_value_t *nv; -nxt_array_t * -nxt_http_arguments_parse(nxt_http_request_t *r) -{ - size_t name_length; - u_char *p, *dst, *dst_start, *start, *end, *name; - uint8_t d0, d1; - uint32_t hash; - nxt_array_t *args; - nxt_http_name_value_t *nv; - - if (r->arguments != NULL) { - return r->arguments; - } + if (r->arguments != NULL) { + return r->arguments; + } - args = nxt_array_create(r->mem_pool, 2, sizeof(nxt_http_name_value_t)); - if (nxt_slow_path(args == NULL)) { - return NULL; - } + args = nxt_array_create(r->mem_pool, 2, sizeof(nxt_http_name_value_t)); + if (nxt_slow_path(args == NULL)) { + return NULL; + } - if (nxt_slow_path(r->args->start == NULL)) { - goto end; - } + if (nxt_slow_path(r->args->start == NULL)) { + goto end; + } - hash = NXT_HTTP_FIELD_HASH_INIT; - name = NULL; - name_length = 0; + hash = NXT_HTTP_FIELD_HASH_INIT; + name = NULL; + name_length = 0; - dst_start = nxt_mp_nget(r->mem_pool, r->args->length); - if (nxt_slow_path(dst_start == NULL)) { - return NULL; - } + dst_start = nxt_mp_nget(r->mem_pool, r->args->length); + if (nxt_slow_path(dst_start == NULL)) { + return NULL; + } - r->args_decoded.start = dst_start; + r->args_decoded.start = dst_start; - start = r->args->start; - end = start + r->args->length; + start = r->args->start; + end = start + r->args->length; - for (p = start, dst = dst_start; p < end; p++, dst++) { - *dst = *p; + for (p = start, dst = dst_start; p < end; p++, dst++) { + *dst = *p; - switch (*p) { - case '=': - if (name == NULL) { - name_length = dst - dst_start; - name = dst_start; - dst_start = dst + 1; - } + switch (*p) { + case '=': + if (name == NULL) { + name_length = dst - dst_start; + name = dst_start; + dst_start = dst + 1; + } - continue; + continue; - case '&': - if (name_length != 0 || dst != dst_start) { - nv = nxt_http_argument(args, name, name_length, hash, dst_start, - dst); - if (nxt_slow_path(nv == NULL)) { - return NULL; - } - } + case '&': + if (name_length != 0 || dst != dst_start) { + nv = nxt_http_argument(args, name, name_length, hash, dst_start, dst); + if (nxt_slow_path(nv == NULL)) { + return NULL; + } + } - hash = NXT_HTTP_FIELD_HASH_INIT; - name_length = 0; - name = NULL; - dst_start = dst + 1; + hash = NXT_HTTP_FIELD_HASH_INIT; + name_length = 0; + name = NULL; + dst_start = dst + 1; - continue; + continue; - case '+': - *dst = ' '; + case '+': + *dst = ' '; - break; + break; - case '%': - if (nxt_slow_path(end - p <= 2)) { - break; - } + case '%': + if (nxt_slow_path(end - p <= 2)) { + break; + } - d0 = nxt_hex2int[p[1]]; - d1 = nxt_hex2int[p[2]]; + d0 = nxt_hex2int[p[1]]; + d1 = nxt_hex2int[p[2]]; - if (nxt_slow_path((d0 | d1) >= 16)) { - break; - } + if (nxt_slow_path((d0 | d1) >= 16)) { + break; + } - p += 2; - *dst = (d0 << 4) + d1; + p += 2; + *dst = (d0 << 4) + d1; - break; - } + break; + } - if (name == NULL) { - hash = nxt_http_field_hash_char(hash, *dst); - } + if (name == NULL) { + hash = nxt_http_field_hash_char(hash, *dst); } + } - r->args_decoded.length = dst - r->args_decoded.start; + r->args_decoded.length = dst - r->args_decoded.start; - if (name_length != 0 || dst != dst_start) { - nv = nxt_http_argument(args, name, name_length, hash, dst_start, dst); - if (nxt_slow_path(nv == NULL)) { - return NULL; - } + if (name_length != 0 || dst != dst_start) { + nv = nxt_http_argument(args, name, name_length, hash, dst_start, dst); + if (nxt_slow_path(nv == NULL)) { + return NULL; } + } end: - r->arguments = args; + r->arguments = args; - return args; + return args; } - static nxt_http_name_value_t * nxt_http_argument(nxt_array_t *array, u_char *name, size_t name_length, - uint32_t hash, u_char *start, const u_char *end) -{ - size_t length; - nxt_http_name_value_t *nv; + uint32_t hash, u_char *start, const u_char *end) { + size_t length; + nxt_http_name_value_t *nv; - nv = nxt_array_add(array); - if (nxt_slow_path(nv == NULL)) { - return NULL; - } + nv = nxt_array_add(array); + if (nxt_slow_path(nv == NULL)) { + return NULL; + } - nv->hash = nxt_http_field_hash_end(hash) & 0xFFFF; + nv->hash = nxt_http_field_hash_end(hash) & 0xFFFF; - length = end - start; + length = end - start; - if (name == NULL) { - name_length = length; - name = start; - length = 0; - } + if (name == NULL) { + name_length = length; + name = start; + length = 0; + } - nv->name_length = name_length; - nv->value_length = length; - nv->name = name; - nv->value = start; + nv->name_length = name_length; + nv->value_length = length; + nv->name = name; + nv->value = start; - return nv; + return nv; } +nxt_array_t *nxt_http_cookies_parse(nxt_http_request_t *r) { + nxt_int_t ret; + nxt_array_t *cookies; + nxt_http_field_t *f; -nxt_array_t * -nxt_http_cookies_parse(nxt_http_request_t *r) -{ - nxt_int_t ret; - nxt_array_t *cookies; - nxt_http_field_t *f; - - if (r->cookies != NULL) { - return r->cookies; - } + if (r->cookies != NULL) { + return r->cookies; + } - cookies = nxt_array_create(r->mem_pool, 2, sizeof(nxt_http_name_value_t)); - if (nxt_slow_path(cookies == NULL)) { - return NULL; - } - - nxt_list_each(f, r->fields) { + cookies = nxt_array_create(r->mem_pool, 2, sizeof(nxt_http_name_value_t)); + if (nxt_slow_path(cookies == NULL)) { + return NULL; + } - if (f->hash != NXT_HTTP_COOKIE_HASH - || f->name_length != 6 - || nxt_strncasecmp(f->name, (u_char *) "Cookie", 6) != 0) - { - continue; - } + nxt_list_each(f, r->fields) { - ret = nxt_http_cookie_parse(cookies, f->value, - f->value + f->value_length); - if (ret != NXT_OK) { - return NULL; - } + if (f->hash != NXT_HTTP_COOKIE_HASH || f->name_length != 6 || + nxt_strncasecmp(f->name, (u_char *)"Cookie", 6) != 0) { + continue; + } - } nxt_list_loop; + ret = nxt_http_cookie_parse(cookies, f->value, f->value + f->value_length); + if (ret != NXT_OK) { + return NULL; + } + } + nxt_list_loop; - r->cookies = cookies; + r->cookies = cookies; - return cookies; + return cookies; } +static nxt_int_t nxt_http_cookie_parse(nxt_array_t *cookies, u_char *start, + const u_char *end) { + size_t name_length; + u_char c, *p, *name; + nxt_http_name_value_t *nv; -static nxt_int_t -nxt_http_cookie_parse(nxt_array_t *cookies, u_char *start, const u_char *end) -{ - size_t name_length; - u_char c, *p, *name; - nxt_http_name_value_t *nv; - - name = NULL; - name_length = 0; - - for (p = start; p < end; p++) { - c = *p; + name = NULL; + name_length = 0; - if (c == '=' && name == NULL) { - while (start[0] == ' ') { start++; } + for (p = start; p < end; p++) { + c = *p; - name_length = p - start; - name = start; + if (c == '=' && name == NULL) { + while (start[0] == ' ') { + start++; + } - start = p + 1; + name_length = p - start; + name = start; - } else if (c == ';') { - if (name != NULL) { - nv = nxt_http_cookie(cookies, name, name_length, start, p); - if (nxt_slow_path(nv == NULL)) { - return NXT_ERROR; - } - } + start = p + 1; - name = NULL; - start = p + 1; - } - } - - if (name != NULL) { + } else if (c == ';') { + if (name != NULL) { nv = nxt_http_cookie(cookies, name, name_length, start, p); if (nxt_slow_path(nv == NULL)) { - return NXT_ERROR; + return NXT_ERROR; } - } - - return NXT_OK; -} + } + name = NULL; + start = p + 1; + } + } -static nxt_http_name_value_t * -nxt_http_cookie(nxt_array_t *array, u_char *name, size_t name_length, - u_char *start, const u_char *end) -{ - u_char c, *p; - uint32_t hash; - nxt_http_name_value_t *nv; - - nv = nxt_array_add(array); + if (name != NULL) { + nv = nxt_http_cookie(cookies, name, name_length, start, p); if (nxt_slow_path(nv == NULL)) { - return NULL; + return NXT_ERROR; } + } - nv->name_length = name_length; - nv->name = name; + return NXT_OK; +} - hash = NXT_HTTP_FIELD_HASH_INIT; +static nxt_http_name_value_t *nxt_http_cookie(nxt_array_t *array, u_char *name, + size_t name_length, u_char *start, + const u_char *end) { + u_char c, *p; + uint32_t hash; + nxt_http_name_value_t *nv; + + nv = nxt_array_add(array); + if (nxt_slow_path(nv == NULL)) { + return NULL; + } - for (p = name; p < name + name_length; p++) { - c = *p; - hash = nxt_http_field_hash_char(hash, c); - } + nv->name_length = name_length; + nv->name = name; - nv->hash = nxt_http_field_hash_end(hash) & 0xFFFF; + hash = NXT_HTTP_FIELD_HASH_INIT; - while (start < end && end[-1] == ' ') { end--; } + for (p = name; p < name + name_length; p++) { + c = *p; + hash = nxt_http_field_hash_char(hash, c); + } - nv->value_length = end - start; - nv->value = start; + nv->hash = nxt_http_field_hash_end(hash) & 0xFFFF; - return nv; -} + while (start < end && end[-1] == ' ') { + end--; + } + nv->value_length = end - start; + nv->value = start; -int64_t -nxt_http_field_hash(nxt_mp_t *mp, nxt_str_t *name, nxt_bool_t case_sensitive, - uint8_t encoding) -{ - u_char c, *p, *src, *start, *end, plus; - uint8_t d0, d1; - uint32_t hash; - nxt_str_t str; - nxt_uint_t i; + return nv; +} - str.length = name->length; +int64_t nxt_http_field_hash(nxt_mp_t *mp, nxt_str_t *name, + nxt_bool_t case_sensitive, uint8_t encoding) { + u_char c, *p, *src, *start, *end, plus; + uint8_t d0, d1; + uint32_t hash; + nxt_str_t str; + nxt_uint_t i; - str.start = nxt_mp_nget(mp, str.length); - if (nxt_slow_path(str.start == NULL)) { - return -1; - } + str.length = name->length; - p = str.start; + str.start = nxt_mp_nget(mp, str.length); + if (nxt_slow_path(str.start == NULL)) { + return -1; + } - hash = NXT_HTTP_FIELD_HASH_INIT; + p = str.start; - if (encoding == NXT_HTTP_URI_ENCODING_NONE) { - for (i = 0; i < name->length; i++) { - c = name->start[i]; - *p++ = c; + hash = NXT_HTTP_FIELD_HASH_INIT; - c = case_sensitive ? c : nxt_lowcase(c); - hash = nxt_http_field_hash_char(hash, c); - } + if (encoding == NXT_HTTP_URI_ENCODING_NONE) { + for (i = 0; i < name->length; i++) { + c = name->start[i]; + *p++ = c; - goto end; + c = case_sensitive ? c : nxt_lowcase(c); + hash = nxt_http_field_hash_char(hash, c); } - plus = (encoding == NXT_HTTP_URI_ENCODING_PLUS) ? ' ' : '+'; + goto end; + } - start = name->start; - end = start + name->length; + plus = (encoding == NXT_HTTP_URI_ENCODING_PLUS) ? ' ' : '+'; - for (src = start; src < end; src++) { - c = *src; + start = name->start; + end = start + name->length; - switch (c) { - case '%': - if (nxt_slow_path(end - src <= 2)) { - return -1; - } + for (src = start; src < end; src++) { + c = *src; - d0 = nxt_hex2int[src[1]]; - d1 = nxt_hex2int[src[2]]; - src += 2; + switch (c) { + case '%': + if (nxt_slow_path(end - src <= 2)) { + return -1; + } - if (nxt_slow_path((d0 | d1) >= 16)) { - return -1; - } + d0 = nxt_hex2int[src[1]]; + d1 = nxt_hex2int[src[2]]; + src += 2; - c = (d0 << 4) + d1; - *p++ = c; - break; + if (nxt_slow_path((d0 | d1) >= 16)) { + return -1; + } - case '+': - c = plus; - *p++ = c; - break; + c = (d0 << 4) + d1; + *p++ = c; + break; - default: - *p++ = c; - break; - } + case '+': + c = plus; + *p++ = c; + break; - c = case_sensitive ? c : nxt_lowcase(c); - hash = nxt_http_field_hash_char(hash, c); + default: + *p++ = c; + break; } - str.length = p - str.start; + c = case_sensitive ? c : nxt_lowcase(c); + hash = nxt_http_field_hash_char(hash, c); + } + + str.length = p - str.start; end: - *name = str; + *name = str; - return nxt_http_field_hash_end(hash) & 0xFFFF; + return nxt_http_field_hash_end(hash) & 0xFFFF; } - -int64_t -nxt_http_argument_hash(nxt_mp_t *mp, nxt_str_t *name) -{ - return nxt_http_field_hash(mp, name, 1, NXT_HTTP_URI_ENCODING_PLUS); +int64_t nxt_http_argument_hash(nxt_mp_t *mp, nxt_str_t *name) { + return nxt_http_field_hash(mp, name, 1, NXT_HTTP_URI_ENCODING_PLUS); } +int64_t nxt_http_header_hash(nxt_mp_t *mp, nxt_str_t *name) { + u_char c, *p; + uint32_t i, hash; + nxt_str_t str; -int64_t -nxt_http_header_hash(nxt_mp_t *mp, nxt_str_t *name) -{ - u_char c, *p; - uint32_t i, hash; - nxt_str_t str; - - str.length = name->length; - - str.start = nxt_mp_nget(mp, str.length); - if (nxt_slow_path(str.start == NULL)) { - return -1; - } + str.length = name->length; - p = str.start; - hash = NXT_HTTP_FIELD_HASH_INIT; + str.start = nxt_mp_nget(mp, str.length); + if (nxt_slow_path(str.start == NULL)) { + return -1; + } - for (i = 0; i < name->length; i++) { - c = name->start[i]; + p = str.start; + hash = NXT_HTTP_FIELD_HASH_INIT; - if (c >= 'A' && c <= 'Z') { - *p = c | 0x20; + for (i = 0; i < name->length; i++) { + c = name->start[i]; - } else if (c == '_') { - *p = '-'; + if (c >= 'A' && c <= 'Z') { + *p = c | 0x20; - } else { - *p = c; - } + } else if (c == '_') { + *p = '-'; - hash = nxt_http_field_hash_char(hash, *p); - p++; + } else { + *p = c; } - *name = str; - - return nxt_http_field_hash_end(hash) & 0xFFFF; -} + hash = nxt_http_field_hash_char(hash, *p); + p++; + } + *name = str; -int64_t -nxt_http_cookie_hash(nxt_mp_t *mp, nxt_str_t *name) -{ - return nxt_http_field_hash(mp, name, 1, NXT_HTTP_URI_ENCODING_NONE); + return nxt_http_field_hash_end(hash) & 0xFFFF; } +int64_t nxt_http_cookie_hash(nxt_mp_t *mp, nxt_str_t *name) { + return nxt_http_field_hash(mp, name, 1, NXT_HTTP_URI_ENCODING_NONE); +} -int -nxt_http_cond_value(nxt_task_t *task, nxt_http_request_t *r, - nxt_tstr_cond_t *cond) -{ - nxt_int_t ret; - nxt_str_t str; - nxt_bool_t expr; - nxt_router_conf_t *rtcf; +int nxt_http_cond_value(nxt_task_t *task, nxt_http_request_t *r, + nxt_tstr_cond_t *cond) { + nxt_int_t ret; + nxt_str_t str; + nxt_bool_t expr; + nxt_router_conf_t *rtcf; - rtcf = r->conf->socket_conf->router_conf; + rtcf = r->conf->socket_conf->router_conf; - expr = 1; + expr = 1; - if (cond->expr != NULL) { + if (cond->expr != NULL) { - if (nxt_tstr_is_const(cond->expr)) { - nxt_tstr_str(cond->expr, &str); + if (nxt_tstr_is_const(cond->expr)) { + nxt_tstr_str(cond->expr, &str); - } else { - ret = nxt_tstr_query_init(&r->tstr_query, rtcf->tstr_state, - &r->tstr_cache, r, r->mem_pool); - if (nxt_slow_path(ret != NXT_OK)) { - return -1; - } + } else { + ret = nxt_tstr_query_init(&r->tstr_query, rtcf->tstr_state, + &r->tstr_cache, r, r->mem_pool); + if (nxt_slow_path(ret != NXT_OK)) { + return -1; + } - ret = nxt_tstr_query(task, r->tstr_query, cond->expr, &str); - if (nxt_slow_path(ret != NXT_OK)) { - return -1; - } - } + ret = nxt_tstr_query(task, r->tstr_query, cond->expr, &str); + if (nxt_slow_path(ret != NXT_OK)) { + return -1; + } + } - if (str.length == 0 - || nxt_str_eq(&str, "0", 1) - || nxt_str_eq(&str, "false", 5) - || nxt_str_eq(&str, "null", 4) - || nxt_str_eq(&str, "undefined", 9)) - { - expr = 0; - } + if (str.length == 0 || nxt_str_eq(&str, "0", 1) || + nxt_str_eq(&str, "false", 5) || nxt_str_eq(&str, "null", 4) || + nxt_str_eq(&str, "undefined", 9)) { + expr = 0; } + } - return cond->negate ^ expr; + return cond->negate ^ expr; } diff --git a/src/nxt_http_response.c b/src/nxt_http_response.c index 55a4686c2..581250190 100644 --- a/src/nxt_http_response.c +++ b/src/nxt_http_response.c @@ -7,81 +7,69 @@ #include #include - static nxt_int_t nxt_http_response_status(void *ctx, nxt_http_field_t *field, - uintptr_t data); + uintptr_t data); static nxt_int_t nxt_http_response_skip(void *ctx, nxt_http_field_t *field, - uintptr_t data); + uintptr_t data); static nxt_int_t nxt_http_response_field(void *ctx, nxt_http_field_t *field, - uintptr_t offset); - - -nxt_lvlhsh_t nxt_response_fields_hash; - -static nxt_http_field_proc_t nxt_response_fields[] = { - { nxt_string("Status"), &nxt_http_response_status, 0 }, - { nxt_string("Server"), &nxt_http_response_skip, 0 }, - { nxt_string("Date"), &nxt_http_response_field, - offsetof(nxt_http_request_t, resp.date) }, - { nxt_string("Connection"), &nxt_http_response_skip, 0 }, - { nxt_string("Content-Type"), &nxt_http_response_field, - offsetof(nxt_http_request_t, resp.content_type) }, - { nxt_string("Content-Length"), &nxt_http_response_field, - offsetof(nxt_http_request_t, resp.content_length) }, - { nxt_string("Upgrade"), &nxt_http_response_skip, 0 }, - { nxt_string("Sec-WebSocket-Accept"), &nxt_http_response_skip, 0 }, + uintptr_t offset); + +nxt_lvlhsh_t nxt_response_fields_hash; + +static nxt_http_field_proc_t nxt_response_fields[] = { + {nxt_string("Status"), &nxt_http_response_status, 0}, + {nxt_string("Server"), &nxt_http_response_skip, 0}, + {nxt_string("Date"), &nxt_http_response_field, + offsetof(nxt_http_request_t, resp.date)}, + {nxt_string("Connection"), &nxt_http_response_skip, 0}, + {nxt_string("Content-Type"), &nxt_http_response_field, + offsetof(nxt_http_request_t, resp.content_type)}, + {nxt_string("Content-Length"), &nxt_http_response_field, + offsetof(nxt_http_request_t, resp.content_length)}, + {nxt_string("Upgrade"), &nxt_http_response_skip, 0}, + {nxt_string("Sec-WebSocket-Accept"), &nxt_http_response_skip, 0}, }; - -nxt_int_t -nxt_http_response_hash_init(nxt_task_t *task) -{ - return nxt_http_fields_hash(&nxt_response_fields_hash, - nxt_response_fields, nxt_nitems(nxt_response_fields)); +nxt_int_t nxt_http_response_hash_init(nxt_task_t *task) { + return nxt_http_fields_hash(&nxt_response_fields_hash, nxt_response_fields, + nxt_nitems(nxt_response_fields)); } +nxt_int_t nxt_http_response_status(void *ctx, nxt_http_field_t *field, + uintptr_t data) { + nxt_int_t status; + nxt_http_request_t *r; -nxt_int_t -nxt_http_response_status(void *ctx, nxt_http_field_t *field, - uintptr_t data) -{ - nxt_int_t status; - nxt_http_request_t *r; - - r = ctx; + r = ctx; - field->skip = 1; + field->skip = 1; - if (field->value_length >= 3) { - status = nxt_int_parse(field->value, 3); + if (field->value_length >= 3) { + status = nxt_int_parse(field->value, 3); - if (status >= 100 && status <= 999) { - r->status = status; - return NXT_OK; - } + if (status >= 100 && status <= 999) { + r->status = status; + return NXT_OK; } + } - return NXT_ERROR; + return NXT_ERROR; } +nxt_int_t nxt_http_response_skip(void *ctx, nxt_http_field_t *field, + uintptr_t data) { + field->skip = 1; -nxt_int_t -nxt_http_response_skip(void *ctx, nxt_http_field_t *field, uintptr_t data) -{ - field->skip = 1; - - return NXT_OK; + return NXT_OK; } +nxt_int_t nxt_http_response_field(void *ctx, nxt_http_field_t *field, + uintptr_t offset) { + nxt_http_request_t *r; -nxt_int_t -nxt_http_response_field(void *ctx, nxt_http_field_t *field, uintptr_t offset) -{ - nxt_http_request_t *r; - - r = ctx; + r = ctx; - nxt_value_at(nxt_http_field_t *, r, offset) = field; + nxt_value_at(nxt_http_field_t *, r, offset) = field; - return NXT_OK; + return NXT_OK; } diff --git a/src/nxt_http_return.c b/src/nxt_http_return.c index a3551683e..95457c7fe 100644 --- a/src/nxt_http_return.c +++ b/src/nxt_http_return.c @@ -6,214 +6,195 @@ #include #include - typedef struct { - nxt_http_status_t status; - nxt_tstr_t *location; - nxt_str_t encoded; + nxt_http_status_t status; + nxt_tstr_t *location; + nxt_str_t encoded; } nxt_http_return_conf_t; - typedef struct { - nxt_str_t location; - nxt_str_t encoded; + nxt_str_t location; + nxt_str_t encoded; } nxt_http_return_ctx_t; - static nxt_http_action_t *nxt_http_return(nxt_task_t *task, - nxt_http_request_t *r, nxt_http_action_t *action); + nxt_http_request_t *r, + nxt_http_action_t *action); static nxt_int_t nxt_http_return_encode(nxt_mp_t *mp, nxt_str_t *encoded, - const nxt_str_t *location); + const nxt_str_t *location); static void nxt_http_return_send(nxt_task_t *task, nxt_http_request_t *r, - nxt_http_return_ctx_t *ctx); + nxt_http_return_ctx_t *ctx); +static const nxt_http_request_state_t nxt_http_return_send_state; -static const nxt_http_request_state_t nxt_http_return_send_state; +nxt_int_t nxt_http_return_init(nxt_router_conf_t *rtcf, + nxt_http_action_t *action, + nxt_http_action_conf_t *acf) { + nxt_mp_t *mp; + nxt_str_t str; + nxt_http_return_conf_t *conf; + mp = rtcf->mem_pool; -nxt_int_t -nxt_http_return_init(nxt_router_conf_t *rtcf, nxt_http_action_t *action, - nxt_http_action_conf_t *acf) -{ - nxt_mp_t *mp; - nxt_str_t str; - nxt_http_return_conf_t *conf; + conf = nxt_mp_zget(mp, sizeof(nxt_http_return_conf_t)); + if (nxt_slow_path(conf == NULL)) { + return NXT_ERROR; + } - mp = rtcf->mem_pool; - - conf = nxt_mp_zget(mp, sizeof(nxt_http_return_conf_t)); - if (nxt_slow_path(conf == NULL)) { - return NXT_ERROR; - } + action->handler = nxt_http_return; + action->u.conf = conf; - action->handler = nxt_http_return; - action->u.conf = conf; + conf->status = nxt_conf_get_number(acf->ret); - conf->status = nxt_conf_get_number(acf->ret); + if (acf->location == NULL) { + return NXT_OK; + } - if (acf->location == NULL) { - return NXT_OK; - } + nxt_conf_get_string(acf->location, &str); - nxt_conf_get_string(acf->location, &str); + conf->location = nxt_tstr_compile(rtcf->tstr_state, &str, 0); + if (nxt_slow_path(conf->location == NULL)) { + return NXT_ERROR; + } - conf->location = nxt_tstr_compile(rtcf->tstr_state, &str, 0); - if (nxt_slow_path(conf->location == NULL)) { - return NXT_ERROR; - } + if (nxt_tstr_is_const(conf->location)) { + nxt_tstr_str(conf->location, &str); + return nxt_http_return_encode(mp, &conf->encoded, &str); + } - if (nxt_tstr_is_const(conf->location)) { - nxt_tstr_str(conf->location, &str); - return nxt_http_return_encode(mp, &conf->encoded, &str); - } - - return NXT_OK; + return NXT_OK; } +nxt_http_action_t *nxt_http_return(nxt_task_t *task, nxt_http_request_t *r, + nxt_http_action_t *action) { + nxt_int_t ret; + nxt_router_conf_t *rtcf; + nxt_http_return_ctx_t *ctx; + nxt_http_return_conf_t *conf; -nxt_http_action_t * -nxt_http_return(nxt_task_t *task, nxt_http_request_t *r, - nxt_http_action_t *action) -{ - nxt_int_t ret; - nxt_router_conf_t *rtcf; - nxt_http_return_ctx_t *ctx; - nxt_http_return_conf_t *conf; - - conf = action->u.conf; + conf = action->u.conf; #if (NXT_DEBUG) - nxt_str_t loc; + nxt_str_t loc; - if (conf->location == NULL) { - nxt_str_set(&loc, ""); + if (conf->location == NULL) { + nxt_str_set(&loc, ""); - } else { - nxt_tstr_str(conf->location, &loc); - } + } else { + nxt_tstr_str(conf->location, &loc); + } - nxt_debug(task, "http return: %d (loc: \"%V\")", conf->status, &loc); + nxt_debug(task, "http return: %d (loc: \"%V\")", conf->status, &loc); #endif - if (conf->status >= NXT_HTTP_BAD_REQUEST - && conf->status <= NXT_HTTP_SERVER_ERROR_MAX) - { - nxt_http_request_error(task, r, conf->status); - return NULL; - } + if (conf->status >= NXT_HTTP_BAD_REQUEST && + conf->status <= NXT_HTTP_SERVER_ERROR_MAX) { + nxt_http_request_error(task, r, conf->status); + return NULL; + } - if (conf->location == NULL) { - ctx = NULL; + if (conf->location == NULL) { + ctx = NULL; - } else { - ctx = nxt_mp_zget(r->mem_pool, sizeof(nxt_http_return_ctx_t)); - if (nxt_slow_path(ctx == NULL)) { - goto fail; - } + } else { + ctx = nxt_mp_zget(r->mem_pool, sizeof(nxt_http_return_ctx_t)); + if (nxt_slow_path(ctx == NULL)) { + goto fail; } + } - r->status = conf->status; - r->resp.content_length_n = 0; + r->status = conf->status; + r->resp.content_length_n = 0; - if (ctx == NULL || nxt_tstr_is_const(conf->location)) { - if (ctx != NULL) { - ctx->encoded = conf->encoded; - } + if (ctx == NULL || nxt_tstr_is_const(conf->location)) { + if (ctx != NULL) { + ctx->encoded = conf->encoded; + } - } else { - rtcf = r->conf->socket_conf->router_conf; + } else { + rtcf = r->conf->socket_conf->router_conf; - ret = nxt_tstr_query_init(&r->tstr_query, rtcf->tstr_state, - &r->tstr_cache, r, r->mem_pool); - if (nxt_slow_path(ret != NXT_OK)) { - goto fail; - } + ret = nxt_tstr_query_init(&r->tstr_query, rtcf->tstr_state, &r->tstr_cache, + r, r->mem_pool); + if (nxt_slow_path(ret != NXT_OK)) { + goto fail; + } - ret = nxt_tstr_query(task, r->tstr_query, conf->location, - &ctx->location); - if (nxt_slow_path(ret != NXT_OK)) { - goto fail; - } + ret = nxt_tstr_query(task, r->tstr_query, conf->location, &ctx->location); + if (nxt_slow_path(ret != NXT_OK)) { + goto fail; } + } - nxt_http_return_send(task, r, ctx); + nxt_http_return_send(task, r, ctx); - return NULL; + return NULL; fail: - nxt_http_request_error(task, r, NXT_HTTP_INTERNAL_SERVER_ERROR); - return NULL; + nxt_http_request_error(task, r, NXT_HTTP_INTERNAL_SERVER_ERROR); + return NULL; } +static nxt_int_t nxt_http_return_encode(nxt_mp_t *mp, nxt_str_t *encoded, + const nxt_str_t *location) { + nxt_uint_t encode; -static nxt_int_t -nxt_http_return_encode(nxt_mp_t *mp, nxt_str_t *encoded, - const nxt_str_t *location) -{ - nxt_uint_t encode; - - if (nxt_is_complex_uri_encoded(location->start, location->length)) { - *encoded = *location; + if (nxt_is_complex_uri_encoded(location->start, location->length)) { + *encoded = *location; - return NXT_OK; - } + return NXT_OK; + } - encode = nxt_encode_complex_uri(NULL, location->start, location->length); - encoded->length = location->length + encode * 2; + encode = nxt_encode_complex_uri(NULL, location->start, location->length); + encoded->length = location->length + encode * 2; - encoded->start = nxt_mp_nget(mp, encoded->length); - if (nxt_slow_path(encoded->start == NULL)) { - return NXT_ERROR; - } + encoded->start = nxt_mp_nget(mp, encoded->length); + if (nxt_slow_path(encoded->start == NULL)) { + return NXT_ERROR; + } - nxt_encode_complex_uri(encoded->start, location->start, location->length); + nxt_encode_complex_uri(encoded->start, location->start, location->length); - return NXT_OK; + return NXT_OK; } +static void nxt_http_return_send(nxt_task_t *task, nxt_http_request_t *r, + nxt_http_return_ctx_t *ctx) { + nxt_int_t ret; + nxt_http_field_t *field; + + if (ctx != NULL) { + if (ctx->location.length > 0) { + ret = nxt_http_return_encode(r->mem_pool, &ctx->encoded, &ctx->location); + if (nxt_slow_path(ret == NXT_ERROR)) { + goto fail; + } + } -static void -nxt_http_return_send(nxt_task_t *task, nxt_http_request_t *r, - nxt_http_return_ctx_t *ctx) -{ - nxt_int_t ret; - nxt_http_field_t *field; - - if (ctx != NULL) { - if (ctx->location.length > 0) { - ret = nxt_http_return_encode(r->mem_pool, &ctx->encoded, - &ctx->location); - if (nxt_slow_path(ret == NXT_ERROR)) { - goto fail; - } - } - - field = nxt_list_zero_add(r->resp.fields); - if (nxt_slow_path(field == NULL)) { - goto fail; - } - - nxt_http_field_name_set(field, "Location"); - - field->value = ctx->encoded.start; - field->value_length = ctx->encoded.length; + field = nxt_list_zero_add(r->resp.fields); + if (nxt_slow_path(field == NULL)) { + goto fail; } - r->state = &nxt_http_return_send_state; + nxt_http_field_name_set(field, "Location"); + + field->value = ctx->encoded.start; + field->value_length = ctx->encoded.length; + } - nxt_http_request_header_send(task, r, NULL, NULL); + r->state = &nxt_http_return_send_state; - return; + nxt_http_request_header_send(task, r, NULL, NULL); + + return; fail: - nxt_http_request_error(task, r, NXT_HTTP_INTERNAL_SERVER_ERROR); + nxt_http_request_error(task, r, NXT_HTTP_INTERNAL_SERVER_ERROR); } - -static const nxt_http_request_state_t nxt_http_return_send_state - nxt_aligned(64) = -{ - .error_handler = nxt_http_request_error_handler, +static const nxt_http_request_state_t + nxt_http_return_send_state nxt_aligned(64) = { + .error_handler = nxt_http_request_error_handler, }; diff --git a/src/nxt_http_rewrite.c b/src/nxt_http_rewrite.c index 5de15ed7c..041607a1d 100644 --- a/src/nxt_http_rewrite.c +++ b/src/nxt_http_rewrite.c @@ -7,82 +7,77 @@ #include #include +nxt_int_t nxt_http_rewrite_init(nxt_router_conf_t *rtcf, + nxt_http_action_t *action, + nxt_http_action_conf_t *acf) { + nxt_str_t str; -nxt_int_t -nxt_http_rewrite_init(nxt_router_conf_t *rtcf, nxt_http_action_t *action, - nxt_http_action_conf_t *acf) -{ - nxt_str_t str; + nxt_conf_get_string(acf->rewrite, &str); - nxt_conf_get_string(acf->rewrite, &str); + action->rewrite = nxt_tstr_compile(rtcf->tstr_state, &str, 0); + if (nxt_slow_path(action->rewrite == NULL)) { + return NXT_ERROR; + } - action->rewrite = nxt_tstr_compile(rtcf->tstr_state, &str, 0); - if (nxt_slow_path(action->rewrite == NULL)) { - return NXT_ERROR; - } - - return NXT_OK; + return NXT_OK; } +nxt_int_t nxt_http_rewrite(nxt_task_t *task, nxt_http_request_t *r) { + nxt_int_t ret; + nxt_str_t str; + nxt_router_conf_t *rtcf; + nxt_http_action_t *action; + nxt_http_request_parse_t rp; -nxt_int_t -nxt_http_rewrite(nxt_task_t *task, nxt_http_request_t *r) -{ - nxt_int_t ret; - nxt_str_t str; - nxt_router_conf_t *rtcf; - nxt_http_action_t *action; - nxt_http_request_parse_t rp; - - action = r->action; + action = r->action; - if (action == NULL || action->rewrite == NULL) { - return NXT_OK; - } + if (action == NULL || action->rewrite == NULL) { + return NXT_OK; + } - if (nxt_tstr_is_const(action->rewrite)) { - nxt_tstr_str(action->rewrite, &str); + if (nxt_tstr_is_const(action->rewrite)) { + nxt_tstr_str(action->rewrite, &str); - } else { - rtcf = r->conf->socket_conf->router_conf; + } else { + rtcf = r->conf->socket_conf->router_conf; - ret = nxt_tstr_query_init(&r->tstr_query, rtcf->tstr_state, - &r->tstr_cache, r, r->mem_pool); - if (nxt_slow_path(ret != NXT_OK)) { - return NXT_ERROR; - } + ret = nxt_tstr_query_init(&r->tstr_query, rtcf->tstr_state, &r->tstr_cache, + r, r->mem_pool); + if (nxt_slow_path(ret != NXT_OK)) { + return NXT_ERROR; + } - ret = nxt_tstr_query(task, r->tstr_query, action->rewrite, &str); - if (nxt_slow_path(ret != NXT_OK)) { - return NXT_ERROR; - } + ret = nxt_tstr_query(task, r->tstr_query, action->rewrite, &str); + if (nxt_slow_path(ret != NXT_OK)) { + return NXT_ERROR; } + } - nxt_memzero(&rp, sizeof(nxt_http_request_parse_t)); + nxt_memzero(&rp, sizeof(nxt_http_request_parse_t)); - rp.mem_pool = r->mem_pool; + rp.mem_pool = r->mem_pool; - rp.target_start = str.start; - rp.target_end = str.start + str.length; + rp.target_start = str.start; + rp.target_end = str.start + str.length; - ret = nxt_http_parse_complex_target(&rp); - if (nxt_slow_path(ret != NXT_OK)) { - return NXT_ERROR; - } + ret = nxt_http_parse_complex_target(&rp); + if (nxt_slow_path(ret != NXT_OK)) { + return NXT_ERROR; + } - r->path = nxt_mp_alloc(r->mem_pool, sizeof(nxt_str_t)); - if (nxt_slow_path(r->path == NULL)) { - return NXT_ERROR; - } + r->path = nxt_mp_alloc(r->mem_pool, sizeof(nxt_str_t)); + if (nxt_slow_path(r->path == NULL)) { + return NXT_ERROR; + } - *r->path = rp.path; + *r->path = rp.path; - r->uri_changed = 1; - r->quoted_target = rp.quoted_target; + r->uri_changed = 1; + r->quoted_target = rp.quoted_target; - if (nxt_slow_path(r->log_route)) { - nxt_log(task, NXT_LOG_NOTICE, "URI rewritten to \"%V\"", r->path); - } + if (nxt_slow_path(r->log_route)) { + nxt_log(task, NXT_LOG_NOTICE, "URI rewritten to \"%V\"", r->path); + } - return NXT_OK; + return NXT_OK; } diff --git a/src/nxt_http_route.c b/src/nxt_http_route.c index bd0646f3b..5426a4764 100644 --- a/src/nxt_http_route.c +++ b/src/nxt_http_route.c @@ -10,295 +10,289 @@ #include #include - typedef enum { - NXT_HTTP_ROUTE_TABLE = 0, - NXT_HTTP_ROUTE_STRING, - NXT_HTTP_ROUTE_STRING_PTR, - NXT_HTTP_ROUTE_HEADER, - NXT_HTTP_ROUTE_ARGUMENT, - NXT_HTTP_ROUTE_COOKIE, - NXT_HTTP_ROUTE_SCHEME, - NXT_HTTP_ROUTE_QUERY, - NXT_HTTP_ROUTE_SOURCE, - NXT_HTTP_ROUTE_DESTINATION, + NXT_HTTP_ROUTE_TABLE = 0, + NXT_HTTP_ROUTE_STRING, + NXT_HTTP_ROUTE_STRING_PTR, + NXT_HTTP_ROUTE_HEADER, + NXT_HTTP_ROUTE_ARGUMENT, + NXT_HTTP_ROUTE_COOKIE, + NXT_HTTP_ROUTE_SCHEME, + NXT_HTTP_ROUTE_QUERY, + NXT_HTTP_ROUTE_SOURCE, + NXT_HTTP_ROUTE_DESTINATION, } nxt_http_route_object_t; - typedef enum { - NXT_HTTP_ROUTE_PATTERN_EXACT = 0, - NXT_HTTP_ROUTE_PATTERN_BEGIN, - NXT_HTTP_ROUTE_PATTERN_END, - NXT_HTTP_ROUTE_PATTERN_SUBSTRING, + NXT_HTTP_ROUTE_PATTERN_EXACT = 0, + NXT_HTTP_ROUTE_PATTERN_BEGIN, + NXT_HTTP_ROUTE_PATTERN_END, + NXT_HTTP_ROUTE_PATTERN_SUBSTRING, } nxt_http_route_pattern_type_t; - typedef enum { - NXT_HTTP_ROUTE_PATTERN_NOCASE = 0, - NXT_HTTP_ROUTE_PATTERN_LOWCASE, - NXT_HTTP_ROUTE_PATTERN_UPCASE, + NXT_HTTP_ROUTE_PATTERN_NOCASE = 0, + NXT_HTTP_ROUTE_PATTERN_LOWCASE, + NXT_HTTP_ROUTE_PATTERN_UPCASE, } nxt_http_route_pattern_case_t; - typedef struct { - nxt_conf_value_t *host; - nxt_conf_value_t *uri; - nxt_conf_value_t *method; - nxt_conf_value_t *headers; - nxt_conf_value_t *arguments; - nxt_conf_value_t *cookies; - nxt_conf_value_t *scheme; - nxt_conf_value_t *query; - nxt_conf_value_t *source; - nxt_conf_value_t *destination; - nxt_conf_value_t *condition; + nxt_conf_value_t *host; + nxt_conf_value_t *uri; + nxt_conf_value_t *method; + nxt_conf_value_t *headers; + nxt_conf_value_t *arguments; + nxt_conf_value_t *cookies; + nxt_conf_value_t *scheme; + nxt_conf_value_t *query; + nxt_conf_value_t *source; + nxt_conf_value_t *destination; + nxt_conf_value_t *condition; } nxt_http_route_match_conf_t; - typedef struct { - u_char *start; - uint32_t length; - nxt_http_route_pattern_type_t type:8; + u_char *start; + uint32_t length; + nxt_http_route_pattern_type_t type : 8; } nxt_http_route_pattern_slice_t; - typedef struct { - union { - nxt_array_t *pattern_slices; + union { + nxt_array_t *pattern_slices; #if (NXT_HAVE_REGEX) - nxt_regex_t *regex; + nxt_regex_t *regex; #endif - } u; - uint32_t min_length; + } u; + uint32_t min_length; - uint8_t case_sensitive; /* 1 bit */ - uint8_t negative; /* 1 bit */ - uint8_t any; /* 1 bit */ + uint8_t case_sensitive; /* 1 bit */ + uint8_t negative; /* 1 bit */ + uint8_t any; /* 1 bit */ #if (NXT_HAVE_REGEX) - uint8_t regex; /* 1 bit */ + uint8_t regex; /* 1 bit */ #endif } nxt_http_route_pattern_t; - typedef struct { - uint16_t hash; - uint16_t name_length; - uint32_t value_length; - u_char *name; - u_char *value; + uint16_t hash; + uint16_t name_length; + uint32_t value_length; + u_char *name; + u_char *value; } nxt_http_cookie_t; - struct nxt_http_route_rule_s { - /* The object must be the first field. */ - nxt_http_route_object_t object:8; - uint32_t items; + /* The object must be the first field. */ + nxt_http_route_object_t object : 8; + uint32_t items; - union { - uintptr_t offset; + union { + uintptr_t offset; - struct { - u_char *start; - uint16_t hash; - uint16_t length; - } name; - } u; + struct { + u_char *start; + uint16_t hash; + uint16_t length; + } name; + } u; - nxt_http_route_pattern_t pattern[]; + nxt_http_route_pattern_t pattern[]; }; - typedef struct { - uint32_t items; - nxt_http_route_rule_t *rule[]; + uint32_t items; + nxt_http_route_rule_t *rule[]; } nxt_http_route_ruleset_t; - typedef struct { - /* The object must be the first field. */ - nxt_http_route_object_t object:8; - uint32_t items; - nxt_http_route_ruleset_t *ruleset[]; + /* The object must be the first field. */ + nxt_http_route_object_t object : 8; + uint32_t items; + nxt_http_route_ruleset_t *ruleset[]; } nxt_http_route_table_t; - struct nxt_http_route_addr_rule_s { - /* The object must be the first field. */ - nxt_http_route_object_t object:8; - uint32_t items; - nxt_http_route_addr_pattern_t addr_pattern[]; + /* The object must be the first field. */ + nxt_http_route_object_t object : 8; + uint32_t items; + nxt_http_route_addr_pattern_t addr_pattern[]; }; - typedef union { - nxt_http_route_rule_t *rule; - nxt_http_route_table_t *table; - nxt_http_route_addr_rule_t *addr_rule; + nxt_http_route_rule_t *rule; + nxt_http_route_table_t *table; + nxt_http_route_addr_rule_t *addr_rule; } nxt_http_route_test_t; - typedef struct { - uint32_t items; - nxt_tstr_cond_t condition; - nxt_http_action_t action; - nxt_http_route_test_t test[]; + uint32_t items; + nxt_tstr_cond_t condition; + nxt_http_action_t action; + nxt_http_route_test_t test[]; } nxt_http_route_match_t; - struct nxt_http_route_s { - nxt_str_t name; - uint32_t items; - nxt_http_route_match_t *match[]; + nxt_str_t name; + uint32_t items; + nxt_http_route_match_t *match[]; }; - struct nxt_http_routes_s { - uint32_t items; - nxt_http_route_t *route[]; + uint32_t items; + nxt_http_route_t *route[]; }; - static nxt_http_route_t *nxt_http_route_create(nxt_task_t *task, - nxt_router_temp_conf_t *tmcf, nxt_conf_value_t *cv); -static nxt_http_route_match_t *nxt_http_route_match_create(nxt_task_t *task, - nxt_router_temp_conf_t *tmcf, nxt_conf_value_t *cv); -static nxt_http_route_table_t *nxt_http_route_table_create(nxt_task_t *task, - nxt_mp_t *mp, nxt_conf_value_t *table_cv, nxt_http_route_object_t object, - nxt_bool_t case_sensitive, nxt_http_uri_encoding_t encoding); -static nxt_http_route_ruleset_t *nxt_http_route_ruleset_create(nxt_task_t *task, - nxt_mp_t *mp, nxt_conf_value_t *ruleset_cv, nxt_http_route_object_t object, - nxt_bool_t case_sensitive, nxt_http_uri_encoding_t encoding); -static nxt_http_route_rule_t *nxt_http_route_rule_name_create(nxt_task_t *task, - nxt_mp_t *mp, nxt_conf_value_t *rule_cv, nxt_str_t *name, - nxt_bool_t case_sensitive, nxt_http_uri_encoding_t encoding); -static nxt_http_route_rule_t *nxt_http_route_rule_create(nxt_task_t *task, - nxt_mp_t *mp, nxt_conf_value_t *cv, nxt_bool_t case_sensitive, - nxt_http_route_pattern_case_t pattern_case, + nxt_router_temp_conf_t *tmcf, + nxt_conf_value_t *cv); +static nxt_http_route_match_t * +nxt_http_route_match_create(nxt_task_t *task, nxt_router_temp_conf_t *tmcf, + nxt_conf_value_t *cv); +static nxt_http_route_table_t *nxt_http_route_table_create( + nxt_task_t *task, nxt_mp_t *mp, nxt_conf_value_t *table_cv, + nxt_http_route_object_t object, nxt_bool_t case_sensitive, + nxt_http_uri_encoding_t encoding); +static nxt_http_route_ruleset_t *nxt_http_route_ruleset_create( + nxt_task_t *task, nxt_mp_t *mp, nxt_conf_value_t *ruleset_cv, + nxt_http_route_object_t object, nxt_bool_t case_sensitive, nxt_http_uri_encoding_t encoding); +static nxt_http_route_rule_t *nxt_http_route_rule_name_create( + nxt_task_t *task, nxt_mp_t *mp, nxt_conf_value_t *rule_cv, nxt_str_t *name, + nxt_bool_t case_sensitive, nxt_http_uri_encoding_t encoding); +static nxt_http_route_rule_t * +nxt_http_route_rule_create(nxt_task_t *task, nxt_mp_t *mp, nxt_conf_value_t *cv, + nxt_bool_t case_sensitive, + nxt_http_route_pattern_case_t pattern_case, + nxt_http_uri_encoding_t encoding); static int nxt_http_pattern_compare(const void *one, const void *two); static int nxt_http_addr_pattern_compare(const void *one, const void *two); -static nxt_int_t nxt_http_route_pattern_create(nxt_task_t *task, nxt_mp_t *mp, - nxt_conf_value_t *cv, nxt_http_route_pattern_t *pattern, - nxt_http_route_pattern_case_t pattern_case, - nxt_http_uri_encoding_t encoding); +static nxt_int_t +nxt_http_route_pattern_create(nxt_task_t *task, nxt_mp_t *mp, + nxt_conf_value_t *cv, + nxt_http_route_pattern_t *pattern, + nxt_http_route_pattern_case_t pattern_case, + nxt_http_uri_encoding_t encoding); static nxt_int_t nxt_http_route_decode_str(nxt_str_t *str, - nxt_http_uri_encoding_t encoding); -static nxt_int_t nxt_http_route_pattern_slice(nxt_array_t *slices, - nxt_str_t *test, - nxt_http_route_pattern_type_t type, - nxt_http_uri_encoding_t encoding, - nxt_http_route_pattern_case_t pattern_case); + nxt_http_uri_encoding_t encoding); +static nxt_int_t +nxt_http_route_pattern_slice(nxt_array_t *slices, nxt_str_t *test, + nxt_http_route_pattern_type_t type, + nxt_http_uri_encoding_t encoding, + nxt_http_route_pattern_case_t pattern_case); static nxt_int_t nxt_http_route_resolve(nxt_task_t *task, - nxt_router_temp_conf_t *tmcf, nxt_http_route_t *route); + nxt_router_temp_conf_t *tmcf, + nxt_http_route_t *route); static nxt_int_t nxt_http_action_resolve(nxt_task_t *task, - nxt_router_temp_conf_t *tmcf, nxt_http_action_t *action); + nxt_router_temp_conf_t *tmcf, + nxt_http_action_t *action); static nxt_http_action_t *nxt_http_pass_var(nxt_task_t *task, - nxt_http_request_t *r, nxt_http_action_t *action); + nxt_http_request_t *r, + nxt_http_action_t *action); static void nxt_http_pass_query(nxt_task_t *task, nxt_http_request_t *r, - nxt_http_action_t *action); + nxt_http_action_t *action); static nxt_int_t nxt_http_pass_find(nxt_mp_t *mp, nxt_router_conf_t *rtcf, - nxt_str_t *pass, nxt_http_action_t *action); + nxt_str_t *pass, nxt_http_action_t *action); static nxt_int_t nxt_http_route_find(nxt_http_routes_t *routes, nxt_str_t *name, - nxt_http_action_t *action); + nxt_http_action_t *action); static nxt_http_action_t *nxt_http_route_handler(nxt_task_t *task, - nxt_http_request_t *r, nxt_http_action_t *start); + nxt_http_request_t *r, + nxt_http_action_t *start); static nxt_http_action_t *nxt_http_route_match(nxt_task_t *task, - nxt_http_request_t *r, nxt_http_route_match_t *match); + nxt_http_request_t *r, + nxt_http_route_match_t *match); static nxt_int_t nxt_http_route_table(nxt_http_request_t *r, - nxt_http_route_table_t *table); + nxt_http_route_table_t *table); static nxt_int_t nxt_http_route_ruleset(nxt_http_request_t *r, - nxt_http_route_ruleset_t *ruleset); + nxt_http_route_ruleset_t *ruleset); static nxt_int_t nxt_http_route_rule(nxt_http_request_t *r, - nxt_http_route_rule_t *rule); + nxt_http_route_rule_t *rule); static nxt_int_t nxt_http_route_header(nxt_http_request_t *r, - nxt_http_route_rule_t *rule); + nxt_http_route_rule_t *rule); static nxt_int_t nxt_http_route_arguments(nxt_http_request_t *r, - nxt_http_route_rule_t *rule); + nxt_http_route_rule_t *rule); static nxt_int_t nxt_http_route_test_argument(nxt_http_request_t *r, - nxt_http_route_rule_t *rule, nxt_array_t *array); + nxt_http_route_rule_t *rule, + nxt_array_t *array); static nxt_int_t nxt_http_route_scheme(nxt_http_request_t *r, - nxt_http_route_rule_t *rule); + nxt_http_route_rule_t *rule); static nxt_int_t nxt_http_route_query(nxt_http_request_t *r, - nxt_http_route_rule_t *rule); + nxt_http_route_rule_t *rule); static nxt_int_t nxt_http_route_cookies(nxt_http_request_t *r, - nxt_http_route_rule_t *rule); + nxt_http_route_rule_t *rule); static nxt_int_t nxt_http_route_test_cookie(nxt_http_request_t *r, - nxt_http_route_rule_t *rule, nxt_array_t *array); + nxt_http_route_rule_t *rule, + nxt_array_t *array); static nxt_int_t nxt_http_route_pattern(nxt_http_request_t *r, - nxt_http_route_pattern_t *pattern, u_char *start, size_t length); + nxt_http_route_pattern_t *pattern, + u_char *start, size_t length); static nxt_int_t nxt_http_route_memcmp(u_char *start, u_char *test, - size_t length, nxt_bool_t case_sensitive); - - -nxt_http_routes_t * -nxt_http_routes_create(nxt_task_t *task, nxt_router_temp_conf_t *tmcf, - nxt_conf_value_t *routes_conf) -{ - size_t size; - uint32_t i, n, next; - nxt_mp_t *mp; - nxt_str_t name, *string; - nxt_bool_t object; - nxt_conf_value_t *route_conf; - nxt_http_route_t *route; - nxt_http_routes_t *routes; - - object = (nxt_conf_type(routes_conf) == NXT_CONF_OBJECT); - n = object ? nxt_conf_object_members_count(routes_conf) : 1; - size = sizeof(nxt_http_routes_t) + n * sizeof(nxt_http_route_t *); - - mp = tmcf->router_conf->mem_pool; - - routes = nxt_mp_alloc(mp, size); - if (nxt_slow_path(routes == NULL)) { - return NULL; - } + size_t length, + nxt_bool_t case_sensitive); + +nxt_http_routes_t *nxt_http_routes_create(nxt_task_t *task, + nxt_router_temp_conf_t *tmcf, + nxt_conf_value_t *routes_conf) { + size_t size; + uint32_t i, n, next; + nxt_mp_t *mp; + nxt_str_t name, *string; + nxt_bool_t object; + nxt_conf_value_t *route_conf; + nxt_http_route_t *route; + nxt_http_routes_t *routes; + + object = (nxt_conf_type(routes_conf) == NXT_CONF_OBJECT); + n = object ? nxt_conf_object_members_count(routes_conf) : 1; + size = sizeof(nxt_http_routes_t) + n * sizeof(nxt_http_route_t *); + + mp = tmcf->router_conf->mem_pool; + + routes = nxt_mp_alloc(mp, size); + if (nxt_slow_path(routes == NULL)) { + return NULL; + } - routes->items = n; + routes->items = n; - if (object) { - next = 0; + if (object) { + next = 0; - for (i = 0; i < n; i++) { - route_conf = nxt_conf_next_object_member(routes_conf, &name, &next); + for (i = 0; i < n; i++) { + route_conf = nxt_conf_next_object_member(routes_conf, &name, &next); - route = nxt_http_route_create(task, tmcf, route_conf); - if (nxt_slow_path(route == NULL)) { - return NULL; - } + route = nxt_http_route_create(task, tmcf, route_conf); + if (nxt_slow_path(route == NULL)) { + return NULL; + } - routes->route[i] = route; + routes->route[i] = route; - string = nxt_str_dup(mp, &route->name, &name); - if (nxt_slow_path(string == NULL)) { - return NULL; - } - } + string = nxt_str_dup(mp, &route->name, &name); + if (nxt_slow_path(string == NULL)) { + return NULL; + } + } - } else { - route = nxt_http_route_create(task, tmcf, routes_conf); - if (nxt_slow_path(route == NULL)) { - return NULL; - } + } else { + route = nxt_http_route_create(task, tmcf, routes_conf); + if (nxt_slow_path(route == NULL)) { + return NULL; + } - routes->route[0] = route; + routes->route[0] = route; - route->name.length = 0; - route->name.start = NULL; - } + route->name.length = 0; + route->name.start = NULL; + } - return routes; + return routes; } - -static nxt_conf_map_t nxt_http_route_match_conf[] = { - { - nxt_string("scheme"), - NXT_CONF_MAP_PTR, - offsetof(nxt_http_route_match_conf_t, scheme) - }, +static nxt_conf_map_t nxt_http_route_match_conf[] = { + {nxt_string("scheme"), NXT_CONF_MAP_PTR, + offsetof(nxt_http_route_match_conf_t, scheme)}, { nxt_string("host"), NXT_CONF_MAP_PTR, @@ -360,1881 +354,1733 @@ static nxt_conf_map_t nxt_http_route_match_conf[] = { }, }; +static nxt_http_route_t *nxt_http_route_create(nxt_task_t *task, + nxt_router_temp_conf_t *tmcf, + nxt_conf_value_t *cv) { + size_t size; + uint32_t i, n; + nxt_conf_value_t *value; + nxt_http_route_t *route; + nxt_http_route_match_t *match, **m; + + n = nxt_conf_array_elements_count(cv); + size = sizeof(nxt_http_route_t) + n * sizeof(nxt_http_route_match_t *); + + route = nxt_mp_alloc(tmcf->router_conf->mem_pool, size); + if (nxt_slow_path(route == NULL)) { + return NULL; + } -static nxt_http_route_t * -nxt_http_route_create(nxt_task_t *task, nxt_router_temp_conf_t *tmcf, - nxt_conf_value_t *cv) -{ - size_t size; - uint32_t i, n; - nxt_conf_value_t *value; - nxt_http_route_t *route; - nxt_http_route_match_t *match, **m; + route->items = n; + m = &route->match[0]; - n = nxt_conf_array_elements_count(cv); - size = sizeof(nxt_http_route_t) + n * sizeof(nxt_http_route_match_t *); + for (i = 0; i < n; i++) { + value = nxt_conf_get_array_element(cv, i); - route = nxt_mp_alloc(tmcf->router_conf->mem_pool, size); - if (nxt_slow_path(route == NULL)) { - return NULL; + match = nxt_http_route_match_create(task, tmcf, value); + if (match == NULL) { + return NULL; } - route->items = n; - m = &route->match[0]; - - for (i = 0; i < n; i++) { - value = nxt_conf_get_array_element(cv, i); - - match = nxt_http_route_match_create(task, tmcf, value); - if (match == NULL) { - return NULL; - } - - *m++ = match; - } + *m++ = match; + } - return route; + return route; } - static nxt_http_route_match_t * nxt_http_route_match_create(nxt_task_t *task, nxt_router_temp_conf_t *tmcf, - nxt_conf_value_t *cv) -{ - size_t size; - uint32_t n; - nxt_mp_t *mp; - nxt_int_t ret; - nxt_str_t str; - nxt_conf_value_t *match_conf, *action_conf, *condition; - nxt_router_conf_t *rtcf; - nxt_http_route_test_t *test; - nxt_http_route_rule_t *rule; - nxt_http_route_table_t *table; - nxt_http_route_match_t *match; - nxt_http_route_addr_rule_t *addr_rule; - nxt_http_route_match_conf_t mtcf; - - static const nxt_str_t if_path = nxt_string("/if"); - static const nxt_str_t match_path = nxt_string("/match"); - static const nxt_str_t action_path = nxt_string("/action"); - - match_conf = nxt_conf_get_path(cv, &match_path); - - n = (match_conf != NULL) ? nxt_conf_object_members_count(match_conf) : 0; - size = sizeof(nxt_http_route_match_t) + n * sizeof(nxt_http_route_test_t *); - - rtcf = tmcf->router_conf; - mp = rtcf->mem_pool; - - condition = NULL; - - if (match_conf != NULL) { - condition = nxt_conf_get_path(match_conf, &if_path); - - if (condition != NULL) { - n--; - size -= sizeof(nxt_http_route_test_t *); - } - } + nxt_conf_value_t *cv) { + size_t size; + uint32_t n; + nxt_mp_t *mp; + nxt_int_t ret; + nxt_str_t str; + nxt_conf_value_t *match_conf, *action_conf, *condition; + nxt_router_conf_t *rtcf; + nxt_http_route_test_t *test; + nxt_http_route_rule_t *rule; + nxt_http_route_table_t *table; + nxt_http_route_match_t *match; + nxt_http_route_addr_rule_t *addr_rule; + nxt_http_route_match_conf_t mtcf; + + static const nxt_str_t if_path = nxt_string("/if"); + static const nxt_str_t match_path = nxt_string("/match"); + static const nxt_str_t action_path = nxt_string("/action"); + + match_conf = nxt_conf_get_path(cv, &match_path); + + n = (match_conf != NULL) ? nxt_conf_object_members_count(match_conf) : 0; + size = sizeof(nxt_http_route_match_t) + n * sizeof(nxt_http_route_test_t *); + + rtcf = tmcf->router_conf; + mp = rtcf->mem_pool; + + condition = NULL; + + if (match_conf != NULL) { + condition = nxt_conf_get_path(match_conf, &if_path); - match = nxt_mp_zalloc(mp, size); - if (nxt_slow_path(match == NULL)) { - return NULL; + if (condition != NULL) { + n--; + size -= sizeof(nxt_http_route_test_t *); } + } - match->items = n; + match = nxt_mp_zalloc(mp, size); + if (nxt_slow_path(match == NULL)) { + return NULL; + } - action_conf = nxt_conf_get_path(cv, &action_path); - if (nxt_slow_path(action_conf == NULL)) { - return NULL; - } + match->items = n; - ret = nxt_http_action_init(task, tmcf, action_conf, &match->action); - if (nxt_slow_path(ret != NXT_OK)) { - return NULL; - } + action_conf = nxt_conf_get_path(cv, &action_path); + if (nxt_slow_path(action_conf == NULL)) { + return NULL; + } - if (n == 0 && condition == NULL) { - return match; - } + ret = nxt_http_action_init(task, tmcf, action_conf, &match->action); + if (nxt_slow_path(ret != NXT_OK)) { + return NULL; + } + + if (n == 0 && condition == NULL) { + return match; + } - nxt_memzero(&mtcf, sizeof(mtcf)); + nxt_memzero(&mtcf, sizeof(mtcf)); - ret = nxt_conf_map_object(tmcf->mem_pool, - match_conf, nxt_http_route_match_conf, - nxt_nitems(nxt_http_route_match_conf), &mtcf); - if (ret != NXT_OK) { - return NULL; - } + ret = + nxt_conf_map_object(tmcf->mem_pool, match_conf, nxt_http_route_match_conf, + nxt_nitems(nxt_http_route_match_conf), &mtcf); + if (ret != NXT_OK) { + return NULL; + } - if (condition != NULL) { - nxt_conf_get_string(condition, &str); + if (condition != NULL) { + nxt_conf_get_string(condition, &str); - ret = nxt_tstr_cond_compile(rtcf->tstr_state, &str, &match->condition); - if (nxt_slow_path(ret != NXT_OK)) { - return NULL; - } + ret = nxt_tstr_cond_compile(rtcf->tstr_state, &str, &match->condition); + if (nxt_slow_path(ret != NXT_OK)) { + return NULL; } + } - test = &match->test[0]; - - if (mtcf.scheme != NULL) { - rule = nxt_http_route_rule_create(task, mp, mtcf.scheme, 1, - NXT_HTTP_ROUTE_PATTERN_NOCASE, - NXT_HTTP_URI_ENCODING_NONE); - if (rule == NULL) { - return NULL; - } + test = &match->test[0]; - rule->object = NXT_HTTP_ROUTE_SCHEME; - test->rule = rule; - test++; + if (mtcf.scheme != NULL) { + rule = nxt_http_route_rule_create(task, mp, mtcf.scheme, 1, + NXT_HTTP_ROUTE_PATTERN_NOCASE, + NXT_HTTP_URI_ENCODING_NONE); + if (rule == NULL) { + return NULL; } - if (mtcf.host != NULL) { - rule = nxt_http_route_rule_create(task, mp, mtcf.host, 1, - NXT_HTTP_ROUTE_PATTERN_LOWCASE, - NXT_HTTP_URI_ENCODING_NONE); - if (rule == NULL) { - return NULL; - } + rule->object = NXT_HTTP_ROUTE_SCHEME; + test->rule = rule; + test++; + } - rule->u.offset = offsetof(nxt_http_request_t, host); - rule->object = NXT_HTTP_ROUTE_STRING; - test->rule = rule; - test++; + if (mtcf.host != NULL) { + rule = nxt_http_route_rule_create(task, mp, mtcf.host, 1, + NXT_HTTP_ROUTE_PATTERN_LOWCASE, + NXT_HTTP_URI_ENCODING_NONE); + if (rule == NULL) { + return NULL; } - if (mtcf.uri != NULL) { - rule = nxt_http_route_rule_create(task, mp, mtcf.uri, 1, - NXT_HTTP_ROUTE_PATTERN_NOCASE, - NXT_HTTP_URI_ENCODING); - if (rule == NULL) { - return NULL; - } + rule->u.offset = offsetof(nxt_http_request_t, host); + rule->object = NXT_HTTP_ROUTE_STRING; + test->rule = rule; + test++; + } - rule->u.offset = offsetof(nxt_http_request_t, path); - rule->object = NXT_HTTP_ROUTE_STRING_PTR; - test->rule = rule; - test++; + if (mtcf.uri != NULL) { + rule = nxt_http_route_rule_create(task, mp, mtcf.uri, 1, + NXT_HTTP_ROUTE_PATTERN_NOCASE, + NXT_HTTP_URI_ENCODING); + if (rule == NULL) { + return NULL; } - if (mtcf.method != NULL) { - rule = nxt_http_route_rule_create(task, mp, mtcf.method, 1, - NXT_HTTP_ROUTE_PATTERN_UPCASE, - NXT_HTTP_URI_ENCODING_NONE); - if (rule == NULL) { - return NULL; - } + rule->u.offset = offsetof(nxt_http_request_t, path); + rule->object = NXT_HTTP_ROUTE_STRING_PTR; + test->rule = rule; + test++; + } - rule->u.offset = offsetof(nxt_http_request_t, method); - rule->object = NXT_HTTP_ROUTE_STRING_PTR; - test->rule = rule; - test++; + if (mtcf.method != NULL) { + rule = nxt_http_route_rule_create(task, mp, mtcf.method, 1, + NXT_HTTP_ROUTE_PATTERN_UPCASE, + NXT_HTTP_URI_ENCODING_NONE); + if (rule == NULL) { + return NULL; } - if (mtcf.headers != NULL) { - table = nxt_http_route_table_create(task, mp, mtcf.headers, - NXT_HTTP_ROUTE_HEADER, 0, - NXT_HTTP_URI_ENCODING_NONE); - if (table == NULL) { - return NULL; - } + rule->u.offset = offsetof(nxt_http_request_t, method); + rule->object = NXT_HTTP_ROUTE_STRING_PTR; + test->rule = rule; + test++; + } - test->table = table; - test++; + if (mtcf.headers != NULL) { + table = nxt_http_route_table_create(task, mp, mtcf.headers, + NXT_HTTP_ROUTE_HEADER, 0, + NXT_HTTP_URI_ENCODING_NONE); + if (table == NULL) { + return NULL; } - if (mtcf.arguments != NULL) { - table = nxt_http_route_table_create(task, mp, mtcf.arguments, - NXT_HTTP_ROUTE_ARGUMENT, 1, - NXT_HTTP_URI_ENCODING_PLUS); - if (table == NULL) { - return NULL; - } + test->table = table; + test++; + } - test->table = table; - test++; + if (mtcf.arguments != NULL) { + table = nxt_http_route_table_create(task, mp, mtcf.arguments, + NXT_HTTP_ROUTE_ARGUMENT, 1, + NXT_HTTP_URI_ENCODING_PLUS); + if (table == NULL) { + return NULL; } - if (mtcf.cookies != NULL) { - table = nxt_http_route_table_create(task, mp, mtcf.cookies, - NXT_HTTP_ROUTE_COOKIE, 1, - NXT_HTTP_URI_ENCODING_NONE); - if (table == NULL) { - return NULL; - } + test->table = table; + test++; + } - test->table = table; - test++; + if (mtcf.cookies != NULL) { + table = nxt_http_route_table_create(task, mp, mtcf.cookies, + NXT_HTTP_ROUTE_COOKIE, 1, + NXT_HTTP_URI_ENCODING_NONE); + if (table == NULL) { + return NULL; } - if (mtcf.query != NULL) { - rule = nxt_http_route_rule_create(task, mp, mtcf.query, 1, - NXT_HTTP_ROUTE_PATTERN_NOCASE, - NXT_HTTP_URI_ENCODING_PLUS); - if (rule == NULL) { - return NULL; - } + test->table = table; + test++; + } - rule->object = NXT_HTTP_ROUTE_QUERY; - test->rule = rule; - test++; + if (mtcf.query != NULL) { + rule = nxt_http_route_rule_create(task, mp, mtcf.query, 1, + NXT_HTTP_ROUTE_PATTERN_NOCASE, + NXT_HTTP_URI_ENCODING_PLUS); + if (rule == NULL) { + return NULL; } - if (mtcf.source != NULL) { - addr_rule = nxt_http_route_addr_rule_create(task, mp, mtcf.source); - if (addr_rule == NULL) { - return NULL; - } + rule->object = NXT_HTTP_ROUTE_QUERY; + test->rule = rule; + test++; + } - addr_rule->object = NXT_HTTP_ROUTE_SOURCE; - test->addr_rule = addr_rule; - test++; + if (mtcf.source != NULL) { + addr_rule = nxt_http_route_addr_rule_create(task, mp, mtcf.source); + if (addr_rule == NULL) { + return NULL; } - if (mtcf.destination != NULL) { - addr_rule = nxt_http_route_addr_rule_create(task, mp, mtcf.destination); - if (addr_rule == NULL) { - return NULL; - } + addr_rule->object = NXT_HTTP_ROUTE_SOURCE; + test->addr_rule = addr_rule; + test++; + } - addr_rule->object = NXT_HTTP_ROUTE_DESTINATION; - test->addr_rule = addr_rule; - test++; + if (mtcf.destination != NULL) { + addr_rule = nxt_http_route_addr_rule_create(task, mp, mtcf.destination); + if (addr_rule == NULL) { + return NULL; } - return match; -} + addr_rule->object = NXT_HTTP_ROUTE_DESTINATION; + test->addr_rule = addr_rule; + test++; + } + return match; +} -static nxt_conf_map_t nxt_http_route_action_conf[] = { - { - nxt_string("rewrite"), - NXT_CONF_MAP_PTR, - offsetof(nxt_http_action_conf_t, rewrite) - }, - { - nxt_string("response_headers"), - NXT_CONF_MAP_PTR, - offsetof(nxt_http_action_conf_t, set_headers) - }, - { - nxt_string("pass"), - NXT_CONF_MAP_PTR, - offsetof(nxt_http_action_conf_t, pass) - }, - { - nxt_string("return"), - NXT_CONF_MAP_PTR, - offsetof(nxt_http_action_conf_t, ret) - }, - { - nxt_string("location"), - NXT_CONF_MAP_PTR, - offsetof(nxt_http_action_conf_t, location) - }, - { - nxt_string("proxy"), - NXT_CONF_MAP_PTR, - offsetof(nxt_http_action_conf_t, proxy) - }, - { - nxt_string("share"), - NXT_CONF_MAP_PTR, - offsetof(nxt_http_action_conf_t, share) - }, - { - nxt_string("index"), - NXT_CONF_MAP_PTR, - offsetof(nxt_http_action_conf_t, index) - }, - { - nxt_string("chroot"), - NXT_CONF_MAP_STR, - offsetof(nxt_http_action_conf_t, chroot) - }, - { - nxt_string("follow_symlinks"), - NXT_CONF_MAP_PTR, - offsetof(nxt_http_action_conf_t, follow_symlinks) - }, - { - nxt_string("traverse_mounts"), - NXT_CONF_MAP_PTR, - offsetof(nxt_http_action_conf_t, traverse_mounts) - }, - { - nxt_string("types"), - NXT_CONF_MAP_PTR, - offsetof(nxt_http_action_conf_t, types) - }, - { - nxt_string("fallback"), - NXT_CONF_MAP_PTR, - offsetof(nxt_http_action_conf_t, fallback) - }, +static nxt_conf_map_t nxt_http_route_action_conf[] = { + {nxt_string("rewrite"), NXT_CONF_MAP_PTR, + offsetof(nxt_http_action_conf_t, rewrite)}, + {nxt_string("response_headers"), NXT_CONF_MAP_PTR, + offsetof(nxt_http_action_conf_t, set_headers)}, + {nxt_string("pass"), NXT_CONF_MAP_PTR, + offsetof(nxt_http_action_conf_t, pass)}, + {nxt_string("return"), NXT_CONF_MAP_PTR, + offsetof(nxt_http_action_conf_t, ret)}, + {nxt_string("location"), NXT_CONF_MAP_PTR, + offsetof(nxt_http_action_conf_t, location)}, + {nxt_string("proxy"), NXT_CONF_MAP_PTR, + offsetof(nxt_http_action_conf_t, proxy)}, + {nxt_string("share"), NXT_CONF_MAP_PTR, + offsetof(nxt_http_action_conf_t, share)}, + {nxt_string("index"), NXT_CONF_MAP_PTR, + offsetof(nxt_http_action_conf_t, index)}, + {nxt_string("chroot"), NXT_CONF_MAP_STR, + offsetof(nxt_http_action_conf_t, chroot)}, + {nxt_string("follow_symlinks"), NXT_CONF_MAP_PTR, + offsetof(nxt_http_action_conf_t, follow_symlinks)}, + {nxt_string("traverse_mounts"), NXT_CONF_MAP_PTR, + offsetof(nxt_http_action_conf_t, traverse_mounts)}, + {nxt_string("types"), NXT_CONF_MAP_PTR, + offsetof(nxt_http_action_conf_t, types)}, + {nxt_string("fallback"), NXT_CONF_MAP_PTR, + offsetof(nxt_http_action_conf_t, fallback)}, }; +nxt_int_t nxt_http_action_init(nxt_task_t *task, nxt_router_temp_conf_t *tmcf, + nxt_conf_value_t *cv, + nxt_http_action_t *action) { + nxt_mp_t *mp; + nxt_int_t ret; + nxt_str_t pass; + nxt_router_conf_t *rtcf; + nxt_http_action_conf_t acf; -nxt_int_t -nxt_http_action_init(nxt_task_t *task, nxt_router_temp_conf_t *tmcf, - nxt_conf_value_t *cv, nxt_http_action_t *action) -{ - nxt_mp_t *mp; - nxt_int_t ret; - nxt_str_t pass; - nxt_router_conf_t *rtcf; - nxt_http_action_conf_t acf; - - nxt_memzero(&acf, sizeof(acf)); + nxt_memzero(&acf, sizeof(acf)); - ret = nxt_conf_map_object(tmcf->mem_pool, cv, nxt_http_route_action_conf, - nxt_nitems(nxt_http_route_action_conf), &acf); - if (ret != NXT_OK) { - return ret; - } + ret = nxt_conf_map_object(tmcf->mem_pool, cv, nxt_http_route_action_conf, + nxt_nitems(nxt_http_route_action_conf), &acf); + if (ret != NXT_OK) { + return ret; + } - nxt_memzero(action, sizeof(nxt_http_action_t)); + nxt_memzero(action, sizeof(nxt_http_action_t)); - rtcf = tmcf->router_conf; - mp = rtcf->mem_pool; + rtcf = tmcf->router_conf; + mp = rtcf->mem_pool; - if (acf.rewrite != NULL) { - ret = nxt_http_rewrite_init(rtcf, action, &acf); - if (nxt_slow_path(ret != NXT_OK)) { - return ret; - } + if (acf.rewrite != NULL) { + ret = nxt_http_rewrite_init(rtcf, action, &acf); + if (nxt_slow_path(ret != NXT_OK)) { + return ret; } + } - if (acf.set_headers != NULL) { - ret = nxt_http_set_headers_init(rtcf, action, &acf); - if (nxt_slow_path(ret != NXT_OK)) { - return ret; - } + if (acf.set_headers != NULL) { + ret = nxt_http_set_headers_init(rtcf, action, &acf); + if (nxt_slow_path(ret != NXT_OK)) { + return ret; } + } - if (acf.ret != NULL) { - return nxt_http_return_init(rtcf, action, &acf); - } + if (acf.ret != NULL) { + return nxt_http_return_init(rtcf, action, &acf); + } - if (acf.share != NULL) { - return nxt_http_static_init(task, tmcf, action, &acf); - } + if (acf.share != NULL) { + return nxt_http_static_init(task, tmcf, action, &acf); + } - if (acf.proxy != NULL) { - return nxt_http_proxy_init(mp, action, &acf); - } + if (acf.proxy != NULL) { + return nxt_http_proxy_init(mp, action, &acf); + } - nxt_conf_get_string(acf.pass, &pass); + nxt_conf_get_string(acf.pass, &pass); - action->u.tstr = nxt_tstr_compile(rtcf->tstr_state, &pass, 0); - if (nxt_slow_path(action->u.tstr == NULL)) { - return NXT_ERROR; - } + action->u.tstr = nxt_tstr_compile(rtcf->tstr_state, &pass, 0); + if (nxt_slow_path(action->u.tstr == NULL)) { + return NXT_ERROR; + } - return NXT_OK; + return NXT_OK; } +static nxt_http_route_table_t *nxt_http_route_table_create( + nxt_task_t *task, nxt_mp_t *mp, nxt_conf_value_t *table_cv, + nxt_http_route_object_t object, nxt_bool_t case_sensitive, + nxt_http_uri_encoding_t encoding) { + size_t size; + uint32_t i, n; + nxt_conf_value_t *ruleset_cv; + nxt_http_route_table_t *table; + nxt_http_route_ruleset_t *ruleset; + + n = nxt_conf_array_elements_count_or_1(table_cv); + size = + sizeof(nxt_http_route_table_t) + n * sizeof(nxt_http_route_ruleset_t *); + + table = nxt_mp_alloc(mp, size); + if (nxt_slow_path(table == NULL)) { + return NULL; + } -static nxt_http_route_table_t * -nxt_http_route_table_create(nxt_task_t *task, nxt_mp_t *mp, - nxt_conf_value_t *table_cv, nxt_http_route_object_t object, - nxt_bool_t case_sensitive, nxt_http_uri_encoding_t encoding) -{ - size_t size; - uint32_t i, n; - nxt_conf_value_t *ruleset_cv; - nxt_http_route_table_t *table; - nxt_http_route_ruleset_t *ruleset; + table->items = n; + table->object = NXT_HTTP_ROUTE_TABLE; - n = nxt_conf_array_elements_count_or_1(table_cv); - size = sizeof(nxt_http_route_table_t) - + n * sizeof(nxt_http_route_ruleset_t *); + for (i = 0; i < n; i++) { + ruleset_cv = nxt_conf_get_array_element_or_itself(table_cv, i); - table = nxt_mp_alloc(mp, size); - if (nxt_slow_path(table == NULL)) { - return NULL; + ruleset = nxt_http_route_ruleset_create(task, mp, ruleset_cv, object, + case_sensitive, encoding); + if (nxt_slow_path(ruleset == NULL)) { + return NULL; } - table->items = n; - table->object = NXT_HTTP_ROUTE_TABLE; - - for (i = 0; i < n; i++) { - ruleset_cv = nxt_conf_get_array_element_or_itself(table_cv, i); - - ruleset = nxt_http_route_ruleset_create(task, mp, ruleset_cv, object, - case_sensitive, encoding); - if (nxt_slow_path(ruleset == NULL)) { - return NULL; - } + table->ruleset[i] = ruleset; + } - table->ruleset[i] = ruleset; - } - - return table; + return table; } +static nxt_http_route_ruleset_t *nxt_http_route_ruleset_create( + nxt_task_t *task, nxt_mp_t *mp, nxt_conf_value_t *ruleset_cv, + nxt_http_route_object_t object, nxt_bool_t case_sensitive, + nxt_http_uri_encoding_t encoding) { + size_t size; + uint32_t i, n, next; + nxt_str_t name; + nxt_conf_value_t *rule_cv; + nxt_http_route_rule_t *rule; + nxt_http_route_ruleset_t *ruleset; + + n = nxt_conf_object_members_count(ruleset_cv); + size = sizeof(nxt_http_route_ruleset_t) + n * sizeof(nxt_http_route_rule_t *); + + ruleset = nxt_mp_alloc(mp, size); + if (nxt_slow_path(ruleset == NULL)) { + return NULL; + } -static nxt_http_route_ruleset_t * -nxt_http_route_ruleset_create(nxt_task_t *task, nxt_mp_t *mp, - nxt_conf_value_t *ruleset_cv, nxt_http_route_object_t object, - nxt_bool_t case_sensitive, nxt_http_uri_encoding_t encoding) -{ - size_t size; - uint32_t i, n, next; - nxt_str_t name; - nxt_conf_value_t *rule_cv; - nxt_http_route_rule_t *rule; - nxt_http_route_ruleset_t *ruleset; - - n = nxt_conf_object_members_count(ruleset_cv); - size = sizeof(nxt_http_route_ruleset_t) - + n * sizeof(nxt_http_route_rule_t *); - - ruleset = nxt_mp_alloc(mp, size); - if (nxt_slow_path(ruleset == NULL)) { - return NULL; - } - - ruleset->items = n; - - next = 0; + ruleset->items = n; - /* - * A workaround for GCC 10 with -flto -O2 flags that warns about "name" - * may be uninitialized in nxt_http_route_rule_name_create(). - */ - nxt_str_null(&name); + next = 0; - for (i = 0; i < n; i++) { - rule_cv = nxt_conf_next_object_member(ruleset_cv, &name, &next); + /* + * A workaround for GCC 10 with -flto -O2 flags that warns about "name" + * may be uninitialized in nxt_http_route_rule_name_create(). + */ + nxt_str_null(&name); - rule = nxt_http_route_rule_name_create(task, mp, rule_cv, &name, - case_sensitive, encoding); - if (nxt_slow_path(rule == NULL)) { - return NULL; - } + for (i = 0; i < n; i++) { + rule_cv = nxt_conf_next_object_member(ruleset_cv, &name, &next); - rule->object = object; - ruleset->rule[i] = rule; + rule = nxt_http_route_rule_name_create(task, mp, rule_cv, &name, + case_sensitive, encoding); + if (nxt_slow_path(rule == NULL)) { + return NULL; } - return ruleset; + rule->object = object; + ruleset->rule[i] = rule; + } + + return ruleset; } +static nxt_http_route_rule_t *nxt_http_route_rule_name_create( + nxt_task_t *task, nxt_mp_t *mp, nxt_conf_value_t *rule_cv, nxt_str_t *name, + nxt_bool_t case_sensitive, nxt_http_uri_encoding_t encoding) { + int64_t hash; + nxt_http_route_rule_t *rule; -static nxt_http_route_rule_t * -nxt_http_route_rule_name_create(nxt_task_t *task, nxt_mp_t *mp, - nxt_conf_value_t *rule_cv, nxt_str_t *name, nxt_bool_t case_sensitive, - nxt_http_uri_encoding_t encoding) -{ - int64_t hash; - nxt_http_route_rule_t *rule; - - rule = nxt_http_route_rule_create(task, mp, rule_cv, case_sensitive, - NXT_HTTP_ROUTE_PATTERN_NOCASE, - encoding); - if (nxt_slow_path(rule == NULL)) { - return NULL; - } + rule = nxt_http_route_rule_create(task, mp, rule_cv, case_sensitive, + NXT_HTTP_ROUTE_PATTERN_NOCASE, encoding); + if (nxt_slow_path(rule == NULL)) { + return NULL; + } - hash = nxt_http_field_hash(mp, name, case_sensitive, encoding); - if (nxt_slow_path(hash == -1)) { - return NULL; - } + hash = nxt_http_field_hash(mp, name, case_sensitive, encoding); + if (nxt_slow_path(hash == -1)) { + return NULL; + } - rule->u.name.hash = hash; - rule->u.name.start = name->start; - rule->u.name.length = name->length; + rule->u.name.hash = hash; + rule->u.name.start = name->start; + rule->u.name.length = name->length; - return rule; + return rule; } - static nxt_http_route_rule_t * -nxt_http_route_rule_create(nxt_task_t *task, nxt_mp_t *mp, - nxt_conf_value_t *cv, nxt_bool_t case_sensitive, - nxt_http_route_pattern_case_t pattern_case, - nxt_http_uri_encoding_t encoding) -{ - size_t size; - uint32_t i, n; - nxt_int_t ret; - nxt_conf_value_t *value; - nxt_http_route_rule_t *rule; - nxt_http_route_pattern_t *pattern; - - n = nxt_conf_array_elements_count_or_1(cv); - size = sizeof(nxt_http_route_rule_t) + n * sizeof(nxt_http_route_pattern_t); - - rule = nxt_mp_alloc(mp, size); - if (nxt_slow_path(rule == NULL)) { - return NULL; - } +nxt_http_route_rule_create(nxt_task_t *task, nxt_mp_t *mp, nxt_conf_value_t *cv, + nxt_bool_t case_sensitive, + nxt_http_route_pattern_case_t pattern_case, + nxt_http_uri_encoding_t encoding) { + size_t size; + uint32_t i, n; + nxt_int_t ret; + nxt_conf_value_t *value; + nxt_http_route_rule_t *rule; + nxt_http_route_pattern_t *pattern; + + n = nxt_conf_array_elements_count_or_1(cv); + size = sizeof(nxt_http_route_rule_t) + n * sizeof(nxt_http_route_pattern_t); + + rule = nxt_mp_alloc(mp, size); + if (nxt_slow_path(rule == NULL)) { + return NULL; + } - rule->items = n; + rule->items = n; - pattern = &rule->pattern[0]; + pattern = &rule->pattern[0]; - nxt_conf_array_qsort(cv, nxt_http_pattern_compare); + nxt_conf_array_qsort(cv, nxt_http_pattern_compare); - for (i = 0; i < n; i++) { - pattern[i].case_sensitive = case_sensitive; - value = nxt_conf_get_array_element_or_itself(cv, i); + for (i = 0; i < n; i++) { + pattern[i].case_sensitive = case_sensitive; + value = nxt_conf_get_array_element_or_itself(cv, i); - ret = nxt_http_route_pattern_create(task, mp, value, &pattern[i], - pattern_case, encoding); - if (nxt_slow_path(ret != NXT_OK)) { - return NULL; - } + ret = nxt_http_route_pattern_create(task, mp, value, &pattern[i], + pattern_case, encoding); + if (nxt_slow_path(ret != NXT_OK)) { + return NULL; } + } - return rule; + return rule; } - nxt_http_route_addr_rule_t * nxt_http_route_addr_rule_create(nxt_task_t *task, nxt_mp_t *mp, - nxt_conf_value_t *cv) -{ - size_t size; - uint32_t i, n; - nxt_conf_value_t *value; - nxt_http_route_addr_rule_t *addr_rule; - nxt_http_route_addr_pattern_t *pattern; + nxt_conf_value_t *cv) { + size_t size; + uint32_t i, n; + nxt_conf_value_t *value; + nxt_http_route_addr_rule_t *addr_rule; + nxt_http_route_addr_pattern_t *pattern; - n = nxt_conf_array_elements_count_or_1(cv); + n = nxt_conf_array_elements_count_or_1(cv); - size = sizeof(nxt_http_route_addr_rule_t) - + n * sizeof(nxt_http_route_addr_pattern_t); + size = sizeof(nxt_http_route_addr_rule_t) + + n * sizeof(nxt_http_route_addr_pattern_t); - addr_rule = nxt_mp_alloc(mp, size); - if (nxt_slow_path(addr_rule == NULL)) { - return NULL; - } + addr_rule = nxt_mp_alloc(mp, size); + if (nxt_slow_path(addr_rule == NULL)) { + return NULL; + } - addr_rule->items = n; + addr_rule->items = n; - for (i = 0; i < n; i++) { - pattern = &addr_rule->addr_pattern[i]; - value = nxt_conf_get_array_element_or_itself(cv, i); + for (i = 0; i < n; i++) { + pattern = &addr_rule->addr_pattern[i]; + value = nxt_conf_get_array_element_or_itself(cv, i); - if (nxt_http_route_addr_pattern_parse(mp, pattern, value) != NXT_OK) { - return NULL; - } + if (nxt_http_route_addr_pattern_parse(mp, pattern, value) != NXT_OK) { + return NULL; } + } - if (n > 1) { - nxt_qsort(addr_rule->addr_pattern, addr_rule->items, - sizeof(nxt_http_route_addr_pattern_t), - nxt_http_addr_pattern_compare); - } + if (n > 1) { + nxt_qsort(addr_rule->addr_pattern, addr_rule->items, + sizeof(nxt_http_route_addr_pattern_t), + nxt_http_addr_pattern_compare); + } - return addr_rule; + return addr_rule; } - nxt_http_route_rule_t * nxt_http_route_types_rule_create(nxt_task_t *task, nxt_mp_t *mp, - nxt_conf_value_t *types) -{ - return nxt_http_route_rule_create(task, mp, types, 0, - NXT_HTTP_ROUTE_PATTERN_LOWCASE, - NXT_HTTP_URI_ENCODING_NONE); + nxt_conf_value_t *types) { + return nxt_http_route_rule_create(task, mp, types, 0, + NXT_HTTP_ROUTE_PATTERN_LOWCASE, + NXT_HTTP_URI_ENCODING_NONE); } +static int nxt_http_pattern_compare(const void *one, const void *two) { + nxt_str_t test; + nxt_bool_t negative1, negative2; + nxt_conf_value_t *value; -static int -nxt_http_pattern_compare(const void *one, const void *two) -{ - nxt_str_t test; - nxt_bool_t negative1, negative2; - nxt_conf_value_t *value; + value = (nxt_conf_value_t *)one; + nxt_conf_get_string(value, &test); + negative1 = (test.length != 0 && test.start[0] == '!'); - value = (nxt_conf_value_t *) one; - nxt_conf_get_string(value, &test); - negative1 = (test.length != 0 && test.start[0] == '!'); + value = (nxt_conf_value_t *)two; + nxt_conf_get_string(value, &test); + negative2 = (test.length != 0 && test.start[0] == '!'); - value = (nxt_conf_value_t *) two; - nxt_conf_get_string(value, &test); - negative2 = (test.length != 0 && test.start[0] == '!'); - - return (negative2 - negative1); + return (negative2 - negative1); } +static int nxt_http_addr_pattern_compare(const void *one, const void *two) { + const nxt_http_route_addr_pattern_t *p1, *p2; -static int -nxt_http_addr_pattern_compare(const void *one, const void *two) -{ - const nxt_http_route_addr_pattern_t *p1, *p2; - - p1 = one; - p2 = two; + p1 = one; + p2 = two; - return (p2->base.negative - p1->base.negative); + return (p2->base.negative - p1->base.negative); } - static nxt_int_t nxt_http_route_pattern_create(nxt_task_t *task, nxt_mp_t *mp, - nxt_conf_value_t *cv, nxt_http_route_pattern_t *pattern, - nxt_http_route_pattern_case_t pattern_case, - nxt_http_uri_encoding_t encoding) -{ - u_char c, *p, *end; - nxt_str_t test, tmp; - nxt_int_t ret; - nxt_array_t *slices; + nxt_conf_value_t *cv, + nxt_http_route_pattern_t *pattern, + nxt_http_route_pattern_case_t pattern_case, + nxt_http_uri_encoding_t encoding) { + u_char c, *p, *end; + nxt_str_t test, tmp; + nxt_int_t ret; + nxt_array_t *slices; #if (NXT_HAVE_REGEX) - nxt_regex_t *re; - nxt_regex_err_t err; + nxt_regex_t *re; + nxt_regex_err_t err; #endif - nxt_http_route_pattern_type_t type; - nxt_http_route_pattern_slice_t *slice; + nxt_http_route_pattern_type_t type; + nxt_http_route_pattern_slice_t *slice; - type = NXT_HTTP_ROUTE_PATTERN_EXACT; + type = NXT_HTTP_ROUTE_PATTERN_EXACT; - nxt_conf_get_string(cv, &test); + nxt_conf_get_string(cv, &test); - pattern->u.pattern_slices = NULL; - pattern->negative = 0; - pattern->any = 1; - pattern->min_length = 0; + pattern->u.pattern_slices = NULL; + pattern->negative = 0; + pattern->any = 1; + pattern->min_length = 0; #if (NXT_HAVE_REGEX) - pattern->regex = 0; + pattern->regex = 0; #endif - if (test.length != 0 && test.start[0] == '!') { - test.start++; - test.length--; + if (test.length != 0 && test.start[0] == '!') { + test.start++; + test.length--; - pattern->negative = 1; - pattern->any = 0; - } + pattern->negative = 1; + pattern->any = 0; + } - if (test.length > 0 && test.start[0] == '~') { + if (test.length > 0 && test.start[0] == '~') { #if (NXT_HAVE_REGEX) - test.start++; - test.length--; - - re = nxt_regex_compile(mp, &test, &err); - if (nxt_slow_path(re == NULL)) { - if (err.offset < test.length) { - nxt_alert(task, "nxt_regex_compile(%V) failed: %s at offset %d", - &test, err.msg, (int) err.offset); - return NXT_ERROR; - } + test.start++; + test.length--; + + re = nxt_regex_compile(mp, &test, &err); + if (nxt_slow_path(re == NULL)) { + if (err.offset < test.length) { + nxt_alert(task, "nxt_regex_compile(%V) failed: %s at offset %d", &test, + err.msg, (int)err.offset); + return NXT_ERROR; + } - nxt_alert(task, "nxt_regex_compile(%V) failed %s", &test, err.msg); + nxt_alert(task, "nxt_regex_compile(%V) failed %s", &test, err.msg); - return NXT_ERROR; - } + return NXT_ERROR; + } - pattern->u.regex = re; - pattern->regex = 1; + pattern->u.regex = re; + pattern->regex = 1; - return NXT_OK; + return NXT_OK; #else - return NXT_ERROR; + return NXT_ERROR; #endif - } - - slices = nxt_array_create(mp, 1, sizeof(nxt_http_route_pattern_slice_t)); - if (nxt_slow_path(slices == NULL)) { - return NXT_ERROR; - } + } - pattern->u.pattern_slices = slices; + slices = nxt_array_create(mp, 1, sizeof(nxt_http_route_pattern_slice_t)); + if (nxt_slow_path(slices == NULL)) { + return NXT_ERROR; + } - if (test.length == 0) { - slice = nxt_array_add(slices); - if (nxt_slow_path(slice == NULL)) { - return NXT_ERROR; - } - - slice->type = NXT_HTTP_ROUTE_PATTERN_EXACT; - slice->start = NULL; - slice->length = 0; + pattern->u.pattern_slices = slices; - return NXT_OK; + if (test.length == 0) { + slice = nxt_array_add(slices); + if (nxt_slow_path(slice == NULL)) { + return NXT_ERROR; } - if (test.start[0] == '*') { - /* 'type' is no longer 'EXACT', assume 'END'. */ - type = NXT_HTTP_ROUTE_PATTERN_END; - test.start++; - test.length--; - } + slice->type = NXT_HTTP_ROUTE_PATTERN_EXACT; + slice->start = NULL; + slice->length = 0; - if (type == NXT_HTTP_ROUTE_PATTERN_EXACT) { - tmp.start = test.start; + return NXT_OK; + } - p = memchr(test.start, '*', test.length); + if (test.start[0] == '*') { + /* 'type' is no longer 'EXACT', assume 'END'. */ + type = NXT_HTTP_ROUTE_PATTERN_END; + test.start++; + test.length--; + } - if (p == NULL) { - /* No '*' found - EXACT pattern. */ - tmp.length = test.length; - type = NXT_HTTP_ROUTE_PATTERN_EXACT; + if (type == NXT_HTTP_ROUTE_PATTERN_EXACT) { + tmp.start = test.start; - test.start += test.length; - test.length = 0; + p = memchr(test.start, '*', test.length); - } else { - /* '*' found - BEGIN pattern. */ - tmp.length = p - test.start; - type = NXT_HTTP_ROUTE_PATTERN_BEGIN; + if (p == NULL) { + /* No '*' found - EXACT pattern. */ + tmp.length = test.length; + type = NXT_HTTP_ROUTE_PATTERN_EXACT; - test.start = p + 1; - test.length -= tmp.length + 1; - } + test.start += test.length; + test.length = 0; - ret = nxt_http_route_pattern_slice(slices, &tmp, type, encoding, - pattern_case); - if (nxt_slow_path(ret != NXT_OK)) { - return ret; - } + } else { + /* '*' found - BEGIN pattern. */ + tmp.length = p - test.start; + type = NXT_HTTP_ROUTE_PATTERN_BEGIN; - pattern->min_length += tmp.length; + test.start = p + 1; + test.length -= tmp.length + 1; } - end = test.start + test.length; - - if (test.length != 0 && end[-1] != '*') { - p = end - 1; - - while (p != test.start) { - c = *p--; + ret = nxt_http_route_pattern_slice(slices, &tmp, type, encoding, + pattern_case); + if (nxt_slow_path(ret != NXT_OK)) { + return ret; + } - if (c == '*') { - p += 2; - break; - } - } + pattern->min_length += tmp.length; + } - tmp.start = p; - tmp.length = end - p; + end = test.start + test.length; - test.length -= tmp.length; - end = p; + if (test.length != 0 && end[-1] != '*') { + p = end - 1; - ret = nxt_http_route_pattern_slice(slices, &tmp, - NXT_HTTP_ROUTE_PATTERN_END, - encoding, pattern_case); - if (nxt_slow_path(ret != NXT_OK)) { - return ret; - } + while (p != test.start) { + c = *p--; - pattern->min_length += tmp.length; + if (c == '*') { + p += 2; + break; + } } - tmp.start = test.start; - tmp.length = 0; + tmp.start = p; + tmp.length = end - p; - p = tmp.start; + test.length -= tmp.length; + end = p; - while (p != end) { - c = *p++; + ret = nxt_http_route_pattern_slice(slices, &tmp, NXT_HTTP_ROUTE_PATTERN_END, + encoding, pattern_case); + if (nxt_slow_path(ret != NXT_OK)) { + return ret; + } - if (c != '*') { - tmp.length++; - continue; - } + pattern->min_length += tmp.length; + } - if (tmp.length == 0) { - tmp.start = p; - continue; - } + tmp.start = test.start; + tmp.length = 0; - ret = nxt_http_route_pattern_slice(slices, &tmp, - NXT_HTTP_ROUTE_PATTERN_SUBSTRING, - encoding, pattern_case); - if (nxt_slow_path(ret != NXT_OK)) { - return ret; - } + p = tmp.start; - pattern->min_length += tmp.length; + while (p != end) { + c = *p++; - tmp.start = p; - tmp.length = 0; + if (c != '*') { + tmp.length++; + continue; } - if (tmp.length != 0) { - ret = nxt_http_route_pattern_slice(slices, &tmp, - NXT_HTTP_ROUTE_PATTERN_SUBSTRING, - encoding, pattern_case); - if (nxt_slow_path(ret != NXT_OK)) { - return ret; - } + if (tmp.length == 0) { + tmp.start = p; + continue; + } - pattern->min_length += tmp.length; + ret = nxt_http_route_pattern_slice( + slices, &tmp, NXT_HTTP_ROUTE_PATTERN_SUBSTRING, encoding, pattern_case); + if (nxt_slow_path(ret != NXT_OK)) { + return ret; } - return NXT_OK; -} + pattern->min_length += tmp.length; + tmp.start = p; + tmp.length = 0; + } -static nxt_int_t -nxt_http_route_decode_str(nxt_str_t *str, nxt_http_uri_encoding_t encoding) -{ - u_char *start, *end; + if (tmp.length != 0) { + ret = nxt_http_route_pattern_slice( + slices, &tmp, NXT_HTTP_ROUTE_PATTERN_SUBSTRING, encoding, pattern_case); + if (nxt_slow_path(ret != NXT_OK)) { + return ret; + } - switch (encoding) { - case NXT_HTTP_URI_ENCODING_NONE: - break; + pattern->min_length += tmp.length; + } - case NXT_HTTP_URI_ENCODING: - start = str->start; + return NXT_OK; +} - end = nxt_decode_uri(start, start, str->length); - if (nxt_slow_path(end == NULL)) { - return NXT_ERROR; - } +static nxt_int_t nxt_http_route_decode_str(nxt_str_t *str, + nxt_http_uri_encoding_t encoding) { + u_char *start, *end; - str->length = end - start; - break; + switch (encoding) { + case NXT_HTTP_URI_ENCODING_NONE: + break; - case NXT_HTTP_URI_ENCODING_PLUS: - start = str->start; + case NXT_HTTP_URI_ENCODING: + start = str->start; - end = nxt_decode_uri_plus(start, start, str->length); - if (nxt_slow_path(end == NULL)) { - return NXT_ERROR; - } + end = nxt_decode_uri(start, start, str->length); + if (nxt_slow_path(end == NULL)) { + return NXT_ERROR; + } - str->length = end - start; - break; + str->length = end - start; + break; - default: - nxt_unreachable(); + case NXT_HTTP_URI_ENCODING_PLUS: + start = str->start; + + end = nxt_decode_uri_plus(start, start, str->length); + if (nxt_slow_path(end == NULL)) { + return NXT_ERROR; } - return NXT_OK; -} + str->length = end - start; + break; + + default: + nxt_unreachable(); + } + return NXT_OK; +} static nxt_int_t -nxt_http_route_pattern_slice(nxt_array_t *slices, - nxt_str_t *test, nxt_http_route_pattern_type_t type, - nxt_http_uri_encoding_t encoding, - nxt_http_route_pattern_case_t pattern_case) -{ - u_char *start; - nxt_int_t ret; - nxt_http_route_pattern_slice_t *slice; - - ret = nxt_http_route_decode_str(test, encoding); - if (nxt_slow_path(ret != NXT_OK)) { - return ret; - } +nxt_http_route_pattern_slice(nxt_array_t *slices, nxt_str_t *test, + nxt_http_route_pattern_type_t type, + nxt_http_uri_encoding_t encoding, + nxt_http_route_pattern_case_t pattern_case) { + u_char *start; + nxt_int_t ret; + nxt_http_route_pattern_slice_t *slice; + + ret = nxt_http_route_decode_str(test, encoding); + if (nxt_slow_path(ret != NXT_OK)) { + return ret; + } - start = nxt_mp_nget(slices->mem_pool, test->length); - if (nxt_slow_path(start == NULL)) { - return NXT_ERROR; - } + start = nxt_mp_nget(slices->mem_pool, test->length); + if (nxt_slow_path(start == NULL)) { + return NXT_ERROR; + } - switch (pattern_case) { + switch (pattern_case) { - case NXT_HTTP_ROUTE_PATTERN_UPCASE: - nxt_memcpy_upcase(start, test->start, test->length); - break; + case NXT_HTTP_ROUTE_PATTERN_UPCASE: + nxt_memcpy_upcase(start, test->start, test->length); + break; - case NXT_HTTP_ROUTE_PATTERN_LOWCASE: - nxt_memcpy_lowcase(start, test->start, test->length); - break; + case NXT_HTTP_ROUTE_PATTERN_LOWCASE: + nxt_memcpy_lowcase(start, test->start, test->length); + break; - case NXT_HTTP_ROUTE_PATTERN_NOCASE: - nxt_memcpy(start, test->start, test->length); - break; - } + case NXT_HTTP_ROUTE_PATTERN_NOCASE: + nxt_memcpy(start, test->start, test->length); + break; + } - slice = nxt_array_add(slices); - if (nxt_slow_path(slice == NULL)) { - return NXT_ERROR; - } + slice = nxt_array_add(slices); + if (nxt_slow_path(slice == NULL)) { + return NXT_ERROR; + } - slice->type = type; - slice->start = start; - slice->length = test->length; + slice->type = type; + slice->start = start; + slice->length = test->length; - return NXT_OK; + return NXT_OK; } +nxt_int_t nxt_http_routes_resolve(nxt_task_t *task, + nxt_router_temp_conf_t *tmcf) { + nxt_int_t ret; + nxt_http_route_t **route, **end; + nxt_http_routes_t *routes; -nxt_int_t -nxt_http_routes_resolve(nxt_task_t *task, nxt_router_temp_conf_t *tmcf) -{ - nxt_int_t ret; - nxt_http_route_t **route, **end; - nxt_http_routes_t *routes; - - routes = tmcf->router_conf->routes; + routes = tmcf->router_conf->routes; - if (routes != NULL) { - route = &routes->route[0]; - end = route + routes->items; + if (routes != NULL) { + route = &routes->route[0]; + end = route + routes->items; - while (route < end) { - ret = nxt_http_route_resolve(task, tmcf, *route); - if (nxt_slow_path(ret != NXT_OK)) { - return NXT_ERROR; - } + while (route < end) { + ret = nxt_http_route_resolve(task, tmcf, *route); + if (nxt_slow_path(ret != NXT_OK)) { + return NXT_ERROR; + } - route++; - } + route++; } + } - return NXT_OK; + return NXT_OK; } +static nxt_int_t nxt_http_route_resolve(nxt_task_t *task, + nxt_router_temp_conf_t *tmcf, + nxt_http_route_t *route) { + nxt_int_t ret; + nxt_http_route_match_t **match, **end; -static nxt_int_t -nxt_http_route_resolve(nxt_task_t *task, nxt_router_temp_conf_t *tmcf, - nxt_http_route_t *route) -{ - nxt_int_t ret; - nxt_http_route_match_t **match, **end; - - match = &route->match[0]; - end = match + route->items; - - while (match < end) { - ret = nxt_http_action_resolve(task, tmcf, &(*match)->action); - if (nxt_slow_path(ret != NXT_OK)) { - return NXT_ERROR; - } + match = &route->match[0]; + end = match + route->items; - match++; + while (match < end) { + ret = nxt_http_action_resolve(task, tmcf, &(*match)->action); + if (nxt_slow_path(ret != NXT_OK)) { + return NXT_ERROR; } - return NXT_OK; -} + match++; + } + return NXT_OK; +} -static nxt_int_t -nxt_http_action_resolve(nxt_task_t *task, nxt_router_temp_conf_t *tmcf, - nxt_http_action_t *action) -{ - nxt_int_t ret; - nxt_str_t pass; - - if (action->handler != NULL) { - if (action->fallback != NULL) { - return nxt_http_action_resolve(task, tmcf, action->fallback); - } +static nxt_int_t nxt_http_action_resolve(nxt_task_t *task, + nxt_router_temp_conf_t *tmcf, + nxt_http_action_t *action) { + nxt_int_t ret; + nxt_str_t pass; - return NXT_OK; + if (action->handler != NULL) { + if (action->fallback != NULL) { + return nxt_http_action_resolve(task, tmcf, action->fallback); } - if (nxt_tstr_is_const(action->u.tstr)) { - nxt_tstr_str(action->u.tstr, &pass); + return NXT_OK; + } - ret = nxt_http_pass_find(tmcf->mem_pool, tmcf->router_conf, &pass, - action); - if (nxt_slow_path(ret != NXT_OK)) { - return NXT_ERROR; - } + if (nxt_tstr_is_const(action->u.tstr)) { + nxt_tstr_str(action->u.tstr, &pass); - } else { - action->handler = nxt_http_pass_var; + ret = nxt_http_pass_find(tmcf->mem_pool, tmcf->router_conf, &pass, action); + if (nxt_slow_path(ret != NXT_OK)) { + return NXT_ERROR; } - return NXT_OK; + } else { + action->handler = nxt_http_pass_var; + } + + return NXT_OK; } +static nxt_http_action_t *nxt_http_pass_var(nxt_task_t *task, + nxt_http_request_t *r, + nxt_http_action_t *action) { + nxt_int_t ret; + nxt_str_t str; + nxt_tstr_t *tstr; + nxt_router_conf_t *rtcf; -static nxt_http_action_t * -nxt_http_pass_var(nxt_task_t *task, nxt_http_request_t *r, - nxt_http_action_t *action) -{ - nxt_int_t ret; - nxt_str_t str; - nxt_tstr_t *tstr; - nxt_router_conf_t *rtcf; + tstr = action->u.tstr; - tstr = action->u.tstr; + nxt_tstr_str(tstr, &str); - nxt_tstr_str(tstr, &str); + nxt_debug(task, "http pass: \"%V\"", &str); - nxt_debug(task, "http pass: \"%V\"", &str); + rtcf = r->conf->socket_conf->router_conf; - rtcf = r->conf->socket_conf->router_conf; + ret = nxt_tstr_query_init(&r->tstr_query, rtcf->tstr_state, &r->tstr_cache, r, + r->mem_pool); + if (nxt_slow_path(ret != NXT_OK)) { + goto fail; + } - ret = nxt_tstr_query_init(&r->tstr_query, rtcf->tstr_state, &r->tstr_cache, - r, r->mem_pool); - if (nxt_slow_path(ret != NXT_OK)) { - goto fail; - } - - action = nxt_mp_zget(r->mem_pool, - sizeof(nxt_http_action_t) + sizeof(nxt_str_t)); - if (nxt_slow_path(action == NULL)) { - goto fail; - } + action = + nxt_mp_zget(r->mem_pool, sizeof(nxt_http_action_t) + sizeof(nxt_str_t)); + if (nxt_slow_path(action == NULL)) { + goto fail; + } - action->u.pass = nxt_pointer_to(action, sizeof(nxt_http_action_t)); + action->u.pass = nxt_pointer_to(action, sizeof(nxt_http_action_t)); - ret = nxt_tstr_query(task, r->tstr_query, tstr, action->u.pass); - if (nxt_slow_path(ret != NXT_OK)) { - goto fail; - } + ret = nxt_tstr_query(task, r->tstr_query, tstr, action->u.pass); + if (nxt_slow_path(ret != NXT_OK)) { + goto fail; + } - nxt_http_pass_query(task, r, action); + nxt_http_pass_query(task, r, action); - return NULL; + return NULL; fail: - nxt_http_request_error(task, r, NXT_HTTP_INTERNAL_SERVER_ERROR); - return NULL; + nxt_http_request_error(task, r, NXT_HTTP_INTERNAL_SERVER_ERROR); + return NULL; } +static void nxt_http_pass_query(nxt_task_t *task, nxt_http_request_t *r, + nxt_http_action_t *action) { + nxt_int_t ret; + nxt_router_conf_t *rtcf; + nxt_http_status_t status; -static void -nxt_http_pass_query(nxt_task_t *task, nxt_http_request_t *r, - nxt_http_action_t *action) -{ - nxt_int_t ret; - nxt_router_conf_t *rtcf; - nxt_http_status_t status; - - rtcf = r->conf->socket_conf->router_conf; + rtcf = r->conf->socket_conf->router_conf; - nxt_debug(task, "http pass lookup: %V", action->u.pass); + nxt_debug(task, "http pass lookup: %V", action->u.pass); - ret = nxt_http_pass_find(r->mem_pool, rtcf, action->u.pass, action); + ret = nxt_http_pass_find(r->mem_pool, rtcf, action->u.pass, action); - if (ret != NXT_OK) { - status = (ret == NXT_DECLINED) ? NXT_HTTP_NOT_FOUND - : NXT_HTTP_INTERNAL_SERVER_ERROR; + if (ret != NXT_OK) { + status = (ret == NXT_DECLINED) ? NXT_HTTP_NOT_FOUND + : NXT_HTTP_INTERNAL_SERVER_ERROR; - nxt_http_request_error(task, r, status); - return; - } + nxt_http_request_error(task, r, status); + return; + } - nxt_http_request_action(task, r, action); + nxt_http_request_action(task, r, action); } +static nxt_int_t nxt_http_pass_find(nxt_mp_t *mp, nxt_router_conf_t *rtcf, + nxt_str_t *pass, + nxt_http_action_t *action) { + nxt_int_t ret; + nxt_str_t segments[3]; -static nxt_int_t -nxt_http_pass_find(nxt_mp_t *mp, nxt_router_conf_t *rtcf, nxt_str_t *pass, - nxt_http_action_t *action) -{ - nxt_int_t ret; - nxt_str_t segments[3]; + ret = nxt_http_pass_segments(mp, pass, segments, 3); + if (nxt_slow_path(ret != NXT_OK)) { + return ret; + } - ret = nxt_http_pass_segments(mp, pass, segments, 3); - if (nxt_slow_path(ret != NXT_OK)) { - return ret; - } + if (nxt_str_eq(&segments[0], "applications", 12)) { + return nxt_router_application_init(rtcf, &segments[1], &segments[2], + action); + } - if (nxt_str_eq(&segments[0], "applications", 12)) { - return nxt_router_application_init(rtcf, &segments[1], &segments[2], - action); + if (segments[2].length == 0) { + if (nxt_str_eq(&segments[0], "upstreams", 9)) { + return nxt_upstream_find(rtcf->upstreams, &segments[1], action); } - if (segments[2].length == 0) { - if (nxt_str_eq(&segments[0], "upstreams", 9)) { - return nxt_upstream_find(rtcf->upstreams, &segments[1], action); - } - - if (nxt_str_eq(&segments[0], "routes", 6)) { - return nxt_http_route_find(rtcf->routes, &segments[1], action); - } + if (nxt_str_eq(&segments[0], "routes", 6)) { + return nxt_http_route_find(rtcf->routes, &segments[1], action); } + } - return NXT_DECLINED; + return NXT_DECLINED; } +nxt_int_t nxt_http_pass_segments(nxt_mp_t *mp, nxt_str_t *pass, + nxt_str_t *segments, nxt_uint_t n) { + u_char *p; + nxt_str_t rest; -nxt_int_t -nxt_http_pass_segments(nxt_mp_t *mp, nxt_str_t *pass, nxt_str_t *segments, - nxt_uint_t n) -{ - u_char *p; - nxt_str_t rest; + if (nxt_slow_path(nxt_str_dup(mp, &rest, pass) == NULL)) { + return NXT_ERROR; + } - if (nxt_slow_path(nxt_str_dup(mp, &rest, pass) == NULL)) { - return NXT_ERROR; - } + nxt_memzero(segments, n * sizeof(nxt_str_t)); - nxt_memzero(segments, n * sizeof(nxt_str_t)); + do { + p = memchr(rest.start, '/', rest.length); - do { - p = memchr(rest.start, '/', rest.length); + if (p != NULL) { + n--; - if (p != NULL) { - n--; - - if (n == 0) { - return NXT_DECLINED; - } + if (n == 0) { + return NXT_DECLINED; + } - segments->length = p - rest.start; - segments->start = rest.start; + segments->length = p - rest.start; + segments->start = rest.start; - rest.length -= segments->length + 1; - rest.start = p + 1; + rest.length -= segments->length + 1; + rest.start = p + 1; - } else { - n = 0; - *segments = rest; - } + } else { + n = 0; + *segments = rest; + } - if (segments->length == 0) { - return NXT_DECLINED; - } + if (segments->length == 0) { + return NXT_DECLINED; + } - p = nxt_decode_uri(segments->start, segments->start, segments->length); - if (p == NULL) { - return NXT_DECLINED; - } + p = nxt_decode_uri(segments->start, segments->start, segments->length); + if (p == NULL) { + return NXT_DECLINED; + } - segments->length = p - segments->start; - segments++; + segments->length = p - segments->start; + segments++; - } while (n); + } while (n); - return NXT_OK; + return NXT_OK; } +static nxt_int_t nxt_http_route_find(nxt_http_routes_t *routes, nxt_str_t *name, + nxt_http_action_t *action) { + nxt_http_route_t **route, **end; -static nxt_int_t -nxt_http_route_find(nxt_http_routes_t *routes, nxt_str_t *name, - nxt_http_action_t *action) -{ - nxt_http_route_t **route, **end; - - if (routes == NULL) { - return NXT_DECLINED; - } - - route = &routes->route[0]; - end = route + routes->items; + if (routes == NULL) { + return NXT_DECLINED; + } - while (route < end) { - if (nxt_strstr_eq(&(*route)->name, name)) { - action->u.route = *route; - action->handler = nxt_http_route_handler; + route = &routes->route[0]; + end = route + routes->items; - return NXT_OK; - } + while (route < end) { + if (nxt_strstr_eq(&(*route)->name, name)) { + action->u.route = *route; + action->handler = nxt_http_route_handler; - route++; + return NXT_OK; } - return NXT_DECLINED; -} + route++; + } + return NXT_DECLINED; +} -nxt_http_action_t * -nxt_http_action_create(nxt_task_t *task, nxt_router_temp_conf_t *tmcf, - nxt_str_t *pass) -{ - nxt_mp_t *mp; - nxt_int_t ret; - nxt_router_conf_t *rtcf; - nxt_http_action_t *action; +nxt_http_action_t *nxt_http_action_create(nxt_task_t *task, + nxt_router_temp_conf_t *tmcf, + nxt_str_t *pass) { + nxt_mp_t *mp; + nxt_int_t ret; + nxt_router_conf_t *rtcf; + nxt_http_action_t *action; - rtcf = tmcf->router_conf; - mp = rtcf->mem_pool; + rtcf = tmcf->router_conf; + mp = rtcf->mem_pool; - action = nxt_mp_zalloc(mp, sizeof(nxt_http_action_t)); - if (nxt_slow_path(action == NULL)) { - return NULL; - } + action = nxt_mp_zalloc(mp, sizeof(nxt_http_action_t)); + if (nxt_slow_path(action == NULL)) { + return NULL; + } - action->u.tstr = nxt_tstr_compile(rtcf->tstr_state, pass, 0); - if (nxt_slow_path(action->u.tstr == NULL)) { - return NULL; - } + action->u.tstr = nxt_tstr_compile(rtcf->tstr_state, pass, 0); + if (nxt_slow_path(action->u.tstr == NULL)) { + return NULL; + } - action->handler = NULL; + action->handler = NULL; - ret = nxt_http_action_resolve(task, tmcf, action); - if (nxt_slow_path(ret != NXT_OK)) { - return NULL; - } + ret = nxt_http_action_resolve(task, tmcf, action); + if (nxt_slow_path(ret != NXT_OK)) { + return NULL; + } - return action; + return action; } - /* COMPATIBILITY: listener application. */ -nxt_http_action_t * -nxt_http_pass_application(nxt_task_t *task, nxt_router_conf_t *rtcf, - nxt_str_t *name) -{ - nxt_http_action_t *action; +nxt_http_action_t *nxt_http_pass_application(nxt_task_t *task, + nxt_router_conf_t *rtcf, + nxt_str_t *name) { + nxt_http_action_t *action; - action = nxt_mp_zalloc(rtcf->mem_pool, sizeof(nxt_http_action_t)); - if (nxt_slow_path(action == NULL)) { - return NULL; - } + action = nxt_mp_zalloc(rtcf->mem_pool, sizeof(nxt_http_action_t)); + if (nxt_slow_path(action == NULL)) { + return NULL; + } - (void) nxt_router_application_init(rtcf, name, NULL, action); + (void)nxt_router_application_init(rtcf, name, NULL, action); - return action; + return action; } +static nxt_http_action_t *nxt_http_route_handler(nxt_task_t *task, + nxt_http_request_t *r, + nxt_http_action_t *start) { + size_t i; + nxt_http_route_t *route; + nxt_http_action_t *action; -static nxt_http_action_t * -nxt_http_route_handler(nxt_task_t *task, nxt_http_request_t *r, - nxt_http_action_t *start) -{ - size_t i; - nxt_http_route_t *route; - nxt_http_action_t *action; - - route = start->u.route; + route = start->u.route; - for (i = 0; i < route->items; i++) { - action = nxt_http_route_match(task, r, route->match[i]); + for (i = 0; i < route->items; i++) { + action = nxt_http_route_match(task, r, route->match[i]); - if (nxt_slow_path(r->log_route)) { - uint32_t lvl = (action == NULL) ? NXT_LOG_INFO : NXT_LOG_NOTICE; - const char *sel = (action == NULL) ? "discarded" : "selected"; + if (nxt_slow_path(r->log_route)) { + uint32_t lvl = (action == NULL) ? NXT_LOG_INFO : NXT_LOG_NOTICE; + const char *sel = (action == NULL) ? "discarded" : "selected"; - if (route->name.length == 0) { - nxt_log(task, lvl, "\"routes/%z\" %s", i, sel); - } else { - nxt_log(task, lvl, "\"routes/%V/%z\" %s", &route->name, i, sel); - } - } + if (route->name.length == 0) { + nxt_log(task, lvl, "\"routes/%z\" %s", i, sel); + } else { + nxt_log(task, lvl, "\"routes/%V/%z\" %s", &route->name, i, sel); + } + } - if (action != NULL) { + if (action != NULL) { - if (action != NXT_HTTP_ACTION_ERROR) { - r->action = action; - } + if (action != NXT_HTTP_ACTION_ERROR) { + r->action = action; + } - return action; - } + return action; } + } - nxt_http_request_error(task, r, NXT_HTTP_NOT_FOUND); + nxt_http_request_error(task, r, NXT_HTTP_NOT_FOUND); - return NULL; + return NULL; } +static nxt_http_action_t *nxt_http_route_match(nxt_task_t *task, + nxt_http_request_t *r, + nxt_http_route_match_t *match) { + nxt_int_t ret; + nxt_http_route_test_t *test, *end; + + ret = nxt_http_cond_value(task, r, &match->condition); + if (ret <= 0) { + /* 0 => NULL, -1 => NXT_HTTP_ACTION_ERROR. */ + return (nxt_http_action_t *)(intptr_t)ret; + } + + test = &match->test[0]; + end = test + match->items; + + while (test < end) { + switch (test->rule->object) { + case NXT_HTTP_ROUTE_TABLE: + ret = nxt_http_route_table(r, test->table); + break; + case NXT_HTTP_ROUTE_SOURCE: + ret = nxt_http_route_addr_rule(r, test->addr_rule, r->remote); + break; + case NXT_HTTP_ROUTE_DESTINATION: + if (r->local == NULL && nxt_fast_path(r->proto.any != NULL)) { + nxt_http_proto[r->protocol].local_addr(task, r); + } + + ret = nxt_http_route_addr_rule(r, test->addr_rule, r->local); + break; + default: + ret = nxt_http_route_rule(r, test->rule); + break; + } -static nxt_http_action_t * -nxt_http_route_match(nxt_task_t *task, nxt_http_request_t *r, - nxt_http_route_match_t *match) -{ - nxt_int_t ret; - nxt_http_route_test_t *test, *end; - - ret = nxt_http_cond_value(task, r, &match->condition); if (ret <= 0) { - /* 0 => NULL, -1 => NXT_HTTP_ACTION_ERROR. */ - return (nxt_http_action_t *) (intptr_t) ret; - } - - test = &match->test[0]; - end = test + match->items; - - while (test < end) { - switch (test->rule->object) { - case NXT_HTTP_ROUTE_TABLE: - ret = nxt_http_route_table(r, test->table); - break; - case NXT_HTTP_ROUTE_SOURCE: - ret = nxt_http_route_addr_rule(r, test->addr_rule, r->remote); - break; - case NXT_HTTP_ROUTE_DESTINATION: - if (r->local == NULL && nxt_fast_path(r->proto.any != NULL)) { - nxt_http_proto[r->protocol].local_addr(task, r); - } - - ret = nxt_http_route_addr_rule(r, test->addr_rule, r->local); - break; - default: - ret = nxt_http_route_rule(r, test->rule); - break; - } - - if (ret <= 0) { - /* 0 => NULL, -1 => NXT_HTTP_ACTION_ERROR. */ - return (nxt_http_action_t *) (intptr_t) ret; - } - - test++; + /* 0 => NULL, -1 => NXT_HTTP_ACTION_ERROR. */ + return (nxt_http_action_t *)(intptr_t)ret; } - return &match->action; -} - + test++; + } -static nxt_int_t -nxt_http_route_table(nxt_http_request_t *r, nxt_http_route_table_t *table) -{ - nxt_int_t ret; - nxt_http_route_ruleset_t **ruleset, **end; + return &match->action; +} - ret = 1; - ruleset = &table->ruleset[0]; - end = ruleset + table->items; +static nxt_int_t nxt_http_route_table(nxt_http_request_t *r, + nxt_http_route_table_t *table) { + nxt_int_t ret; + nxt_http_route_ruleset_t **ruleset, **end; - while (ruleset < end) { - ret = nxt_http_route_ruleset(r, *ruleset); + ret = 1; + ruleset = &table->ruleset[0]; + end = ruleset + table->items; - if (ret != 0) { - return ret; - } + while (ruleset < end) { + ret = nxt_http_route_ruleset(r, *ruleset); - ruleset++; + if (ret != 0) { + return ret; } - return ret; -} - + ruleset++; + } -static nxt_int_t -nxt_http_route_ruleset(nxt_http_request_t *r, nxt_http_route_ruleset_t *ruleset) -{ - nxt_int_t ret; - nxt_http_route_rule_t **rule, **end; + return ret; +} - rule = &ruleset->rule[0]; - end = rule + ruleset->items; +static nxt_int_t nxt_http_route_ruleset(nxt_http_request_t *r, + nxt_http_route_ruleset_t *ruleset) { + nxt_int_t ret; + nxt_http_route_rule_t **rule, **end; - while (rule < end) { - ret = nxt_http_route_rule(r, *rule); + rule = &ruleset->rule[0]; + end = rule + ruleset->items; - if (ret <= 0) { - return ret; - } + while (rule < end) { + ret = nxt_http_route_rule(r, *rule); - rule++; + if (ret <= 0) { + return ret; } - return 1; -} + rule++; + } + return 1; +} -static nxt_int_t -nxt_http_route_rule(nxt_http_request_t *r, nxt_http_route_rule_t *rule) -{ - void *p, **pp; - u_char *start; - size_t length; - nxt_str_t *s; +static nxt_int_t nxt_http_route_rule(nxt_http_request_t *r, + nxt_http_route_rule_t *rule) { + void *p, **pp; + u_char *start; + size_t length; + nxt_str_t *s; - switch (rule->object) { + switch (rule->object) { - case NXT_HTTP_ROUTE_HEADER: - return nxt_http_route_header(r, rule); + case NXT_HTTP_ROUTE_HEADER: + return nxt_http_route_header(r, rule); - case NXT_HTTP_ROUTE_ARGUMENT: - return nxt_http_route_arguments(r, rule); + case NXT_HTTP_ROUTE_ARGUMENT: + return nxt_http_route_arguments(r, rule); - case NXT_HTTP_ROUTE_COOKIE: - return nxt_http_route_cookies(r, rule); + case NXT_HTTP_ROUTE_COOKIE: + return nxt_http_route_cookies(r, rule); - case NXT_HTTP_ROUTE_SCHEME: - return nxt_http_route_scheme(r, rule); + case NXT_HTTP_ROUTE_SCHEME: + return nxt_http_route_scheme(r, rule); - case NXT_HTTP_ROUTE_QUERY: - return nxt_http_route_query(r, rule); + case NXT_HTTP_ROUTE_QUERY: + return nxt_http_route_query(r, rule); - default: - break; - } + default: + break; + } - p = nxt_pointer_to(r, rule->u.offset); + p = nxt_pointer_to(r, rule->u.offset); - if (rule->object == NXT_HTTP_ROUTE_STRING) { - s = p; + if (rule->object == NXT_HTTP_ROUTE_STRING) { + s = p; - } else { - /* NXT_HTTP_ROUTE_STRING_PTR */ - pp = p; - s = *pp; + } else { + /* NXT_HTTP_ROUTE_STRING_PTR */ + pp = p; + s = *pp; - if (s == NULL) { - return 0; - } + if (s == NULL) { + return 0; } + } - length = s->length; - start = s->start; + length = s->length; + start = s->start; - return nxt_http_route_test_rule(r, rule, start, length); + return nxt_http_route_test_rule(r, rule, start, length); } - static nxt_int_t nxt_http_route_addr_pattern_match(nxt_http_route_addr_pattern_t *p, - nxt_sockaddr_t *sa) -{ + nxt_sockaddr_t *sa) { #if (NXT_INET6) - uint32_t i; + uint32_t i; #endif - in_port_t in_port; - nxt_int_t match; - struct sockaddr_in *sin; + in_port_t in_port; + nxt_int_t match; + struct sockaddr_in *sin; #if (NXT_INET6) - struct sockaddr_in6 *sin6; + struct sockaddr_in6 *sin6; #endif - nxt_http_route_addr_base_t *base; + nxt_http_route_addr_base_t *base; - base = &p->base; + base = &p->base; - switch (sa->u.sockaddr.sa_family) { + switch (sa->u.sockaddr.sa_family) { - case AF_INET: + case AF_INET: - match = (base->addr_family == AF_INET - || base->addr_family == AF_UNSPEC); - if (!match) { - break; - } + match = (base->addr_family == AF_INET || base->addr_family == AF_UNSPEC); + if (!match) { + break; + } - sin = &sa->u.sockaddr_in; - in_port = ntohs(sin->sin_port); + sin = &sa->u.sockaddr_in; + in_port = ntohs(sin->sin_port); - match = (in_port >= base->port.start && in_port <= base->port.end); - if (!match) { - break; - } + match = (in_port >= base->port.start && in_port <= base->port.end); + if (!match) { + break; + } - switch (base->match_type) { + switch (base->match_type) { - case NXT_HTTP_ROUTE_ADDR_ANY: - break; + case NXT_HTTP_ROUTE_ADDR_ANY: + break; - case NXT_HTTP_ROUTE_ADDR_EXACT: - match = (memcmp(&sin->sin_addr, &p->addr.v4.start, - sizeof(struct in_addr)) - == 0); - break; + case NXT_HTTP_ROUTE_ADDR_EXACT: + match = (memcmp(&sin->sin_addr, &p->addr.v4.start, + sizeof(struct in_addr)) == 0); + break; - case NXT_HTTP_ROUTE_ADDR_RANGE: - match = (memcmp(&sin->sin_addr, &p->addr.v4.start, - sizeof(struct in_addr)) >= 0 - && memcmp(&sin->sin_addr, &p->addr.v4.end, - sizeof(struct in_addr)) <= 0); - break; + case NXT_HTTP_ROUTE_ADDR_RANGE: + match = (memcmp(&sin->sin_addr, &p->addr.v4.start, + sizeof(struct in_addr)) >= 0 && + memcmp(&sin->sin_addr, &p->addr.v4.end, + sizeof(struct in_addr)) <= 0); + break; - case NXT_HTTP_ROUTE_ADDR_CIDR: - match = ((sin->sin_addr.s_addr & p->addr.v4.end) - == p->addr.v4.start); - break; + case NXT_HTTP_ROUTE_ADDR_CIDR: + match = ((sin->sin_addr.s_addr & p->addr.v4.end) == p->addr.v4.start); + break; - default: - nxt_unreachable(); - } + default: + nxt_unreachable(); + } - break; + break; #if (NXT_INET6) - case AF_INET6: + case AF_INET6: - match = (base->addr_family == AF_INET6 - || base->addr_family == AF_UNSPEC); - if (!match) { - break; - } + match = (base->addr_family == AF_INET6 || base->addr_family == AF_UNSPEC); + if (!match) { + break; + } - sin6 = &sa->u.sockaddr_in6; - in_port = ntohs(sin6->sin6_port); + sin6 = &sa->u.sockaddr_in6; + in_port = ntohs(sin6->sin6_port); - match = (in_port >= base->port.start && in_port <= base->port.end); - if (!match) { - break; - } + match = (in_port >= base->port.start && in_port <= base->port.end); + if (!match) { + break; + } - switch (base->match_type) { + switch (base->match_type) { - case NXT_HTTP_ROUTE_ADDR_ANY: - break; + case NXT_HTTP_ROUTE_ADDR_ANY: + break; - case NXT_HTTP_ROUTE_ADDR_EXACT: - match = (memcmp(&sin6->sin6_addr, &p->addr.v6.start, - sizeof(struct in6_addr)) - == 0); - break; + case NXT_HTTP_ROUTE_ADDR_EXACT: + match = (memcmp(&sin6->sin6_addr, &p->addr.v6.start, + sizeof(struct in6_addr)) == 0); + break; - case NXT_HTTP_ROUTE_ADDR_RANGE: - match = (memcmp(&sin6->sin6_addr, &p->addr.v6.start, - sizeof(struct in6_addr)) >= 0 - && memcmp(&sin6->sin6_addr, &p->addr.v6.end, - sizeof(struct in6_addr)) <= 0); - break; + case NXT_HTTP_ROUTE_ADDR_RANGE: + match = (memcmp(&sin6->sin6_addr, &p->addr.v6.start, + sizeof(struct in6_addr)) >= 0 && + memcmp(&sin6->sin6_addr, &p->addr.v6.end, + sizeof(struct in6_addr)) <= 0); + break; - case NXT_HTTP_ROUTE_ADDR_CIDR: - for (i = 0; i < 16; i++) { - match = ((sin6->sin6_addr.s6_addr[i] - & p->addr.v6.end.s6_addr[i]) - == p->addr.v6.start.s6_addr[i]); + case NXT_HTTP_ROUTE_ADDR_CIDR: + for (i = 0; i < 16; i++) { + match = ((sin6->sin6_addr.s6_addr[i] & p->addr.v6.end.s6_addr[i]) == + p->addr.v6.start.s6_addr[i]); - if (!match) { - break; - } - } + if (!match) { + break; + } + } - break; + break; - default: - nxt_unreachable(); - } + default: + nxt_unreachable(); + } - break; + break; #endif #if (NXT_HAVE_UNIX_DOMAIN) - case AF_UNIX: + case AF_UNIX: - match = (base->addr_family == AF_UNIX); - break; + match = (base->addr_family == AF_UNIX); + break; #endif - default: - match = 0; - break; - } + default: + match = 0; + break; + } - return match ^ base->negative; + return match ^ base->negative; } +nxt_int_t nxt_http_route_addr_rule(nxt_http_request_t *r, + nxt_http_route_addr_rule_t *addr_rule, + nxt_sockaddr_t *sa) { + uint32_t n; + nxt_bool_t matches; + nxt_http_route_addr_pattern_t *p; -nxt_int_t -nxt_http_route_addr_rule(nxt_http_request_t *r, - nxt_http_route_addr_rule_t *addr_rule, nxt_sockaddr_t *sa) -{ - uint32_t n; - nxt_bool_t matches; - nxt_http_route_addr_pattern_t *p; + n = addr_rule->items; - n = addr_rule->items; + if (n == 0) { + return 0; + } - if (n == 0) { - return 0; - } + p = &addr_rule->addr_pattern[0] - 1; - p = &addr_rule->addr_pattern[0] - 1; + do { + p++; + n--; - do { - p++; - n--; + matches = nxt_http_route_addr_pattern_match(p, sa); - matches = nxt_http_route_addr_pattern_match(p, sa); + if (p->base.negative) { + if (matches) { + continue; + } - if (p->base.negative) { - if (matches) { - continue; - } - - return 0; - } + return 0; + } - if (matches) { - return 1; - } + if (matches) { + return 1; + } - } while (n > 0); + } while (n > 0); - return p->base.negative; + return p->base.negative; } +static nxt_int_t nxt_http_route_header(nxt_http_request_t *r, + nxt_http_route_rule_t *rule) { + nxt_int_t ret; + nxt_http_field_t *f; -static nxt_int_t -nxt_http_route_header(nxt_http_request_t *r, nxt_http_route_rule_t *rule) -{ - nxt_int_t ret; - nxt_http_field_t *f; + ret = 0; - ret = 0; + nxt_list_each(f, r->fields) { - nxt_list_each(f, r->fields) { + if (rule->u.name.hash != f->hash || rule->u.name.length != f->name_length || + nxt_strncasecmp(rule->u.name.start, f->name, f->name_length) != 0) { + continue; + } - if (rule->u.name.hash != f->hash - || rule->u.name.length != f->name_length - || nxt_strncasecmp(rule->u.name.start, f->name, f->name_length) - != 0) - { - continue; - } + ret = nxt_http_route_test_rule(r, rule, f->value, f->value_length); + if (nxt_slow_path(ret == NXT_ERROR)) { + return NXT_ERROR; + } - ret = nxt_http_route_test_rule(r, rule, f->value, f->value_length); - if (nxt_slow_path(ret == NXT_ERROR)) { - return NXT_ERROR; - } + if (ret == 0) { + return ret; + } + } + nxt_list_loop; - if (ret == 0) { - return ret; - } + return ret; +} + +static nxt_int_t nxt_http_route_arguments(nxt_http_request_t *r, + nxt_http_route_rule_t *rule) { + nxt_array_t *arguments; - } nxt_list_loop; + arguments = nxt_http_arguments_parse(r); + if (nxt_slow_path(arguments == NULL)) { + return -1; + } - return ret; + return nxt_http_route_test_argument(r, rule, arguments); } +static nxt_int_t nxt_http_route_test_argument(nxt_http_request_t *r, + nxt_http_route_rule_t *rule, + nxt_array_t *array) { + nxt_int_t ret; + nxt_http_name_value_t *nv, *end; -static nxt_int_t -nxt_http_route_arguments(nxt_http_request_t *r, nxt_http_route_rule_t *rule) -{ - nxt_array_t *arguments; - - arguments = nxt_http_arguments_parse(r); - if (nxt_slow_path(arguments == NULL)) { - return -1; - } + ret = 0; - return nxt_http_route_test_argument(r, rule, arguments); -} + nv = array->elts; + end = nv + array->nelts; + while (nv < end) { -static nxt_int_t -nxt_http_route_test_argument(nxt_http_request_t *r, - nxt_http_route_rule_t *rule, nxt_array_t *array) -{ - nxt_int_t ret; - nxt_http_name_value_t *nv, *end; - - ret = 0; - - nv = array->elts; - end = nv + array->nelts; - - while (nv < end) { - - if (rule->u.name.hash == nv->hash - && rule->u.name.length == nv->name_length - && memcmp(rule->u.name.start, nv->name, nv->name_length) == 0) - { - ret = nxt_http_route_test_rule(r, rule, nv->value, - nv->value_length); - if (nxt_slow_path(ret == NXT_ERROR)) { - return NXT_ERROR; - } - - if (ret == 0) { - break; - } - } + if (rule->u.name.hash == nv->hash && + rule->u.name.length == nv->name_length && + memcmp(rule->u.name.start, nv->name, nv->name_length) == 0) { + ret = nxt_http_route_test_rule(r, rule, nv->value, nv->value_length); + if (nxt_slow_path(ret == NXT_ERROR)) { + return NXT_ERROR; + } - nv++; + if (ret == 0) { + break; + } } - return ret; -} + nv++; + } + return ret; +} -static nxt_int_t -nxt_http_route_scheme(nxt_http_request_t *r, nxt_http_route_rule_t *rule) -{ - nxt_bool_t https; - nxt_http_route_pattern_slice_t *pattern_slice; +static nxt_int_t nxt_http_route_scheme(nxt_http_request_t *r, + nxt_http_route_rule_t *rule) { + nxt_bool_t https; + nxt_http_route_pattern_slice_t *pattern_slice; - pattern_slice = rule->pattern[0].u.pattern_slices->elts; - https = (pattern_slice->length == nxt_length("https")); + pattern_slice = rule->pattern[0].u.pattern_slices->elts; + https = (pattern_slice->length == nxt_length("https")); - return (r->tls == https); + return (r->tls == https); } +static nxt_int_t nxt_http_route_query(nxt_http_request_t *r, + nxt_http_route_rule_t *rule) { + nxt_array_t *arguments; -static nxt_int_t -nxt_http_route_query(nxt_http_request_t *r, nxt_http_route_rule_t *rule) -{ - nxt_array_t *arguments; - - arguments = nxt_http_arguments_parse(r); - if (nxt_slow_path(arguments == NULL)) { - return -1; - } + arguments = nxt_http_arguments_parse(r); + if (nxt_slow_path(arguments == NULL)) { + return -1; + } - return nxt_http_route_test_rule(r, rule, r->args_decoded.start, - r->args_decoded.length); + return nxt_http_route_test_rule(r, rule, r->args_decoded.start, + r->args_decoded.length); } +static nxt_int_t nxt_http_route_cookies(nxt_http_request_t *r, + nxt_http_route_rule_t *rule) { + nxt_array_t *cookies; -static nxt_int_t -nxt_http_route_cookies(nxt_http_request_t *r, nxt_http_route_rule_t *rule) -{ - nxt_array_t *cookies; - - cookies = nxt_http_cookies_parse(r); - if (nxt_slow_path(cookies == NULL)) { - return -1; - } + cookies = nxt_http_cookies_parse(r); + if (nxt_slow_path(cookies == NULL)) { + return -1; + } - return nxt_http_route_test_cookie(r, rule, cookies); + return nxt_http_route_test_cookie(r, rule, cookies); } +static nxt_int_t nxt_http_route_test_cookie(nxt_http_request_t *r, + nxt_http_route_rule_t *rule, + nxt_array_t *array) { + nxt_int_t ret; + nxt_http_name_value_t *nv, *end; -static nxt_int_t -nxt_http_route_test_cookie(nxt_http_request_t *r, - nxt_http_route_rule_t *rule, nxt_array_t *array) -{ - nxt_int_t ret; - nxt_http_name_value_t *nv, *end; - - ret = 0; - - nv = array->elts; - end = nv + array->nelts; - - while (nv < end) { - - if (rule->u.name.hash == nv->hash - && rule->u.name.length == nv->name_length - && memcmp(rule->u.name.start, nv->name, nv->name_length) == 0) - { - ret = nxt_http_route_test_rule(r, rule, nv->value, - nv->value_length); - if (nxt_slow_path(ret == NXT_ERROR)) { - return NXT_ERROR; - } - - if (ret == 0) { - break; - } - } + ret = 0; - nv++; - } + nv = array->elts; + end = nv + array->nelts; - return ret; -} + while (nv < end) { + if (rule->u.name.hash == nv->hash && + rule->u.name.length == nv->name_length && + memcmp(rule->u.name.start, nv->name, nv->name_length) == 0) { + ret = nxt_http_route_test_rule(r, rule, nv->value, nv->value_length); + if (nxt_slow_path(ret == NXT_ERROR)) { + return NXT_ERROR; + } -nxt_int_t -nxt_http_route_test_rule(nxt_http_request_t *r, nxt_http_route_rule_t *rule, - u_char *start, size_t length) -{ - nxt_int_t ret; - nxt_http_route_pattern_t *pattern, *end; + if (ret == 0) { + break; + } + } - ret = 1; - pattern = &rule->pattern[0]; - end = pattern + rule->items; + nv++; + } - while (pattern < end) { - ret = nxt_http_route_pattern(r, pattern, start, length); - if (nxt_slow_path(ret == NXT_ERROR)) { - return NXT_ERROR; - } + return ret; +} - /* nxt_http_route_pattern() returns either 1 or 0. */ - ret ^= pattern->negative; +nxt_int_t nxt_http_route_test_rule(nxt_http_request_t *r, + nxt_http_route_rule_t *rule, u_char *start, + size_t length) { + nxt_int_t ret; + nxt_http_route_pattern_t *pattern, *end; - if (pattern->any == ret) { - return ret; - } + ret = 1; + pattern = &rule->pattern[0]; + end = pattern + rule->items; - pattern++; + while (pattern < end) { + ret = nxt_http_route_pattern(r, pattern, start, length); + if (nxt_slow_path(ret == NXT_ERROR)) { + return NXT_ERROR; } - return ret; -} + /* nxt_http_route_pattern() returns either 1 or 0. */ + ret ^= pattern->negative; + if (pattern->any == ret) { + return ret; + } -static nxt_int_t -nxt_http_route_pattern(nxt_http_request_t *r, nxt_http_route_pattern_t *pattern, - u_char *start, size_t length) -{ - u_char *p, *end, *test; - size_t test_length; - uint32_t i; - nxt_array_t *pattern_slices; - nxt_http_route_pattern_slice_t *pattern_slice; + pattern++; + } -#if (NXT_HAVE_REGEX) - if (pattern->regex) { - if (r->regex_match == NULL) { - r->regex_match = nxt_regex_match_create(r->mem_pool, 0); - if (nxt_slow_path(r->regex_match == NULL)) { - return NXT_ERROR; - } - } + return ret; +} + +static nxt_int_t nxt_http_route_pattern(nxt_http_request_t *r, + nxt_http_route_pattern_t *pattern, + u_char *start, size_t length) { + u_char *p, *end, *test; + size_t test_length; + uint32_t i; + nxt_array_t *pattern_slices; + nxt_http_route_pattern_slice_t *pattern_slice; - return nxt_regex_match(pattern->u.regex, start, length, r->regex_match); +#if (NXT_HAVE_REGEX) + if (pattern->regex) { + if (r->regex_match == NULL) { + r->regex_match = nxt_regex_match_create(r->mem_pool, 0); + if (nxt_slow_path(r->regex_match == NULL)) { + return NXT_ERROR; + } } + + return nxt_regex_match(pattern->u.regex, start, length, r->regex_match); + } #endif - if (length < pattern->min_length) { - return 0; - } + if (length < pattern->min_length) { + return 0; + } - if (nxt_slow_path(start == NULL)) { - return 1; - } + if (nxt_slow_path(start == NULL)) { + return 1; + } - nxt_assert(pattern->u.pattern_slices != NULL); + nxt_assert(pattern->u.pattern_slices != NULL); - pattern_slices = pattern->u.pattern_slices; - pattern_slice = pattern_slices->elts; - end = start + length; + pattern_slices = pattern->u.pattern_slices; + pattern_slice = pattern_slices->elts; + end = start + length; - for (i = 0; i < pattern_slices->nelts; i++, pattern_slice++) { - test = pattern_slice->start; - test_length = pattern_slice->length; + for (i = 0; i < pattern_slices->nelts; i++, pattern_slice++) { + test = pattern_slice->start; + test_length = pattern_slice->length; - switch (pattern_slice->type) { - case NXT_HTTP_ROUTE_PATTERN_EXACT: - return ((length == pattern->min_length) && - nxt_http_route_memcmp(start, test, test_length, - pattern->case_sensitive)); + switch (pattern_slice->type) { + case NXT_HTTP_ROUTE_PATTERN_EXACT: + return ((length == pattern->min_length) && + nxt_http_route_memcmp(start, test, test_length, + pattern->case_sensitive)); - case NXT_HTTP_ROUTE_PATTERN_BEGIN: - if (nxt_http_route_memcmp(start, test, test_length, - pattern->case_sensitive)) - { - start += test_length; - break; - } + case NXT_HTTP_ROUTE_PATTERN_BEGIN: + if (nxt_http_route_memcmp(start, test, test_length, + pattern->case_sensitive)) { + start += test_length; + break; + } - return 0; + return 0; - case NXT_HTTP_ROUTE_PATTERN_END: - p = end - test_length; + case NXT_HTTP_ROUTE_PATTERN_END: + p = end - test_length; - if (nxt_http_route_memcmp(p, test, test_length, - pattern->case_sensitive)) - { - end = p; - break; - } + if (nxt_http_route_memcmp(p, test, test_length, + pattern->case_sensitive)) { + end = p; + break; + } - return 0; + return 0; - case NXT_HTTP_ROUTE_PATTERN_SUBSTRING: - if (pattern->case_sensitive) { - p = nxt_memstrn(start, end, (char *) test, test_length); + case NXT_HTTP_ROUTE_PATTERN_SUBSTRING: + if (pattern->case_sensitive) { + p = nxt_memstrn(start, end, (char *)test, test_length); - } else { - p = nxt_memcasestrn(start, end, (char *) test, test_length); - } + } else { + p = nxt_memcasestrn(start, end, (char *)test, test_length); + } - if (p == NULL) { - return 0; - } + if (p == NULL) { + return 0; + } - start = p + test_length; - } + start = p + test_length; } + } - return 1; + return 1; } +static nxt_int_t nxt_http_route_memcmp(u_char *start, u_char *test, + size_t test_length, + nxt_bool_t case_sensitive) { + nxt_int_t n; -static nxt_int_t -nxt_http_route_memcmp(u_char *start, u_char *test, size_t test_length, - nxt_bool_t case_sensitive) -{ - nxt_int_t n; - - if (case_sensitive) { - n = memcmp(start, test, test_length); + if (case_sensitive) { + n = memcmp(start, test, test_length); - } else { - n = nxt_memcasecmp(start, test, test_length); - } + } else { + n = nxt_memcasecmp(start, test, test_length); + } - return (n == 0); + return (n == 0); } diff --git a/src/nxt_http_route_addr.c b/src/nxt_http_route_addr.c index 5a0d7679d..527a7be04 100644 --- a/src/nxt_http_route_addr.c +++ b/src/nxt_http_route_addr.c @@ -7,340 +7,331 @@ #include #include - #if (NXT_INET6) static nxt_bool_t nxt_valid_ipv6_blocks(u_char *c, size_t len); #endif - nxt_int_t nxt_http_route_addr_pattern_parse(nxt_mp_t *mp, - nxt_http_route_addr_pattern_t *pattern, nxt_conf_value_t *cv) -{ - u_char *delim; - nxt_int_t ret, cidr_prefix; - nxt_str_t addr, port; - nxt_http_route_addr_base_t *base; - nxt_http_route_addr_range_t *inet; - - if (nxt_conf_type(cv) != NXT_CONF_STRING) { - return NXT_ADDR_PATTERN_CV_TYPE_ERROR; - } + nxt_http_route_addr_pattern_t *pattern, + nxt_conf_value_t *cv) { + u_char *delim; + nxt_int_t ret, cidr_prefix; + nxt_str_t addr, port; + nxt_http_route_addr_base_t *base; + nxt_http_route_addr_range_t *inet; - nxt_conf_get_string(cv, &addr); + if (nxt_conf_type(cv) != NXT_CONF_STRING) { + return NXT_ADDR_PATTERN_CV_TYPE_ERROR; + } - base = &pattern->base; + nxt_conf_get_string(cv, &addr); - if (addr.length > 0 && addr.start[0] == '!') { - addr.start++; - addr.length--; + base = &pattern->base; - base->negative = 1; + if (addr.length > 0 && addr.start[0] == '!') { + addr.start++; + addr.length--; - } else { - base->negative = 0; - } + base->negative = 1; + + } else { + base->negative = 0; + } - if (nxt_str_eq(&addr, "unix", 4)) { + if (nxt_str_eq(&addr, "unix", 4)) { #if (NXT_HAVE_UNIX_DOMAIN) - base->addr_family = AF_UNIX; + base->addr_family = AF_UNIX; - return NXT_OK; + return NXT_OK; #else - return NXT_ADDR_PATTERN_NO_UNIX_ERROR; + return NXT_ADDR_PATTERN_NO_UNIX_ERROR; #endif - } + } - if (nxt_slow_path(addr.length < 2)) { - return NXT_ADDR_PATTERN_LENGTH_ERROR; - } + if (nxt_slow_path(addr.length < 2)) { + return NXT_ADDR_PATTERN_LENGTH_ERROR; + } - nxt_str_null(&port); + nxt_str_null(&port); - if (addr.start[0] == '*' && addr.start[1] == ':') { - port.start = addr.start + 2; - port.length = addr.length - 2; - base->addr_family = AF_UNSPEC; - base->match_type = NXT_HTTP_ROUTE_ADDR_ANY; + if (addr.start[0] == '*' && addr.start[1] == ':') { + port.start = addr.start + 2; + port.length = addr.length - 2; + base->addr_family = AF_UNSPEC; + base->match_type = NXT_HTTP_ROUTE_ADDR_ANY; - goto parse_port; - } + goto parse_port; + } - if (nxt_inet6_probe(&addr)) { + if (nxt_inet6_probe(&addr)) { #if (NXT_INET6) - u_char *end; - uint8_t i; - nxt_int_t len; - nxt_http_route_in6_addr_range_t *inet6; + u_char *end; + uint8_t i; + nxt_int_t len; + nxt_http_route_in6_addr_range_t *inet6; - base->addr_family = AF_INET6; + base->addr_family = AF_INET6; - if (addr.start[0] == '[') { - addr.start++; - addr.length--; + if (addr.start[0] == '[') { + addr.start++; + addr.length--; - end = addr.start + addr.length; + end = addr.start + addr.length; - port.start = nxt_rmemstrn(addr.start, end, "]:", 2); - if (nxt_slow_path(port.start == NULL)) { - return NXT_ADDR_PATTERN_FORMAT_ERROR; - } - - addr.length = port.start - addr.start; - port.start += nxt_length("]:"); - port.length = end - port.start; - } - - inet6 = &pattern->addr.v6; - - delim = memchr(addr.start, '-', addr.length); - if (delim != NULL) { - len = delim - addr.start; - if (nxt_slow_path(!nxt_valid_ipv6_blocks(addr.start, len))) { - return NXT_ADDR_PATTERN_FORMAT_ERROR; - } - - ret = nxt_inet6_addr(&inet6->start, addr.start, len); - if (nxt_slow_path(ret != NXT_OK)) { - return NXT_ADDR_PATTERN_FORMAT_ERROR; - } - - len = addr.start + addr.length - delim - 1; - if (nxt_slow_path(!nxt_valid_ipv6_blocks(delim + 1, len))) { - return NXT_ADDR_PATTERN_FORMAT_ERROR; - } + port.start = nxt_rmemstrn(addr.start, end, "]:", 2); + if (nxt_slow_path(port.start == NULL)) { + return NXT_ADDR_PATTERN_FORMAT_ERROR; + } - ret = nxt_inet6_addr(&inet6->end, delim + 1, len); - if (nxt_slow_path(ret != NXT_OK)) { - return NXT_ADDR_PATTERN_FORMAT_ERROR; - } + addr.length = port.start - addr.start; + port.start += nxt_length("]:"); + port.length = end - port.start; + } - if (nxt_slow_path(memcmp(&inet6->start, &inet6->end, - sizeof(struct in6_addr)) > 0)) - { - return NXT_ADDR_PATTERN_RANGE_OVERLAP_ERROR; - } + inet6 = &pattern->addr.v6; - base->match_type = NXT_HTTP_ROUTE_ADDR_RANGE; + delim = memchr(addr.start, '-', addr.length); + if (delim != NULL) { + len = delim - addr.start; + if (nxt_slow_path(!nxt_valid_ipv6_blocks(addr.start, len))) { + return NXT_ADDR_PATTERN_FORMAT_ERROR; + } - goto parse_port; - } + ret = nxt_inet6_addr(&inet6->start, addr.start, len); + if (nxt_slow_path(ret != NXT_OK)) { + return NXT_ADDR_PATTERN_FORMAT_ERROR; + } - delim = memchr(addr.start, '/', addr.length); - if (delim != NULL) { - cidr_prefix = nxt_int_parse(delim + 1, - addr.start + addr.length - (delim + 1)); - if (nxt_slow_path(cidr_prefix < 0 || cidr_prefix > 128)) { - return NXT_ADDR_PATTERN_CIDR_ERROR; - } + len = addr.start + addr.length - delim - 1; + if (nxt_slow_path(!nxt_valid_ipv6_blocks(delim + 1, len))) { + return NXT_ADDR_PATTERN_FORMAT_ERROR; + } - addr.length = delim - addr.start; - if (nxt_slow_path(!nxt_valid_ipv6_blocks(addr.start, - addr.length))) - { - return NXT_ADDR_PATTERN_FORMAT_ERROR; - } + ret = nxt_inet6_addr(&inet6->end, delim + 1, len); + if (nxt_slow_path(ret != NXT_OK)) { + return NXT_ADDR_PATTERN_FORMAT_ERROR; + } - ret = nxt_inet6_addr(&inet6->start, addr.start, addr.length); - if (nxt_slow_path(ret != NXT_OK)) { - return NXT_ADDR_PATTERN_FORMAT_ERROR; - } + if (nxt_slow_path(memcmp(&inet6->start, &inet6->end, + sizeof(struct in6_addr)) > 0)) { + return NXT_ADDR_PATTERN_RANGE_OVERLAP_ERROR; + } - if (nxt_slow_path(cidr_prefix == 0)) { - base->match_type = NXT_HTTP_ROUTE_ADDR_ANY; + base->match_type = NXT_HTTP_ROUTE_ADDR_RANGE; - goto parse_port; - } + goto parse_port; + } - if (nxt_slow_path(cidr_prefix == 128)) { - base->match_type = NXT_HTTP_ROUTE_ADDR_EXACT; + delim = memchr(addr.start, '/', addr.length); + if (delim != NULL) { + cidr_prefix = + nxt_int_parse(delim + 1, addr.start + addr.length - (delim + 1)); + if (nxt_slow_path(cidr_prefix < 0 || cidr_prefix > 128)) { + return NXT_ADDR_PATTERN_CIDR_ERROR; + } + + addr.length = delim - addr.start; + if (nxt_slow_path(!nxt_valid_ipv6_blocks(addr.start, addr.length))) { + return NXT_ADDR_PATTERN_FORMAT_ERROR; + } - goto parse_port; - } + ret = nxt_inet6_addr(&inet6->start, addr.start, addr.length); + if (nxt_slow_path(ret != NXT_OK)) { + return NXT_ADDR_PATTERN_FORMAT_ERROR; + } - base->match_type = NXT_HTTP_ROUTE_ADDR_CIDR; + if (nxt_slow_path(cidr_prefix == 0)) { + base->match_type = NXT_HTTP_ROUTE_ADDR_ANY; - for (i = 0; i < sizeof(struct in6_addr); i++) { - if (cidr_prefix >= 8) { - inet6->end.s6_addr[i] = 0xFF; - cidr_prefix -= 8; + goto parse_port; + } - continue; - } + if (nxt_slow_path(cidr_prefix == 128)) { + base->match_type = NXT_HTTP_ROUTE_ADDR_EXACT; - if (cidr_prefix > 0) { - inet6->end.s6_addr[i] = 0xFF & (0xFF << (8 - cidr_prefix)); - inet6->start.s6_addr[i] &= inet6->end.s6_addr[i]; - cidr_prefix = 0; + goto parse_port; + } - continue; - } + base->match_type = NXT_HTTP_ROUTE_ADDR_CIDR; - inet6->start.s6_addr[i] = 0; - inet6->end.s6_addr[i] = 0; - } + for (i = 0; i < sizeof(struct in6_addr); i++) { + if (cidr_prefix >= 8) { + inet6->end.s6_addr[i] = 0xFF; + cidr_prefix -= 8; - goto parse_port; + continue; } - base->match_type = NXT_HTTP_ROUTE_ADDR_EXACT; + if (cidr_prefix > 0) { + inet6->end.s6_addr[i] = 0xFF & (0xFF << (8 - cidr_prefix)); + inet6->start.s6_addr[i] &= inet6->end.s6_addr[i]; + cidr_prefix = 0; - if (nxt_slow_path(!nxt_valid_ipv6_blocks(addr.start, addr.length))) { - return NXT_ADDR_PATTERN_FORMAT_ERROR; + continue; } - ret = nxt_inet6_addr(&inet6->start, addr.start, addr.length); - if (nxt_slow_path(ret != NXT_OK)) { - return NXT_ADDR_PATTERN_FORMAT_ERROR; - } + inet6->start.s6_addr[i] = 0; + inet6->end.s6_addr[i] = 0; + } - goto parse_port; -#endif - return NXT_ADDR_PATTERN_NO_IPv6_ERROR; + goto parse_port; } - base->addr_family = AF_INET; + base->match_type = NXT_HTTP_ROUTE_ADDR_EXACT; - delim = memchr(addr.start, ':', addr.length); - if (delim != NULL) { - port.start = delim + 1; - port.length = addr.start + addr.length - port.start; - addr.length = delim - addr.start; + if (nxt_slow_path(!nxt_valid_ipv6_blocks(addr.start, addr.length))) { + return NXT_ADDR_PATTERN_FORMAT_ERROR; } - inet = &pattern->addr.v4; + ret = nxt_inet6_addr(&inet6->start, addr.start, addr.length); + if (nxt_slow_path(ret != NXT_OK)) { + return NXT_ADDR_PATTERN_FORMAT_ERROR; + } - delim = memchr(addr.start, '-', addr.length); - if (delim != NULL) { - inet->start = nxt_inet_addr(addr.start, delim - addr.start); - if (nxt_slow_path(inet->start == INADDR_NONE)) { - return NXT_ADDR_PATTERN_FORMAT_ERROR; - } + goto parse_port; +#endif + return NXT_ADDR_PATTERN_NO_IPv6_ERROR; + } - inet->end = nxt_inet_addr(delim + 1, - addr.start + addr.length - (delim + 1)); - if (nxt_slow_path(inet->end == INADDR_NONE)) { - return NXT_ADDR_PATTERN_FORMAT_ERROR; - } + base->addr_family = AF_INET; - if (nxt_slow_path(memcmp(&inet->start, &inet->end, - sizeof(struct in_addr)) > 0)) - { - return NXT_ADDR_PATTERN_RANGE_OVERLAP_ERROR; - } + delim = memchr(addr.start, ':', addr.length); + if (delim != NULL) { + port.start = delim + 1; + port.length = addr.start + addr.length - port.start; + addr.length = delim - addr.start; + } - base->match_type = NXT_HTTP_ROUTE_ADDR_RANGE; + inet = &pattern->addr.v4; - goto parse_port; + delim = memchr(addr.start, '-', addr.length); + if (delim != NULL) { + inet->start = nxt_inet_addr(addr.start, delim - addr.start); + if (nxt_slow_path(inet->start == INADDR_NONE)) { + return NXT_ADDR_PATTERN_FORMAT_ERROR; } - delim = memchr(addr.start, '/', addr.length); - if (delim != NULL) { - cidr_prefix = nxt_int_parse(delim + 1, - addr.start + addr.length - (delim + 1)); - if (nxt_slow_path(cidr_prefix < 0 || cidr_prefix > 32)) { - return NXT_ADDR_PATTERN_CIDR_ERROR; - } + inet->end = + nxt_inet_addr(delim + 1, addr.start + addr.length - (delim + 1)); + if (nxt_slow_path(inet->end == INADDR_NONE)) { + return NXT_ADDR_PATTERN_FORMAT_ERROR; + } - addr.length = delim - addr.start; - inet->end = htonl(0xFFFFFFFF & (0xFFFFFFFFULL << (32 - cidr_prefix))); + if (nxt_slow_path(memcmp(&inet->start, &inet->end, sizeof(struct in_addr)) > + 0)) { + return NXT_ADDR_PATTERN_RANGE_OVERLAP_ERROR; + } - inet->start = nxt_inet_addr(addr.start, addr.length) & inet->end; - if (nxt_slow_path(inet->start == INADDR_NONE)) { - return NXT_ADDR_PATTERN_FORMAT_ERROR; - } + base->match_type = NXT_HTTP_ROUTE_ADDR_RANGE; - if (cidr_prefix == 0) { - base->match_type = NXT_HTTP_ROUTE_ADDR_ANY; + goto parse_port; + } - goto parse_port; - } + delim = memchr(addr.start, '/', addr.length); + if (delim != NULL) { + cidr_prefix = + nxt_int_parse(delim + 1, addr.start + addr.length - (delim + 1)); + if (nxt_slow_path(cidr_prefix < 0 || cidr_prefix > 32)) { + return NXT_ADDR_PATTERN_CIDR_ERROR; + } - if (cidr_prefix < 32) { - base->match_type = NXT_HTTP_ROUTE_ADDR_CIDR; + addr.length = delim - addr.start; + inet->end = htonl(0xFFFFFFFF & (0xFFFFFFFFULL << (32 - cidr_prefix))); - goto parse_port; - } + inet->start = nxt_inet_addr(addr.start, addr.length) & inet->end; + if (nxt_slow_path(inet->start == INADDR_NONE)) { + return NXT_ADDR_PATTERN_FORMAT_ERROR; } - inet->start = nxt_inet_addr(addr.start, addr.length); - if (nxt_slow_path(inet->start == INADDR_NONE)) { - return NXT_ADDR_PATTERN_FORMAT_ERROR; + if (cidr_prefix == 0) { + base->match_type = NXT_HTTP_ROUTE_ADDR_ANY; + + goto parse_port; } - base->match_type = NXT_HTTP_ROUTE_ADDR_EXACT; + if (cidr_prefix < 32) { + base->match_type = NXT_HTTP_ROUTE_ADDR_CIDR; -parse_port: + goto parse_port; + } + } - if (port.length == 0) { - if (nxt_slow_path(port.start != NULL)) { - return NXT_ADDR_PATTERN_FORMAT_ERROR; - } + inet->start = nxt_inet_addr(addr.start, addr.length); + if (nxt_slow_path(inet->start == INADDR_NONE)) { + return NXT_ADDR_PATTERN_FORMAT_ERROR; + } + + base->match_type = NXT_HTTP_ROUTE_ADDR_EXACT; - base->port.start = 0; - base->port.end = 65535; +parse_port: - return NXT_OK; + if (port.length == 0) { + if (nxt_slow_path(port.start != NULL)) { + return NXT_ADDR_PATTERN_FORMAT_ERROR; } - delim = memchr(port.start, '-', port.length - 1); - if (delim != NULL) { - ret = nxt_int_parse(port.start, delim - port.start); - if (nxt_slow_path(ret < 0 || ret > 65535)) { - return NXT_ADDR_PATTERN_PORT_ERROR; - } + base->port.start = 0; + base->port.end = 65535; - base->port.start = ret; + return NXT_OK; + } - ret = nxt_int_parse(delim + 1, port.start + port.length - (delim + 1)); - if (nxt_slow_path(ret < base->port.start || ret > 65535)) { - return NXT_ADDR_PATTERN_PORT_ERROR; - } + delim = memchr(port.start, '-', port.length - 1); + if (delim != NULL) { + ret = nxt_int_parse(port.start, delim - port.start); + if (nxt_slow_path(ret < 0 || ret > 65535)) { + return NXT_ADDR_PATTERN_PORT_ERROR; + } - base->port.end = ret; + base->port.start = ret; - } else { - ret = nxt_int_parse(port.start, port.length); - if (nxt_slow_path(ret < 0 || ret > 65535)) { - return NXT_ADDR_PATTERN_PORT_ERROR; - } + ret = nxt_int_parse(delim + 1, port.start + port.length - (delim + 1)); + if (nxt_slow_path(ret < base->port.start || ret > 65535)) { + return NXT_ADDR_PATTERN_PORT_ERROR; + } - base->port.start = ret; - base->port.end = ret; + base->port.end = ret; + + } else { + ret = nxt_int_parse(port.start, port.length); + if (nxt_slow_path(ret < 0 || ret > 65535)) { + return NXT_ADDR_PATTERN_PORT_ERROR; } - return NXT_OK; -} + base->port.start = ret; + base->port.end = ret; + } + return NXT_OK; +} #if (NXT_INET6) -static nxt_bool_t -nxt_valid_ipv6_blocks(u_char *c, size_t len) -{ - u_char *end; - nxt_uint_t colon_gap; +static nxt_bool_t nxt_valid_ipv6_blocks(u_char *c, size_t len) { + u_char *end; + nxt_uint_t colon_gap; - end = c + len; - colon_gap = 0; + end = c + len; + colon_gap = 0; - while (c != end) { - if (*c == ':') { - colon_gap = 0; - c++; + while (c != end) { + if (*c == ':') { + colon_gap = 0; + c++; - continue; - } + continue; + } - colon_gap++; - c++; + colon_gap++; + c++; - if (nxt_slow_path(colon_gap > 4)) { - return 0; - } + if (nxt_slow_path(colon_gap > 4)) { + return 0; } + } - return 1; + return 1; } #endif diff --git a/src/nxt_http_route_addr.h b/src/nxt_http_route_addr.h index 2deda6f80..ef1038dcf 100644 --- a/src/nxt_http_route_addr.h +++ b/src/nxt_http_route_addr.h @@ -9,66 +9,59 @@ #ifndef _NXT_HTTP_ROUTE_ADDR_H_INCLUDED_ #define _NXT_HTTP_ROUTE_ADDR_H_INCLUDED_ - enum { - NXT_HTTP_ROUTE_ADDR_ANY = 0, - NXT_HTTP_ROUTE_ADDR_RANGE, - NXT_HTTP_ROUTE_ADDR_EXACT, - NXT_HTTP_ROUTE_ADDR_CIDR, + NXT_HTTP_ROUTE_ADDR_ANY = 0, + NXT_HTTP_ROUTE_ADDR_RANGE, + NXT_HTTP_ROUTE_ADDR_EXACT, + NXT_HTTP_ROUTE_ADDR_CIDR, }; - enum { - NXT_ADDR_PATTERN_PORT_ERROR = NXT_OK + 1, - NXT_ADDR_PATTERN_CV_TYPE_ERROR, - NXT_ADDR_PATTERN_LENGTH_ERROR, - NXT_ADDR_PATTERN_FORMAT_ERROR, - NXT_ADDR_PATTERN_RANGE_OVERLAP_ERROR, - NXT_ADDR_PATTERN_CIDR_ERROR, - NXT_ADDR_PATTERN_NO_IPv6_ERROR, - NXT_ADDR_PATTERN_NO_UNIX_ERROR, + NXT_ADDR_PATTERN_PORT_ERROR = NXT_OK + 1, + NXT_ADDR_PATTERN_CV_TYPE_ERROR, + NXT_ADDR_PATTERN_LENGTH_ERROR, + NXT_ADDR_PATTERN_FORMAT_ERROR, + NXT_ADDR_PATTERN_RANGE_OVERLAP_ERROR, + NXT_ADDR_PATTERN_CIDR_ERROR, + NXT_ADDR_PATTERN_NO_IPv6_ERROR, + NXT_ADDR_PATTERN_NO_UNIX_ERROR, }; - typedef struct { - in_addr_t start; - in_addr_t end; + in_addr_t start; + in_addr_t end; } nxt_http_route_addr_range_t; - #if (NXT_INET6) typedef struct { - struct in6_addr start; - struct in6_addr end; + struct in6_addr start; + struct in6_addr end; } nxt_http_route_in6_addr_range_t; #endif - typedef struct { - uint8_t match_type:2; - uint8_t negative:1; - uint8_t addr_family; - - struct { - uint16_t start; - uint16_t end; - } port; + uint8_t match_type : 2; + uint8_t negative : 1; + uint8_t addr_family; + + struct { + uint16_t start; + uint16_t end; + } port; } nxt_http_route_addr_base_t; - typedef struct { - nxt_http_route_addr_base_t base; + nxt_http_route_addr_base_t base; - union { - nxt_http_route_addr_range_t v4; + union { + nxt_http_route_addr_range_t v4; #if (NXT_INET6) - nxt_http_route_in6_addr_range_t v6; + nxt_http_route_in6_addr_range_t v6; #endif - } addr; + } addr; } nxt_http_route_addr_pattern_t; - -NXT_EXPORT nxt_int_t nxt_http_route_addr_pattern_parse(nxt_mp_t *mp, - nxt_http_route_addr_pattern_t *pattern, nxt_conf_value_t *cv); +NXT_EXPORT nxt_int_t nxt_http_route_addr_pattern_parse( + nxt_mp_t *mp, nxt_http_route_addr_pattern_t *pattern, nxt_conf_value_t *cv); #endif /* _NXT_HTTP_ROUTE_ADDR_H_INCLUDED_ */ diff --git a/src/nxt_http_set_headers.c b/src/nxt_http_set_headers.c index 7fd6aba52..84c226aac 100644 --- a/src/nxt_http_set_headers.c +++ b/src/nxt_http_set_headers.c @@ -7,169 +7,159 @@ #include #include - typedef struct { - nxt_str_t name; - nxt_tstr_t *value; + nxt_str_t name; + nxt_tstr_t *value; } nxt_http_header_val_t; +nxt_int_t nxt_http_set_headers_init(nxt_router_conf_t *rtcf, + nxt_http_action_t *action, + nxt_http_action_conf_t *acf) { + uint32_t next; + nxt_str_t str, name; + nxt_array_t *headers; + nxt_conf_value_t *value; + nxt_http_header_val_t *hv; -nxt_int_t -nxt_http_set_headers_init(nxt_router_conf_t *rtcf, nxt_http_action_t *action, - nxt_http_action_conf_t *acf) - { - uint32_t next; - nxt_str_t str, name; - nxt_array_t *headers; - nxt_conf_value_t *value; - nxt_http_header_val_t *hv; + headers = nxt_array_create(rtcf->mem_pool, 4, sizeof(nxt_http_header_val_t)); + if (nxt_slow_path(headers == NULL)) { + return NXT_ERROR; + } - headers = nxt_array_create(rtcf->mem_pool, 4, - sizeof(nxt_http_header_val_t)); - if (nxt_slow_path(headers == NULL)) { - return NXT_ERROR; - } + action->set_headers = headers; - action->set_headers = headers; + next = 0; - next = 0; - - for ( ;; ) { - value = nxt_conf_next_object_member(acf->set_headers, &name, &next); - if (value == NULL) { - break; - } + for (;;) { + value = nxt_conf_next_object_member(acf->set_headers, &name, &next); + if (value == NULL) { + break; + } - hv = nxt_array_zero_add(headers); - if (nxt_slow_path(hv == NULL)) { - return NXT_ERROR; - } + hv = nxt_array_zero_add(headers); + if (nxt_slow_path(hv == NULL)) { + return NXT_ERROR; + } - hv->name.length = name.length; + hv->name.length = name.length; - hv->name.start = nxt_mp_nget(rtcf->mem_pool, name.length); - if (nxt_slow_path(hv->name.start == NULL)) { - return NXT_ERROR; - } + hv->name.start = nxt_mp_nget(rtcf->mem_pool, name.length); + if (nxt_slow_path(hv->name.start == NULL)) { + return NXT_ERROR; + } - nxt_memcpy(hv->name.start, name.start, name.length); + nxt_memcpy(hv->name.start, name.start, name.length); - if (nxt_conf_type(value) == NXT_CONF_STRING) { - nxt_conf_get_string(value, &str); + if (nxt_conf_type(value) == NXT_CONF_STRING) { + nxt_conf_get_string(value, &str); - hv->value = nxt_tstr_compile(rtcf->tstr_state, &str, 0); - if (nxt_slow_path(hv->value == NULL)) { - return NXT_ERROR; - } - } + hv->value = nxt_tstr_compile(rtcf->tstr_state, &str, 0); + if (nxt_slow_path(hv->value == NULL)) { + return NXT_ERROR; + } } + } - return NXT_OK; + return NXT_OK; } - static nxt_http_field_t * -nxt_http_resp_header_find(nxt_http_request_t *r, u_char *name, size_t length) -{ - nxt_http_field_t *f; - - nxt_list_each(f, r->resp.fields) { +nxt_http_resp_header_find(nxt_http_request_t *r, u_char *name, size_t length) { + nxt_http_field_t *f; - if (f->skip) { - continue; - } + nxt_list_each(f, r->resp.fields) { - if (length == f->name_length - && nxt_memcasecmp(name, f->name, f->name_length) == 0) - { - return f; - } + if (f->skip) { + continue; + } - } nxt_list_loop; + if (length == f->name_length && + nxt_memcasecmp(name, f->name, f->name_length) == 0) { + return f; + } + } + nxt_list_loop; - return NULL; + return NULL; } +nxt_int_t nxt_http_set_headers(nxt_http_request_t *r) { + nxt_int_t ret; + nxt_uint_t i, n; + nxt_str_t *value; + nxt_http_field_t *f; + nxt_router_conf_t *rtcf; + nxt_http_action_t *action; + nxt_http_header_val_t *hv, *header; -nxt_int_t -nxt_http_set_headers(nxt_http_request_t *r) -{ - nxt_int_t ret; - nxt_uint_t i, n; - nxt_str_t *value; - nxt_http_field_t *f; - nxt_router_conf_t *rtcf; - nxt_http_action_t *action; - nxt_http_header_val_t *hv, *header; - - action = r->action; + action = r->action; - if (action == NULL || action->set_headers == NULL) { - return NXT_OK; - } + if (action == NULL || action->set_headers == NULL) { + return NXT_OK; + } - if ((r->status < NXT_HTTP_OK || r->status >= NXT_HTTP_BAD_REQUEST)) { - return NXT_OK; - } + if ((r->status < NXT_HTTP_OK || r->status >= NXT_HTTP_BAD_REQUEST)) { + return NXT_OK; + } - rtcf = r->conf->socket_conf->router_conf; + rtcf = r->conf->socket_conf->router_conf; - header = action->set_headers->elts; - n = action->set_headers->nelts; + header = action->set_headers->elts; + n = action->set_headers->nelts; - value = nxt_mp_zalloc(r->mem_pool, sizeof(nxt_str_t) * n); - if (nxt_slow_path(value == NULL)) { - return NXT_ERROR; - } + value = nxt_mp_zalloc(r->mem_pool, sizeof(nxt_str_t) * n); + if (nxt_slow_path(value == NULL)) { + return NXT_ERROR; + } - for (i = 0; i < n; i++) { - hv = &header[i]; + for (i = 0; i < n; i++) { + hv = &header[i]; - if (hv->value == NULL) { - continue; - } + if (hv->value == NULL) { + continue; + } - if (nxt_tstr_is_const(hv->value)) { - nxt_tstr_str(hv->value, &value[i]); + if (nxt_tstr_is_const(hv->value)) { + nxt_tstr_str(hv->value, &value[i]); - } else { - ret = nxt_tstr_query_init(&r->tstr_query, rtcf->tstr_state, - &r->tstr_cache, r, r->mem_pool); - if (nxt_slow_path(ret != NXT_OK)) { - return NXT_ERROR; - } + } else { + ret = nxt_tstr_query_init(&r->tstr_query, rtcf->tstr_state, + &r->tstr_cache, r, r->mem_pool); + if (nxt_slow_path(ret != NXT_OK)) { + return NXT_ERROR; + } - ret = nxt_tstr_query(&r->task, r->tstr_query, hv->value, &value[i]); - if (nxt_slow_path(ret != NXT_OK)) { - return NXT_ERROR; - } - } + ret = nxt_tstr_query(&r->task, r->tstr_query, hv->value, &value[i]); + if (nxt_slow_path(ret != NXT_OK)) { + return NXT_ERROR; + } } + } - for (i = 0; i < n; i++) { - hv = &header[i]; + for (i = 0; i < n; i++) { + hv = &header[i]; - f = nxt_http_resp_header_find(r, hv->name.start, hv->name.length); + f = nxt_http_resp_header_find(r, hv->name.start, hv->name.length); - if (value[i].start != NULL) { + if (value[i].start != NULL) { - if (f == NULL) { - f = nxt_list_zero_add(r->resp.fields); - if (nxt_slow_path(f == NULL)) { - return NXT_ERROR; - } + if (f == NULL) { + f = nxt_list_zero_add(r->resp.fields); + if (nxt_slow_path(f == NULL)) { + return NXT_ERROR; + } - f->name = hv->name.start; - f->name_length = hv->name.length; - } + f->name = hv->name.start; + f->name_length = hv->name.length; + } - f->value = value[i].start; - f->value_length = value[i].length; + f->value = value[i].start; + f->value_length = value[i].length; - } else if (f != NULL) { - f->skip = 1; - } + } else if (f != NULL) { + f->skip = 1; } + } - return NXT_OK; + return NXT_OK; } diff --git a/src/nxt_http_static.c b/src/nxt_http_static.c index 67591595a..82a1a9f7b 100644 --- a/src/nxt_http_static.c +++ b/src/nxt_http_static.c @@ -6,1091 +6,1036 @@ #include #include - typedef struct { - nxt_tstr_t *tstr; + nxt_tstr_t *tstr; #if (NXT_HAVE_OPENAT2) - u_char *fname; + u_char *fname; #endif - uint8_t is_const; /* 1 bit */ + uint8_t is_const; /* 1 bit */ } nxt_http_static_share_t; - typedef struct { - nxt_uint_t nshares; - nxt_http_static_share_t *shares; - nxt_str_t index; + nxt_uint_t nshares; + nxt_http_static_share_t *shares; + nxt_str_t index; #if (NXT_HAVE_OPENAT2) - nxt_tstr_t *chroot; - nxt_uint_t resolve; + nxt_tstr_t *chroot; + nxt_uint_t resolve; #endif - nxt_http_route_rule_t *types; + nxt_http_route_rule_t *types; } nxt_http_static_conf_t; - typedef struct { - nxt_http_action_t *action; - nxt_str_t share; + nxt_http_action_t *action; + nxt_str_t share; #if (NXT_HAVE_OPENAT2) - nxt_str_t chroot; + nxt_str_t chroot; #endif - uint32_t share_idx; - uint8_t need_body; /* 1 bit */ + uint32_t share_idx; + uint8_t need_body; /* 1 bit */ } nxt_http_static_ctx_t; - -#define NXT_HTTP_STATIC_BUF_COUNT 2 -#define NXT_HTTP_STATIC_BUF_SIZE (128 * 1024) - +#define NXT_HTTP_STATIC_BUF_COUNT 2 +#define NXT_HTTP_STATIC_BUF_SIZE (128 * 1024) static nxt_http_action_t *nxt_http_static(nxt_task_t *task, - nxt_http_request_t *r, nxt_http_action_t *action); + nxt_http_request_t *r, + nxt_http_action_t *action); static void nxt_http_static_iterate(nxt_task_t *task, nxt_http_request_t *r, - nxt_http_static_ctx_t *ctx); + nxt_http_static_ctx_t *ctx); static void nxt_http_static_send(nxt_task_t *task, nxt_http_request_t *r, - nxt_http_static_ctx_t *ctx); + nxt_http_static_ctx_t *ctx); static void nxt_http_static_next(nxt_task_t *task, nxt_http_request_t *r, - nxt_http_static_ctx_t *ctx, nxt_http_status_t status); + nxt_http_static_ctx_t *ctx, + nxt_http_status_t status); #if (NXT_HAVE_OPENAT2) static u_char *nxt_http_static_chroot_match(u_char *chr, u_char *shr); #endif static void nxt_http_static_extract_extension(nxt_str_t *path, - nxt_str_t *exten); + nxt_str_t *exten); static void nxt_http_static_body_handler(nxt_task_t *task, void *obj, - void *data); + void *data); static void nxt_http_static_buf_completion(nxt_task_t *task, void *obj, - void *data); + void *data); static nxt_int_t nxt_http_static_mtypes_hash_test(nxt_lvlhsh_query_t *lhq, - void *data); + void *data); static void *nxt_http_static_mtypes_hash_alloc(void *data, size_t size); static void nxt_http_static_mtypes_hash_free(void *data, void *p); - -static const nxt_http_request_state_t nxt_http_static_send_state; - - -nxt_int_t -nxt_http_static_init(nxt_task_t *task, nxt_router_temp_conf_t *tmcf, - nxt_http_action_t *action, nxt_http_action_conf_t *acf) -{ - uint32_t i; - nxt_mp_t *mp; - nxt_str_t str, *ret; - nxt_tstr_t *tstr; - nxt_conf_value_t *cv; - nxt_router_conf_t *rtcf; - nxt_http_static_conf_t *conf; - - rtcf = tmcf->router_conf; - mp = rtcf->mem_pool; - - conf = nxt_mp_zget(mp, sizeof(nxt_http_static_conf_t)); - if (nxt_slow_path(conf == NULL)) { - return NXT_ERROR; - } - - action->handler = nxt_http_static; - action->u.conf = conf; - - conf->nshares = nxt_conf_array_elements_count_or_1(acf->share); - conf->shares = nxt_mp_zget(mp, sizeof(nxt_http_static_share_t) - * conf->nshares); - if (nxt_slow_path(conf->shares == NULL)) { - return NXT_ERROR; +static const nxt_http_request_state_t nxt_http_static_send_state; + +nxt_int_t nxt_http_static_init(nxt_task_t *task, nxt_router_temp_conf_t *tmcf, + nxt_http_action_t *action, + nxt_http_action_conf_t *acf) { + uint32_t i; + nxt_mp_t *mp; + nxt_str_t str, *ret; + nxt_tstr_t *tstr; + nxt_conf_value_t *cv; + nxt_router_conf_t *rtcf; + nxt_http_static_conf_t *conf; + + rtcf = tmcf->router_conf; + mp = rtcf->mem_pool; + + conf = nxt_mp_zget(mp, sizeof(nxt_http_static_conf_t)); + if (nxt_slow_path(conf == NULL)) { + return NXT_ERROR; + } + + action->handler = nxt_http_static; + action->u.conf = conf; + + conf->nshares = nxt_conf_array_elements_count_or_1(acf->share); + conf->shares = + nxt_mp_zget(mp, sizeof(nxt_http_static_share_t) * conf->nshares); + if (nxt_slow_path(conf->shares == NULL)) { + return NXT_ERROR; + } + + for (i = 0; i < conf->nshares; i++) { + cv = nxt_conf_get_array_element_or_itself(acf->share, i); + nxt_conf_get_string(cv, &str); + + tstr = nxt_tstr_compile(rtcf->tstr_state, &str, NXT_TSTR_STRZ); + if (nxt_slow_path(tstr == NULL)) { + return NXT_ERROR; } - for (i = 0; i < conf->nshares; i++) { - cv = nxt_conf_get_array_element_or_itself(acf->share, i); - nxt_conf_get_string(cv, &str); - - tstr = nxt_tstr_compile(rtcf->tstr_state, &str, NXT_TSTR_STRZ); - if (nxt_slow_path(tstr == NULL)) { - return NXT_ERROR; - } + conf->shares[i].tstr = tstr; + conf->shares[i].is_const = nxt_tstr_is_const(tstr); + } - conf->shares[i].tstr = tstr; - conf->shares[i].is_const = nxt_tstr_is_const(tstr); - } + if (acf->index == NULL) { + nxt_str_set(&conf->index, "index.html"); - if (acf->index == NULL) { - nxt_str_set(&conf->index, "index.html"); - - } else { - ret = nxt_conf_get_string_dup(acf->index, mp, &conf->index); - if (nxt_slow_path(ret == NULL)) { - return NXT_ERROR; - } + } else { + ret = nxt_conf_get_string_dup(acf->index, mp, &conf->index); + if (nxt_slow_path(ret == NULL)) { + return NXT_ERROR; } + } #if (NXT_HAVE_OPENAT2) - if (acf->chroot.length > 0) { - nxt_str_t chr, shr; - nxt_bool_t is_const; - - conf->chroot = nxt_tstr_compile(rtcf->tstr_state, &acf->chroot, - NXT_TSTR_STRZ); - if (nxt_slow_path(conf->chroot == NULL)) { - return NXT_ERROR; - } + if (acf->chroot.length > 0) { + nxt_str_t chr, shr; + nxt_bool_t is_const; + + conf->chroot = + nxt_tstr_compile(rtcf->tstr_state, &acf->chroot, NXT_TSTR_STRZ); + if (nxt_slow_path(conf->chroot == NULL)) { + return NXT_ERROR; + } - is_const = nxt_tstr_is_const(conf->chroot); + is_const = nxt_tstr_is_const(conf->chroot); - for (i = 0; i < conf->nshares; i++) { - conf->shares[i].is_const &= is_const; + for (i = 0; i < conf->nshares; i++) { + conf->shares[i].is_const &= is_const; - if (conf->shares[i].is_const) { - nxt_tstr_str(conf->chroot, &chr); - nxt_tstr_str(conf->shares[i].tstr, &shr); + if (conf->shares[i].is_const) { + nxt_tstr_str(conf->chroot, &chr); + nxt_tstr_str(conf->shares[i].tstr, &shr); - conf->shares[i].fname = nxt_http_static_chroot_match(chr.start, - shr.start); - } - } + conf->shares[i].fname = + nxt_http_static_chroot_match(chr.start, shr.start); + } } + } - if (acf->follow_symlinks != NULL - && !nxt_conf_get_boolean(acf->follow_symlinks)) - { - conf->resolve |= RESOLVE_NO_SYMLINKS; - } + if (acf->follow_symlinks != NULL && + !nxt_conf_get_boolean(acf->follow_symlinks)) { + conf->resolve |= RESOLVE_NO_SYMLINKS; + } - if (acf->traverse_mounts != NULL - && !nxt_conf_get_boolean(acf->traverse_mounts)) - { - conf->resolve |= RESOLVE_NO_XDEV; - } + if (acf->traverse_mounts != NULL && + !nxt_conf_get_boolean(acf->traverse_mounts)) { + conf->resolve |= RESOLVE_NO_XDEV; + } #endif - if (acf->types != NULL) { - conf->types = nxt_http_route_types_rule_create(task, mp, acf->types); - if (nxt_slow_path(conf->types == NULL)) { - return NXT_ERROR; - } + if (acf->types != NULL) { + conf->types = nxt_http_route_types_rule_create(task, mp, acf->types); + if (nxt_slow_path(conf->types == NULL)) { + return NXT_ERROR; } + } - if (acf->fallback != NULL) { - action->fallback = nxt_mp_alloc(mp, sizeof(nxt_http_action_t)); - if (nxt_slow_path(action->fallback == NULL)) { - return NXT_ERROR; - } - - return nxt_http_action_init(task, tmcf, acf->fallback, - action->fallback); + if (acf->fallback != NULL) { + action->fallback = nxt_mp_alloc(mp, sizeof(nxt_http_action_t)); + if (nxt_slow_path(action->fallback == NULL)) { + return NXT_ERROR; } - return NXT_OK; -} - + return nxt_http_action_init(task, tmcf, acf->fallback, action->fallback); + } -static nxt_http_action_t * -nxt_http_static(nxt_task_t *task, nxt_http_request_t *r, - nxt_http_action_t *action) -{ - nxt_bool_t need_body; - nxt_http_static_ctx_t *ctx; + return NXT_OK; +} - if (nxt_slow_path(!nxt_str_eq(r->method, "GET", 3))) { +static nxt_http_action_t *nxt_http_static(nxt_task_t *task, + nxt_http_request_t *r, + nxt_http_action_t *action) { + nxt_bool_t need_body; + nxt_http_static_ctx_t *ctx; - if (!nxt_str_eq(r->method, "HEAD", 4)) { - if (action->fallback != NULL) { - if (nxt_slow_path(r->log_route)) { - nxt_log(task, NXT_LOG_NOTICE, "\"fallback\" taken"); - } - return action->fallback; - } + if (nxt_slow_path(!nxt_str_eq(r->method, "GET", 3))) { - nxt_http_request_error(task, r, NXT_HTTP_METHOD_NOT_ALLOWED); - return NULL; + if (!nxt_str_eq(r->method, "HEAD", 4)) { + if (action->fallback != NULL) { + if (nxt_slow_path(r->log_route)) { + nxt_log(task, NXT_LOG_NOTICE, "\"fallback\" taken"); } + return action->fallback; + } - need_body = 0; - - } else { - need_body = 1; - } - - ctx = nxt_mp_zget(r->mem_pool, sizeof(nxt_http_static_ctx_t)); - if (nxt_slow_path(ctx == NULL)) { - nxt_http_request_error(task, r, NXT_HTTP_INTERNAL_SERVER_ERROR); - return NULL; + nxt_http_request_error(task, r, NXT_HTTP_METHOD_NOT_ALLOWED); + return NULL; } - ctx->action = action; - ctx->need_body = need_body; + need_body = 0; - nxt_http_static_iterate(task, r, ctx); + } else { + need_body = 1; + } + ctx = nxt_mp_zget(r->mem_pool, sizeof(nxt_http_static_ctx_t)); + if (nxt_slow_path(ctx == NULL)) { + nxt_http_request_error(task, r, NXT_HTTP_INTERNAL_SERVER_ERROR); return NULL; -} + } + ctx->action = action; + ctx->need_body = need_body; -static void -nxt_http_static_iterate(nxt_task_t *task, nxt_http_request_t *r, - nxt_http_static_ctx_t *ctx) -{ - nxt_int_t ret; - nxt_router_conf_t *rtcf; - nxt_http_static_conf_t *conf; - nxt_http_static_share_t *share; + nxt_http_static_iterate(task, r, ctx); - conf = ctx->action->u.conf; + return NULL; +} - share = &conf->shares[ctx->share_idx]; +static void nxt_http_static_iterate(nxt_task_t *task, nxt_http_request_t *r, + nxt_http_static_ctx_t *ctx) { + nxt_int_t ret; + nxt_router_conf_t *rtcf; + nxt_http_static_conf_t *conf; + nxt_http_static_share_t *share; + + conf = ctx->action->u.conf; + + share = &conf->shares[ctx->share_idx]; #if (NXT_DEBUG) - nxt_str_t shr; - nxt_str_t idx; + nxt_str_t shr; + nxt_str_t idx; - nxt_tstr_str(share->tstr, &shr); - idx = conf->index; + nxt_tstr_str(share->tstr, &shr); + idx = conf->index; #if (NXT_HAVE_OPENAT2) - nxt_str_t chr; + nxt_str_t chr; - if (conf->chroot != NULL) { - nxt_tstr_str(conf->chroot, &chr); + if (conf->chroot != NULL) { + nxt_tstr_str(conf->chroot, &chr); - } else { - nxt_str_set(&chr, ""); - } + } else { + nxt_str_set(&chr, ""); + } - nxt_debug(task, "http static: \"%V\", index: \"%V\" (chroot: \"%V\")", - &shr, &idx, &chr); + nxt_debug(task, "http static: \"%V\", index: \"%V\" (chroot: \"%V\")", &shr, + &idx, &chr); #else - nxt_debug(task, "http static: \"%V\", index: \"%V\"", &shr, &idx); + nxt_debug(task, "http static: \"%V\", index: \"%V\"", &shr, &idx); #endif #endif /* NXT_DEBUG */ - if (share->is_const) { - nxt_tstr_str(share->tstr, &ctx->share); + if (share->is_const) { + nxt_tstr_str(share->tstr, &ctx->share); #if (NXT_HAVE_OPENAT2) - if (conf->chroot != NULL && ctx->share_idx == 0) { - nxt_tstr_str(conf->chroot, &ctx->chroot); - } + if (conf->chroot != NULL && ctx->share_idx == 0) { + nxt_tstr_str(conf->chroot, &ctx->chroot); + } #endif - } else { - rtcf = r->conf->socket_conf->router_conf; + } else { + rtcf = r->conf->socket_conf->router_conf; - ret = nxt_tstr_query_init(&r->tstr_query, rtcf->tstr_state, - &r->tstr_cache, r, r->mem_pool); - if (nxt_slow_path(ret != NXT_OK)) { - goto fail; - } + ret = nxt_tstr_query_init(&r->tstr_query, rtcf->tstr_state, &r->tstr_cache, + r, r->mem_pool); + if (nxt_slow_path(ret != NXT_OK)) { + goto fail; + } - ret = nxt_tstr_query(task, r->tstr_query, share->tstr, &ctx->share); - if (nxt_slow_path(ret != NXT_OK)) { - goto fail; - } + ret = nxt_tstr_query(task, r->tstr_query, share->tstr, &ctx->share); + if (nxt_slow_path(ret != NXT_OK)) { + goto fail; + } #if (NXT_HAVE_OPENAT2) - if (conf->chroot != NULL && ctx->share_idx == 0) { - ret = nxt_tstr_query(task, r->tstr_query, conf->chroot, - &ctx->chroot); - if (nxt_slow_path(ret != NXT_OK)) { - goto fail; - } - } -#endif + if (conf->chroot != NULL && ctx->share_idx == 0) { + ret = nxt_tstr_query(task, r->tstr_query, conf->chroot, &ctx->chroot); + if (nxt_slow_path(ret != NXT_OK)) { + goto fail; + } } +#endif + } - nxt_http_static_send(task, r, ctx); + nxt_http_static_send(task, r, ctx); - return; + return; fail: - nxt_http_request_error(task, r, NXT_HTTP_INTERNAL_SERVER_ERROR); + nxt_http_request_error(task, r, NXT_HTTP_INTERNAL_SERVER_ERROR); } +static void nxt_http_static_send(nxt_task_t *task, nxt_http_request_t *r, + nxt_http_static_ctx_t *ctx) { + size_t length, encode; + u_char *p, *fname; + struct tm tm; + nxt_buf_t *fb; + nxt_int_t ret; + nxt_str_t *shr, *index, exten, *mtype; + nxt_uint_t level; + nxt_file_t *f, file; + nxt_file_info_t fi; + nxt_http_field_t *field; + nxt_http_status_t status; + nxt_router_conf_t *rtcf; + nxt_http_action_t *action; + nxt_work_handler_t body_handler; + nxt_http_static_conf_t *conf; + + action = ctx->action; + conf = action->u.conf; + rtcf = r->conf->socket_conf->router_conf; + + f = NULL; + mtype = NULL; + + shr = &ctx->share; + index = &conf->index; + + if (shr->start[shr->length - 1] == '/') { + nxt_http_static_extract_extension(index, &exten); + + length = shr->length + index->length; + + fname = nxt_mp_nget(r->mem_pool, length + 1); + if (nxt_slow_path(fname == NULL)) { + goto fail; + } -static void -nxt_http_static_send(nxt_task_t *task, nxt_http_request_t *r, - nxt_http_static_ctx_t *ctx) -{ - size_t length, encode; - u_char *p, *fname; - struct tm tm; - nxt_buf_t *fb; - nxt_int_t ret; - nxt_str_t *shr, *index, exten, *mtype; - nxt_uint_t level; - nxt_file_t *f, file; - nxt_file_info_t fi; - nxt_http_field_t *field; - nxt_http_status_t status; - nxt_router_conf_t *rtcf; - nxt_http_action_t *action; - nxt_work_handler_t body_handler; - nxt_http_static_conf_t *conf; - - action = ctx->action; - conf = action->u.conf; - rtcf = r->conf->socket_conf->router_conf; - - f = NULL; - mtype = NULL; - - shr = &ctx->share; - index = &conf->index; - - if (shr->start[shr->length - 1] == '/') { - nxt_http_static_extract_extension(index, &exten); - - length = shr->length + index->length; - - fname = nxt_mp_nget(r->mem_pool, length + 1); - if (nxt_slow_path(fname == NULL)) { - goto fail; - } + p = fname; + p = nxt_cpymem(p, shr->start, shr->length); + p = nxt_cpymem(p, index->start, index->length); + *p = '\0'; - p = fname; - p = nxt_cpymem(p, shr->start, shr->length); - p = nxt_cpymem(p, index->start, index->length); - *p = '\0'; + } else { + if (conf->types == NULL) { + nxt_str_null(&exten); } else { - if (conf->types == NULL) { - nxt_str_null(&exten); - - } else { - nxt_http_static_extract_extension(shr, &exten); - mtype = nxt_http_static_mtype_get(&rtcf->mtypes_hash, &exten); - - ret = nxt_http_route_test_rule(r, conf->types, mtype->start, - mtype->length); - if (nxt_slow_path(ret == NXT_ERROR)) { - goto fail; - } - - if (ret == 0) { - nxt_http_static_next(task, r, ctx, NXT_HTTP_FORBIDDEN); - return; - } - } + nxt_http_static_extract_extension(shr, &exten); + mtype = nxt_http_static_mtype_get(&rtcf->mtypes_hash, &exten); + + ret = + nxt_http_route_test_rule(r, conf->types, mtype->start, mtype->length); + if (nxt_slow_path(ret == NXT_ERROR)) { + goto fail; + } - fname = ctx->share.start; + if (ret == 0) { + nxt_http_static_next(task, r, ctx, NXT_HTTP_FORBIDDEN); + return; + } } - nxt_memzero(&file, sizeof(nxt_file_t)); + fname = ctx->share.start; + } - file.name = fname; + nxt_memzero(&file, sizeof(nxt_file_t)); -#if (NXT_HAVE_OPENAT2) - if (conf->resolve != 0 || ctx->chroot.length > 0) { - nxt_str_t *chr; - nxt_uint_t resolve; - nxt_http_static_share_t *share; + file.name = fname; - share = &conf->shares[ctx->share_idx]; +#if (NXT_HAVE_OPENAT2) + if (conf->resolve != 0 || ctx->chroot.length > 0) { + nxt_str_t *chr; + nxt_uint_t resolve; + nxt_http_static_share_t *share; - resolve = conf->resolve; - chr = &ctx->chroot; + share = &conf->shares[ctx->share_idx]; - if (chr->length > 0) { - resolve |= RESOLVE_IN_ROOT; + resolve = conf->resolve; + chr = &ctx->chroot; - fname = share->is_const - ? share->fname - : nxt_http_static_chroot_match(chr->start, file.name); + if (chr->length > 0) { + resolve |= RESOLVE_IN_ROOT; - if (fname != NULL) { - file.name = chr->start; - ret = nxt_file_open(task, &file, NXT_FILE_SEARCH, NXT_FILE_OPEN, - 0); + fname = share->is_const + ? share->fname + : nxt_http_static_chroot_match(chr->start, file.name); - } else { - file.error = NXT_EACCES; - ret = NXT_ERROR; - } + if (fname != NULL) { + file.name = chr->start; + ret = nxt_file_open(task, &file, NXT_FILE_SEARCH, NXT_FILE_OPEN, 0); - } else if (fname[0] == '/') { - file.name = (u_char *) "/"; - ret = nxt_file_open(task, &file, NXT_FILE_SEARCH, NXT_FILE_OPEN, 0); + } else { + file.error = NXT_EACCES; + ret = NXT_ERROR; + } - } else { - file.name = (u_char *) "."; - file.fd = AT_FDCWD; - ret = NXT_OK; - } + } else if (fname[0] == '/') { + file.name = (u_char *)"/"; + ret = nxt_file_open(task, &file, NXT_FILE_SEARCH, NXT_FILE_OPEN, 0); - if (nxt_fast_path(ret == NXT_OK)) { - nxt_file_t af; + } else { + file.name = (u_char *)"."; + file.fd = AT_FDCWD; + ret = NXT_OK; + } - af = file; - nxt_memzero(&file, sizeof(nxt_file_t)); - file.name = fname; + if (nxt_fast_path(ret == NXT_OK)) { + nxt_file_t af; - ret = nxt_file_openat2(task, &file, NXT_FILE_RDONLY, - NXT_FILE_OPEN, 0, af.fd, resolve); + af = file; + nxt_memzero(&file, sizeof(nxt_file_t)); + file.name = fname; - if (af.fd != AT_FDCWD) { - nxt_file_close(task, &af); - } - } + ret = nxt_file_openat2(task, &file, NXT_FILE_RDONLY, NXT_FILE_OPEN, 0, + af.fd, resolve); - } else { - ret = nxt_file_open(task, &file, NXT_FILE_RDONLY, NXT_FILE_OPEN, 0); + if (af.fd != AT_FDCWD) { + nxt_file_close(task, &af); + } } -#else + } else { ret = nxt_file_open(task, &file, NXT_FILE_RDONLY, NXT_FILE_OPEN, 0); + } + +#else + ret = nxt_file_open(task, &file, NXT_FILE_RDONLY, NXT_FILE_OPEN, 0); #endif - if (nxt_slow_path(ret != NXT_OK)) { + if (nxt_slow_path(ret != NXT_OK)) { - switch (file.error) { + switch (file.error) { - /* - * For Unix domain sockets "errno" is set to: - * - ENXIO on Linux; - * - EOPNOTSUPP on *BSD, MacOSX, and Solaris. - */ + /* + * For Unix domain sockets "errno" is set to: + * - ENXIO on Linux; + * - EOPNOTSUPP on *BSD, MacOSX, and Solaris. + */ - case NXT_ENOENT: - case NXT_ENOTDIR: - case NXT_ENAMETOOLONG: + case NXT_ENOENT: + case NXT_ENOTDIR: + case NXT_ENAMETOOLONG: #if (NXT_LINUX) - case NXT_ENXIO: + case NXT_ENXIO: #else - case NXT_EOPNOTSUPP: + case NXT_EOPNOTSUPP: #endif - level = NXT_LOG_ERR; - status = NXT_HTTP_NOT_FOUND; - break; + level = NXT_LOG_ERR; + status = NXT_HTTP_NOT_FOUND; + break; - case NXT_EACCES: + case NXT_EACCES: #if (NXT_HAVE_OPENAT2) - case NXT_ELOOP: - case NXT_EXDEV: + case NXT_ELOOP: + case NXT_EXDEV: #endif - level = NXT_LOG_ERR; - status = NXT_HTTP_FORBIDDEN; - break; - - default: - level = NXT_LOG_ALERT; - status = NXT_HTTP_INTERNAL_SERVER_ERROR; - break; - } + level = NXT_LOG_ERR; + status = NXT_HTTP_FORBIDDEN; + break; + + default: + level = NXT_LOG_ALERT; + status = NXT_HTTP_INTERNAL_SERVER_ERROR; + break; + } - if (status != NXT_HTTP_NOT_FOUND) { + if (status != NXT_HTTP_NOT_FOUND) { #if (NXT_HAVE_OPENAT2) - nxt_str_t *chr = &ctx->chroot; + nxt_str_t *chr = &ctx->chroot; - if (chr->length > 0) { - nxt_log(task, level, "opening \"%s\" at \"%V\" failed %E", - fname, chr, file.error); + if (chr->length > 0) { + nxt_log(task, level, "opening \"%s\" at \"%V\" failed %E", fname, chr, + file.error); - } else { - nxt_log(task, level, "opening \"%s\" failed %E", - fname, file.error); - } + } else { + nxt_log(task, level, "opening \"%s\" failed %E", fname, file.error); + } #else - nxt_log(task, level, "opening \"%s\" failed %E", fname, file.error); + nxt_log(task, level, "opening \"%s\" failed %E", fname, file.error); #endif - } - - if (level == NXT_LOG_ERR) { - nxt_http_static_next(task, r, ctx, status); - return; - } - - goto fail; } - f = nxt_mp_get(r->mem_pool, sizeof(nxt_file_t)); - if (nxt_slow_path(f == NULL)) { - nxt_file_close(task, &file); - goto fail; + if (level == NXT_LOG_ERR) { + nxt_http_static_next(task, r, ctx, status); + return; } - *f = file; + goto fail; + } - ret = nxt_file_info(f, &fi); - if (nxt_slow_path(ret != NXT_OK)) { - goto fail; - } + f = nxt_mp_get(r->mem_pool, sizeof(nxt_file_t)); + if (nxt_slow_path(f == NULL)) { + nxt_file_close(task, &file); + goto fail; + } - if (nxt_fast_path(nxt_is_file(&fi))) { - r->status = NXT_HTTP_OK; - r->resp.content_length_n = nxt_file_size(&fi); + *f = file; - field = nxt_list_zero_add(r->resp.fields); - if (nxt_slow_path(field == NULL)) { - goto fail; - } + ret = nxt_file_info(f, &fi); + if (nxt_slow_path(ret != NXT_OK)) { + goto fail; + } - nxt_http_field_name_set(field, "Last-Modified"); + if (nxt_fast_path(nxt_is_file(&fi))) { + r->status = NXT_HTTP_OK; + r->resp.content_length_n = nxt_file_size(&fi); - p = nxt_mp_nget(r->mem_pool, NXT_HTTP_DATE_LEN); - if (nxt_slow_path(p == NULL)) { - goto fail; - } + field = nxt_list_zero_add(r->resp.fields); + if (nxt_slow_path(field == NULL)) { + goto fail; + } - nxt_localtime(nxt_file_mtime(&fi), &tm); + nxt_http_field_name_set(field, "Last-Modified"); - field->value = p; - field->value_length = nxt_http_date(p, &tm) - p; + p = nxt_mp_nget(r->mem_pool, NXT_HTTP_DATE_LEN); + if (nxt_slow_path(p == NULL)) { + goto fail; + } - field = nxt_list_zero_add(r->resp.fields); - if (nxt_slow_path(field == NULL)) { - goto fail; - } + nxt_localtime(nxt_file_mtime(&fi), &tm); - nxt_http_field_name_set(field, "ETag"); + field->value = p; + field->value_length = nxt_http_date(p, &tm) - p; - length = NXT_TIME_T_HEXLEN + NXT_OFF_T_HEXLEN + 3; + field = nxt_list_zero_add(r->resp.fields); + if (nxt_slow_path(field == NULL)) { + goto fail; + } - p = nxt_mp_nget(r->mem_pool, length); - if (nxt_slow_path(p == NULL)) { - goto fail; - } + nxt_http_field_name_set(field, "ETag"); - field->value = p; - field->value_length = nxt_sprintf(p, p + length, "\"%xT-%xO\"", - nxt_file_mtime(&fi), - nxt_file_size(&fi)) - - p; + length = NXT_TIME_T_HEXLEN + NXT_OFF_T_HEXLEN + 3; - if (exten.start == NULL) { - nxt_http_static_extract_extension(shr, &exten); - } + p = nxt_mp_nget(r->mem_pool, length); + if (nxt_slow_path(p == NULL)) { + goto fail; + } - if (mtype == NULL) { - mtype = nxt_http_static_mtype_get(&rtcf->mtypes_hash, &exten); - } + field->value = p; + field->value_length = nxt_sprintf(p, p + length, "\"%xT-%xO\"", + nxt_file_mtime(&fi), nxt_file_size(&fi)) - + p; - if (mtype->length != 0) { - field = nxt_list_zero_add(r->resp.fields); - if (nxt_slow_path(field == NULL)) { - goto fail; - } + if (exten.start == NULL) { + nxt_http_static_extract_extension(shr, &exten); + } - nxt_http_field_name_set(field, "Content-Type"); + if (mtype == NULL) { + mtype = nxt_http_static_mtype_get(&rtcf->mtypes_hash, &exten); + } - field->value = mtype->start; - field->value_length = mtype->length; - } + if (mtype->length != 0) { + field = nxt_list_zero_add(r->resp.fields); + if (nxt_slow_path(field == NULL)) { + goto fail; + } - if (ctx->need_body && nxt_file_size(&fi) > 0) { - fb = nxt_mp_zget(r->mem_pool, NXT_BUF_FILE_SIZE); - if (nxt_slow_path(fb == NULL)) { - goto fail; - } + nxt_http_field_name_set(field, "Content-Type"); - fb->file = f; - fb->file_end = nxt_file_size(&fi); + field->value = mtype->start; + field->value_length = mtype->length; + } + + if (ctx->need_body && nxt_file_size(&fi) > 0) { + fb = nxt_mp_zget(r->mem_pool, NXT_BUF_FILE_SIZE); + if (nxt_slow_path(fb == NULL)) { + goto fail; + } - r->out = fb; + fb->file = f; + fb->file_end = nxt_file_size(&fi); - body_handler = &nxt_http_static_body_handler; + r->out = fb; - } else { - nxt_file_close(task, f); - body_handler = NULL; - } + body_handler = &nxt_http_static_body_handler; } else { - /* Not a file. */ - nxt_file_close(task, f); + nxt_file_close(task, f); + body_handler = NULL; + } - if (nxt_slow_path(!nxt_is_dir(&fi) - || shr->start[shr->length - 1] == '/')) - { - nxt_log(task, NXT_LOG_ERR, "\"%FN\" is not a regular file", - f->name); + } else { + /* Not a file. */ + nxt_file_close(task, f); - nxt_http_static_next(task, r, ctx, NXT_HTTP_NOT_FOUND); - return; - } + if (nxt_slow_path(!nxt_is_dir(&fi) || shr->start[shr->length - 1] == '/')) { + nxt_log(task, NXT_LOG_ERR, "\"%FN\" is not a regular file", f->name); - f = NULL; + nxt_http_static_next(task, r, ctx, NXT_HTTP_NOT_FOUND); + return; + } - r->status = NXT_HTTP_MOVED_PERMANENTLY; - r->resp.content_length_n = 0; + f = NULL; - field = nxt_list_zero_add(r->resp.fields); - if (nxt_slow_path(field == NULL)) { - goto fail; - } + r->status = NXT_HTTP_MOVED_PERMANENTLY; + r->resp.content_length_n = 0; - nxt_http_field_name_set(field, "Location"); + field = nxt_list_zero_add(r->resp.fields); + if (nxt_slow_path(field == NULL)) { + goto fail; + } - encode = nxt_encode_uri(NULL, r->path->start, r->path->length); - length = r->path->length + encode * 2 + 1; + nxt_http_field_name_set(field, "Location"); - if (r->args->length > 0) { - length += 1 + r->args->length; - } + encode = nxt_encode_uri(NULL, r->path->start, r->path->length); + length = r->path->length + encode * 2 + 1; - p = nxt_mp_nget(r->mem_pool, length); - if (nxt_slow_path(p == NULL)) { - goto fail; - } + if (r->args->length > 0) { + length += 1 + r->args->length; + } - field->value = p; - field->value_length = length; + p = nxt_mp_nget(r->mem_pool, length); + if (nxt_slow_path(p == NULL)) { + goto fail; + } - if (encode > 0) { - p = (u_char *) nxt_encode_uri(p, r->path->start, r->path->length); + field->value = p; + field->value_length = length; - } else { - p = nxt_cpymem(p, r->path->start, r->path->length); - } + if (encode > 0) { + p = (u_char *)nxt_encode_uri(p, r->path->start, r->path->length); - *p++ = '/'; + } else { + p = nxt_cpymem(p, r->path->start, r->path->length); + } - if (r->args->length > 0) { - *p++ = '?'; - nxt_memcpy(p, r->args->start, r->args->length); - } + *p++ = '/'; - body_handler = NULL; + if (r->args->length > 0) { + *p++ = '?'; + nxt_memcpy(p, r->args->start, r->args->length); } - nxt_http_request_header_send(task, r, body_handler, NULL); + body_handler = NULL; + } - r->state = &nxt_http_static_send_state; - return; + nxt_http_request_header_send(task, r, body_handler, NULL); + + r->state = &nxt_http_static_send_state; + return; fail: - if (f != NULL) { - nxt_file_close(task, f); - } + if (f != NULL) { + nxt_file_close(task, f); + } - nxt_http_request_error(task, r, NXT_HTTP_INTERNAL_SERVER_ERROR); + nxt_http_request_error(task, r, NXT_HTTP_INTERNAL_SERVER_ERROR); } +static void nxt_http_static_next(nxt_task_t *task, nxt_http_request_t *r, + nxt_http_static_ctx_t *ctx, + nxt_http_status_t status) { + nxt_http_action_t *action; + nxt_http_static_conf_t *conf; -static void -nxt_http_static_next(nxt_task_t *task, nxt_http_request_t *r, - nxt_http_static_ctx_t *ctx, nxt_http_status_t status) -{ - nxt_http_action_t *action; - nxt_http_static_conf_t *conf; + action = ctx->action; + conf = action->u.conf; - action = ctx->action; - conf = action->u.conf; + ctx->share_idx++; - ctx->share_idx++; + if (ctx->share_idx < conf->nshares) { + nxt_http_static_iterate(task, r, ctx); + return; + } - if (ctx->share_idx < conf->nshares) { - nxt_http_static_iterate(task, r, ctx); - return; + if (action->fallback != NULL) { + if (nxt_slow_path(r->log_route)) { + nxt_log(task, NXT_LOG_NOTICE, "\"fallback\" taken"); } - if (action->fallback != NULL) { - if (nxt_slow_path(r->log_route)) { - nxt_log(task, NXT_LOG_NOTICE, "\"fallback\" taken"); - } - - r->action = action->fallback; - nxt_http_request_action(task, r, action->fallback); - return; - } + r->action = action->fallback; + nxt_http_request_action(task, r, action->fallback); + return; + } - nxt_http_request_error(task, r, status); + nxt_http_request_error(task, r, status); } - #if (NXT_HAVE_OPENAT2) -static u_char * -nxt_http_static_chroot_match(u_char *chr, u_char *shr) -{ - if (*chr != *shr) { - return NULL; - } - - chr++; - shr++; - - for ( ;; ) { - if (*shr == '\0') { - return NULL; - } - - if (*chr == *shr) { - chr++; - shr++; - continue; - } +static u_char *nxt_http_static_chroot_match(u_char *chr, u_char *shr) { + if (*chr != *shr) { + return NULL; + } - if (*chr == '\0') { - break; - } + chr++; + shr++; - if (*chr == '/') { - if (chr[-1] == '/') { - chr++; - continue; - } - - } else if (*shr == '/') { - if (shr[-1] == '/') { - shr++; - continue; - } - } + for (;;) { + if (*shr == '\0') { + return NULL; + } - return NULL; + if (*chr == *shr) { + chr++; + shr++; + continue; } - if (shr[-1] != '/' && *shr != '/') { - return NULL; + if (*chr == '\0') { + break; } - while (*shr == '/') { + if (*chr == '/') { + if (chr[-1] == '/') { + chr++; + continue; + } + + } else if (*shr == '/') { + if (shr[-1] == '/') { shr++; + continue; + } } - return (*shr != '\0') ? shr : NULL; -} - -#endif + return NULL; + } + if (shr[-1] != '/' && *shr != '/') { + return NULL; + } -static void -nxt_http_static_extract_extension(nxt_str_t *path, nxt_str_t *exten) -{ - u_char ch, *p, *end; + while (*shr == '/') { + shr++; + } - end = path->start + path->length; - p = end; + return (*shr != '\0') ? shr : NULL; +} - while (p > path->start) { - p--; - ch = *p; +#endif - switch (ch) { - case '/': - p++; - /* Fall through. */ - case '.': - goto extension; - } +static void nxt_http_static_extract_extension(nxt_str_t *path, + nxt_str_t *exten) { + u_char ch, *p, *end; + + end = path->start + path->length; + p = end; + + while (p > path->start) { + p--; + ch = *p; + + switch (ch) { + case '/': + p++; + /* Fall through. */ + case '.': + goto extension; } + } extension: - exten->length = end - p; - exten->start = p; + exten->length = end - p; + exten->start = p; } +static void nxt_http_static_body_handler(nxt_task_t *task, void *obj, + void *data) { + size_t alloc; + nxt_buf_t *fb, *b, **next, *out; + nxt_off_t rest; + nxt_int_t n; + nxt_work_queue_t *wq; + nxt_http_request_t *r; + + r = obj; + fb = r->out; + + rest = fb->file_end - fb->file_pos; + out = NULL; + next = &out; + n = 0; + + do { + alloc = nxt_min(rest, NXT_HTTP_STATIC_BUF_SIZE); + + b = nxt_buf_mem_alloc(r->mem_pool, alloc, 0); + if (nxt_slow_path(b == NULL)) { + goto fail; + } -static void -nxt_http_static_body_handler(nxt_task_t *task, void *obj, void *data) -{ - size_t alloc; - nxt_buf_t *fb, *b, **next, *out; - nxt_off_t rest; - nxt_int_t n; - nxt_work_queue_t *wq; - nxt_http_request_t *r; - - r = obj; - fb = r->out; - - rest = fb->file_end - fb->file_pos; - out = NULL; - next = &out; - n = 0; - - do { - alloc = nxt_min(rest, NXT_HTTP_STATIC_BUF_SIZE); - - b = nxt_buf_mem_alloc(r->mem_pool, alloc, 0); - if (nxt_slow_path(b == NULL)) { - goto fail; - } - - b->completion_handler = nxt_http_static_buf_completion; - b->parent = r; + b->completion_handler = nxt_http_static_buf_completion; + b->parent = r; - nxt_mp_retain(r->mem_pool); + nxt_mp_retain(r->mem_pool); - *next = b; - next = &b->next; + *next = b; + next = &b->next; - rest -= alloc; + rest -= alloc; - } while (rest > 0 && ++n < NXT_HTTP_STATIC_BUF_COUNT); + } while (rest > 0 && ++n < NXT_HTTP_STATIC_BUF_COUNT); - wq = &task->thread->engine->fast_work_queue; + wq = &task->thread->engine->fast_work_queue; - nxt_sendbuf_drain(task, wq, out); - return; + nxt_sendbuf_drain(task, wq, out); + return; fail: - while (out != NULL) { - b = out; - out = b->next; + while (out != NULL) { + b = out; + out = b->next; - nxt_mp_free(r->mem_pool, b); - nxt_mp_release(r->mem_pool); - } + nxt_mp_free(r->mem_pool, b); + nxt_mp_release(r->mem_pool); + } } - -static const nxt_http_request_state_t nxt_http_static_send_state - nxt_aligned(64) = -{ - .error_handler = nxt_http_request_error_handler, +static const nxt_http_request_state_t + nxt_http_static_send_state nxt_aligned(64) = { + .error_handler = nxt_http_request_error_handler, }; +static void nxt_http_static_buf_completion(nxt_task_t *task, void *obj, + void *data) { + ssize_t n, size; + nxt_buf_t *b, *fb, *next; + nxt_off_t rest; + nxt_http_request_t *r; -static void -nxt_http_static_buf_completion(nxt_task_t *task, void *obj, void *data) -{ - ssize_t n, size; - nxt_buf_t *b, *fb, *next; - nxt_off_t rest; - nxt_http_request_t *r; - - b = obj; - r = data; + b = obj; + r = data; complete_buf: - fb = r->out; + fb = r->out; - if (nxt_slow_path(fb == NULL || r->error)) { - goto clean; - } + if (nxt_slow_path(fb == NULL || r->error)) { + goto clean; + } - rest = fb->file_end - fb->file_pos; - size = nxt_buf_mem_size(&b->mem); + rest = fb->file_end - fb->file_pos; + size = nxt_buf_mem_size(&b->mem); - size = nxt_min(rest, (nxt_off_t) size); + size = nxt_min(rest, (nxt_off_t)size); - n = nxt_file_read(fb->file, b->mem.start, size, fb->file_pos); + n = nxt_file_read(fb->file, b->mem.start, size, fb->file_pos); - if (nxt_slow_path(n == NXT_ERROR)) { - nxt_http_request_error_handler(task, r, r->proto.any); - goto clean; - } + if (nxt_slow_path(n == NXT_ERROR)) { + nxt_http_request_error_handler(task, r, r->proto.any); + goto clean; + } - next = b->next; + next = b->next; - if (n == rest) { - nxt_file_close(task, fb->file); - r->out = NULL; + if (n == rest) { + nxt_file_close(task, fb->file); + r->out = NULL; - b->next = nxt_http_buf_last(r); + b->next = nxt_http_buf_last(r); - } else { - fb->file_pos += n; - b->next = NULL; - } + } else { + fb->file_pos += n; + b->next = NULL; + } - b->mem.pos = b->mem.start; - b->mem.free = b->mem.pos + n; + b->mem.pos = b->mem.start; + b->mem.free = b->mem.pos + n; - nxt_http_request_send(task, r, b); + nxt_http_request_send(task, r, b); - if (next != NULL) { - b = next; - goto complete_buf; - } + if (next != NULL) { + b = next; + goto complete_buf; + } - return; + return; clean: - do { - next = b->next; + do { + next = b->next; - nxt_mp_free(r->mem_pool, b); - nxt_mp_release(r->mem_pool); + nxt_mp_free(r->mem_pool, b); + nxt_mp_release(r->mem_pool); - b = next; - } while (b != NULL); + b = next; + } while (b != NULL); - if (fb != NULL) { - nxt_file_close(task, fb->file); - r->out = NULL; - } + if (fb != NULL) { + nxt_file_close(task, fb->file); + r->out = NULL; + } } - -nxt_int_t -nxt_http_static_mtypes_init(nxt_mp_t *mp, nxt_lvlhsh_t *hash) -{ - nxt_str_t *type, exten; - nxt_int_t ret; - nxt_uint_t i; - - static const struct { - nxt_str_t type; - const char *exten; - } default_types[] = { - - { nxt_string("text/html"), ".html" }, - { nxt_string("text/html"), ".htm" }, - { nxt_string("text/css"), ".css" }, - - { nxt_string("image/svg+xml"), ".svg" }, - { nxt_string("image/webp"), ".webp" }, - { nxt_string("image/png"), ".png" }, - { nxt_string("image/apng"), ".apng" }, - { nxt_string("image/jpeg"), ".jpeg" }, - { nxt_string("image/jpeg"), ".jpg" }, - { nxt_string("image/gif"), ".gif" }, - { nxt_string("image/x-icon"), ".ico" }, - - { nxt_string("image/avif"), ".avif" }, - { nxt_string("image/avif-sequence"), ".avifs" }, - - { nxt_string("font/woff"), ".woff" }, - { nxt_string("font/woff2"), ".woff2" }, - { nxt_string("font/otf"), ".otf" }, - { nxt_string("font/ttf"), ".ttf" }, - - { nxt_string("text/plain"), ".txt" }, - { nxt_string("text/markdown"), ".md" }, - { nxt_string("text/x-rst"), ".rst" }, - - { nxt_string("application/javascript"), ".js" }, - { nxt_string("application/json"), ".json" }, - { nxt_string("application/xml"), ".xml" }, - { nxt_string("application/rss+xml"), ".rss" }, - { nxt_string("application/atom+xml"), ".atom" }, - { nxt_string("application/pdf"), ".pdf" }, - - { nxt_string("application/zip"), ".zip" }, - - { nxt_string("audio/mpeg"), ".mp3" }, - { nxt_string("audio/ogg"), ".ogg" }, - { nxt_string("audio/midi"), ".midi" }, - { nxt_string("audio/midi"), ".mid" }, - { nxt_string("audio/flac"), ".flac" }, - { nxt_string("audio/aac"), ".aac" }, - { nxt_string("audio/wav"), ".wav" }, - - { nxt_string("video/mpeg"), ".mpeg" }, - { nxt_string("video/mpeg"), ".mpg" }, - { nxt_string("video/mp4"), ".mp4" }, - { nxt_string("video/webm"), ".webm" }, - { nxt_string("video/x-msvideo"), ".avi" }, - - { nxt_string("application/octet-stream"), ".exe" }, - { nxt_string("application/octet-stream"), ".bin" }, - { nxt_string("application/octet-stream"), ".dll" }, - { nxt_string("application/octet-stream"), ".iso" }, - { nxt_string("application/octet-stream"), ".img" }, - { nxt_string("application/octet-stream"), ".msi" }, - - { nxt_string("application/octet-stream"), ".deb" }, - { nxt_string("application/octet-stream"), ".rpm" }, - - { nxt_string("application/x-httpd-php"), ".php" }, - }; - - for (i = 0; i < nxt_nitems(default_types); i++) { - type = (nxt_str_t *) &default_types[i].type; - - exten.start = (u_char *) default_types[i].exten; - exten.length = nxt_strlen(exten.start); - - ret = nxt_http_static_mtypes_hash_add(mp, hash, &exten, type); - if (nxt_slow_path(ret != NXT_OK)) { - return NXT_ERROR; - } +nxt_int_t nxt_http_static_mtypes_init(nxt_mp_t *mp, nxt_lvlhsh_t *hash) { + nxt_str_t *type, exten; + nxt_int_t ret; + nxt_uint_t i; + + static const struct { + nxt_str_t type; + const char *exten; + } default_types[] = { + + {nxt_string("text/html"), ".html"}, + {nxt_string("text/html"), ".htm"}, + {nxt_string("text/css"), ".css"}, + + {nxt_string("image/svg+xml"), ".svg"}, + {nxt_string("image/webp"), ".webp"}, + {nxt_string("image/png"), ".png"}, + {nxt_string("image/apng"), ".apng"}, + {nxt_string("image/jpeg"), ".jpeg"}, + {nxt_string("image/jpeg"), ".jpg"}, + {nxt_string("image/gif"), ".gif"}, + {nxt_string("image/x-icon"), ".ico"}, + + {nxt_string("image/avif"), ".avif"}, + {nxt_string("image/avif-sequence"), ".avifs"}, + + {nxt_string("font/woff"), ".woff"}, + {nxt_string("font/woff2"), ".woff2"}, + {nxt_string("font/otf"), ".otf"}, + {nxt_string("font/ttf"), ".ttf"}, + + {nxt_string("text/plain"), ".txt"}, + {nxt_string("text/markdown"), ".md"}, + {nxt_string("text/x-rst"), ".rst"}, + + {nxt_string("application/javascript"), ".js"}, + {nxt_string("application/json"), ".json"}, + {nxt_string("application/xml"), ".xml"}, + {nxt_string("application/rss+xml"), ".rss"}, + {nxt_string("application/atom+xml"), ".atom"}, + {nxt_string("application/pdf"), ".pdf"}, + + {nxt_string("application/zip"), ".zip"}, + + {nxt_string("audio/mpeg"), ".mp3"}, + {nxt_string("audio/ogg"), ".ogg"}, + {nxt_string("audio/midi"), ".midi"}, + {nxt_string("audio/midi"), ".mid"}, + {nxt_string("audio/flac"), ".flac"}, + {nxt_string("audio/aac"), ".aac"}, + {nxt_string("audio/wav"), ".wav"}, + + {nxt_string("video/mpeg"), ".mpeg"}, + {nxt_string("video/mpeg"), ".mpg"}, + {nxt_string("video/mp4"), ".mp4"}, + {nxt_string("video/webm"), ".webm"}, + {nxt_string("video/x-msvideo"), ".avi"}, + + {nxt_string("application/octet-stream"), ".exe"}, + {nxt_string("application/octet-stream"), ".bin"}, + {nxt_string("application/octet-stream"), ".dll"}, + {nxt_string("application/octet-stream"), ".iso"}, + {nxt_string("application/octet-stream"), ".img"}, + {nxt_string("application/octet-stream"), ".msi"}, + + {nxt_string("application/octet-stream"), ".deb"}, + {nxt_string("application/octet-stream"), ".rpm"}, + + {nxt_string("application/x-httpd-php"), ".php"}, + }; + + for (i = 0; i < nxt_nitems(default_types); i++) { + type = (nxt_str_t *)&default_types[i].type; + + exten.start = (u_char *)default_types[i].exten; + exten.length = nxt_strlen(exten.start); + + ret = nxt_http_static_mtypes_hash_add(mp, hash, &exten, type); + if (nxt_slow_path(ret != NXT_OK)) { + return NXT_ERROR; } + } - return NXT_OK; + return NXT_OK; } - -static const nxt_lvlhsh_proto_t nxt_http_static_mtypes_hash_proto - nxt_aligned(64) = -{ - NXT_LVLHSH_DEFAULT, - nxt_http_static_mtypes_hash_test, - nxt_http_static_mtypes_hash_alloc, - nxt_http_static_mtypes_hash_free, +static const nxt_lvlhsh_proto_t + nxt_http_static_mtypes_hash_proto nxt_aligned(64) = { + NXT_LVLHSH_DEFAULT, + nxt_http_static_mtypes_hash_test, + nxt_http_static_mtypes_hash_alloc, + nxt_http_static_mtypes_hash_free, }; - typedef struct { - nxt_str_t exten; - nxt_str_t *type; + nxt_str_t exten; + nxt_str_t *type; } nxt_http_static_mtype_t; +nxt_int_t nxt_http_static_mtypes_hash_add(nxt_mp_t *mp, nxt_lvlhsh_t *hash, + const nxt_str_t *exten, + nxt_str_t *type) { + nxt_lvlhsh_query_t lhq; + nxt_http_static_mtype_t *mtype; -nxt_int_t -nxt_http_static_mtypes_hash_add(nxt_mp_t *mp, nxt_lvlhsh_t *hash, - const nxt_str_t *exten, nxt_str_t *type) -{ - nxt_lvlhsh_query_t lhq; - nxt_http_static_mtype_t *mtype; - - mtype = nxt_mp_get(mp, sizeof(nxt_http_static_mtype_t)); - if (nxt_slow_path(mtype == NULL)) { - return NXT_ERROR; - } + mtype = nxt_mp_get(mp, sizeof(nxt_http_static_mtype_t)); + if (nxt_slow_path(mtype == NULL)) { + return NXT_ERROR; + } - mtype->exten = *exten; - mtype->type = type; + mtype->exten = *exten; + mtype->type = type; - lhq.key = *exten; - lhq.key_hash = nxt_djb_hash_lowcase(lhq.key.start, lhq.key.length); - lhq.replace = 1; - lhq.value = mtype; - lhq.proto = &nxt_http_static_mtypes_hash_proto; - lhq.pool = mp; + lhq.key = *exten; + lhq.key_hash = nxt_djb_hash_lowcase(lhq.key.start, lhq.key.length); + lhq.replace = 1; + lhq.value = mtype; + lhq.proto = &nxt_http_static_mtypes_hash_proto; + lhq.pool = mp; - return nxt_lvlhsh_insert(hash, &lhq); + return nxt_lvlhsh_insert(hash, &lhq); } +nxt_str_t *nxt_http_static_mtype_get(nxt_lvlhsh_t *hash, + const nxt_str_t *exten) { + nxt_lvlhsh_query_t lhq; + nxt_http_static_mtype_t *mtype; -nxt_str_t * -nxt_http_static_mtype_get(nxt_lvlhsh_t *hash, const nxt_str_t *exten) -{ - nxt_lvlhsh_query_t lhq; - nxt_http_static_mtype_t *mtype; + static nxt_str_t empty = nxt_string(""); - static nxt_str_t empty = nxt_string(""); + lhq.key = *exten; + lhq.key_hash = nxt_djb_hash_lowcase(lhq.key.start, lhq.key.length); + lhq.proto = &nxt_http_static_mtypes_hash_proto; - lhq.key = *exten; - lhq.key_hash = nxt_djb_hash_lowcase(lhq.key.start, lhq.key.length); - lhq.proto = &nxt_http_static_mtypes_hash_proto; + if (nxt_lvlhsh_find(hash, &lhq) == NXT_OK) { + mtype = lhq.value; + return mtype->type; + } - if (nxt_lvlhsh_find(hash, &lhq) == NXT_OK) { - mtype = lhq.value; - return mtype->type; - } - - return ∅ + return ∅ } +static nxt_int_t nxt_http_static_mtypes_hash_test(nxt_lvlhsh_query_t *lhq, + void *data) { + nxt_http_static_mtype_t *mtype; -static nxt_int_t -nxt_http_static_mtypes_hash_test(nxt_lvlhsh_query_t *lhq, void *data) -{ - nxt_http_static_mtype_t *mtype; - - mtype = data; + mtype = data; - return nxt_strcasestr_eq(&lhq->key, &mtype->exten) ? NXT_OK : NXT_DECLINED; + return nxt_strcasestr_eq(&lhq->key, &mtype->exten) ? NXT_OK : NXT_DECLINED; } - -static void * -nxt_http_static_mtypes_hash_alloc(void *data, size_t size) -{ - return nxt_mp_align(data, size, size); +static void *nxt_http_static_mtypes_hash_alloc(void *data, size_t size) { + return nxt_mp_align(data, size, size); } - -static void -nxt_http_static_mtypes_hash_free(void *data, void *p) -{ - nxt_mp_free(data, p); +static void nxt_http_static_mtypes_hash_free(void *data, void *p) { + nxt_mp_free(data, p); } diff --git a/src/nxt_http_variables.c b/src/nxt_http_variables.c index 3a1746b3a..45c13f8a8 100644 --- a/src/nxt_http_variables.c +++ b/src/nxt_http_variables.c @@ -7,773 +7,725 @@ #include #include - static nxt_int_t nxt_http_var_dollar(nxt_task_t *task, nxt_str_t *str, - void *ctx, void *data); + void *ctx, void *data); static nxt_int_t nxt_http_var_request_time(nxt_task_t *task, nxt_str_t *str, - void *ctx, void *data); + void *ctx, void *data); static nxt_int_t nxt_http_var_method(nxt_task_t *task, nxt_str_t *str, - void *ctx, void *data); + void *ctx, void *data); static nxt_int_t nxt_http_var_request_uri(nxt_task_t *task, nxt_str_t *str, - void *ctx, void *data); + void *ctx, void *data); static nxt_int_t nxt_http_var_uri(nxt_task_t *task, nxt_str_t *str, void *ctx, - void *data); + void *data); static nxt_int_t nxt_http_var_host(nxt_task_t *task, nxt_str_t *str, void *ctx, - void *data); + void *data); static nxt_int_t nxt_http_var_remote_addr(nxt_task_t *task, nxt_str_t *str, - void *ctx, void *data); + void *ctx, void *data); static nxt_int_t nxt_http_var_time_local(nxt_task_t *task, nxt_str_t *str, - void *ctx, void *data); + void *ctx, void *data); static u_char *nxt_http_log_date(u_char *buf, nxt_realtime_t *now, - struct tm *tm, size_t size, const char *format); + struct tm *tm, size_t size, + const char *format); static nxt_int_t nxt_http_var_request_line(nxt_task_t *task, nxt_str_t *str, - void *ctx, void *data); + void *ctx, void *data); static nxt_int_t nxt_http_var_request_id(nxt_task_t *task, nxt_str_t *str, - void *ctx, void *data); + void *ctx, void *data); static nxt_int_t nxt_http_var_status(nxt_task_t *task, nxt_str_t *str, - void *ctx, void *data); + void *ctx, void *data); static nxt_int_t nxt_http_var_body_bytes_sent(nxt_task_t *task, nxt_str_t *str, - void *ctx, void *data); + void *ctx, void *data); static nxt_int_t nxt_http_var_referer(nxt_task_t *task, nxt_str_t *str, - void *ctx, void *data); + void *ctx, void *data); static nxt_int_t nxt_http_var_user_agent(nxt_task_t *task, nxt_str_t *str, - void *ctx, void *data); + void *ctx, void *data); static nxt_int_t nxt_http_var_response_connection(nxt_task_t *task, - nxt_str_t *str, void *ctx, void *data); + nxt_str_t *str, void *ctx, + void *data); static nxt_int_t nxt_http_var_response_content_length(nxt_task_t *task, - nxt_str_t *str, void *ctx, void *data); + nxt_str_t *str, void *ctx, + void *data); static nxt_int_t nxt_http_var_response_transfer_encoding(nxt_task_t *task, - nxt_str_t *str, void *ctx, void *data); + nxt_str_t *str, + void *ctx, void *data); static nxt_int_t nxt_http_var_arg(nxt_task_t *task, nxt_str_t *str, void *ctx, - void *data); + void *data); static nxt_int_t nxt_http_var_header(nxt_task_t *task, nxt_str_t *str, - void *ctx, void *data); + void *ctx, void *data); static nxt_int_t nxt_http_var_cookie(nxt_task_t *task, nxt_str_t *str, - void *ctx, void *data); + void *ctx, void *data); static nxt_int_t nxt_http_var_response_header(nxt_task_t *task, nxt_str_t *str, - void *ctx, void *data); - + void *ctx, void *data); -static nxt_var_decl_t nxt_http_vars[] = { +static nxt_var_decl_t nxt_http_vars[] = { { .name = nxt_string("dollar"), .handler = nxt_http_var_dollar, .cacheable = 1, - }, { + }, + { .name = nxt_string("request_time"), .handler = nxt_http_var_request_time, .cacheable = 1, - }, { + }, + { .name = nxt_string("method"), .handler = nxt_http_var_method, .cacheable = 1, - }, { + }, + { .name = nxt_string("request_uri"), .handler = nxt_http_var_request_uri, .cacheable = 1, - }, { + }, + { .name = nxt_string("uri"), .handler = nxt_http_var_uri, .cacheable = 0, - }, { + }, + { .name = nxt_string("host"), .handler = nxt_http_var_host, .cacheable = 1, - }, { + }, + { .name = nxt_string("remote_addr"), .handler = nxt_http_var_remote_addr, .cacheable = 1, - }, { + }, + { .name = nxt_string("time_local"), .handler = nxt_http_var_time_local, .cacheable = 1, - }, { + }, + { .name = nxt_string("request_line"), .handler = nxt_http_var_request_line, .cacheable = 1, - }, { + }, + { .name = nxt_string("request_id"), .handler = nxt_http_var_request_id, .cacheable = 1, - }, { + }, + { .name = nxt_string("status"), .handler = nxt_http_var_status, .cacheable = 1, - }, { + }, + { .name = nxt_string("body_bytes_sent"), .handler = nxt_http_var_body_bytes_sent, .cacheable = 1, - }, { + }, + { .name = nxt_string("header_referer"), .handler = nxt_http_var_referer, .cacheable = 1, - }, { + }, + { .name = nxt_string("response_header_connection"), .handler = nxt_http_var_response_connection, .cacheable = 1, - }, { + }, + { .name = nxt_string("response_header_content_length"), .handler = nxt_http_var_response_content_length, .cacheable = 1, - }, { + }, + { .name = nxt_string("response_header_transfer_encoding"), .handler = nxt_http_var_response_transfer_encoding, .cacheable = 1, - }, { + }, + { .name = nxt_string("header_user_agent"), .handler = nxt_http_var_user_agent, .cacheable = 1, }, }; - -nxt_int_t -nxt_http_register_variables(void) -{ - return nxt_var_register(nxt_http_vars, nxt_nitems(nxt_http_vars)); +nxt_int_t nxt_http_register_variables(void) { + return nxt_var_register(nxt_http_vars, nxt_nitems(nxt_http_vars)); } +nxt_int_t nxt_http_unknown_var_ref(nxt_mp_t *mp, nxt_var_ref_t *ref, + nxt_str_t *name) { + int64_t hash; + nxt_str_t str, *lower; -nxt_int_t -nxt_http_unknown_var_ref(nxt_mp_t *mp, nxt_var_ref_t *ref, nxt_str_t *name) -{ - int64_t hash; - nxt_str_t str, *lower; - - if (nxt_str_start(name, "response_header_", 16)) { - ref->handler = nxt_http_var_response_header; - ref->cacheable = 0; - - str.start = name->start + 16; - str.length = name->length - 16; - - if (str.length == 0) { - return NXT_ERROR; - } - - lower = nxt_str_alloc(mp, str.length); - if (nxt_slow_path(lower == NULL)) { - return NXT_ERROR; - } + if (nxt_str_start(name, "response_header_", 16)) { + ref->handler = nxt_http_var_response_header; + ref->cacheable = 0; - nxt_memcpy_lowcase(lower->start, str.start, str.length); + str.start = name->start + 16; + str.length = name->length - 16; - ref->data = lower; + if (str.length == 0) { + return NXT_ERROR; + } - return NXT_OK; + lower = nxt_str_alloc(mp, str.length); + if (nxt_slow_path(lower == NULL)) { + return NXT_ERROR; } - if (nxt_str_start(name, "header_", 7)) { - ref->handler = nxt_http_var_header; - ref->cacheable = 1; + nxt_memcpy_lowcase(lower->start, str.start, str.length); - str.start = name->start + 7; - str.length = name->length - 7; + ref->data = lower; - if (str.length == 0) { - return NXT_ERROR; - } + return NXT_OK; + } - hash = nxt_http_header_hash(mp, &str); - if (nxt_slow_path(hash == -1)) { - return NXT_ERROR; - } + if (nxt_str_start(name, "header_", 7)) { + ref->handler = nxt_http_var_header; + ref->cacheable = 1; - } else if (nxt_str_start(name, "arg_", 4)) { - ref->handler = nxt_http_var_arg; - ref->cacheable = 1; + str.start = name->start + 7; + str.length = name->length - 7; - str.start = name->start + 4; - str.length = name->length - 4; + if (str.length == 0) { + return NXT_ERROR; + } + + hash = nxt_http_header_hash(mp, &str); + if (nxt_slow_path(hash == -1)) { + return NXT_ERROR; + } - if (str.length == 0) { - return NXT_ERROR; - } + } else if (nxt_str_start(name, "arg_", 4)) { + ref->handler = nxt_http_var_arg; + ref->cacheable = 1; - hash = nxt_http_argument_hash(mp, &str); - if (nxt_slow_path(hash == -1)) { - return NXT_ERROR; - } + str.start = name->start + 4; + str.length = name->length - 4; - } else if (nxt_str_start(name, "cookie_", 7)) { - ref->handler = nxt_http_var_cookie; - ref->cacheable = 1; + if (str.length == 0) { + return NXT_ERROR; + } - str.start = name->start + 7; - str.length = name->length - 7; + hash = nxt_http_argument_hash(mp, &str); + if (nxt_slow_path(hash == -1)) { + return NXT_ERROR; + } - if (str.length == 0) { - return NXT_ERROR; - } + } else if (nxt_str_start(name, "cookie_", 7)) { + ref->handler = nxt_http_var_cookie; + ref->cacheable = 1; - hash = nxt_http_cookie_hash(mp, &str); - if (nxt_slow_path(hash == -1)) { - return NXT_ERROR; - } + str.start = name->start + 7; + str.length = name->length - 7; - } else { - return NXT_ERROR; + if (str.length == 0) { + return NXT_ERROR; } - ref->data = nxt_var_field_new(mp, &str, (uint32_t) hash); - if (nxt_slow_path(ref->data == NULL)) { - return NXT_ERROR; + hash = nxt_http_cookie_hash(mp, &str); + if (nxt_slow_path(hash == -1)) { + return NXT_ERROR; } - return NXT_OK; -} - + } else { + return NXT_ERROR; + } -static nxt_int_t -nxt_http_var_dollar(nxt_task_t *task, nxt_str_t *str, void *ctx, void *data) -{ - nxt_str_set(str, "$"); + ref->data = nxt_var_field_new(mp, &str, (uint32_t)hash); + if (nxt_slow_path(ref->data == NULL)) { + return NXT_ERROR; + } - return NXT_OK; + return NXT_OK; } +static nxt_int_t nxt_http_var_dollar(nxt_task_t *task, nxt_str_t *str, + void *ctx, void *data) { + nxt_str_set(str, "$"); -static nxt_int_t -nxt_http_var_request_time(nxt_task_t *task, nxt_str_t *str, void *ctx, - void *data) -{ - u_char *p; - nxt_msec_t ms; - nxt_nsec_t now; - nxt_http_request_t *r; + return NXT_OK; +} - r = ctx; +static nxt_int_t nxt_http_var_request_time(nxt_task_t *task, nxt_str_t *str, + void *ctx, void *data) { + u_char *p; + nxt_msec_t ms; + nxt_nsec_t now; + nxt_http_request_t *r; - now = nxt_thread_monotonic_time(task->thread); - ms = (now - r->start_time) / 1000000; + r = ctx; - str->start = nxt_mp_nget(r->mem_pool, NXT_TIME_T_LEN + 4); - if (nxt_slow_path(str->start == NULL)) { - return NXT_ERROR; - } + now = nxt_thread_monotonic_time(task->thread); + ms = (now - r->start_time) / 1000000; - p = nxt_sprintf(str->start, str->start + NXT_TIME_T_LEN, "%T.%03M", - (nxt_time_t) ms / 1000, ms % 1000); + str->start = nxt_mp_nget(r->mem_pool, NXT_TIME_T_LEN + 4); + if (nxt_slow_path(str->start == NULL)) { + return NXT_ERROR; + } - str->length = p - str->start; + p = nxt_sprintf(str->start, str->start + NXT_TIME_T_LEN, "%T.%03M", + (nxt_time_t)ms / 1000, ms % 1000); - return NXT_OK; -} + str->length = p - str->start; + return NXT_OK; +} -static nxt_int_t -nxt_http_var_method(nxt_task_t *task, nxt_str_t *str, void *ctx, void *data) -{ - nxt_http_request_t *r; +static nxt_int_t nxt_http_var_method(nxt_task_t *task, nxt_str_t *str, + void *ctx, void *data) { + nxt_http_request_t *r; - r = ctx; + r = ctx; - *str = *r->method; + *str = *r->method; - return NXT_OK; + return NXT_OK; } +static nxt_int_t nxt_http_var_request_uri(nxt_task_t *task, nxt_str_t *str, + void *ctx, void *data) { + nxt_http_request_t *r; -static nxt_int_t -nxt_http_var_request_uri(nxt_task_t *task, nxt_str_t *str, void *ctx, - void *data) -{ - nxt_http_request_t *r; - - r = ctx; + r = ctx; - *str = r->target; + *str = r->target; - return NXT_OK; + return NXT_OK; } +static nxt_int_t nxt_http_var_uri(nxt_task_t *task, nxt_str_t *str, void *ctx, + void *data) { + nxt_http_request_t *r; -static nxt_int_t -nxt_http_var_uri(nxt_task_t *task, nxt_str_t *str, void *ctx, void *data) -{ - nxt_http_request_t *r; - - r = ctx; + r = ctx; - *str = *r->path; + *str = *r->path; - return NXT_OK; + return NXT_OK; } +static nxt_int_t nxt_http_var_host(nxt_task_t *task, nxt_str_t *str, void *ctx, + void *data) { + nxt_http_request_t *r; -static nxt_int_t -nxt_http_var_host(nxt_task_t *task, nxt_str_t *str, void *ctx, void *data) -{ - nxt_http_request_t *r; - - r = ctx; + r = ctx; - *str = r->host; + *str = r->host; - return NXT_OK; + return NXT_OK; } +static nxt_int_t nxt_http_var_remote_addr(nxt_task_t *task, nxt_str_t *str, + void *ctx, void *data) { + nxt_http_request_t *r; -static nxt_int_t -nxt_http_var_remote_addr(nxt_task_t *task, nxt_str_t *str, void *ctx, - void *data) -{ - nxt_http_request_t *r; - - r = ctx; + r = ctx; - str->length = r->remote->address_length; - str->start = nxt_sockaddr_address(r->remote); + str->length = r->remote->address_length; + str->start = nxt_sockaddr_address(r->remote); - return NXT_OK; + return NXT_OK; } +static nxt_int_t nxt_http_var_time_local(nxt_task_t *task, nxt_str_t *str, + void *ctx, void *data) { + nxt_http_request_t *r; -static nxt_int_t -nxt_http_var_time_local(nxt_task_t *task, nxt_str_t *str, void *ctx, void *data) -{ - nxt_http_request_t *r; + static nxt_time_string_t date_cache = { + (nxt_atomic_uint_t)-1, + nxt_http_log_date, + "%02d/%s/%4d:%02d:%02d:%02d %c%02d%02d", + nxt_length("31/Dec/1986:19:40:00 +0300"), + NXT_THREAD_TIME_LOCAL, + NXT_THREAD_TIME_SEC, + }; - static nxt_time_string_t date_cache = { - (nxt_atomic_uint_t) -1, - nxt_http_log_date, - "%02d/%s/%4d:%02d:%02d:%02d %c%02d%02d", - nxt_length("31/Dec/1986:19:40:00 +0300"), - NXT_THREAD_TIME_LOCAL, - NXT_THREAD_TIME_SEC, - }; + r = ctx; - r = ctx; + str->length = date_cache.size; - str->length = date_cache.size; + str->start = nxt_mp_nget(r->mem_pool, str->length); + if (nxt_slow_path(str->start == NULL)) { + return NXT_ERROR; + } - str->start = nxt_mp_nget(r->mem_pool, str->length); - if (nxt_slow_path(str->start == NULL)) { - return NXT_ERROR; - } + str->length = nxt_thread_time_string(task->thread, &date_cache, str->start) - + str->start; - str->length = nxt_thread_time_string(task->thread, &date_cache, str->start) - - str->start; - - return NXT_OK; + return NXT_OK; } +static u_char *nxt_http_log_date(u_char *buf, nxt_realtime_t *now, + struct tm *tm, size_t size, + const char *format) { + u_char sign; + time_t gmtoff; -static u_char * -nxt_http_log_date(u_char *buf, nxt_realtime_t *now, struct tm *tm, - size_t size, const char *format) -{ - u_char sign; - time_t gmtoff; + static const char *const month[] = {"Jan", "Feb", "Mar", "Apr", "May", "Jun", + "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"}; - static const char * const month[] = { "Jan", "Feb", "Mar", "Apr", "May", - "Jun", "Jul", "Aug", "Sep", "Oct", - "Nov", "Dec" }; + gmtoff = nxt_timezone(tm) / 60; - gmtoff = nxt_timezone(tm) / 60; + if (gmtoff < 0) { + gmtoff = -gmtoff; + sign = '-'; - if (gmtoff < 0) { - gmtoff = -gmtoff; - sign = '-'; + } else { + sign = '+'; + } - } else { - sign = '+'; - } - - return nxt_sprintf(buf, buf + size, format, - tm->tm_mday, month[tm->tm_mon], tm->tm_year + 1900, - tm->tm_hour, tm->tm_min, tm->tm_sec, - sign, gmtoff / 60, gmtoff % 60); + return nxt_sprintf(buf, buf + size, format, tm->tm_mday, month[tm->tm_mon], + tm->tm_year + 1900, tm->tm_hour, tm->tm_min, tm->tm_sec, + sign, gmtoff / 60, gmtoff % 60); } +static nxt_int_t nxt_http_var_request_line(nxt_task_t *task, nxt_str_t *str, + void *ctx, void *data) { + nxt_http_request_t *r; -static nxt_int_t -nxt_http_var_request_line(nxt_task_t *task, nxt_str_t *str, void *ctx, - void *data) -{ - nxt_http_request_t *r; - - r = ctx; + r = ctx; - *str = r->request_line; + *str = r->request_line; - return NXT_OK; + return NXT_OK; } +static nxt_int_t nxt_http_var_request_id(nxt_task_t *task, nxt_str_t *str, + void *ctx, void *data) { + nxt_random_t *rand; + nxt_http_request_t *r; -static nxt_int_t -nxt_http_var_request_id(nxt_task_t *task, nxt_str_t *str, void *ctx, - void *data) -{ - nxt_random_t *rand; - nxt_http_request_t *r; - - r = ctx; + r = ctx; - str->start = nxt_mp_nget(r->mem_pool, 32); - if (nxt_slow_path(str->start == NULL)) { - return NXT_ERROR; - } + str->start = nxt_mp_nget(r->mem_pool, 32); + if (nxt_slow_path(str->start == NULL)) { + return NXT_ERROR; + } - str->length = 32; + str->length = 32; - rand = &task->thread->random; + rand = &task->thread->random; - (void) nxt_sprintf(str->start, str->start + 32, "%08xD%08xD%08xD%08xD", - nxt_random(rand), nxt_random(rand), - nxt_random(rand), nxt_random(rand)); + (void)nxt_sprintf(str->start, str->start + 32, "%08xD%08xD%08xD%08xD", + nxt_random(rand), nxt_random(rand), nxt_random(rand), + nxt_random(rand)); - return NXT_OK; + return NXT_OK; } +static nxt_int_t nxt_http_var_body_bytes_sent(nxt_task_t *task, nxt_str_t *str, + void *ctx, void *data) { + u_char *p; + nxt_off_t bytes; + nxt_http_request_t *r; -static nxt_int_t -nxt_http_var_body_bytes_sent(nxt_task_t *task, nxt_str_t *str, void *ctx, - void *data) -{ - u_char *p; - nxt_off_t bytes; - nxt_http_request_t *r; - - r = ctx; + r = ctx; - str->start = nxt_mp_nget(r->mem_pool, NXT_OFF_T_LEN); - if (nxt_slow_path(str->start == NULL)) { - return NXT_ERROR; - } + str->start = nxt_mp_nget(r->mem_pool, NXT_OFF_T_LEN); + if (nxt_slow_path(str->start == NULL)) { + return NXT_ERROR; + } - bytes = nxt_http_proto[r->protocol].body_bytes_sent(task, r->proto); + bytes = nxt_http_proto[r->protocol].body_bytes_sent(task, r->proto); - p = nxt_sprintf(str->start, str->start + NXT_OFF_T_LEN, "%O", bytes); + p = nxt_sprintf(str->start, str->start + NXT_OFF_T_LEN, "%O", bytes); - str->length = p - str->start; + str->length = p - str->start; - return NXT_OK; + return NXT_OK; } +static nxt_int_t nxt_http_var_status(nxt_task_t *task, nxt_str_t *str, + void *ctx, void *data) { + nxt_http_request_t *r; -static nxt_int_t -nxt_http_var_status(nxt_task_t *task, nxt_str_t *str, void *ctx, void *data) -{ - nxt_http_request_t *r; - - r = ctx; + r = ctx; - str->start = nxt_mp_nget(r->mem_pool, 3); - if (nxt_slow_path(str->start == NULL)) { - return NXT_ERROR; - } + str->start = nxt_mp_nget(r->mem_pool, 3); + if (nxt_slow_path(str->start == NULL)) { + return NXT_ERROR; + } - (void) nxt_sprintf(str->start, str->start + 3, "%03d", r->status); + (void)nxt_sprintf(str->start, str->start + 3, "%03d", r->status); - str->length = 3; + str->length = 3; - return NXT_OK; + return NXT_OK; } +static nxt_int_t nxt_http_var_referer(nxt_task_t *task, nxt_str_t *str, + void *ctx, void *data) { + nxt_http_request_t *r; -static nxt_int_t -nxt_http_var_referer(nxt_task_t *task, nxt_str_t *str, void *ctx, void *data) -{ - nxt_http_request_t *r; - - r = ctx; + r = ctx; - if (r->referer != NULL) { - str->start = r->referer->value; - str->length = r->referer->value_length; + if (r->referer != NULL) { + str->start = r->referer->value; + str->length = r->referer->value_length; - } else { - nxt_str_null(str); - } + } else { + nxt_str_null(str); + } - return NXT_OK; + return NXT_OK; } +static nxt_int_t nxt_http_var_user_agent(nxt_task_t *task, nxt_str_t *str, + void *ctx, void *data) { + nxt_http_request_t *r; -static nxt_int_t -nxt_http_var_user_agent(nxt_task_t *task, nxt_str_t *str, void *ctx, void *data) -{ - nxt_http_request_t *r; - - r = ctx; + r = ctx; - if (r->user_agent != NULL) { - str->start = r->user_agent->value; - str->length = r->user_agent->value_length; + if (r->user_agent != NULL) { + str->start = r->user_agent->value; + str->length = r->user_agent->value_length; - } else { - nxt_str_null(str); - } + } else { + nxt_str_null(str); + } - return NXT_OK; + return NXT_OK; } +static nxt_int_t nxt_http_var_response_connection(nxt_task_t *task, + nxt_str_t *str, void *ctx, + void *data) { + nxt_int_t conn; + nxt_bool_t http11; + nxt_h1proto_t *h1p; + nxt_http_request_t *r; -static nxt_int_t -nxt_http_var_response_connection(nxt_task_t *task, nxt_str_t *str, void *ctx, - void *data) -{ - nxt_int_t conn; - nxt_bool_t http11; - nxt_h1proto_t *h1p; - nxt_http_request_t *r; - - static const nxt_str_t connection[3] = { - nxt_string("close"), - nxt_string("keep-alive"), - nxt_string("Upgrade"), - }; + static const nxt_str_t connection[3] = { + nxt_string("close"), + nxt_string("keep-alive"), + nxt_string("Upgrade"), + }; - r = ctx; - h1p = r->proto.h1; + r = ctx; + h1p = r->proto.h1; - conn = -1; + conn = -1; - if (r->websocket_handshake && r->status == NXT_HTTP_SWITCHING_PROTOCOLS) { - conn = 2; + if (r->websocket_handshake && r->status == NXT_HTTP_SWITCHING_PROTOCOLS) { + conn = 2; - } else { - http11 = nxt_h1p_is_http11(h1p); + } else { + http11 = nxt_h1p_is_http11(h1p); - if (http11 ^ h1p->keepalive) { - conn = h1p->keepalive; - } + if (http11 ^ h1p->keepalive) { + conn = h1p->keepalive; } + } - if (conn >= 0) { - *str = connection[conn]; + if (conn >= 0) { + *str = connection[conn]; - } else { - nxt_str_null(str); - } + } else { + nxt_str_null(str); + } - return NXT_OK; + return NXT_OK; } +static nxt_int_t nxt_http_var_response_content_length(nxt_task_t *task, + nxt_str_t *str, void *ctx, + void *data) { + u_char *p; + nxt_http_request_t *r; -static nxt_int_t -nxt_http_var_response_content_length(nxt_task_t *task, nxt_str_t *str, - void *ctx, void *data) -{ - u_char *p; - nxt_http_request_t *r; + r = ctx; - r = ctx; + if (r->resp.content_length != NULL) { + str->length = r->resp.content_length->value_length; + str->start = r->resp.content_length->value; - if (r->resp.content_length != NULL) { - str->length = r->resp.content_length->value_length; - str->start = r->resp.content_length->value; + return NXT_OK; + } - return NXT_OK; + if (r->resp.content_length_n >= 0) { + str->start = nxt_mp_nget(r->mem_pool, NXT_OFF_T_LEN); + if (str->start == NULL) { + return NXT_ERROR; } - if (r->resp.content_length_n >= 0) { - str->start = nxt_mp_nget(r->mem_pool, NXT_OFF_T_LEN); - if (str->start == NULL) { - return NXT_ERROR; - } - - p = nxt_sprintf(str->start, str->start + NXT_OFF_T_LEN, - "%O", r->resp.content_length_n); + p = nxt_sprintf(str->start, str->start + NXT_OFF_T_LEN, "%O", + r->resp.content_length_n); - str->length = p - str->start; + str->length = p - str->start; - return NXT_OK; - } + return NXT_OK; + } - nxt_str_null(str); + nxt_str_null(str); - return NXT_OK; + return NXT_OK; } +static nxt_int_t nxt_http_var_response_transfer_encoding(nxt_task_t *task, + nxt_str_t *str, + void *ctx, + void *data) { + nxt_http_request_t *r; -static nxt_int_t -nxt_http_var_response_transfer_encoding(nxt_task_t *task, nxt_str_t *str, - void *ctx, void *data) -{ - nxt_http_request_t *r; - - r = ctx; + r = ctx; - if (r->proto.h1->chunked) { - nxt_str_set(str, "chunked"); + if (r->proto.h1->chunked) { + nxt_str_set(str, "chunked"); - } else { - nxt_str_null(str); - } + } else { + nxt_str_null(str); + } - return NXT_OK; + return NXT_OK; } +static nxt_int_t nxt_http_var_arg(nxt_task_t *task, nxt_str_t *str, void *ctx, + void *data) { + nxt_array_t *args; + nxt_var_field_t *vf; + nxt_http_request_t *r; + nxt_http_name_value_t *nv, *start; -static nxt_int_t -nxt_http_var_arg(nxt_task_t *task, nxt_str_t *str, void *ctx, void *data) -{ - nxt_array_t *args; - nxt_var_field_t *vf; - nxt_http_request_t *r; - nxt_http_name_value_t *nv, *start; - - r = ctx; - vf = data; - - args = nxt_http_arguments_parse(r); - if (nxt_slow_path(args == NULL)) { - return NXT_ERROR; - } + r = ctx; + vf = data; - start = args->elts; - nv = start + args->nelts - 1; + args = nxt_http_arguments_parse(r); + if (nxt_slow_path(args == NULL)) { + return NXT_ERROR; + } - while (nv >= start) { + start = args->elts; + nv = start + args->nelts - 1; - if (vf->hash == nv->hash - && vf->name.length == nv->name_length - && memcmp(vf->name.start, nv->name, nv->name_length) == 0) - { - str->start = nv->value; - str->length = nv->value_length; + while (nv >= start) { - return NXT_OK; - } + if (vf->hash == nv->hash && vf->name.length == nv->name_length && + memcmp(vf->name.start, nv->name, nv->name_length) == 0) { + str->start = nv->value; + str->length = nv->value_length; - nv--; + return NXT_OK; } - nxt_str_null(str); + nv--; + } - return NXT_OK; -} + nxt_str_null(str); + return NXT_OK; +} -static nxt_int_t -nxt_http_var_header(nxt_task_t *task, nxt_str_t *str, void *ctx, void *data) -{ - nxt_var_field_t *vf; - nxt_http_field_t *f; - nxt_http_request_t *r; - - r = ctx; - vf = data; +static nxt_int_t nxt_http_var_header(nxt_task_t *task, nxt_str_t *str, + void *ctx, void *data) { + nxt_var_field_t *vf; + nxt_http_field_t *f; + nxt_http_request_t *r; - nxt_list_each(f, r->fields) { + r = ctx; + vf = data; - if (vf->hash == f->hash - && vf->name.length == f->name_length - && nxt_strncasecmp(vf->name.start, f->name, f->name_length) == 0) - { - str->start = f->value; - str->length = f->value_length; + nxt_list_each(f, r->fields) { - return NXT_OK; - } + if (vf->hash == f->hash && vf->name.length == f->name_length && + nxt_strncasecmp(vf->name.start, f->name, f->name_length) == 0) { + str->start = f->value; + str->length = f->value_length; - } nxt_list_loop; + return NXT_OK; + } + } + nxt_list_loop; - nxt_str_null(str); + nxt_str_null(str); - return NXT_OK; + return NXT_OK; } +static nxt_int_t nxt_http_var_cookie(nxt_task_t *task, nxt_str_t *str, + void *ctx, void *data) { + nxt_array_t *cookies; + nxt_var_field_t *vf; + nxt_http_request_t *r; + nxt_http_name_value_t *nv, *end; -static nxt_int_t -nxt_http_var_cookie(nxt_task_t *task, nxt_str_t *str, void *ctx, void *data) -{ - nxt_array_t *cookies; - nxt_var_field_t *vf; - nxt_http_request_t *r; - nxt_http_name_value_t *nv, *end; - - r = ctx; - vf = data; - - cookies = nxt_http_cookies_parse(r); - if (nxt_slow_path(cookies == NULL)) { - return NXT_ERROR; - } + r = ctx; + vf = data; - nv = cookies->elts; - end = nv + cookies->nelts; + cookies = nxt_http_cookies_parse(r); + if (nxt_slow_path(cookies == NULL)) { + return NXT_ERROR; + } - while (nv < end) { + nv = cookies->elts; + end = nv + cookies->nelts; - if (vf->hash == nv->hash - && vf->name.length == nv->name_length - && memcmp(vf->name.start, nv->name, nv->name_length) == 0) - { - str->start = nv->value; - str->length = nv->value_length; + while (nv < end) { - return NXT_OK; - } + if (vf->hash == nv->hash && vf->name.length == nv->name_length && + memcmp(vf->name.start, nv->name, nv->name_length) == 0) { + str->start = nv->value; + str->length = nv->value_length; - nv++; + return NXT_OK; } - nxt_str_null(str); + nv++; + } - return NXT_OK; + nxt_str_null(str); + + return NXT_OK; } +static int nxt_http_field_name_cmp(nxt_str_t *name, nxt_http_field_t *field) { + size_t i; + u_char c1, c2; -static int -nxt_http_field_name_cmp(nxt_str_t *name, nxt_http_field_t *field) -{ - size_t i; - u_char c1, c2; + if (name->length != field->name_length) { + return 1; + } - if (name->length != field->name_length) { - return 1; - } + for (i = 0; i < name->length; i++) { + c1 = name->start[i]; + c2 = field->name[i]; - for (i = 0; i < name->length; i++) { - c1 = name->start[i]; - c2 = field->name[i]; + if (c2 >= 'A' && c2 <= 'Z') { + c2 |= 0x20; - if (c2 >= 'A' && c2 <= 'Z') { - c2 |= 0x20; - - } else if (c2 == '-') { - c2 = '_'; - } + } else if (c2 == '-') { + c2 = '_'; + } - if (c1 != c2) { - return 1; - } + if (c1 != c2) { + return 1; } + } - return 0; + return 0; } +static nxt_int_t nxt_http_var_response_header(nxt_task_t *task, nxt_str_t *str, + void *ctx, void *data) { + nxt_str_t *name; + nxt_http_field_t *f; + nxt_http_request_t *r; -static nxt_int_t -nxt_http_var_response_header(nxt_task_t *task, nxt_str_t *str, void *ctx, - void *data) -{ - nxt_str_t *name; - nxt_http_field_t *f; - nxt_http_request_t *r; - - r = ctx; - name = data; - - nxt_list_each(f, r->resp.fields) { + r = ctx; + name = data; - if (f->skip) { - continue; - } + nxt_list_each(f, r->resp.fields) { - if (nxt_http_field_name_cmp(name, f) == 0) { - str->start = f->value; - str->length = f->value_length; + if (f->skip) { + continue; + } - return NXT_OK; - } + if (nxt_http_field_name_cmp(name, f) == 0) { + str->start = f->value; + str->length = f->value_length; - } nxt_list_loop; + return NXT_OK; + } + } + nxt_list_loop; - nxt_str_null(str); + nxt_str_null(str); - return NXT_OK; + return NXT_OK; } diff --git a/src/nxt_http_websocket.c b/src/nxt_http_websocket.c index 1968633ea..45db98e20 100644 --- a/src/nxt_http_websocket.c +++ b/src/nxt_http_websocket.c @@ -11,145 +11,133 @@ #include #include - static void nxt_http_websocket_client(nxt_task_t *task, void *obj, void *data); static void nxt_http_websocket_error_handler(nxt_task_t *task, void *obj, - void *data); - + void *data); -const nxt_http_request_state_t nxt_http_websocket - nxt_aligned(64) = -{ +const nxt_http_request_state_t nxt_http_websocket nxt_aligned(64) = { .ready_handler = nxt_http_websocket_client, .error_handler = nxt_http_websocket_error_handler, }; +static void nxt_http_websocket_client(nxt_task_t *task, void *obj, void *data) { + size_t frame_size, used_size, copy_size, buf_free_size; + size_t chunk_copy_size; + nxt_buf_t *out, *buf, **out_tail, *b, *next; + nxt_int_t res; + nxt_http_request_t *r; + nxt_request_rpc_data_t *req_rpc_data; + nxt_websocket_header_t *wsh; -static void -nxt_http_websocket_client(nxt_task_t *task, void *obj, void *data) -{ - size_t frame_size, used_size, copy_size, buf_free_size; - size_t chunk_copy_size; - nxt_buf_t *out, *buf, **out_tail, *b, *next; - nxt_int_t res; - nxt_http_request_t *r; - nxt_request_rpc_data_t *req_rpc_data; - nxt_websocket_header_t *wsh; - - r = obj; - req_rpc_data = r->req_rpc_data; + r = obj; + req_rpc_data = r->req_rpc_data; - if (nxt_slow_path(req_rpc_data == NULL)) { - nxt_debug(task, "websocket client frame for destroyed request"); + if (nxt_slow_path(req_rpc_data == NULL)) { + nxt_debug(task, "websocket client frame for destroyed request"); - return; - } - - nxt_debug(task, "http websocket client frame"); + return; + } - wsh = (nxt_websocket_header_t *) r->ws_frame->mem.pos; + nxt_debug(task, "http websocket client frame"); - frame_size = nxt_websocket_frame_header_size(wsh) - + nxt_websocket_frame_payload_len(wsh); + wsh = (nxt_websocket_header_t *)r->ws_frame->mem.pos; - buf = NULL; - buf_free_size = 0; - out = NULL; - out_tail = &out; + frame_size = nxt_websocket_frame_header_size(wsh) + + nxt_websocket_frame_payload_len(wsh); - b = r->ws_frame; + buf = NULL; + buf_free_size = 0; + out = NULL; + out_tail = &out; - while (b != NULL && frame_size > 0) { - used_size = nxt_buf_mem_used_size(&b->mem); - copy_size = nxt_min(used_size, frame_size); + b = r->ws_frame; - while (copy_size > 0) { - if (buf == NULL || buf_free_size == 0) { - buf_free_size = nxt_min(frame_size, PORT_MMAP_DATA_SIZE); + while (b != NULL && frame_size > 0) { + used_size = nxt_buf_mem_used_size(&b->mem); + copy_size = nxt_min(used_size, frame_size); - buf = nxt_port_mmap_get_buf(task, &req_rpc_data->app->outgoing, - buf_free_size); + while (copy_size > 0) { + if (buf == NULL || buf_free_size == 0) { + buf_free_size = nxt_min(frame_size, PORT_MMAP_DATA_SIZE); - *out_tail = buf; - out_tail = &buf->next; - } + buf = nxt_port_mmap_get_buf(task, &req_rpc_data->app->outgoing, + buf_free_size); - chunk_copy_size = nxt_min(buf_free_size, copy_size); + *out_tail = buf; + out_tail = &buf->next; + } - buf->mem.free = nxt_cpymem(buf->mem.free, b->mem.pos, - chunk_copy_size); + chunk_copy_size = nxt_min(buf_free_size, copy_size); - copy_size -= chunk_copy_size; - b->mem.pos += chunk_copy_size; - buf_free_size -= chunk_copy_size; - } + buf->mem.free = nxt_cpymem(buf->mem.free, b->mem.pos, chunk_copy_size); - frame_size -= copy_size; - next = b->next; - b->next = NULL; + copy_size -= chunk_copy_size; + b->mem.pos += chunk_copy_size; + buf_free_size -= chunk_copy_size; + } - if (nxt_buf_mem_used_size(&b->mem) == 0) { - nxt_work_queue_add(&task->thread->engine->fast_work_queue, - b->completion_handler, task, b, b->parent); + frame_size -= copy_size; + next = b->next; + b->next = NULL; - r->ws_frame = next; - } + if (nxt_buf_mem_used_size(&b->mem) == 0) { + nxt_work_queue_add(&task->thread->engine->fast_work_queue, + b->completion_handler, task, b, b->parent); - b = next; + r->ws_frame = next; } - res = nxt_port_socket_write(task, req_rpc_data->app_port, - NXT_PORT_MSG_WEBSOCKET, -1, - req_rpc_data->stream, - task->thread->engine->port->id, out); - if (nxt_slow_path(res != NXT_OK)) { - // TODO: handle - } + b = next; + } + + res = nxt_port_socket_write(task, req_rpc_data->app_port, + NXT_PORT_MSG_WEBSOCKET, -1, req_rpc_data->stream, + task->thread->engine->port->id, out); + if (nxt_slow_path(res != NXT_OK)) { + // TODO: handle + } - b = r->ws_frame; + b = r->ws_frame; - if (b != NULL) { - used_size = nxt_buf_mem_used_size(&b->mem); + if (b != NULL) { + used_size = nxt_buf_mem_used_size(&b->mem); - if (used_size > 0) { - nxt_memmove(b->mem.start, b->mem.pos, used_size); + if (used_size > 0) { + nxt_memmove(b->mem.start, b->mem.pos, used_size); - b->mem.pos = b->mem.start; - b->mem.free = b->mem.start + used_size; - } + b->mem.pos = b->mem.start; + b->mem.free = b->mem.start + used_size; } + } - nxt_http_request_ws_frame_start(task, r, r->ws_frame); + nxt_http_request_ws_frame_start(task, r, r->ws_frame); } +static void nxt_http_websocket_error_handler(nxt_task_t *task, void *obj, + void *data) { + nxt_http_request_t *r; + nxt_request_rpc_data_t *req_rpc_data; -static void -nxt_http_websocket_error_handler(nxt_task_t *task, void *obj, void *data) -{ - nxt_http_request_t *r; - nxt_request_rpc_data_t *req_rpc_data; - - nxt_debug(task, "http websocket error handler"); + nxt_debug(task, "http websocket error handler"); - r = obj; - req_rpc_data = r->req_rpc_data; + r = obj; + req_rpc_data = r->req_rpc_data; - if (req_rpc_data == NULL) { - nxt_debug(task, " req_rpc_data is NULL"); - goto close_handler; - } + if (req_rpc_data == NULL) { + nxt_debug(task, " req_rpc_data is NULL"); + goto close_handler; + } - if (req_rpc_data->app_port == NULL) { - nxt_debug(task, " app_port is NULL"); - goto close_handler; - } + if (req_rpc_data->app_port == NULL) { + nxt_debug(task, " app_port is NULL"); + goto close_handler; + } - (void) nxt_port_socket_write(task, req_rpc_data->app_port, - NXT_PORT_MSG_WEBSOCKET_LAST, - -1, req_rpc_data->stream, - task->thread->engine->port->id, NULL); + (void)nxt_port_socket_write( + task, req_rpc_data->app_port, NXT_PORT_MSG_WEBSOCKET_LAST, -1, + req_rpc_data->stream, task->thread->engine->port->id, NULL); close_handler: - nxt_http_request_close_handler(task, obj, data); + nxt_http_request_close_handler(task, obj, data); } diff --git a/src/nxt_isolation.c b/src/nxt_isolation.c index 909a43f4b..e0bff8845 100644 --- a/src/nxt_isolation.c +++ b/src/nxt_isolation.c @@ -12,49 +12,58 @@ #include #endif - static nxt_int_t nxt_isolation_set(nxt_task_t *task, - nxt_conf_value_t *isolation, nxt_process_t *process); + nxt_conf_value_t *isolation, + nxt_process_t *process); #if (NXT_HAVE_CGROUP) static nxt_int_t nxt_isolation_set_cgroup(nxt_task_t *task, - nxt_conf_value_t *isolation, nxt_process_t *process); + nxt_conf_value_t *isolation, + nxt_process_t *process); #endif #if (NXT_HAVE_LINUX_NS) static nxt_int_t nxt_isolation_set_namespaces(nxt_task_t *task, - nxt_conf_value_t *isolation, nxt_process_t *process); + nxt_conf_value_t *isolation, + nxt_process_t *process); static nxt_int_t nxt_isolation_clone_flags(nxt_task_t *task, - nxt_conf_value_t *namespaces, nxt_clone_t *clone); + nxt_conf_value_t *namespaces, + nxt_clone_t *clone); #endif #if (NXT_HAVE_CLONE_NEWUSER) static nxt_int_t nxt_isolation_set_creds(nxt_task_t *task, - nxt_conf_value_t *isolation, nxt_process_t *process); + nxt_conf_value_t *isolation, + nxt_process_t *process); static nxt_int_t nxt_isolation_credential_map(nxt_task_t *task, - nxt_mp_t *mem_pool, nxt_conf_value_t *map_array, - nxt_clone_credential_map_t *map); + nxt_mp_t *mem_pool, + nxt_conf_value_t *map_array, + nxt_clone_credential_map_t *map); static nxt_int_t nxt_isolation_vldt_creds(nxt_task_t *task, - nxt_process_t *process); + nxt_process_t *process); #endif #if (NXT_HAVE_ISOLATION_ROOTFS) static nxt_int_t nxt_isolation_set_rootfs(nxt_task_t *task, - nxt_conf_value_t *isolation, nxt_process_t *process); + nxt_conf_value_t *isolation, + nxt_process_t *process); static nxt_int_t nxt_isolation_set_automount(nxt_task_t *task, - nxt_conf_value_t *isolation, nxt_process_t *process); + nxt_conf_value_t *isolation, + nxt_process_t *process); static nxt_int_t nxt_isolation_set_mounts(nxt_task_t *task, - nxt_process_t *process, nxt_str_t *app_type); + nxt_process_t *process, + nxt_str_t *app_type); static nxt_int_t nxt_isolation_set_lang_mounts(nxt_task_t *task, - nxt_process_t *process, nxt_array_t *syspaths); + nxt_process_t *process, + nxt_array_t *syspaths); static int nxt_cdecl nxt_isolation_mount_compare(const void *v1, - const void *v2); + const void *v2); static void nxt_isolation_unmount_all(nxt_task_t *task, nxt_process_t *process); #if (NXT_HAVE_LINUX_PIVOT_ROOT) && (NXT_HAVE_CLONE_NEWNS) static nxt_int_t nxt_isolation_pivot_root(nxt_task_t *task, const char *rootfs); static nxt_int_t nxt_isolation_make_private_mount(nxt_task_t *task, - const char *rootfs); + const char *rootfs); nxt_inline int nxt_pivot_root(const char *new_root, const char *old_root); #endif @@ -63,1061 +72,1006 @@ static nxt_int_t nxt_isolation_chroot(nxt_task_t *task, const char *path); #if (NXT_HAVE_PR_SET_NO_NEW_PRIVS) static nxt_int_t nxt_isolation_set_new_privs(nxt_task_t *task, - nxt_conf_value_t *isolation, nxt_process_t *process); + nxt_conf_value_t *isolation, + nxt_process_t *process); #endif +nxt_int_t nxt_isolation_main_prefork(nxt_task_t *task, nxt_process_t *process, + nxt_mp_t *mp) { + nxt_int_t cap_setid; + nxt_int_t ret; + nxt_runtime_t *rt; + nxt_common_app_conf_t *app_conf; -nxt_int_t -nxt_isolation_main_prefork(nxt_task_t *task, nxt_process_t *process, - nxt_mp_t *mp) -{ - nxt_int_t cap_setid; - nxt_int_t ret; - nxt_runtime_t *rt; - nxt_common_app_conf_t *app_conf; - - rt = task->thread->runtime; - app_conf = process->data.app; - cap_setid = rt->capabilities.setid; + rt = task->thread->runtime; + app_conf = process->data.app; + cap_setid = rt->capabilities.setid; #if (NXT_HAVE_PR_SET_NO_NEW_PRIVS) - process->isolation.new_privs = 1; + process->isolation.new_privs = 1; #endif - if (app_conf->isolation != NULL) { - ret = nxt_isolation_set(task, app_conf->isolation, process); - if (nxt_slow_path(ret != NXT_OK)) { - return ret; - } + if (app_conf->isolation != NULL) { + ret = nxt_isolation_set(task, app_conf->isolation, process); + if (nxt_slow_path(ret != NXT_OK)) { + return ret; } + } #if (NXT_HAVE_CLONE_NEWUSER) - if (nxt_is_clone_flag_set(process->isolation.clone.flags, NEWUSER)) { - cap_setid = 1; - } + if (nxt_is_clone_flag_set(process->isolation.clone.flags, NEWUSER)) { + cap_setid = 1; + } #endif - if (cap_setid) { - ret = nxt_process_creds_set(task, process, &app_conf->user, - &app_conf->group); + if (cap_setid) { + ret = + nxt_process_creds_set(task, process, &app_conf->user, &app_conf->group); - if (nxt_slow_path(ret != NXT_OK)) { - return ret; - } + if (nxt_slow_path(ret != NXT_OK)) { + return ret; + } - } else { - if (!nxt_str_eq(&app_conf->user, (u_char *) rt->user_cred.user, - nxt_strlen(rt->user_cred.user))) - { - nxt_alert(task, "cannot set user \"%V\" for app \"%V\": " - "missing capabilities", &app_conf->user, &app_conf->name); + } else { + if (!nxt_str_eq(&app_conf->user, (u_char *)rt->user_cred.user, + nxt_strlen(rt->user_cred.user))) { + nxt_alert(task, + "cannot set user \"%V\" for app \"%V\": " + "missing capabilities", + &app_conf->user, &app_conf->name); - return NXT_ERROR; - } + return NXT_ERROR; + } - if (app_conf->group.length > 0 - && !nxt_str_eq(&app_conf->group, (u_char *) rt->group, - nxt_strlen(rt->group))) - { - nxt_alert(task, "cannot set group \"%V\" for app \"%V\": " - "missing capabilities", &app_conf->group, - &app_conf->name); + if (app_conf->group.length > 0 && + !nxt_str_eq(&app_conf->group, (u_char *)rt->group, + nxt_strlen(rt->group))) { + nxt_alert(task, + "cannot set group \"%V\" for app \"%V\": " + "missing capabilities", + &app_conf->group, &app_conf->name); - return NXT_ERROR; - } + return NXT_ERROR; } + } #if (NXT_HAVE_ISOLATION_ROOTFS) - if (process->isolation.rootfs != NULL) { - nxt_int_t has_mnt; + if (process->isolation.rootfs != NULL) { + nxt_int_t has_mnt; - ret = nxt_isolation_set_mounts(task, process, &app_conf->type); - if (nxt_slow_path(ret != NXT_OK)) { - return ret; - } + ret = nxt_isolation_set_mounts(task, process, &app_conf->type); + if (nxt_slow_path(ret != NXT_OK)) { + return ret; + } #if (NXT_HAVE_CLONE_NEWNS) - has_mnt = nxt_is_clone_flag_set(process->isolation.clone.flags, NEWNS); + has_mnt = nxt_is_clone_flag_set(process->isolation.clone.flags, NEWNS); #else - has_mnt = 0; + has_mnt = 0; #endif - if (process->user_cred->uid == 0 && !has_mnt) { - nxt_log(task, NXT_LOG_WARN, - "setting user \"root\" with \"rootfs\" is unsafe without " - "\"mount\" namespace isolation"); - } + if (process->user_cred->uid == 0 && !has_mnt) { + nxt_log(task, NXT_LOG_WARN, + "setting user \"root\" with \"rootfs\" is unsafe without " + "\"mount\" namespace isolation"); } + } #endif #if (NXT_HAVE_CLONE_NEWUSER) - ret = nxt_isolation_vldt_creds(task, process); - if (nxt_slow_path(ret != NXT_OK)) { - return ret; - } + ret = nxt_isolation_vldt_creds(task, process); + if (nxt_slow_path(ret != NXT_OK)) { + return ret; + } #endif - return NXT_OK; + return NXT_OK; } - -static nxt_int_t -nxt_isolation_set(nxt_task_t *task, nxt_conf_value_t *isolation, - nxt_process_t *process) -{ +static nxt_int_t nxt_isolation_set(nxt_task_t *task, + nxt_conf_value_t *isolation, + nxt_process_t *process) { #if (NXT_HAVE_CGROUP) - if (nxt_slow_path(nxt_isolation_set_cgroup(task, isolation, process) - != NXT_OK)) - { - return NXT_ERROR; - } + if (nxt_slow_path(nxt_isolation_set_cgroup(task, isolation, process) != + NXT_OK)) { + return NXT_ERROR; + } #endif #if (NXT_HAVE_LINUX_NS) - if (nxt_slow_path(nxt_isolation_set_namespaces(task, isolation, process) - != NXT_OK)) - { - return NXT_ERROR; - } + if (nxt_slow_path(nxt_isolation_set_namespaces(task, isolation, process) != + NXT_OK)) { + return NXT_ERROR; + } #endif #if (NXT_HAVE_CLONE_NEWUSER) - if (nxt_slow_path(nxt_isolation_set_creds(task, isolation, process) - != NXT_OK)) - { - return NXT_ERROR; - } + if (nxt_slow_path(nxt_isolation_set_creds(task, isolation, process) != + NXT_OK)) { + return NXT_ERROR; + } #endif #if (NXT_HAVE_ISOLATION_ROOTFS) - if (nxt_slow_path(nxt_isolation_set_rootfs(task, isolation, process) - != NXT_OK)) - { - return NXT_ERROR; - } + if (nxt_slow_path(nxt_isolation_set_rootfs(task, isolation, process) != + NXT_OK)) { + return NXT_ERROR; + } - if (nxt_slow_path(nxt_isolation_set_automount(task, isolation, process) - != NXT_OK)) - { - return NXT_ERROR; - } + if (nxt_slow_path(nxt_isolation_set_automount(task, isolation, process) != + NXT_OK)) { + return NXT_ERROR; + } #endif #if (NXT_HAVE_PR_SET_NO_NEW_PRIVS) - if (nxt_slow_path(nxt_isolation_set_new_privs(task, isolation, process) - != NXT_OK)) - { - return NXT_ERROR; - } + if (nxt_slow_path(nxt_isolation_set_new_privs(task, isolation, process) != + NXT_OK)) { + return NXT_ERROR; + } #endif - return NXT_OK; + return NXT_OK; } - #if (NXT_HAVE_CGROUP) -static nxt_int_t -nxt_isolation_set_cgroup(nxt_task_t *task, nxt_conf_value_t *isolation, - nxt_process_t *process) -{ - nxt_str_t str; - nxt_conf_value_t *obj; +static nxt_int_t nxt_isolation_set_cgroup(nxt_task_t *task, + nxt_conf_value_t *isolation, + nxt_process_t *process) { + nxt_str_t str; + nxt_conf_value_t *obj; - static const nxt_str_t cgname = nxt_string("cgroup"); - static const nxt_str_t path = nxt_string("path"); + static const nxt_str_t cgname = nxt_string("cgroup"); + static const nxt_str_t path = nxt_string("path"); - obj = nxt_conf_get_object_member(isolation, &cgname, NULL); - if (obj == NULL) { - return NXT_OK; - } + obj = nxt_conf_get_object_member(isolation, &cgname, NULL); + if (obj == NULL) { + return NXT_OK; + } - obj = nxt_conf_get_object_member(obj, &path, NULL); - if (obj == NULL) { - return NXT_ERROR; - } + obj = nxt_conf_get_object_member(obj, &path, NULL); + if (obj == NULL) { + return NXT_ERROR; + } - nxt_conf_get_string(obj, &str); - process->isolation.cgroup.path = nxt_mp_alloc(process->mem_pool, - str.length + 1); - nxt_memcpy(process->isolation.cgroup.path, str.start, str.length); - process->isolation.cgroup.path[str.length] = '\0'; + nxt_conf_get_string(obj, &str); + process->isolation.cgroup.path = + nxt_mp_alloc(process->mem_pool, str.length + 1); + nxt_memcpy(process->isolation.cgroup.path, str.start, str.length); + process->isolation.cgroup.path[str.length] = '\0'; - process->isolation.cgroup_cleanup = nxt_cgroup_cleanup; + process->isolation.cgroup_cleanup = nxt_cgroup_cleanup; - return NXT_OK; + return NXT_OK; } #endif - #if (NXT_HAVE_LINUX_NS) -static nxt_int_t -nxt_isolation_set_namespaces(nxt_task_t *task, nxt_conf_value_t *isolation, - nxt_process_t *process) -{ - nxt_int_t ret; - nxt_conf_value_t *obj; +static nxt_int_t nxt_isolation_set_namespaces(nxt_task_t *task, + nxt_conf_value_t *isolation, + nxt_process_t *process) { + nxt_int_t ret; + nxt_conf_value_t *obj; - static const nxt_str_t nsname = nxt_string("namespaces"); + static const nxt_str_t nsname = nxt_string("namespaces"); - obj = nxt_conf_get_object_member(isolation, &nsname, NULL); - if (obj != NULL) { - ret = nxt_isolation_clone_flags(task, obj, &process->isolation.clone); - if (nxt_slow_path(ret != NXT_OK)) { - return NXT_ERROR; - } + obj = nxt_conf_get_object_member(isolation, &nsname, NULL); + if (obj != NULL) { + ret = nxt_isolation_clone_flags(task, obj, &process->isolation.clone); + if (nxt_slow_path(ret != NXT_OK)) { + return NXT_ERROR; } + } - return NXT_OK; + return NXT_OK; } #endif - #if (NXT_HAVE_CLONE_NEWUSER) -static nxt_int_t -nxt_isolation_set_creds(nxt_task_t *task, nxt_conf_value_t *isolation, - nxt_process_t *process) -{ - nxt_int_t ret; - nxt_clone_t *clone; - nxt_conf_value_t *array; +static nxt_int_t nxt_isolation_set_creds(nxt_task_t *task, + nxt_conf_value_t *isolation, + nxt_process_t *process) { + nxt_int_t ret; + nxt_clone_t *clone; + nxt_conf_value_t *array; - static const nxt_str_t uidname = nxt_string("uidmap"); - static const nxt_str_t gidname = nxt_string("gidmap"); + static const nxt_str_t uidname = nxt_string("uidmap"); + static const nxt_str_t gidname = nxt_string("gidmap"); - clone = &process->isolation.clone; + clone = &process->isolation.clone; - array = nxt_conf_get_object_member(isolation, &uidname, NULL); - if (array != NULL) { - ret = nxt_isolation_credential_map(task, process->mem_pool, array, - &clone->uidmap); + array = nxt_conf_get_object_member(isolation, &uidname, NULL); + if (array != NULL) { + ret = nxt_isolation_credential_map(task, process->mem_pool, array, + &clone->uidmap); - if (nxt_slow_path(ret != NXT_OK)) { - return NXT_ERROR; - } + if (nxt_slow_path(ret != NXT_OK)) { + return NXT_ERROR; } + } - array = nxt_conf_get_object_member(isolation, &gidname, NULL); - if (array != NULL) { - ret = nxt_isolation_credential_map(task, process->mem_pool, array, - &clone->gidmap); + array = nxt_conf_get_object_member(isolation, &gidname, NULL); + if (array != NULL) { + ret = nxt_isolation_credential_map(task, process->mem_pool, array, + &clone->gidmap); - if (nxt_slow_path(ret != NXT_OK)) { - return NXT_ERROR; - } + if (nxt_slow_path(ret != NXT_OK)) { + return NXT_ERROR; } + } - return NXT_OK; + return NXT_OK; } +static nxt_int_t nxt_isolation_credential_map(nxt_task_t *task, nxt_mp_t *mp, + nxt_conf_value_t *map_array, + nxt_clone_credential_map_t *map) { + nxt_int_t ret; + nxt_uint_t i; + nxt_conf_value_t *obj; + + static const nxt_conf_map_t nxt_clone_map_entry_conf[] = { + { + nxt_string("container"), + NXT_CONF_MAP_INT64, + offsetof(nxt_clone_map_entry_t, container), + }, + + { + nxt_string("host"), + NXT_CONF_MAP_INT64, + offsetof(nxt_clone_map_entry_t, host), + }, + + { + nxt_string("size"), + NXT_CONF_MAP_INT64, + offsetof(nxt_clone_map_entry_t, size), + }, + }; + + map->size = nxt_conf_array_elements_count(map_array); + + if (map->size == 0) { + return NXT_OK; + } -static nxt_int_t -nxt_isolation_credential_map(nxt_task_t *task, nxt_mp_t *mp, - nxt_conf_value_t *map_array, nxt_clone_credential_map_t *map) -{ - nxt_int_t ret; - nxt_uint_t i; - nxt_conf_value_t *obj; - - static const nxt_conf_map_t nxt_clone_map_entry_conf[] = { - { - nxt_string("container"), - NXT_CONF_MAP_INT64, - offsetof(nxt_clone_map_entry_t, container), - }, - - { - nxt_string("host"), - NXT_CONF_MAP_INT64, - offsetof(nxt_clone_map_entry_t, host), - }, - - { - nxt_string("size"), - NXT_CONF_MAP_INT64, - offsetof(nxt_clone_map_entry_t, size), - }, - }; - - map->size = nxt_conf_array_elements_count(map_array); - - if (map->size == 0) { - return NXT_OK; - } - - map->map = nxt_mp_alloc(mp, map->size * sizeof(nxt_clone_map_entry_t)); - if (nxt_slow_path(map->map == NULL)) { - return NXT_ERROR; - } + map->map = nxt_mp_alloc(mp, map->size * sizeof(nxt_clone_map_entry_t)); + if (nxt_slow_path(map->map == NULL)) { + return NXT_ERROR; + } - for (i = 0; i < map->size; i++) { - obj = nxt_conf_get_array_element(map_array, i); + for (i = 0; i < map->size; i++) { + obj = nxt_conf_get_array_element(map_array, i); - ret = nxt_conf_map_object(mp, obj, nxt_clone_map_entry_conf, - nxt_nitems(nxt_clone_map_entry_conf), - map->map + i); - if (nxt_slow_path(ret != NXT_OK)) { - nxt_alert(task, "clone map entry map error"); - return NXT_ERROR; - } + ret = + nxt_conf_map_object(mp, obj, nxt_clone_map_entry_conf, + nxt_nitems(nxt_clone_map_entry_conf), map->map + i); + if (nxt_slow_path(ret != NXT_OK)) { + nxt_alert(task, "clone map entry map error"); + return NXT_ERROR; } + } - return NXT_OK; + return NXT_OK; } +static nxt_int_t nxt_isolation_vldt_creds(nxt_task_t *task, + nxt_process_t *process) { + nxt_int_t ret; + nxt_clone_t *clone; + nxt_credential_t *creds; -static nxt_int_t -nxt_isolation_vldt_creds(nxt_task_t *task, nxt_process_t *process) -{ - nxt_int_t ret; - nxt_clone_t *clone; - nxt_credential_t *creds; - - clone = &process->isolation.clone; - creds = process->user_cred; - - if (clone->uidmap.size == 0 && clone->gidmap.size == 0) { - return NXT_OK; - } + clone = &process->isolation.clone; + creds = process->user_cred; - if (!nxt_is_clone_flag_set(clone->flags, NEWUSER)) { - if (nxt_slow_path(clone->uidmap.size > 0)) { - nxt_log(task, NXT_LOG_ERR, "\"uidmap\" is set but " - "\"isolation.namespaces.credential\" is false or unset"); + if (clone->uidmap.size == 0 && clone->gidmap.size == 0) { + return NXT_OK; + } - return NXT_ERROR; - } + if (!nxt_is_clone_flag_set(clone->flags, NEWUSER)) { + if (nxt_slow_path(clone->uidmap.size > 0)) { + nxt_log(task, NXT_LOG_ERR, + "\"uidmap\" is set but " + "\"isolation.namespaces.credential\" is false or unset"); - if (nxt_slow_path(clone->gidmap.size > 0)) { - nxt_log(task, NXT_LOG_ERR, "\"gidmap\" is set but " - "\"isolation.namespaces.credential\" is false or unset"); + return NXT_ERROR; + } - return NXT_ERROR; - } + if (nxt_slow_path(clone->gidmap.size > 0)) { + nxt_log(task, NXT_LOG_ERR, + "\"gidmap\" is set but " + "\"isolation.namespaces.credential\" is false or unset"); - return NXT_OK; + return NXT_ERROR; } - ret = nxt_clone_vldt_credential_uidmap(task, &clone->uidmap, creds); - if (nxt_slow_path(ret != NXT_OK)) { - return NXT_ERROR; - } + return NXT_OK; + } + + ret = nxt_clone_vldt_credential_uidmap(task, &clone->uidmap, creds); + if (nxt_slow_path(ret != NXT_OK)) { + return NXT_ERROR; + } - return nxt_clone_vldt_credential_gidmap(task, &clone->gidmap, creds); + return nxt_clone_vldt_credential_gidmap(task, &clone->gidmap, creds); } #endif - #if (NXT_HAVE_LINUX_NS) -static nxt_int_t -nxt_isolation_clone_flags(nxt_task_t *task, nxt_conf_value_t *namespaces, - nxt_clone_t *clone) -{ - uint32_t index; - nxt_str_t name; - nxt_int_t flag; - nxt_conf_value_t *value; +static nxt_int_t nxt_isolation_clone_flags(nxt_task_t *task, + nxt_conf_value_t *namespaces, + nxt_clone_t *clone) { + uint32_t index; + nxt_str_t name; + nxt_int_t flag; + nxt_conf_value_t *value; - index = 0; + index = 0; - for ( ;; ) { - value = nxt_conf_next_object_member(namespaces, &name, &index); + for (;;) { + value = nxt_conf_next_object_member(namespaces, &name, &index); - if (value == NULL) { - break; - } + if (value == NULL) { + break; + } - flag = 0; + flag = 0; #if (NXT_HAVE_CLONE_NEWUSER) - if (nxt_str_eq(&name, "credential", 10)) { - flag = CLONE_NEWUSER; - } + if (nxt_str_eq(&name, "credential", 10)) { + flag = CLONE_NEWUSER; + } #endif #if (NXT_HAVE_CLONE_NEWPID) - if (nxt_str_eq(&name, "pid", 3)) { - flag = CLONE_NEWPID; - } + if (nxt_str_eq(&name, "pid", 3)) { + flag = CLONE_NEWPID; + } #endif #if (NXT_HAVE_CLONE_NEWNET) - if (nxt_str_eq(&name, "network", 7)) { - flag = CLONE_NEWNET; - } + if (nxt_str_eq(&name, "network", 7)) { + flag = CLONE_NEWNET; + } #endif #if (NXT_HAVE_CLONE_NEWUTS) - if (nxt_str_eq(&name, "uname", 5)) { - flag = CLONE_NEWUTS; - } + if (nxt_str_eq(&name, "uname", 5)) { + flag = CLONE_NEWUTS; + } #endif #if (NXT_HAVE_CLONE_NEWNS) - if (nxt_str_eq(&name, "mount", 5)) { - flag = CLONE_NEWNS; - } + if (nxt_str_eq(&name, "mount", 5)) { + flag = CLONE_NEWNS; + } #endif #if (NXT_HAVE_CLONE_NEWCGROUP) - if (nxt_str_eq(&name, "cgroup", 6)) { - flag = CLONE_NEWCGROUP; - } + if (nxt_str_eq(&name, "cgroup", 6)) { + flag = CLONE_NEWCGROUP; + } #endif - if (!flag) { - nxt_alert(task, "unknown namespace flag: \"%V\"", &name); - return NXT_ERROR; - } + if (!flag) { + nxt_alert(task, "unknown namespace flag: \"%V\"", &name); + return NXT_ERROR; + } - if (nxt_conf_get_boolean(value)) { - clone->flags |= flag; - } + if (nxt_conf_get_boolean(value)) { + clone->flags |= flag; } + } - return NXT_OK; + return NXT_OK; } #endif - #if (NXT_HAVE_ISOLATION_ROOTFS) -static nxt_int_t -nxt_isolation_set_rootfs(nxt_task_t *task, nxt_conf_value_t *isolation, - nxt_process_t *process) -{ - nxt_str_t str; - nxt_conf_value_t *obj; - - static const nxt_str_t rootfs_name = nxt_string("rootfs"); - - obj = nxt_conf_get_object_member(isolation, &rootfs_name, NULL); - if (obj != NULL) { - nxt_conf_get_string(obj, &str); - - if (nxt_slow_path(str.length <= 1 || str.start[0] != '/')) { - nxt_log(task, NXT_LOG_ERR, "rootfs requires an absolute path other " - "than \"/\" but given \"%V\"", &str); - - return NXT_ERROR; - } - - if (str.start[str.length - 1] == '/') { - str.length--; - } +static nxt_int_t nxt_isolation_set_rootfs(nxt_task_t *task, + nxt_conf_value_t *isolation, + nxt_process_t *process) { + nxt_str_t str; + nxt_conf_value_t *obj; - process->isolation.rootfs = nxt_mp_alloc(process->mem_pool, - str.length + 1); + static const nxt_str_t rootfs_name = nxt_string("rootfs"); - if (nxt_slow_path(process->isolation.rootfs == NULL)) { - return NXT_ERROR; - } + obj = nxt_conf_get_object_member(isolation, &rootfs_name, NULL); + if (obj != NULL) { + nxt_conf_get_string(obj, &str); - nxt_memcpy(process->isolation.rootfs, str.start, str.length); + if (nxt_slow_path(str.length <= 1 || str.start[0] != '/')) { + nxt_log(task, NXT_LOG_ERR, + "rootfs requires an absolute path other " + "than \"/\" but given \"%V\"", + &str); - process->isolation.rootfs[str.length] = '\0'; + return NXT_ERROR; } - return NXT_OK; -} + if (str.start[str.length - 1] == '/') { + str.length--; + } + process->isolation.rootfs = nxt_mp_alloc(process->mem_pool, str.length + 1); -static nxt_int_t -nxt_isolation_set_automount(nxt_task_t *task, nxt_conf_value_t *isolation, - nxt_process_t *process) -{ - nxt_conf_value_t *conf, *value; - nxt_process_automount_t *automount; + if (nxt_slow_path(process->isolation.rootfs == NULL)) { + return NXT_ERROR; + } - static const nxt_str_t automount_name = nxt_string("automount"); - static const nxt_str_t langdeps_name = nxt_string("language_deps"); - static const nxt_str_t tmp_name = nxt_string("tmpfs"); - static const nxt_str_t proc_name = nxt_string("procfs"); + nxt_memcpy(process->isolation.rootfs, str.start, str.length); - automount = &process->isolation.automount; + process->isolation.rootfs[str.length] = '\0'; + } - automount->language_deps = 1; - automount->tmpfs = 1; - automount->procfs = 1; + return NXT_OK; +} - conf = nxt_conf_get_object_member(isolation, &automount_name, NULL); - if (conf != NULL) { - value = nxt_conf_get_object_member(conf, &langdeps_name, NULL); - if (value != NULL) { - automount->language_deps = nxt_conf_get_boolean(value); - } +static nxt_int_t nxt_isolation_set_automount(nxt_task_t *task, + nxt_conf_value_t *isolation, + nxt_process_t *process) { + nxt_conf_value_t *conf, *value; + nxt_process_automount_t *automount; + + static const nxt_str_t automount_name = nxt_string("automount"); + static const nxt_str_t langdeps_name = nxt_string("language_deps"); + static const nxt_str_t tmp_name = nxt_string("tmpfs"); + static const nxt_str_t proc_name = nxt_string("procfs"); + + automount = &process->isolation.automount; + + automount->language_deps = 1; + automount->tmpfs = 1; + automount->procfs = 1; + + conf = nxt_conf_get_object_member(isolation, &automount_name, NULL); + if (conf != NULL) { + value = nxt_conf_get_object_member(conf, &langdeps_name, NULL); + if (value != NULL) { + automount->language_deps = nxt_conf_get_boolean(value); + } - value = nxt_conf_get_object_member(conf, &tmp_name, NULL); - if (value != NULL) { - automount->tmpfs = nxt_conf_get_boolean(value); - } + value = nxt_conf_get_object_member(conf, &tmp_name, NULL); + if (value != NULL) { + automount->tmpfs = nxt_conf_get_boolean(value); + } - value = nxt_conf_get_object_member(conf, &proc_name, NULL); - if (value != NULL) { - automount->procfs = nxt_conf_get_boolean(value); - } + value = nxt_conf_get_object_member(conf, &proc_name, NULL); + if (value != NULL) { + automount->procfs = nxt_conf_get_boolean(value); } + } - return NXT_OK; + return NXT_OK; } +static nxt_int_t nxt_isolation_set_mounts(nxt_task_t *task, + nxt_process_t *process, + nxt_str_t *app_type) { + nxt_int_t ret, cap_chroot; + nxt_runtime_t *rt; + nxt_app_lang_module_t *lang; -static nxt_int_t -nxt_isolation_set_mounts(nxt_task_t *task, nxt_process_t *process, - nxt_str_t *app_type) -{ - nxt_int_t ret, cap_chroot; - nxt_runtime_t *rt; - nxt_app_lang_module_t *lang; - - rt = task->thread->runtime; - cap_chroot = rt->capabilities.chroot; - lang = nxt_app_lang_module(rt, app_type); + rt = task->thread->runtime; + cap_chroot = rt->capabilities.chroot; + lang = nxt_app_lang_module(rt, app_type); - nxt_assert(lang != NULL); + nxt_assert(lang != NULL); #if (NXT_HAVE_CLONE_NEWUSER) - if (nxt_is_clone_flag_set(process->isolation.clone.flags, NEWUSER)) { - cap_chroot = 1; - } + if (nxt_is_clone_flag_set(process->isolation.clone.flags, NEWUSER)) { + cap_chroot = 1; + } #endif - if (!cap_chroot) { - nxt_log(task, NXT_LOG_ERR, "The \"rootfs\" field requires privileges"); - return NXT_ERROR; - } + if (!cap_chroot) { + nxt_log(task, NXT_LOG_ERR, "The \"rootfs\" field requires privileges"); + return NXT_ERROR; + } - ret = nxt_isolation_set_lang_mounts(task, process, lang->mounts); - if (nxt_slow_path(ret != NXT_OK)) { - return NXT_ERROR; - } + ret = nxt_isolation_set_lang_mounts(task, process, lang->mounts); + if (nxt_slow_path(ret != NXT_OK)) { + return NXT_ERROR; + } - process->isolation.cleanup = nxt_isolation_unmount_all; + process->isolation.cleanup = nxt_isolation_unmount_all; - return NXT_OK; + return NXT_OK; } +static nxt_int_t nxt_isolation_set_lang_mounts(nxt_task_t *task, + nxt_process_t *process, + nxt_array_t *lang_mounts) { + u_char *p; + size_t i, n, rootfs_len, len; + nxt_mp_t *mp; + nxt_array_t *mounts; + const u_char *rootfs; + nxt_fs_mount_t *mnt, *lang_mnt; + + mp = process->mem_pool; + + /* copy to init mem pool */ + mounts = nxt_array_copy(mp, NULL, lang_mounts); + if (mounts == NULL) { + return NXT_ERROR; + } -static nxt_int_t -nxt_isolation_set_lang_mounts(nxt_task_t *task, nxt_process_t *process, - nxt_array_t *lang_mounts) -{ - u_char *p; - size_t i, n, rootfs_len, len; - nxt_mp_t *mp; - nxt_array_t *mounts; - const u_char *rootfs; - nxt_fs_mount_t *mnt, *lang_mnt; - - mp = process->mem_pool; + n = mounts->nelts; + mnt = mounts->elts; + lang_mnt = lang_mounts->elts; - /* copy to init mem pool */ - mounts = nxt_array_copy(mp, NULL, lang_mounts); - if (mounts == NULL) { - return NXT_ERROR; - } + rootfs = process->isolation.rootfs; + rootfs_len = nxt_strlen(rootfs); - n = mounts->nelts; - mnt = mounts->elts; - lang_mnt = lang_mounts->elts; + for (i = 0; i < n; i++) { + len = nxt_strlen(lang_mnt[i].dst); - rootfs = process->isolation.rootfs; - rootfs_len = nxt_strlen(rootfs); - - for (i = 0; i < n; i++) { - len = nxt_strlen(lang_mnt[i].dst); + mnt[i].dst = nxt_mp_alloc(mp, rootfs_len + len + 1); + if (nxt_slow_path(mnt[i].dst == NULL)) { + return NXT_ERROR; + } - mnt[i].dst = nxt_mp_alloc(mp, rootfs_len + len + 1); - if (nxt_slow_path(mnt[i].dst == NULL)) { - return NXT_ERROR; - } + p = nxt_cpymem(mnt[i].dst, rootfs, rootfs_len); + p = nxt_cpymem(p, lang_mnt[i].dst, len); + *p = '\0'; + } - p = nxt_cpymem(mnt[i].dst, rootfs, rootfs_len); - p = nxt_cpymem(p, lang_mnt[i].dst, len); - *p = '\0'; + if (process->isolation.automount.tmpfs) { + mnt = nxt_array_add(mounts); + if (nxt_slow_path(mnt == NULL)) { + return NXT_ERROR; } - if (process->isolation.automount.tmpfs) { - mnt = nxt_array_add(mounts); - if (nxt_slow_path(mnt == NULL)) { - return NXT_ERROR; - } + mnt->src = (u_char *)"tmpfs"; + mnt->name = (u_char *)"tmpfs"; + mnt->type = NXT_FS_TMP; + mnt->flags = + (NXT_FS_FLAGS_NOSUID | NXT_FS_FLAGS_NODEV | NXT_FS_FLAGS_NOEXEC); + mnt->data = (u_char *)"size=1m,mode=1777"; + mnt->builtin = 1; + mnt->deps = 0; + + mnt->dst = nxt_mp_nget(mp, rootfs_len + nxt_length("/tmp") + 1); + if (nxt_slow_path(mnt->dst == NULL)) { + return NXT_ERROR; + } - mnt->src = (u_char *) "tmpfs"; - mnt->name = (u_char *) "tmpfs"; - mnt->type = NXT_FS_TMP; - mnt->flags = (NXT_FS_FLAGS_NOSUID - | NXT_FS_FLAGS_NODEV - | NXT_FS_FLAGS_NOEXEC); - mnt->data = (u_char *) "size=1m,mode=1777"; - mnt->builtin = 1; - mnt->deps = 0; - - mnt->dst = nxt_mp_nget(mp, rootfs_len + nxt_length("/tmp") + 1); - if (nxt_slow_path(mnt->dst == NULL)) { - return NXT_ERROR; - } + p = nxt_cpymem(mnt->dst, rootfs, rootfs_len); + p = nxt_cpymem(p, "/tmp", 4); + *p = '\0'; + } - p = nxt_cpymem(mnt->dst, rootfs, rootfs_len); - p = nxt_cpymem(p, "/tmp", 4); - *p = '\0'; + if (process->isolation.automount.procfs) { + mnt = nxt_array_add(mounts); + if (nxt_slow_path(mnt == NULL)) { + return NXT_ERROR; } - if (process->isolation.automount.procfs) { - mnt = nxt_array_add(mounts); - if (nxt_slow_path(mnt == NULL)) { - return NXT_ERROR; - } - - mnt->name = (u_char *) "proc"; - mnt->type = NXT_FS_PROC; - mnt->src = (u_char *) "none"; - mnt->dst = nxt_mp_nget(mp, rootfs_len + nxt_length("/proc") + 1); - if (nxt_slow_path(mnt->dst == NULL)) { - return NXT_ERROR; - } + mnt->name = (u_char *)"proc"; + mnt->type = NXT_FS_PROC; + mnt->src = (u_char *)"none"; + mnt->dst = nxt_mp_nget(mp, rootfs_len + nxt_length("/proc") + 1); + if (nxt_slow_path(mnt->dst == NULL)) { + return NXT_ERROR; + } - p = nxt_cpymem(mnt->dst, rootfs, rootfs_len); - p = nxt_cpymem(p, "/proc", 5); - *p = '\0'; + p = nxt_cpymem(mnt->dst, rootfs, rootfs_len); + p = nxt_cpymem(p, "/proc", 5); + *p = '\0'; - mnt->data = (u_char *) ""; - mnt->flags = NXT_FS_FLAGS_NOEXEC | NXT_FS_FLAGS_NOSUID; - mnt->builtin = 1; - mnt->deps = 0; - } + mnt->data = (u_char *)""; + mnt->flags = NXT_FS_FLAGS_NOEXEC | NXT_FS_FLAGS_NOSUID; + mnt->builtin = 1; + mnt->deps = 0; + } - qsort(mounts->elts, mounts->nelts, sizeof(nxt_fs_mount_t), - nxt_isolation_mount_compare); + qsort(mounts->elts, mounts->nelts, sizeof(nxt_fs_mount_t), + nxt_isolation_mount_compare); - process->isolation.mounts = mounts; + process->isolation.mounts = mounts; - return NXT_OK; + return NXT_OK; } +static int nxt_cdecl nxt_isolation_mount_compare(const void *v1, + const void *v2) { + const nxt_fs_mount_t *mnt1, *mnt2; -static int nxt_cdecl -nxt_isolation_mount_compare(const void *v1, const void *v2) -{ - const nxt_fs_mount_t *mnt1, *mnt2; - - mnt1 = v1; - mnt2 = v2; + mnt1 = v1; + mnt2 = v2; - return nxt_strlen(mnt1->src) > nxt_strlen(mnt2->src); + return nxt_strlen(mnt1->src) > nxt_strlen(mnt2->src); } +void nxt_isolation_unmount_all(nxt_task_t *task, nxt_process_t *process) { + size_t n; + nxt_array_t *mounts; + nxt_runtime_t *rt; + nxt_fs_mount_t *mnt; + nxt_process_automount_t *automount; -void -nxt_isolation_unmount_all(nxt_task_t *task, nxt_process_t *process) -{ - size_t n; - nxt_array_t *mounts; - nxt_runtime_t *rt; - nxt_fs_mount_t *mnt; - nxt_process_automount_t *automount; + rt = task->thread->runtime; - rt = task->thread->runtime; + if (!rt->capabilities.setid) { + return; + } - if (!rt->capabilities.setid) { - return; - } + nxt_debug(task, "unmount all (%s)", process->name); - nxt_debug(task, "unmount all (%s)", process->name); + automount = &process->isolation.automount; + mounts = process->isolation.mounts; + n = mounts->nelts; + mnt = mounts->elts; - automount = &process->isolation.automount; - mounts = process->isolation.mounts; - n = mounts->nelts; - mnt = mounts->elts; - - while (n > 0) { - n--; - - if (mnt[n].deps && !automount->language_deps) { - continue; - } + while (n > 0) { + n--; - nxt_fs_unmount(mnt[n].dst); + if (mnt[n].deps && !automount->language_deps) { + continue; } -} + nxt_fs_unmount(mnt[n].dst); + } +} -nxt_int_t -nxt_isolation_prepare_rootfs(nxt_task_t *task, nxt_process_t *process) -{ - size_t i, n; - nxt_int_t ret; - struct stat st; - nxt_array_t *mounts; - const u_char *dst; - nxt_fs_mount_t *mnt; - nxt_process_automount_t *automount; +nxt_int_t nxt_isolation_prepare_rootfs(nxt_task_t *task, + nxt_process_t *process) { + size_t i, n; + nxt_int_t ret; + struct stat st; + nxt_array_t *mounts; + const u_char *dst; + nxt_fs_mount_t *mnt; + nxt_process_automount_t *automount; - automount = &process->isolation.automount; - mounts = process->isolation.mounts; + automount = &process->isolation.automount; + mounts = process->isolation.mounts; - n = mounts->nelts; - mnt = mounts->elts; + n = mounts->nelts; + mnt = mounts->elts; - for (i = 0; i < n; i++) { - dst = mnt[i].dst; + for (i = 0; i < n; i++) { + dst = mnt[i].dst; - if (mnt[i].deps && !automount->language_deps) { - continue; - } + if (mnt[i].deps && !automount->language_deps) { + continue; + } - if (nxt_slow_path(mnt[i].type == NXT_FS_BIND - && stat((const char *) mnt[i].src, &st) != 0)) - { - nxt_log(task, NXT_LOG_WARN, "host path not found: %s", mnt[i].src); - continue; - } + if (nxt_slow_path(mnt[i].type == NXT_FS_BIND && + stat((const char *)mnt[i].src, &st) != 0)) { + nxt_log(task, NXT_LOG_WARN, "host path not found: %s", mnt[i].src); + continue; + } - ret = nxt_fs_mkdir_p(dst, 0777); - if (nxt_slow_path(ret != NXT_OK)) { - nxt_alert(task, "mkdir(%s) %E", dst, nxt_errno); - goto undo; - } + ret = nxt_fs_mkdir_p(dst, 0777); + if (nxt_slow_path(ret != NXT_OK)) { + nxt_alert(task, "mkdir(%s) %E", dst, nxt_errno); + goto undo; + } - ret = nxt_fs_mount(task, &mnt[i]); - if (nxt_slow_path(ret != NXT_OK)) { - goto undo; - } + ret = nxt_fs_mount(task, &mnt[i]); + if (nxt_slow_path(ret != NXT_OK)) { + goto undo; } + } - return NXT_OK; + return NXT_OK; undo: - n = i + 1; + n = i + 1; - for (i = 0; i < n; i++) { - nxt_fs_unmount(mnt[i].dst); - } + for (i = 0; i < n; i++) { + nxt_fs_unmount(mnt[i].dst); + } - return NXT_ERROR; + return NXT_ERROR; } - #if (NXT_HAVE_LINUX_PIVOT_ROOT) && (NXT_HAVE_CLONE_NEWNS) -nxt_int_t -nxt_isolation_change_root(nxt_task_t *task, nxt_process_t *process) -{ - char *rootfs; - nxt_int_t ret; +nxt_int_t nxt_isolation_change_root(nxt_task_t *task, nxt_process_t *process) { + char *rootfs; + nxt_int_t ret; - rootfs = (char *) process->isolation.rootfs; + rootfs = (char *)process->isolation.rootfs; - nxt_debug(task, "change root: %s", rootfs); + nxt_debug(task, "change root: %s", rootfs); - if (nxt_is_clone_flag_set(process->isolation.clone.flags, NEWNS)) { - ret = nxt_isolation_pivot_root(task, rootfs); + if (nxt_is_clone_flag_set(process->isolation.clone.flags, NEWNS)) { + ret = nxt_isolation_pivot_root(task, rootfs); - } else { - ret = nxt_isolation_chroot(task, rootfs); - } + } else { + ret = nxt_isolation_chroot(task, rootfs); + } - if (nxt_fast_path(ret == NXT_OK)) { - if (nxt_slow_path(chdir("/") < 0)) { - nxt_alert(task, "chdir(\"/\") %E", nxt_errno); - return NXT_ERROR; - } + if (nxt_fast_path(ret == NXT_OK)) { + if (nxt_slow_path(chdir("/") < 0)) { + nxt_alert(task, "chdir(\"/\") %E", nxt_errno); + return NXT_ERROR; } + } - return ret; + return ret; } - /* * pivot_root(2) can only be safely used with containers, otherwise it can * umount(2) the global root filesystem and screw up the machine. */ -static nxt_int_t -nxt_isolation_pivot_root(nxt_task_t *task, const char *path) -{ - /* - * This implementation makes use of a kernel trick that works for ages - * and now documented in Linux kernel 5. - * https://lore.kernel.org/linux-man/87r24piwhm.fsf@x220.int.ebiederm.org/T/ - */ - - if (nxt_slow_path(mount("", "/", "", MS_SLAVE|MS_REC, "") != 0)) { - nxt_alert(task, "mount(\"/\", MS_SLAVE|MS_REC) failed: %E", nxt_errno); - return NXT_ERROR; - } +static nxt_int_t nxt_isolation_pivot_root(nxt_task_t *task, const char *path) { + /* + * This implementation makes use of a kernel trick that works for ages + * and now documented in Linux kernel 5. + * https://lore.kernel.org/linux-man/87r24piwhm.fsf@x220.int.ebiederm.org/T/ + */ - if (nxt_slow_path(nxt_isolation_make_private_mount(task, path) != NXT_OK)) { - return NXT_ERROR; - } + if (nxt_slow_path(mount("", "/", "", MS_SLAVE | MS_REC, "") != 0)) { + nxt_alert(task, "mount(\"/\", MS_SLAVE|MS_REC) failed: %E", nxt_errno); + return NXT_ERROR; + } - if (nxt_slow_path(mount(path, path, "bind", MS_BIND|MS_REC, "") != 0)) { - nxt_alert(task, "error bind mounting rootfs %E", nxt_errno); - return NXT_ERROR; - } + if (nxt_slow_path(nxt_isolation_make_private_mount(task, path) != NXT_OK)) { + return NXT_ERROR; + } - if (nxt_slow_path(chdir(path) != 0)) { - nxt_alert(task, "failed to chdir(%s) %E", path, nxt_errno); - return NXT_ERROR; - } + if (nxt_slow_path(mount(path, path, "bind", MS_BIND | MS_REC, "") != 0)) { + nxt_alert(task, "error bind mounting rootfs %E", nxt_errno); + return NXT_ERROR; + } - if (nxt_slow_path(nxt_pivot_root(".", ".") != 0)) { - nxt_alert(task, "failed to pivot_root %E", nxt_errno); - return NXT_ERROR; - } + if (nxt_slow_path(chdir(path) != 0)) { + nxt_alert(task, "failed to chdir(%s) %E", path, nxt_errno); + return NXT_ERROR; + } - /* - * Demote the oldroot mount to avoid unmounts getting propagated to - * the host. - */ - if (nxt_slow_path(mount("", ".", "", MS_SLAVE | MS_REC, NULL) != 0)) { - nxt_alert(task, "failed to bind mount rootfs %E", nxt_errno); - return NXT_ERROR; - } + if (nxt_slow_path(nxt_pivot_root(".", ".") != 0)) { + nxt_alert(task, "failed to pivot_root %E", nxt_errno); + return NXT_ERROR; + } + + /* + * Demote the oldroot mount to avoid unmounts getting propagated to + * the host. + */ + if (nxt_slow_path(mount("", ".", "", MS_SLAVE | MS_REC, NULL) != 0)) { + nxt_alert(task, "failed to bind mount rootfs %E", nxt_errno); + return NXT_ERROR; + } - if (nxt_slow_path(umount2(".", MNT_DETACH) != 0)) { - nxt_alert(task, "failed to umount old root directory %E", nxt_errno); - return NXT_ERROR; - } + if (nxt_slow_path(umount2(".", MNT_DETACH) != 0)) { + nxt_alert(task, "failed to umount old root directory %E", nxt_errno); + return NXT_ERROR; + } - return NXT_OK; + return NXT_OK; } +static nxt_int_t nxt_isolation_make_private_mount(nxt_task_t *task, + const char *rootfs) { + char *parent_mnt; + FILE *procfile; + u_char **mounts; + size_t len; + uint8_t *shared; + nxt_int_t ret, index, nmounts; + struct mntent *ent; -static nxt_int_t -nxt_isolation_make_private_mount(nxt_task_t *task, const char *rootfs) -{ - char *parent_mnt; - FILE *procfile; - u_char **mounts; - size_t len; - uint8_t *shared; - nxt_int_t ret, index, nmounts; - struct mntent *ent; + static const char *mount_path = "/proc/self/mounts"; - static const char *mount_path = "/proc/self/mounts"; + ret = NXT_ERROR; + ent = NULL; + shared = NULL; + procfile = NULL; + parent_mnt = NULL; - ret = NXT_ERROR; - ent = NULL; - shared = NULL; - procfile = NULL; - parent_mnt = NULL; + nmounts = 256; - nmounts = 256; + mounts = nxt_malloc(nmounts * sizeof(uintptr_t)); + if (nxt_slow_path(mounts == NULL)) { + goto fail; + } - mounts = nxt_malloc(nmounts * sizeof(uintptr_t)); - if (nxt_slow_path(mounts == NULL)) { - goto fail; - } + shared = nxt_malloc(nmounts); + if (nxt_slow_path(shared == NULL)) { + goto fail; + } - shared = nxt_malloc(nmounts); - if (nxt_slow_path(shared == NULL)) { - goto fail; - } + procfile = setmntent(mount_path, "r"); + if (nxt_slow_path(procfile == NULL)) { + nxt_alert(task, "failed to open %s %E", mount_path, nxt_errno); - procfile = setmntent(mount_path, "r"); - if (nxt_slow_path(procfile == NULL)) { - nxt_alert(task, "failed to open %s %E", mount_path, nxt_errno); + goto fail; + } - goto fail; - } - - index = 0; + index = 0; again: - for ( ; index < nmounts; index++) { - ent = getmntent(procfile); - if (ent == NULL) { - nmounts = index; - break; - } - - mounts[index] = (u_char *) strdup(ent->mnt_dir); - shared[index] = hasmntopt(ent, "shared") != NULL; + for (; index < nmounts; index++) { + ent = getmntent(procfile); + if (ent == NULL) { + nmounts = index; + break; } - if (ent != NULL) { - /* there are still entries to be read */ + mounts[index] = (u_char *)strdup(ent->mnt_dir); + shared[index] = hasmntopt(ent, "shared") != NULL; + } - nmounts *= 2; - mounts = nxt_realloc(mounts, nmounts); - if (nxt_slow_path(mounts == NULL)) { - goto fail; - } + if (ent != NULL) { + /* there are still entries to be read */ - shared = nxt_realloc(shared, nmounts); - if (nxt_slow_path(shared == NULL)) { - goto fail; - } + nmounts *= 2; + mounts = nxt_realloc(mounts, nmounts); + if (nxt_slow_path(mounts == NULL)) { + goto fail; + } - goto again; + shared = nxt_realloc(shared, nmounts); + if (nxt_slow_path(shared == NULL)) { + goto fail; } - for (index = 0; index < nmounts; index++) { - if (nxt_strcmp(mounts[index], rootfs) == 0) { - parent_mnt = (char *) rootfs; - break; - } + goto again; + } + + for (index = 0; index < nmounts; index++) { + if (nxt_strcmp(mounts[index], rootfs) == 0) { + parent_mnt = (char *)rootfs; + break; } + } + + if (parent_mnt == NULL) { + len = nxt_strlen(rootfs); + parent_mnt = nxt_malloc(len + 1); if (parent_mnt == NULL) { - len = nxt_strlen(rootfs); + goto fail; + } - parent_mnt = nxt_malloc(len + 1); - if (parent_mnt == NULL) { - goto fail; - } + nxt_memcpy(parent_mnt, rootfs, len); + parent_mnt[len] = '\0'; - nxt_memcpy(parent_mnt, rootfs, len); - parent_mnt[len] = '\0'; + if (parent_mnt[len - 1] == '/') { + parent_mnt[len - 1] = '\0'; + len--; + } - if (parent_mnt[len - 1] == '/') { - parent_mnt[len - 1] = '\0'; - len--; + for (;;) { + for (index = 0; index < nmounts; index++) { + if (nxt_strcmp(mounts[index], parent_mnt) == 0) { + goto found; } + } - for ( ;; ) { - for (index = 0; index < nmounts; index++) { - if (nxt_strcmp(mounts[index], parent_mnt) == 0) { - goto found; - } - } - - if (len == 1 && parent_mnt[0] == '/') { - nxt_alert(task, "parent mount not found"); - goto fail; - } - - /* parent dir */ - while (parent_mnt[len - 1] != '/' && len > 0) { - len--; - } - - if (nxt_slow_path(len == 0)) { - nxt_alert(task, "parent mount not found"); - goto fail; - } - - if (len == 1) { - parent_mnt[len] = '\0'; /* / */ - } else { - parent_mnt[len - 1] = '\0'; /* / */ - } - } - } + if (len == 1 && parent_mnt[0] == '/') { + nxt_alert(task, "parent mount not found"); + goto fail; + } -found: + /* parent dir */ + while (parent_mnt[len - 1] != '/' && len > 0) { + len--; + } - if (shared[index]) { - if (nxt_slow_path(mount("", parent_mnt, "", MS_PRIVATE, "") != 0)) { - nxt_alert(task, "mount(\"\", \"%s\", MS_PRIVATE) %E", parent_mnt, - nxt_errno); + if (nxt_slow_path(len == 0)) { + nxt_alert(task, "parent mount not found"); + goto fail; + } - goto fail; - } + if (len == 1) { + parent_mnt[len] = '\0'; /* / */ + } else { + parent_mnt[len - 1] = '\0'; /* / */ + } } + } - ret = NXT_OK; +found: -fail: + if (shared[index]) { + if (nxt_slow_path(mount("", parent_mnt, "", MS_PRIVATE, "") != 0)) { + nxt_alert(task, "mount(\"\", \"%s\", MS_PRIVATE) %E", parent_mnt, + nxt_errno); - if (procfile != NULL) { - endmntent(procfile); + goto fail; } + } - if (mounts != NULL) { - for (index = 0; index < nmounts; index++) { - nxt_free(mounts[index]); - } + ret = NXT_OK; - nxt_free(mounts); - } +fail: - if (shared != NULL) { - nxt_free(shared); - } + if (procfile != NULL) { + endmntent(procfile); + } - if (parent_mnt != NULL && parent_mnt != rootfs) { - nxt_free(parent_mnt); + if (mounts != NULL) { + for (index = 0; index < nmounts; index++) { + nxt_free(mounts[index]); } - return ret; -} + nxt_free(mounts); + } + + if (shared != NULL) { + nxt_free(shared); + } + if (parent_mnt != NULL && parent_mnt != rootfs) { + nxt_free(parent_mnt); + } -nxt_inline int -nxt_pivot_root(const char *new_root, const char *old_root) -{ - return syscall(SYS_pivot_root, new_root, old_root); + return ret; } +nxt_inline int nxt_pivot_root(const char *new_root, const char *old_root) { + return syscall(SYS_pivot_root, new_root, old_root); +} #else /* !(NXT_HAVE_LINUX_PIVOT_ROOT) || !(NXT_HAVE_CLONE_NEWNS) */ +nxt_int_t nxt_isolation_change_root(nxt_task_t *task, nxt_process_t *process) { + char *rootfs; -nxt_int_t -nxt_isolation_change_root(nxt_task_t *task, nxt_process_t *process) -{ - char *rootfs; + rootfs = (char *)process->isolation.rootfs; - rootfs = (char *) process->isolation.rootfs; + nxt_debug(task, "change root: %s", rootfs); - nxt_debug(task, "change root: %s", rootfs); - - if (nxt_fast_path(nxt_isolation_chroot(task, rootfs) == NXT_OK)) { - if (nxt_slow_path(chdir("/") < 0)) { - nxt_alert(task, "chdir(\"/\") %E", nxt_errno); - return NXT_ERROR; - } - - return NXT_OK; + if (nxt_fast_path(nxt_isolation_chroot(task, rootfs) == NXT_OK)) { + if (nxt_slow_path(chdir("/") < 0)) { + nxt_alert(task, "chdir(\"/\") %E", nxt_errno); + return NXT_ERROR; } - return NXT_ERROR; + return NXT_OK; + } + + return NXT_ERROR; } #endif +static nxt_int_t nxt_isolation_chroot(nxt_task_t *task, const char *path) { + if (nxt_slow_path(chroot(path) < 0)) { + nxt_alert(task, "chroot(%s) %E", path, nxt_errno); + return NXT_ERROR; + } -static nxt_int_t -nxt_isolation_chroot(nxt_task_t *task, const char *path) -{ - if (nxt_slow_path(chroot(path) < 0)) { - nxt_alert(task, "chroot(%s) %E", path, nxt_errno); - return NXT_ERROR; - } - - return NXT_OK; + return NXT_OK; } #endif /* NXT_HAVE_ISOLATION_ROOTFS */ - #if (NXT_HAVE_PR_SET_NO_NEW_PRIVS) -static nxt_int_t -nxt_isolation_set_new_privs(nxt_task_t *task, nxt_conf_value_t *isolation, - nxt_process_t *process) -{ - nxt_conf_value_t *obj; +static nxt_int_t nxt_isolation_set_new_privs(nxt_task_t *task, + nxt_conf_value_t *isolation, + nxt_process_t *process) { + nxt_conf_value_t *obj; - static const nxt_str_t new_privs_name = nxt_string("new_privs"); + static const nxt_str_t new_privs_name = nxt_string("new_privs"); - obj = nxt_conf_get_object_member(isolation, &new_privs_name, NULL); - if (obj != NULL) { - process->isolation.new_privs = nxt_conf_get_boolean(obj); - } + obj = nxt_conf_get_object_member(isolation, &new_privs_name, NULL); + if (obj != NULL) { + process->isolation.new_privs = nxt_conf_get_boolean(obj); + } - return NXT_OK; + return NXT_OK; } #endif diff --git a/src/nxt_isolation.h b/src/nxt_isolation.h index b1bfc33c7..477acb5b9 100644 --- a/src/nxt_isolation.h +++ b/src/nxt_isolation.h @@ -5,13 +5,12 @@ #ifndef _NXT_ISOLATION_H_INCLUDED_ #define _NXT_ISOLATION_H_INCLUDED_ - nxt_int_t nxt_isolation_main_prefork(nxt_task_t *task, nxt_process_t *process, - nxt_mp_t *mp); + nxt_mp_t *mp); #if (NXT_HAVE_ISOLATION_ROOTFS) nxt_int_t nxt_isolation_prepare_rootfs(nxt_task_t *task, - nxt_process_t *process); + nxt_process_t *process); nxt_int_t nxt_isolation_change_root(nxt_task_t *task, nxt_process_t *process); #endif diff --git a/src/nxt_java.c b/src/nxt_java.c index 75c8ee198..7f5f94cf9 100644 --- a/src/nxt_java.c +++ b/src/nxt_java.c @@ -3,7 +3,6 @@ * Copyright (C) NGINX, Inc. */ - #include #include @@ -30,731 +29,692 @@ #include NXT_JAVA_MOUNTS_H static nxt_int_t nxt_java_setup(nxt_task_t *task, nxt_process_t *process, - nxt_common_app_conf_t *conf); -static nxt_int_t nxt_java_start(nxt_task_t *task, - nxt_process_data_t *data); + nxt_common_app_conf_t *conf); +static nxt_int_t nxt_java_start(nxt_task_t *task, nxt_process_data_t *data); static void nxt_java_request_handler(nxt_unit_request_info_t *req); static void nxt_java_websocket_handler(nxt_unit_websocket_frame_t *ws); static void nxt_java_close_handler(nxt_unit_request_info_t *req); static int nxt_java_ready_handler(nxt_unit_ctx_t *ctx); static void *nxt_java_thread_func(void *main_ctx); static int nxt_java_init_threads(nxt_java_app_conf_t *c); -static void nxt_java_join_threads(nxt_unit_ctx_t *ctx, - nxt_java_app_conf_t *c); +static void nxt_java_join_threads(nxt_unit_ctx_t *ctx, nxt_java_app_conf_t *c); -static uint32_t compat[] = { - NXT_VERNUM, NXT_DEBUG, +static uint32_t compat[] = { + NXT_VERNUM, + NXT_DEBUG, }; -char *nxt_java_modules; - -static pthread_t *nxt_java_threads; -static pthread_attr_t *nxt_java_thread_attr; +char *nxt_java_modules; +static pthread_t *nxt_java_threads; +static pthread_attr_t *nxt_java_thread_attr; -#define NXT_STRING(x) _NXT_STRING(x) -#define _NXT_STRING(x) #x +#define NXT_STRING(x) _NXT_STRING(x) +#define _NXT_STRING(x) #x -NXT_EXPORT nxt_app_module_t nxt_app_module = { - sizeof(compat), - compat, - nxt_string("java"), - NXT_STRING(NXT_JAVA_VERSION), - nxt_java_mounts, - nxt_nitems(nxt_java_mounts), - nxt_java_setup, - nxt_java_start, +NXT_EXPORT nxt_app_module_t nxt_app_module = { + sizeof(compat), compat, + nxt_string("java"), NXT_STRING(NXT_JAVA_VERSION), + nxt_java_mounts, nxt_nitems(nxt_java_mounts), + nxt_java_setup, nxt_java_start, }; typedef struct { - JavaVM *jvm; - jobject cl; - jobject ctx; - nxt_java_app_conf_t *conf; + JavaVM *jvm; + jobject cl; + jobject ctx; + nxt_java_app_conf_t *conf; } nxt_java_data_t; +static nxt_int_t nxt_java_setup(nxt_task_t *task, nxt_process_t *process, + nxt_common_app_conf_t *conf) { + char *path, *relpath, *p, *rootfs; + size_t jars_dir_len, rootfs_len; + const char *unit_jars; -static nxt_int_t -nxt_java_setup(nxt_task_t *task, nxt_process_t *process, - nxt_common_app_conf_t *conf) -{ - char *path, *relpath, *p, *rootfs; - size_t jars_dir_len, rootfs_len; - const char *unit_jars; - - rootfs = (char *) process->isolation.rootfs; - rootfs_len = 0; - - unit_jars = conf->u.java.unit_jars; - if (unit_jars == NULL) { - if (rootfs != NULL) { - unit_jars = "/"; - } else { - unit_jars = NXT_JARS; - } - } - - relpath = strdup(unit_jars); - if (nxt_slow_path(relpath == NULL)) { - return NXT_ERROR; - } + rootfs = (char *)process->isolation.rootfs; + rootfs_len = 0; + unit_jars = conf->u.java.unit_jars; + if (unit_jars == NULL) { if (rootfs != NULL) { - jars_dir_len = strlen(unit_jars); - rootfs_len = strlen(rootfs); - - path = nxt_malloc(jars_dir_len + rootfs_len + 1); - if (nxt_slow_path(path == NULL)) { - free(relpath); - return NXT_ERROR; - } - - p = nxt_cpymem(path, process->isolation.rootfs, rootfs_len); - p = nxt_cpymem(p, relpath, jars_dir_len); - *p = '\0'; - - free(relpath); - + unit_jars = "/"; } else { - path = relpath; - } - - nxt_java_modules = realpath(path, NULL); - if (nxt_java_modules == NULL) { - nxt_alert(task, "realpath(\"%s\") failed %E", path, nxt_errno); - goto free; - } - - if (rootfs != NULL && strlen(path) > rootfs_len) { - nxt_java_modules = path + rootfs_len; + unit_jars = NXT_JARS; } + } - nxt_debug(task, "JAVA MODULES: %s", nxt_java_modules); - - return NXT_OK; - -free: - - nxt_free(path); - + relpath = strdup(unit_jars); + if (nxt_slow_path(relpath == NULL)) { return NXT_ERROR; -} + } + if (rootfs != NULL) { + jars_dir_len = strlen(unit_jars); + rootfs_len = strlen(rootfs); -static char ** -nxt_java_module_jars(const char *jars[], int jar_count) -{ - char **res, *jurl; - uint8_t pathsep; - nxt_int_t modules_len, jlen, i; - const char **jar; - - res = nxt_malloc(jar_count * sizeof(char*)); - if (res == NULL) { - return NULL; + path = nxt_malloc(jars_dir_len + rootfs_len + 1); + if (nxt_slow_path(path == NULL)) { + free(relpath); + return NXT_ERROR; } - modules_len = nxt_strlen(nxt_java_modules); + p = nxt_cpymem(path, process->isolation.rootfs, rootfs_len); + p = nxt_cpymem(p, relpath, jars_dir_len); + *p = '\0'; - pathsep = nxt_java_modules[modules_len - 1] == '/'; + free(relpath); - for (i = 0, jar = jars; *jar != NULL; jar++) { - jlen = nxt_length("file:") + modules_len - + (!pathsep ? nxt_length("/") : 0) - + nxt_strlen(*jar) + 1; + } else { + path = relpath; + } - jurl = nxt_malloc(jlen); - if (jurl == NULL) { - return NULL; - } + nxt_java_modules = realpath(path, NULL); + if (nxt_java_modules == NULL) { + nxt_alert(task, "realpath(\"%s\") failed %E", path, nxt_errno); + goto free; + } - res[i++] = jurl; + if (rootfs != NULL && strlen(path) > rootfs_len) { + nxt_java_modules = path + rootfs_len; + } - jurl = nxt_cpymem(jurl, "file:", nxt_length("file:")); - jurl = nxt_cpymem(jurl, nxt_java_modules, modules_len); + nxt_debug(task, "JAVA MODULES: %s", nxt_java_modules); - if (!pathsep) { - *jurl++ = '/'; - } + return NXT_OK; - jurl = nxt_cpymem(jurl, *jar, nxt_strlen(*jar)); - *jurl++ = '\0'; - } +free: - return res; + nxt_free(path); + + return NXT_ERROR; } +static char **nxt_java_module_jars(const char *jars[], int jar_count) { + char **res, *jurl; + uint8_t pathsep; + nxt_int_t modules_len, jlen, i; + const char **jar; -static nxt_int_t -nxt_java_start(nxt_task_t *task, nxt_process_data_t *data) -{ - jint rc; - char *opt, *real_path; - char **classpath_arr, **unit_jars, **system_jars; - JavaVM *jvm; - JNIEnv *env; - jobject cl, classpath; - nxt_str_t str; - nxt_int_t opt_len, real_path_len; - nxt_uint_t i, unit_jars_count, classpath_count; - nxt_uint_t system_jars_count; - JavaVMOption *jvm_opt; - JavaVMInitArgs jvm_args; - nxt_unit_ctx_t *ctx; - nxt_unit_init_t java_init; - nxt_java_data_t java_data; - nxt_conf_value_t *value; - nxt_java_app_conf_t *c; - nxt_common_app_conf_t *app_conf; - - //setenv("ASAN_OPTIONS", "handle_segv=0", 1); - - jvm_args.version = JNI_VERSION_1_6; - jvm_args.nOptions = 0; - jvm_args.ignoreUnrecognized = 0; - - app_conf = data->app; - c = &app_conf->u.java; - - if (c->options != NULL) { - jvm_args.nOptions += nxt_conf_array_elements_count(c->options); - } - - jvm_opt = nxt_malloc(jvm_args.nOptions * sizeof(JavaVMOption)); - if (jvm_opt == NULL) { - nxt_alert(task, "failed to allocate jvm_opt"); - return NXT_ERROR; - } + res = nxt_malloc(jar_count * sizeof(char *)); + if (res == NULL) { + return NULL; + } - jvm_args.options = jvm_opt; + modules_len = nxt_strlen(nxt_java_modules); - unit_jars_count = nxt_nitems(nxt_java_unit_jars) - 1; + pathsep = nxt_java_modules[modules_len - 1] == '/'; - unit_jars = nxt_java_module_jars(nxt_java_unit_jars, unit_jars_count); - if (unit_jars == NULL) { - nxt_alert(task, "failed to allocate buffer for unit_jars array"); + for (i = 0, jar = jars; *jar != NULL; jar++) { + jlen = nxt_length("file:") + modules_len + + (!pathsep ? nxt_length("/") : 0) + nxt_strlen(*jar) + 1; - return NXT_ERROR; + jurl = nxt_malloc(jlen); + if (jurl == NULL) { + return NULL; } - system_jars_count = nxt_nitems(nxt_java_system_jars) - 1; + res[i++] = jurl; - system_jars = nxt_java_module_jars(nxt_java_system_jars, system_jars_count); - if (system_jars == NULL) { - nxt_alert(task, "failed to allocate buffer for system_jars array"); + jurl = nxt_cpymem(jurl, "file:", nxt_length("file:")); + jurl = nxt_cpymem(jurl, nxt_java_modules, modules_len); - return NXT_ERROR; + if (!pathsep) { + *jurl++ = '/'; } - if (c->options != NULL) { - - for (i = 0; /* void */ ; i++) { - value = nxt_conf_get_array_element(c->options, i); - if (value == NULL) { - break; - } - - nxt_conf_get_string(value, &str); + jurl = nxt_cpymem(jurl, *jar, nxt_strlen(*jar)); + *jurl++ = '\0'; + } - opt = nxt_malloc(str.length + 1); - if (opt == NULL) { - nxt_alert(task, "failed to allocate jvm_opt"); - return NXT_ERROR; - } + return res; +} - memcpy(opt, str.start, str.length); - opt[str.length] = '\0'; +static nxt_int_t nxt_java_start(nxt_task_t *task, nxt_process_data_t *data) { + jint rc; + char *opt, *real_path; + char **classpath_arr, **unit_jars, **system_jars; + JavaVM *jvm; + JNIEnv *env; + jobject cl, classpath; + nxt_str_t str; + nxt_int_t opt_len, real_path_len; + nxt_uint_t i, unit_jars_count, classpath_count; + nxt_uint_t system_jars_count; + JavaVMOption *jvm_opt; + JavaVMInitArgs jvm_args; + nxt_unit_ctx_t *ctx; + nxt_unit_init_t java_init; + nxt_java_data_t java_data; + nxt_conf_value_t *value; + nxt_java_app_conf_t *c; + nxt_common_app_conf_t *app_conf; + + // setenv("ASAN_OPTIONS", "handle_segv=0", 1); + + jvm_args.version = JNI_VERSION_1_6; + jvm_args.nOptions = 0; + jvm_args.ignoreUnrecognized = 0; + + app_conf = data->app; + c = &app_conf->u.java; + + if (c->options != NULL) { + jvm_args.nOptions += nxt_conf_array_elements_count(c->options); + } + + jvm_opt = nxt_malloc(jvm_args.nOptions * sizeof(JavaVMOption)); + if (jvm_opt == NULL) { + nxt_alert(task, "failed to allocate jvm_opt"); + return NXT_ERROR; + } - jvm_opt[i].optionString = opt; - } - } + jvm_args.options = jvm_opt; - if (c->classpath != NULL) { - classpath_count = nxt_conf_array_elements_count(c->classpath); - classpath_arr = nxt_malloc(classpath_count * sizeof(char *)); + unit_jars_count = nxt_nitems(nxt_java_unit_jars) - 1; - for (i = 0; /* void */ ; i++) { - value = nxt_conf_get_array_element(c->classpath, i); - if (value == NULL) { - break; - } + unit_jars = nxt_java_module_jars(nxt_java_unit_jars, unit_jars_count); + if (unit_jars == NULL) { + nxt_alert(task, "failed to allocate buffer for unit_jars array"); - nxt_conf_get_string(value, &str); + return NXT_ERROR; + } - opt_len = str.length + 1; + system_jars_count = nxt_nitems(nxt_java_system_jars) - 1; - char *sc = memchr(str.start, ':', str.length); - if (sc == NULL && str.start[0] == '/') { - opt_len += nxt_length("file:"); - } + system_jars = nxt_java_module_jars(nxt_java_system_jars, system_jars_count); + if (system_jars == NULL) { + nxt_alert(task, "failed to allocate buffer for system_jars array"); - opt = nxt_malloc(opt_len); - if (opt == NULL) { - nxt_alert(task, "failed to allocate classpath"); - return NXT_ERROR; - } + return NXT_ERROR; + } - if (sc == NULL && str.start[0] != '/') { - nxt_memcpy(opt, str.start, str.length); - opt[str.length] = '\0'; + if (c->options != NULL) { - real_path = realpath(opt, NULL); - if (real_path == NULL) { - nxt_alert(task, "realpath(%s) failed: %E", opt, nxt_errno); - return NXT_ERROR; - } + for (i = 0; /* void */; i++) { + value = nxt_conf_get_array_element(c->options, i); + if (value == NULL) { + break; + } - real_path_len = nxt_strlen(real_path); + nxt_conf_get_string(value, &str); - free(opt); + opt = nxt_malloc(str.length + 1); + if (opt == NULL) { + nxt_alert(task, "failed to allocate jvm_opt"); + return NXT_ERROR; + } - opt_len = nxt_length("file:") + real_path_len + 1; + memcpy(opt, str.start, str.length); + opt[str.length] = '\0'; - opt = nxt_malloc(opt_len); - if (opt == NULL) { - nxt_alert(task, "failed to allocate classpath"); - return NXT_ERROR; - } + jvm_opt[i].optionString = opt; + } + } - } else { - real_path = (char *) str.start; /* I love this cast! */ - real_path_len = str.length; - } + if (c->classpath != NULL) { + classpath_count = nxt_conf_array_elements_count(c->classpath); + classpath_arr = nxt_malloc(classpath_count * sizeof(char *)); - classpath_arr[i] = opt; + for (i = 0; /* void */; i++) { + value = nxt_conf_get_array_element(c->classpath, i); + if (value == NULL) { + break; + } - if (sc == NULL) { - opt = nxt_cpymem(opt, "file:", nxt_length("file:")); - } + nxt_conf_get_string(value, &str); - opt = nxt_cpymem(opt, real_path, real_path_len); - *opt = '\0'; - } + opt_len = str.length + 1; - } else { - classpath_count = 0; - classpath_arr = NULL; - } + char *sc = memchr(str.start, ':', str.length); + if (sc == NULL && str.start[0] == '/') { + opt_len += nxt_length("file:"); + } - rc = JNI_CreateJavaVM(&jvm, (void **) &env, &jvm_args); - if (rc != JNI_OK) { - nxt_alert(task, "failed to create Java VM: %d", (int) rc); + opt = nxt_malloc(opt_len); + if (opt == NULL) { + nxt_alert(task, "failed to allocate classpath"); return NXT_ERROR; - } + } - rc = nxt_java_initThread(env); - if (rc != NXT_UNIT_OK) { - nxt_alert(task, "nxt_java_initThread() failed"); - goto env_failed; - } - - rc = nxt_java_initURLClassLoader(env); - if (rc != NXT_UNIT_OK) { - nxt_alert(task, "nxt_java_initURLClassLoader() failed"); - goto env_failed; - } - - cl = nxt_java_newURLClassLoader(env, system_jars_count, system_jars); - if (cl == NULL) { - nxt_alert(task, "nxt_java_newURLClassLoader failed"); - goto env_failed; - } + if (sc == NULL && str.start[0] != '/') { + nxt_memcpy(opt, str.start, str.length); + opt[str.length] = '\0'; - nxt_java_setContextClassLoader(env, cl); - - cl = nxt_java_newURLClassLoader_parent(env, unit_jars_count, unit_jars, cl); - if (cl == NULL) { - nxt_alert(task, "nxt_java_newURLClassLoader_parent failed"); - goto env_failed; - } + real_path = realpath(opt, NULL); + if (real_path == NULL) { + nxt_alert(task, "realpath(%s) failed: %E", opt, nxt_errno); + return NXT_ERROR; + } - nxt_java_setContextClassLoader(env, cl); + real_path_len = nxt_strlen(real_path); - rc = nxt_java_initContext(env, cl); - if (rc != NXT_UNIT_OK) { - nxt_alert(task, "nxt_java_initContext() failed"); - goto env_failed; - } + free(opt); - rc = nxt_java_initRequest(env, cl); - if (rc != NXT_UNIT_OK) { - nxt_alert(task, "nxt_java_initRequest() failed"); - goto env_failed; - } + opt_len = nxt_length("file:") + real_path_len + 1; - rc = nxt_java_initResponse(env, cl); - if (rc != NXT_UNIT_OK) { - nxt_alert(task, "nxt_java_initResponse() failed"); - goto env_failed; - } + opt = nxt_malloc(opt_len); + if (opt == NULL) { + nxt_alert(task, "failed to allocate classpath"); + return NXT_ERROR; + } - rc = nxt_java_initInputStream(env, cl); - if (rc != NXT_UNIT_OK) { - nxt_alert(task, "nxt_java_initInputStream() failed"); - goto env_failed; - } + } else { + real_path = (char *)str.start; /* I love this cast! */ + real_path_len = str.length; + } - rc = nxt_java_initOutputStream(env, cl); - if (rc != NXT_UNIT_OK) { - nxt_alert(task, "nxt_java_initOutputStream() failed"); - goto env_failed; - } + classpath_arr[i] = opt; - nxt_java_jni_init(env); - if (rc != NXT_UNIT_OK) { - nxt_alert(task, "nxt_java_jni_init() failed"); - goto env_failed; - } + if (sc == NULL) { + opt = nxt_cpymem(opt, "file:", nxt_length("file:")); + } - classpath = nxt_java_newURLs(env, classpath_count, classpath_arr); - if (classpath == NULL) { - nxt_alert(task, "nxt_java_newURLs failed"); - goto env_failed; + opt = nxt_cpymem(opt, real_path, real_path_len); + *opt = '\0'; } - java_data.jvm = jvm; - java_data.cl = cl; - java_data.ctx = nxt_java_startContext(env, c->webapp, classpath); - java_data.conf = c; + } else { + classpath_count = 0; + classpath_arr = NULL; + } - if ((*env)->ExceptionCheck(env)) { - nxt_alert(task, "Unhandled exception in application start"); - (*env)->ExceptionDescribe(env); - return NXT_ERROR; - } + rc = JNI_CreateJavaVM(&jvm, (void **)&env, &jvm_args); + if (rc != JNI_OK) { + nxt_alert(task, "failed to create Java VM: %d", (int)rc); + return NXT_ERROR; + } + + rc = nxt_java_initThread(env); + if (rc != NXT_UNIT_OK) { + nxt_alert(task, "nxt_java_initThread() failed"); + goto env_failed; + } + + rc = nxt_java_initURLClassLoader(env); + if (rc != NXT_UNIT_OK) { + nxt_alert(task, "nxt_java_initURLClassLoader() failed"); + goto env_failed; + } + + cl = nxt_java_newURLClassLoader(env, system_jars_count, system_jars); + if (cl == NULL) { + nxt_alert(task, "nxt_java_newURLClassLoader failed"); + goto env_failed; + } + + nxt_java_setContextClassLoader(env, cl); + + cl = nxt_java_newURLClassLoader_parent(env, unit_jars_count, unit_jars, cl); + if (cl == NULL) { + nxt_alert(task, "nxt_java_newURLClassLoader_parent failed"); + goto env_failed; + } + + nxt_java_setContextClassLoader(env, cl); + + rc = nxt_java_initContext(env, cl); + if (rc != NXT_UNIT_OK) { + nxt_alert(task, "nxt_java_initContext() failed"); + goto env_failed; + } + + rc = nxt_java_initRequest(env, cl); + if (rc != NXT_UNIT_OK) { + nxt_alert(task, "nxt_java_initRequest() failed"); + goto env_failed; + } + + rc = nxt_java_initResponse(env, cl); + if (rc != NXT_UNIT_OK) { + nxt_alert(task, "nxt_java_initResponse() failed"); + goto env_failed; + } + + rc = nxt_java_initInputStream(env, cl); + if (rc != NXT_UNIT_OK) { + nxt_alert(task, "nxt_java_initInputStream() failed"); + goto env_failed; + } + + rc = nxt_java_initOutputStream(env, cl); + if (rc != NXT_UNIT_OK) { + nxt_alert(task, "nxt_java_initOutputStream() failed"); + goto env_failed; + } + + nxt_java_jni_init(env); + if (rc != NXT_UNIT_OK) { + nxt_alert(task, "nxt_java_jni_init() failed"); + goto env_failed; + } + + classpath = nxt_java_newURLs(env, classpath_count, classpath_arr); + if (classpath == NULL) { + nxt_alert(task, "nxt_java_newURLs failed"); + goto env_failed; + } + + java_data.jvm = jvm; + java_data.cl = cl; + java_data.ctx = nxt_java_startContext(env, c->webapp, classpath); + java_data.conf = c; + + if ((*env)->ExceptionCheck(env)) { + nxt_alert(task, "Unhandled exception in application start"); + (*env)->ExceptionDescribe(env); + return NXT_ERROR; + } - rc = nxt_java_init_threads(c); - if (nxt_slow_path(rc == NXT_UNIT_ERROR)) { - return NXT_ERROR; - } + rc = nxt_java_init_threads(c); + if (nxt_slow_path(rc == NXT_UNIT_ERROR)) { + return NXT_ERROR; + } - nxt_unit_default_init(task, &java_init, app_conf); + nxt_unit_default_init(task, &java_init, app_conf); - java_init.callbacks.request_handler = nxt_java_request_handler; - java_init.callbacks.websocket_handler = nxt_java_websocket_handler; - java_init.callbacks.close_handler = nxt_java_close_handler; - java_init.callbacks.ready_handler = nxt_java_ready_handler; - java_init.request_data_size = sizeof(nxt_java_request_data_t); - java_init.data = &java_data; - java_init.ctx_data = env; + java_init.callbacks.request_handler = nxt_java_request_handler; + java_init.callbacks.websocket_handler = nxt_java_websocket_handler; + java_init.callbacks.close_handler = nxt_java_close_handler; + java_init.callbacks.ready_handler = nxt_java_ready_handler; + java_init.request_data_size = sizeof(nxt_java_request_data_t); + java_init.data = &java_data; + java_init.ctx_data = env; - ctx = nxt_unit_init(&java_init); - if (nxt_slow_path(ctx == NULL)) { - nxt_alert(task, "nxt_unit_init() failed"); - return NXT_ERROR; - } + ctx = nxt_unit_init(&java_init); + if (nxt_slow_path(ctx == NULL)) { + nxt_alert(task, "nxt_unit_init() failed"); + return NXT_ERROR; + } - rc = nxt_unit_run(ctx); + rc = nxt_unit_run(ctx); - nxt_java_join_threads(ctx, c); + nxt_java_join_threads(ctx, c); - nxt_java_stopContext(env, java_data.ctx); + nxt_java_stopContext(env, java_data.ctx); - if ((*env)->ExceptionCheck(env)) { - (*env)->ExceptionDescribe(env); - } + if ((*env)->ExceptionCheck(env)) { + (*env)->ExceptionDescribe(env); + } - nxt_unit_done(ctx); + nxt_unit_done(ctx); - (*jvm)->DestroyJavaVM(jvm); + (*jvm)->DestroyJavaVM(jvm); - exit(rc); + exit(rc); - return NXT_OK; + return NXT_OK; env_failed: - if ((*env)->ExceptionCheck(env)) { - (*env)->ExceptionDescribe(env); - } + if ((*env)->ExceptionCheck(env)) { + (*env)->ExceptionDescribe(env); + } - return NXT_ERROR; + return NXT_ERROR; } +static void nxt_java_request_handler(nxt_unit_request_info_t *req) { + JNIEnv *env; + jobject jreq, jresp; + nxt_java_data_t *java_data; + nxt_java_request_data_t *data; -static void -nxt_java_request_handler(nxt_unit_request_info_t *req) -{ - JNIEnv *env; - jobject jreq, jresp; - nxt_java_data_t *java_data; - nxt_java_request_data_t *data; - - java_data = req->unit->data; - env = req->ctx->data; - data = req->data; - - jreq = nxt_java_newRequest(env, java_data->ctx, req); - if (jreq == NULL) { - nxt_unit_req_alert(req, "failed to create Request instance"); + java_data = req->unit->data; + env = req->ctx->data; + data = req->data; - if ((*env)->ExceptionCheck(env)) { - (*env)->ExceptionDescribe(env); - (*env)->ExceptionClear(env); - } + jreq = nxt_java_newRequest(env, java_data->ctx, req); + if (jreq == NULL) { + nxt_unit_req_alert(req, "failed to create Request instance"); - nxt_unit_request_done(req, NXT_UNIT_ERROR); - return; + if ((*env)->ExceptionCheck(env)) { + (*env)->ExceptionDescribe(env); + (*env)->ExceptionClear(env); } - jresp = nxt_java_newResponse(env, req); - if (jresp == NULL) { - nxt_unit_req_alert(req, "failed to create Response instance"); + nxt_unit_request_done(req, NXT_UNIT_ERROR); + return; + } - if ((*env)->ExceptionCheck(env)) { - (*env)->ExceptionDescribe(env); - (*env)->ExceptionClear(env); - } + jresp = nxt_java_newResponse(env, req); + if (jresp == NULL) { + nxt_unit_req_alert(req, "failed to create Response instance"); - (*env)->DeleteLocalRef(env, jreq); - - nxt_unit_request_done(req, NXT_UNIT_ERROR); - return; + if ((*env)->ExceptionCheck(env)) { + (*env)->ExceptionDescribe(env); + (*env)->ExceptionClear(env); } - data->header_size = 10 * 1024; - data->buf_size = 32 * 1024; /* from Jetty */ - data->jreq = jreq; - data->jresp = jresp; - data->buf = NULL; + (*env)->DeleteLocalRef(env, jreq); - nxt_unit_request_group_dup_fields(req); + nxt_unit_request_done(req, NXT_UNIT_ERROR); + return; + } - nxt_java_service(env, java_data->ctx, jreq, jresp); + data->header_size = 10 * 1024; + data->buf_size = 32 * 1024; /* from Jetty */ + data->jreq = jreq; + data->jresp = jresp; + data->buf = NULL; - if ((*env)->ExceptionCheck(env)) { - (*env)->ExceptionDescribe(env); - (*env)->ExceptionClear(env); - } + nxt_unit_request_group_dup_fields(req); - if (!nxt_unit_response_is_init(req)) { - nxt_unit_response_init(req, 200, 0, 0); - } + nxt_java_service(env, java_data->ctx, jreq, jresp); - if (!nxt_unit_response_is_sent(req)) { - nxt_unit_response_send(req); - } + if ((*env)->ExceptionCheck(env)) { + (*env)->ExceptionDescribe(env); + (*env)->ExceptionClear(env); + } - if (data->buf != NULL) { - nxt_unit_buf_send(data->buf); + if (!nxt_unit_response_is_init(req)) { + nxt_unit_response_init(req, 200, 0, 0); + } - data->buf = NULL; - } + if (!nxt_unit_response_is_sent(req)) { + nxt_unit_response_send(req); + } - if (nxt_unit_response_is_websocket(req)) { - data->jreq = (*env)->NewGlobalRef(env, jreq); - data->jresp = (*env)->NewGlobalRef(env, jresp); + if (data->buf != NULL) { + nxt_unit_buf_send(data->buf); - } else { - nxt_unit_request_done(req, NXT_UNIT_OK); - } + data->buf = NULL; + } - (*env)->DeleteLocalRef(env, jresp); - (*env)->DeleteLocalRef(env, jreq); -} + if (nxt_unit_response_is_websocket(req)) { + data->jreq = (*env)->NewGlobalRef(env, jreq); + data->jresp = (*env)->NewGlobalRef(env, jresp); + } else { + nxt_unit_request_done(req, NXT_UNIT_OK); + } -static void -nxt_java_websocket_handler(nxt_unit_websocket_frame_t *ws) -{ - void *b; - JNIEnv *env; - jobject jbuf; - nxt_java_request_data_t *data; + (*env)->DeleteLocalRef(env, jresp); + (*env)->DeleteLocalRef(env, jreq); +} - env = ws->req->ctx->data; - data = ws->req->data; +static void nxt_java_websocket_handler(nxt_unit_websocket_frame_t *ws) { + void *b; + JNIEnv *env; + jobject jbuf; + nxt_java_request_data_t *data; - b = malloc(ws->payload_len); - if (b != NULL) { - nxt_unit_websocket_read(ws, b, ws->payload_len); + env = ws->req->ctx->data; + data = ws->req->data; - jbuf = (*env)->NewDirectByteBuffer(env, b, ws->payload_len); - if (jbuf != NULL) { - nxt_java_Request_websocket(env, data->jreq, jbuf, - ws->header->opcode, ws->header->fin); + b = malloc(ws->payload_len); + if (b != NULL) { + nxt_unit_websocket_read(ws, b, ws->payload_len); - if ((*env)->ExceptionCheck(env)) { - (*env)->ExceptionDescribe(env); - (*env)->ExceptionClear(env); - } + jbuf = (*env)->NewDirectByteBuffer(env, b, ws->payload_len); + if (jbuf != NULL) { + nxt_java_Request_websocket(env, data->jreq, jbuf, ws->header->opcode, + ws->header->fin); - (*env)->DeleteLocalRef(env, jbuf); - } + if ((*env)->ExceptionCheck(env)) { + (*env)->ExceptionDescribe(env); + (*env)->ExceptionClear(env); + } - free(b); + (*env)->DeleteLocalRef(env, jbuf); } - nxt_unit_websocket_done(ws); -} + free(b); + } + nxt_unit_websocket_done(ws); +} -static void -nxt_java_close_handler(nxt_unit_request_info_t *req) -{ - JNIEnv *env; - nxt_java_request_data_t *data; +static void nxt_java_close_handler(nxt_unit_request_info_t *req) { + JNIEnv *env; + nxt_java_request_data_t *data; - env = req->ctx->data; - data = req->data; + env = req->ctx->data; + data = req->data; - nxt_java_Request_close(env, data->jreq); + nxt_java_Request_close(env, data->jreq); - (*env)->DeleteGlobalRef(env, data->jresp); - (*env)->DeleteGlobalRef(env, data->jreq); + (*env)->DeleteGlobalRef(env, data->jresp); + (*env)->DeleteGlobalRef(env, data->jreq); - nxt_unit_request_done(req, NXT_UNIT_OK); + nxt_unit_request_done(req, NXT_UNIT_OK); } +static int nxt_java_ready_handler(nxt_unit_ctx_t *ctx) { + int res; + uint32_t i; + nxt_java_data_t *java_data; + nxt_java_app_conf_t *c; -static int -nxt_java_ready_handler(nxt_unit_ctx_t *ctx) -{ - int res; - uint32_t i; - nxt_java_data_t *java_data; - nxt_java_app_conf_t *c; + java_data = ctx->unit->data; + c = java_data->conf; - java_data = ctx->unit->data; - c = java_data->conf; - - if (c->threads <= 1) { - return NXT_UNIT_OK; - } + if (c->threads <= 1) { + return NXT_UNIT_OK; + } - for (i = 0; i < c->threads - 1; i++) { - res = pthread_create(&nxt_java_threads[i], nxt_java_thread_attr, - nxt_java_thread_func, ctx); + for (i = 0; i < c->threads - 1; i++) { + res = pthread_create(&nxt_java_threads[i], nxt_java_thread_attr, + nxt_java_thread_func, ctx); - if (nxt_fast_path(res == 0)) { - nxt_unit_debug(ctx, "thread #%d created", (int) (i + 1)); + if (nxt_fast_path(res == 0)) { + nxt_unit_debug(ctx, "thread #%d created", (int)(i + 1)); - } else { - nxt_unit_alert(ctx, "thread #%d create failed: %s (%d)", - (int) (i + 1), strerror(res), res); + } else { + nxt_unit_alert(ctx, "thread #%d create failed: %s (%d)", (int)(i + 1), + strerror(res), res); - return NXT_UNIT_ERROR; - } + return NXT_UNIT_ERROR; } + } - return NXT_UNIT_OK; + return NXT_UNIT_OK; } +static void *nxt_java_thread_func(void *data) { + int rc; + JavaVM *jvm; + JNIEnv *env; + nxt_unit_ctx_t *main_ctx, *ctx; + nxt_java_data_t *java_data; -static void * -nxt_java_thread_func(void *data) -{ - int rc; - JavaVM *jvm; - JNIEnv *env; - nxt_unit_ctx_t *main_ctx, *ctx; - nxt_java_data_t *java_data; - - main_ctx = data; + main_ctx = data; - nxt_unit_debug(main_ctx, "worker thread start"); + nxt_unit_debug(main_ctx, "worker thread start"); - java_data = main_ctx->unit->data; - jvm = java_data->jvm; + java_data = main_ctx->unit->data; + jvm = java_data->jvm; - rc = (*jvm)->AttachCurrentThread(jvm, (void **) &env, NULL); - if (rc != JNI_OK) { - nxt_unit_alert(main_ctx, "failed to attach Java VM: %d", (int) rc); - return NULL; - } + rc = (*jvm)->AttachCurrentThread(jvm, (void **)&env, NULL); + if (rc != JNI_OK) { + nxt_unit_alert(main_ctx, "failed to attach Java VM: %d", (int)rc); + return NULL; + } - nxt_java_setContextClassLoader(env, java_data->cl); + nxt_java_setContextClassLoader(env, java_data->cl); - ctx = nxt_unit_ctx_alloc(main_ctx, env); - if (nxt_slow_path(ctx == NULL)) { - goto fail; - } + ctx = nxt_unit_ctx_alloc(main_ctx, env); + if (nxt_slow_path(ctx == NULL)) { + goto fail; + } - (void) nxt_unit_run(ctx); + (void)nxt_unit_run(ctx); - nxt_unit_done(ctx); + nxt_unit_done(ctx); fail: - (*jvm)->DetachCurrentThread(jvm); + (*jvm)->DetachCurrentThread(jvm); - nxt_unit_debug(NULL, "worker thread end"); + nxt_unit_debug(NULL, "worker thread end"); - return NULL; + return NULL; } +static int nxt_java_init_threads(nxt_java_app_conf_t *c) { + int res; + static pthread_attr_t attr; -static int -nxt_java_init_threads(nxt_java_app_conf_t *c) -{ - int res; - static pthread_attr_t attr; - - if (c->threads <= 1) { - return NXT_UNIT_OK; - } - - if (c->thread_stack_size > 0) { - res = pthread_attr_init(&attr); - if (nxt_slow_path(res != 0)) { - nxt_unit_alert(NULL, "thread attr init failed: %s (%d)", - strerror(res), res); + if (c->threads <= 1) { + return NXT_UNIT_OK; + } - return NXT_UNIT_ERROR; - } + if (c->thread_stack_size > 0) { + res = pthread_attr_init(&attr); + if (nxt_slow_path(res != 0)) { + nxt_unit_alert(NULL, "thread attr init failed: %s (%d)", strerror(res), + res); - res = pthread_attr_setstacksize(&attr, c->thread_stack_size); - if (nxt_slow_path(res != 0)) { - nxt_unit_alert(NULL, "thread attr set stack size failed: %s (%d)", - strerror(res), res); + return NXT_UNIT_ERROR; + } - return NXT_UNIT_ERROR; - } + res = pthread_attr_setstacksize(&attr, c->thread_stack_size); + if (nxt_slow_path(res != 0)) { + nxt_unit_alert(NULL, "thread attr set stack size failed: %s (%d)", + strerror(res), res); - nxt_java_thread_attr = &attr; + return NXT_UNIT_ERROR; } - nxt_java_threads = nxt_unit_malloc(NULL, - sizeof(pthread_t) * (c->threads - 1)); - if (nxt_slow_path(nxt_java_threads == NULL)) { - nxt_unit_alert(NULL, "Failed to allocate thread id array"); + nxt_java_thread_attr = &attr; + } - return NXT_UNIT_ERROR; - } + nxt_java_threads = + nxt_unit_malloc(NULL, sizeof(pthread_t) * (c->threads - 1)); + if (nxt_slow_path(nxt_java_threads == NULL)) { + nxt_unit_alert(NULL, "Failed to allocate thread id array"); - memset(nxt_java_threads, 0, sizeof(pthread_t) * (c->threads - 1)); + return NXT_UNIT_ERROR; + } - return NXT_UNIT_OK; + memset(nxt_java_threads, 0, sizeof(pthread_t) * (c->threads - 1)); + + return NXT_UNIT_OK; } +static void nxt_java_join_threads(nxt_unit_ctx_t *ctx, nxt_java_app_conf_t *c) { + int res; + uint32_t i; -static void -nxt_java_join_threads(nxt_unit_ctx_t *ctx, nxt_java_app_conf_t *c) -{ - int res; - uint32_t i; + if (nxt_java_threads == NULL) { + return; + } - if (nxt_java_threads == NULL) { - return; + for (i = 0; i < c->threads - 1; i++) { + if ((uintptr_t)nxt_java_threads[i] == 0) { + continue; } - for (i = 0; i < c->threads - 1; i++) { - if ((uintptr_t) nxt_java_threads[i] == 0) { - continue; - } - - res = pthread_join(nxt_java_threads[i], NULL); + res = pthread_join(nxt_java_threads[i], NULL); - if (nxt_fast_path(res == 0)) { - nxt_unit_debug(ctx, "thread #%d joined", (int) i); + if (nxt_fast_path(res == 0)) { + nxt_unit_debug(ctx, "thread #%d joined", (int)i); - } else { - nxt_unit_alert(ctx, "thread #%d join failed: %s (%d)", - (int) i, strerror(res), res); - } + } else { + nxt_unit_alert(ctx, "thread #%d join failed: %s (%d)", (int)i, + strerror(res), res); } + } - nxt_unit_free(ctx, nxt_java_threads); + nxt_unit_free(ctx, nxt_java_threads); } - - diff --git a/src/nxt_job.c b/src/nxt_job.c index 560739537..aa120ce45 100644 --- a/src/nxt_job.c +++ b/src/nxt_job.c @@ -6,78 +6,67 @@ #include - static void nxt_job_thread_trampoline(nxt_task_t *task, void *obj, void *data); static void nxt_job_thread_return_handler(nxt_task_t *task, void *obj, - void *data); - + void *data); -void * -nxt_job_create(nxt_mp_t *mp, size_t size) -{ - size_t cache_size; - nxt_job_t *job; +void *nxt_job_create(nxt_mp_t *mp, size_t size) { + size_t cache_size; + nxt_job_t *job; - if (mp == NULL) { - mp = nxt_mp_create(1024, 128, 256, 32); - if (nxt_slow_path(mp == NULL)) { - return NULL; - } + if (mp == NULL) { + mp = nxt_mp_create(1024, 128, 256, 32); + if (nxt_slow_path(mp == NULL)) { + return NULL; + } - job = nxt_mp_zget(mp, size); - cache_size = 0; + job = nxt_mp_zget(mp, size); + cache_size = 0; - } else { - job = nxt_mp_zalloc(mp, size); - cache_size = size; - } + } else { + job = nxt_mp_zalloc(mp, size); + cache_size = size; + } - if (nxt_slow_path(job == NULL)) { - return NULL; - } + if (nxt_slow_path(job == NULL)) { + return NULL; + } - job->cache_size = (uint16_t) cache_size; - job->mem_pool = mp; - nxt_job_set_name(job, "job"); + job->cache_size = (uint16_t)cache_size; + job->mem_pool = mp; + nxt_job_set_name(job, "job"); - /* Allow safe nxt_queue_remove() in nxt_job_destroy(). */ - nxt_queue_self(&job->link); + /* Allow safe nxt_queue_remove() in nxt_job_destroy(). */ + nxt_queue_self(&job->link); - return job; + return job; } +void nxt_job_init(nxt_job_t *job, size_t size) { + nxt_memzero(job, size); -void -nxt_job_init(nxt_job_t *job, size_t size) -{ - nxt_memzero(job, size); - - nxt_job_set_name(job, "job"); + nxt_job_set_name(job, "job"); - nxt_queue_self(&job->link); + nxt_queue_self(&job->link); } +void nxt_job_destroy(nxt_task_t *task, void *data) { + nxt_job_t *job; -void -nxt_job_destroy(nxt_task_t *task, void *data) -{ - nxt_job_t *job; - - job = data; + job = data; - nxt_queue_remove(&job->link); + nxt_queue_remove(&job->link); - if (job->cache_size == 0) { + if (job->cache_size == 0) { - if (job->mem_pool != NULL) { - nxt_mp_destroy(job->mem_pool); - } - - } else { - nxt_mp_free(job->mem_pool, job); + if (job->mem_pool != NULL) { + nxt_mp_destroy(job->mem_pool); } -} + } else { + nxt_mp_free(job->mem_pool, job); + } +} #if 0 @@ -99,101 +88,92 @@ nxt_job_cleanup_add(nxt_mp_t *mp, nxt_job_t *job) #endif - /* * The (void *) casts in nxt_thread_pool_post() and nxt_event_engine_post() * calls and to the "nxt_work_handler_t" are required by Sun C. */ -void -nxt_job_start(nxt_task_t *task, nxt_job_t *job, nxt_work_handler_t handler) -{ - nxt_debug(task, "%s start", job->name); - - if (job->thread_pool != NULL) { - nxt_int_t ret; +void nxt_job_start(nxt_task_t *task, nxt_job_t *job, + nxt_work_handler_t handler) { + nxt_debug(task, "%s start", job->name); - job->engine = task->thread->engine; + if (job->thread_pool != NULL) { + nxt_int_t ret; - nxt_work_set(&job->work, nxt_job_thread_trampoline, - job->task, job, (void *) handler); + job->engine = task->thread->engine; - ret = nxt_thread_pool_post(job->thread_pool, &job->work); + nxt_work_set(&job->work, nxt_job_thread_trampoline, job->task, job, + (void *)handler); - if (ret == NXT_OK) { - return; - } + ret = nxt_thread_pool_post(job->thread_pool, &job->work); - handler = job->abort_handler; + if (ret == NXT_OK) { + return; } - handler(job->task, job, job->data); -} + handler = job->abort_handler; + } + handler(job->task, job, job->data); +} /* A trampoline function is called by a thread pool thread. */ -static void -nxt_job_thread_trampoline(nxt_task_t *task, void *obj, void *data) -{ - nxt_job_t *job; - nxt_work_handler_t handler; +static void nxt_job_thread_trampoline(nxt_task_t *task, void *obj, void *data) { + nxt_job_t *job; + nxt_work_handler_t handler; - job = obj; - handler = (nxt_work_handler_t) data; + job = obj; + handler = (nxt_work_handler_t)data; - nxt_debug(task, "%s thread", job->name); + nxt_debug(task, "%s thread", job->name); - if (nxt_slow_path(job->cancel)) { - nxt_job_return(task, job, job->abort_handler); + if (nxt_slow_path(job->cancel)) { + nxt_job_return(task, job, job->abort_handler); - } else { - handler(job->task, job, job->data); - } + } else { + handler(job->task, job, job->data); + } } +void nxt_job_return(nxt_task_t *task, nxt_job_t *job, + nxt_work_handler_t handler) { + nxt_debug(task, "%s return", job->name); -void -nxt_job_return(nxt_task_t *task, nxt_job_t *job, nxt_work_handler_t handler) -{ - nxt_debug(task, "%s return", job->name); + if (job->engine != NULL) { + /* A return function is called in thread pool thread context. */ - if (job->engine != NULL) { - /* A return function is called in thread pool thread context. */ + nxt_work_set(&job->work, nxt_job_thread_return_handler, job->task, job, + (void *)handler); - nxt_work_set(&job->work, nxt_job_thread_return_handler, - job->task, job, (void *) handler); + nxt_event_engine_post(job->engine, &job->work); - nxt_event_engine_post(job->engine, &job->work); + return; + } - return; - } + if (nxt_slow_path(job->cancel)) { + nxt_debug(task, "%s cancellation", job->name); + handler = job->abort_handler; + } - if (nxt_slow_path(job->cancel)) { - nxt_debug(task, "%s cancellation", job->name); - handler = job->abort_handler; - } - - nxt_work_queue_add(&task->thread->engine->fast_work_queue, - handler, job->task, job, job->data); + nxt_work_queue_add(&task->thread->engine->fast_work_queue, handler, job->task, + job, job->data); } +static void nxt_job_thread_return_handler(nxt_task_t *task, void *obj, + void *data) { + nxt_job_t *job; + nxt_work_handler_t handler; -static void -nxt_job_thread_return_handler(nxt_task_t *task, void *obj, void *data) -{ - nxt_job_t *job; - nxt_work_handler_t handler; - - job = obj; - handler = (nxt_work_handler_t) data; + job = obj; + handler = (nxt_work_handler_t)data; - job->task->thread = task->thread; + job->task->thread = task->thread; - if (nxt_slow_path(job->cancel)) { - nxt_debug(task, "%s cancellation", job->name); - handler = job->abort_handler; - } + if (nxt_slow_path(job->cancel)) { + nxt_debug(task, "%s cancellation", job->name); + handler = job->abort_handler; + } - handler(job->task, job, job->data); + handler(job->task, job, job->data); } diff --git a/src/nxt_job.h b/src/nxt_job.h index 0495c4844..6e0bdb7b0 100644 --- a/src/nxt_job.h +++ b/src/nxt_job.h @@ -7,7 +7,6 @@ #ifndef _NXT_JOB_H_INCLUDED_ #define _NXT_JOB_H_INCLUDED_ - /* * A job may run by separate thread, so each job should have its * its own mem_pool. A job itself is allocated from this mem_pool. @@ -29,52 +28,46 @@ * handler may be as simple as nxt_job_destroy(). */ - typedef struct { - void *data; + void *data; - nxt_task_t *task; + nxt_task_t *task; - nxt_work_handler_t abort_handler; + nxt_work_handler_t abort_handler; - uint16_t cache_size; - uint8_t cancel; /* 1 bit */ + uint16_t cache_size; + uint8_t cancel; /* 1 bit */ - nxt_mp_t *mem_pool; - nxt_queue_link_t link; + nxt_mp_t *mem_pool; + nxt_queue_link_t link; - nxt_thread_pool_t *thread_pool; - nxt_event_engine_t *engine; - nxt_log_t *log; + nxt_thread_pool_t *thread_pool; + nxt_event_engine_t *engine; + nxt_log_t *log; - nxt_work_t work; + nxt_work_t work; #if (NXT_DEBUG) - const char *name; + const char *name; #endif } nxt_job_t; - NXT_EXPORT void *nxt_job_create(nxt_mp_t *mp, size_t size); NXT_EXPORT void nxt_job_init(nxt_job_t *job, size_t size); NXT_EXPORT void nxt_job_destroy(nxt_task_t *task, void *data); NXT_EXPORT nxt_int_t nxt_job_cleanup_add(nxt_mp_t *mp, nxt_job_t *job); NXT_EXPORT void nxt_job_start(nxt_task_t *task, nxt_job_t *job, - nxt_work_handler_t handler); + nxt_work_handler_t handler); NXT_EXPORT void nxt_job_return(nxt_task_t *task, nxt_job_t *job, - nxt_work_handler_t handler); - - -#define nxt_job_cancel(job) \ - (job)->cancel = 1 + nxt_work_handler_t handler); +#define nxt_job_cancel(job) (job)->cancel = 1 #if (NXT_DEBUG) -#define nxt_job_set_name(job, text) \ - (job)->name = text +#define nxt_job_set_name(job, text) (job)->name = text #else @@ -82,5 +75,4 @@ NXT_EXPORT void nxt_job_return(nxt_task_t *task, nxt_job_t *job, #endif - #endif /* _NXT_JOB_H_INCLUDED_ */ diff --git a/src/nxt_job_cache_file.c b/src/nxt_job_cache_file.c index 13f01a453..b8b3295e5 100644 --- a/src/nxt_job_cache_file.c +++ b/src/nxt_job_cache_file.c @@ -4,21 +4,17 @@ * Copyright (C) NGINX, Inc. */ - #include +nxt_job_cache_file_t *nxt_job_cache_file_create(nxt_mp_t *mp) { + nxt_job_cache_file_t *jbc; -nxt_job_cache_file_t * -nxt_job_cache_file_create(nxt_mp_t *mp) -{ - nxt_job_cache_file_t *jbc; - - jbc = nxt_job_create(mp, sizeof(nxt_job_cache_file_t)); + jbc = nxt_job_create(mp, sizeof(nxt_job_cache_file_t)); - if (nxt_fast_path(jbc != NULL)) { - jbc->file.fd = NXT_FILE_INVALID; - jbc->read_required = nxt_job_file_read_required; - } + if (nxt_fast_path(jbc != NULL)) { + jbc->file.fd = NXT_FILE_INVALID; + jbc->read_required = nxt_job_file_read_required; + } - return jbc; + return jbc; } diff --git a/src/nxt_js.c b/src/nxt_js.c index 0482482ae..a61a9bf73 100644 --- a/src/nxt_js.c +++ b/src/nxt_js.c @@ -5,494 +5,448 @@ #include - struct nxt_js_s { - uint32_t index; + uint32_t index; }; - typedef struct { - nxt_str_t name; - nxt_str_t text; + nxt_str_t name; + nxt_str_t text; } nxt_js_module_t; - struct nxt_js_conf_s { - nxt_mp_t *pool; - njs_vm_t *vm; - njs_uint_t protos; - njs_external_t *proto; - nxt_str_t init; - nxt_array_t *modules; /* of nxt_js_module_t */ - nxt_array_t *funcs; - uint8_t test; /* 1 bit */ + nxt_mp_t *pool; + njs_vm_t *vm; + njs_uint_t protos; + njs_external_t *proto; + nxt_str_t init; + nxt_array_t *modules; /* of nxt_js_module_t */ + nxt_array_t *funcs; + uint8_t test; /* 1 bit */ }; +njs_mod_t *nxt_js_module_loader(njs_vm_t *vm, njs_external_ptr_t external, + njs_str_t *name) { + nxt_str_t text; + nxt_uint_t i, n; + nxt_js_conf_t *jcf; + nxt_js_module_t *modules, *module; -njs_mod_t * -nxt_js_module_loader(njs_vm_t *vm, njs_external_ptr_t external, njs_str_t *name) -{ - nxt_str_t text; - nxt_uint_t i, n; - nxt_js_conf_t *jcf; - nxt_js_module_t *modules, *module; + jcf = external; - jcf = external; + module = NULL; - module = NULL; + n = jcf->modules->nelts; + modules = jcf->modules->elts; - n = jcf->modules->nelts; - modules = jcf->modules->elts; - - for (i = 0; i < n; i++) { - if (nxt_strstr_eq(name, &modules[i].name)) { - module = &modules[i]; - break; - } + for (i = 0; i < n; i++) { + if (nxt_strstr_eq(name, &modules[i].name)) { + module = &modules[i]; + break; } + } - if (module == NULL) { - return NULL; - } + if (module == NULL) { + return NULL; + } - text.length = module->text.length; + text.length = module->text.length; - text.start = njs_mp_alloc(vm->mem_pool, text.length); - if (nxt_slow_path(text.start == NULL)) { - return NULL; - } + text.start = njs_mp_alloc(vm->mem_pool, text.length); + if (nxt_slow_path(text.start == NULL)) { + return NULL; + } - nxt_memcpy(text.start, module->text.start, text.length); + nxt_memcpy(text.start, module->text.start, text.length); - return njs_vm_compile_module(vm, name, &text.start, - &text.start[text.length]); + return njs_vm_compile_module(vm, name, &text.start, &text.start[text.length]); } +njs_int_t nxt_js_proto_id; -njs_int_t nxt_js_proto_id; - - -nxt_js_conf_t * -nxt_js_conf_new(nxt_mp_t *mp, nxt_bool_t test) -{ - nxt_js_conf_t *jcf; - - jcf = nxt_mp_zget(mp, sizeof(nxt_js_conf_t)); - if (nxt_slow_path(jcf == NULL)) { - return NULL; - } +nxt_js_conf_t *nxt_js_conf_new(nxt_mp_t *mp, nxt_bool_t test) { + nxt_js_conf_t *jcf; - jcf->pool = mp; - jcf->test = test; + jcf = nxt_mp_zget(mp, sizeof(nxt_js_conf_t)); + if (nxt_slow_path(jcf == NULL)) { + return NULL; + } - jcf->modules = nxt_array_create(mp, 4, sizeof(nxt_js_module_t)); - if (nxt_slow_path(jcf->modules == NULL)) { - return NULL; - } + jcf->pool = mp; + jcf->test = test; - jcf->funcs = nxt_array_create(mp, 4, sizeof(nxt_str_t)); - if (nxt_slow_path(jcf->funcs == NULL)) { - return NULL; - } - - return jcf; -} + jcf->modules = nxt_array_create(mp, 4, sizeof(nxt_js_module_t)); + if (nxt_slow_path(jcf->modules == NULL)) { + return NULL; + } + jcf->funcs = nxt_array_create(mp, 4, sizeof(nxt_str_t)); + if (nxt_slow_path(jcf->funcs == NULL)) { + return NULL; + } -void -nxt_js_conf_release(nxt_js_conf_t *jcf) -{ - njs_vm_destroy(jcf->vm); + return jcf; } +void nxt_js_conf_release(nxt_js_conf_t *jcf) { njs_vm_destroy(jcf->vm); } -void -nxt_js_set_proto(nxt_js_conf_t *jcf, njs_external_t *proto, njs_uint_t n) -{ - jcf->protos = n; - jcf->proto = proto; +void nxt_js_set_proto(nxt_js_conf_t *jcf, njs_external_t *proto, njs_uint_t n) { + jcf->protos = n; + jcf->proto = proto; } +static njs_vm_t *nxt_js_vm_create(nxt_js_conf_t *jcf) { + u_char *p; + size_t size; + njs_vm_t *vm; + nxt_uint_t i; + njs_vm_opt_t opts; + nxt_js_module_t *module, *mod; -static njs_vm_t * -nxt_js_vm_create(nxt_js_conf_t *jcf) -{ - u_char *p; - size_t size; - njs_vm_t *vm; - nxt_uint_t i; - njs_vm_opt_t opts; - nxt_js_module_t *module, *mod; + static const nxt_str_t import_str = nxt_string("import"); + static const nxt_str_t from_str = nxt_string("from"); + static const nxt_str_t global_str = nxt_string("globalThis"); - static const nxt_str_t import_str = nxt_string("import"); - static const nxt_str_t from_str = nxt_string("from"); - static const nxt_str_t global_str = nxt_string("globalThis"); + njs_vm_opt_init(&opts); - njs_vm_opt_init(&opts); + opts.backtrace = 1; - opts.backtrace = 1; + opts.file.start = (u_char *)"default"; + opts.file.length = 7; - opts.file.start = (u_char *) "default"; - opts.file.length = 7; + if (jcf->test || jcf->modules->nelts == 0) { + goto done; + } - if (jcf->test || jcf->modules->nelts == 0) { - goto done; - } - - opts.external = jcf; + opts.external = jcf; - size = 0; - module = jcf->modules->elts; + size = 0; + module = jcf->modules->elts; - for (i = 0; i < jcf->modules->nelts; i++) { - mod = &module[i]; + for (i = 0; i < jcf->modules->nelts; i++) { + mod = &module[i]; - size += import_str.length + 1 + mod->name.length + 1 - + from_str.length + 2 + mod->name.length + 3; + size += import_str.length + 1 + mod->name.length + 1 + from_str.length + 2 + + mod->name.length + 3; - size += global_str.length + 1 + mod->name.length + 3 - + mod->name.length + 2; - } + size += global_str.length + 1 + mod->name.length + 3 + mod->name.length + 2; + } - p = nxt_mp_nget(jcf->pool, size); - if (nxt_slow_path(p == NULL)) { - return NULL; - } + p = nxt_mp_nget(jcf->pool, size); + if (nxt_slow_path(p == NULL)) { + return NULL; + } - jcf->init.length = size; - jcf->init.start = p; + jcf->init.length = size; + jcf->init.start = p; - for (i = 0; i < jcf->modules->nelts; i++) { - mod = &module[i]; + for (i = 0; i < jcf->modules->nelts; i++) { + mod = &module[i]; - p = nxt_cpymem(p, import_str.start, import_str.length); - *p++ = ' '; + p = nxt_cpymem(p, import_str.start, import_str.length); + *p++ = ' '; - p = nxt_cpymem(p, mod->name.start, mod->name.length); - *p++ = ' '; + p = nxt_cpymem(p, mod->name.start, mod->name.length); + *p++ = ' '; - p = nxt_cpymem(p, from_str.start, from_str.length); - *p++ = ' '; + p = nxt_cpymem(p, from_str.start, from_str.length); + *p++ = ' '; - *p++ = '\"'; - p = nxt_cpymem(p, mod->name.start, mod->name.length); - *p++ = '\"'; - *p++ = ';'; - *p++ = '\n'; + *p++ = '\"'; + p = nxt_cpymem(p, mod->name.start, mod->name.length); + *p++ = '\"'; + *p++ = ';'; + *p++ = '\n'; - p = nxt_cpymem(p, global_str.start, global_str.length); - *p++ = '.'; + p = nxt_cpymem(p, global_str.start, global_str.length); + *p++ = '.'; - p = nxt_cpymem(p, mod->name.start, mod->name.length); - *p++ = ' '; - *p++ = '='; - *p++ = ' '; + p = nxt_cpymem(p, mod->name.start, mod->name.length); + *p++ = ' '; + *p++ = '='; + *p++ = ' '; - p = nxt_cpymem(p, mod->name.start, mod->name.length); - *p++ = ';'; - *p++ = '\n'; - } + p = nxt_cpymem(p, mod->name.start, mod->name.length); + *p++ = ';'; + *p++ = '\n'; + } done: - vm = njs_vm_create(&opts); + vm = njs_vm_create(&opts); - if (nxt_fast_path(vm != NULL)) { - njs_vm_set_module_loader(vm, nxt_js_module_loader, jcf); - } + if (nxt_fast_path(vm != NULL)) { + njs_vm_set_module_loader(vm, nxt_js_module_loader, jcf); + } - return vm; + return vm; } +nxt_int_t nxt_js_add_module(nxt_js_conf_t *jcf, nxt_str_t *name, + nxt_str_t *text) { + nxt_js_module_t *module; -nxt_int_t -nxt_js_add_module(nxt_js_conf_t *jcf, nxt_str_t *name, nxt_str_t *text) -{ - nxt_js_module_t *module; - - module = nxt_array_add(jcf->modules); - if (nxt_slow_path(module == NULL)) { - return NXT_ERROR; - } + module = nxt_array_add(jcf->modules); + if (nxt_slow_path(module == NULL)) { + return NXT_ERROR; + } - module->name = *name; + module->name = *name; - module->text.length = text->length; - module->text.start = nxt_mp_nget(jcf->pool, text->length); - if (nxt_slow_path(module->text.start == NULL)) { - return NXT_ERROR; - } + module->text.length = text->length; + module->text.start = nxt_mp_nget(jcf->pool, text->length); + if (nxt_slow_path(module->text.start == NULL)) { + return NXT_ERROR; + } - nxt_memcpy(module->text.start, text->start, text->length); + nxt_memcpy(module->text.start, text->start, text->length); - return NXT_OK; + return NXT_OK; } +nxt_js_t *nxt_js_add_tpl(nxt_js_conf_t *jcf, nxt_str_t *str, nxt_uint_t flags) { + size_t size; + u_char *p, *start; + nxt_js_t *js; + nxt_str_t *func; -nxt_js_t * -nxt_js_add_tpl(nxt_js_conf_t *jcf, nxt_str_t *str, nxt_uint_t flags) -{ - size_t size; - u_char *p, *start; - nxt_js_t *js; - nxt_str_t *func; - - static const nxt_str_t func_str = - nxt_string("function(uri, host, remoteAddr, " - "args, headers, cookies, vars) {" - " return "); + static const nxt_str_t func_str = + nxt_string("function(uri, host, remoteAddr, " + "args, headers, cookies, vars) {" + " return "); - /* - * Append a newline character if newline is true. - * Append a terminating null character if strz is true. - */ - static const nxt_str_t newline_str = nxt_string(" + '\\x0A'"); - static const nxt_str_t strz_str = nxt_string(" + '\\x00'"); + /* + * Append a newline character if newline is true. + * Append a terminating null character if strz is true. + */ + static const nxt_str_t newline_str = nxt_string(" + '\\x0A'"); + static const nxt_str_t strz_str = nxt_string(" + '\\x00'"); - size = func_str.length + str->length + 1; + size = func_str.length + str->length + 1; - if (flags & NXT_TSTR_NEWLINE) { - size += newline_str.length; - } + if (flags & NXT_TSTR_NEWLINE) { + size += newline_str.length; + } - if (flags & NXT_TSTR_STRZ) { - size += strz_str.length; - } + if (flags & NXT_TSTR_STRZ) { + size += strz_str.length; + } - start = nxt_mp_nget(jcf->pool, size); - if (nxt_slow_path(start == NULL)) { - return NULL; - } + start = nxt_mp_nget(jcf->pool, size); + if (nxt_slow_path(start == NULL)) { + return NULL; + } - p = start; + p = start; - p = nxt_cpymem(p, func_str.start, func_str.length); - p = nxt_cpymem(p, str->start, str->length); + p = nxt_cpymem(p, func_str.start, func_str.length); + p = nxt_cpymem(p, str->start, str->length); - if (flags & NXT_TSTR_NEWLINE) { - p = nxt_cpymem(p, newline_str.start, newline_str.length); - } + if (flags & NXT_TSTR_NEWLINE) { + p = nxt_cpymem(p, newline_str.start, newline_str.length); + } - if (flags & NXT_TSTR_STRZ) { - p = nxt_cpymem(p, strz_str.start, strz_str.length); - } + if (flags & NXT_TSTR_STRZ) { + p = nxt_cpymem(p, strz_str.start, strz_str.length); + } - *p++ = '}'; + *p++ = '}'; - js = nxt_mp_get(jcf->pool, sizeof(nxt_js_t)); - if (nxt_slow_path(js == NULL)) { - return NULL; - } + js = nxt_mp_get(jcf->pool, sizeof(nxt_js_t)); + if (nxt_slow_path(js == NULL)) { + return NULL; + } - func = nxt_array_add(jcf->funcs); - if (nxt_slow_path(func == NULL)) { - return NULL; - } + func = nxt_array_add(jcf->funcs); + if (nxt_slow_path(func == NULL)) { + return NULL; + } - func->start = start; - func->length = p - start; + func->start = start; + func->length = p - start; - js->index = jcf->funcs->nelts - 1; + js->index = jcf->funcs->nelts - 1; - return js; + return js; } +nxt_int_t nxt_js_compile(nxt_js_conf_t *jcf) { + size_t size; + u_char *p, *start; + njs_int_t ret; + nxt_str_t *func; + nxt_uint_t i; -nxt_int_t -nxt_js_compile(nxt_js_conf_t *jcf) -{ - size_t size; - u_char *p, *start; - njs_int_t ret; - nxt_str_t *func; - nxt_uint_t i; - - if (jcf->test) { - return NXT_OK; - } + if (jcf->test) { + return NXT_OK; + } - jcf->vm = nxt_js_vm_create(jcf); - if (nxt_slow_path(jcf->vm == NULL)) { - return NXT_ERROR; - } + jcf->vm = nxt_js_vm_create(jcf); + if (nxt_slow_path(jcf->vm == NULL)) { + return NXT_ERROR; + } - size = jcf->init.length + 2; - func = jcf->funcs->elts; + size = jcf->init.length + 2; + func = jcf->funcs->elts; - for (i = 0; i < jcf->funcs->nelts; i++) { - size += func[i].length + 1; - } + for (i = 0; i < jcf->funcs->nelts; i++) { + size += func[i].length + 1; + } - start = nxt_mp_nget(jcf->pool, size); - if (nxt_slow_path(start == NULL)) { - return NXT_ERROR; - } + start = nxt_mp_nget(jcf->pool, size); + if (nxt_slow_path(start == NULL)) { + return NXT_ERROR; + } - p = nxt_cpymem(start, jcf->init.start, jcf->init.length); - *p++ = '['; + p = nxt_cpymem(start, jcf->init.start, jcf->init.length); + *p++ = '['; - func = jcf->funcs->elts; + func = jcf->funcs->elts; - for (i = 0; i < jcf->funcs->nelts; i++) { - p = nxt_cpymem(p, func[i].start, func[i].length); - *p++ = ','; - } + for (i = 0; i < jcf->funcs->nelts; i++) { + p = nxt_cpymem(p, func[i].start, func[i].length); + *p++ = ','; + } - *p++ = ']'; + *p++ = ']'; - nxt_js_proto_id = njs_vm_external_prototype(jcf->vm, jcf->proto, - jcf->protos); - if (nxt_slow_path(nxt_js_proto_id < 0)) { - return NXT_ERROR; - } + nxt_js_proto_id = njs_vm_external_prototype(jcf->vm, jcf->proto, jcf->protos); + if (nxt_slow_path(nxt_js_proto_id < 0)) { + return NXT_ERROR; + } - ret = njs_vm_compile(jcf->vm, &start, p); + ret = njs_vm_compile(jcf->vm, &start, p); - return (ret == NJS_OK) ? NXT_OK : NXT_ERROR; + return (ret == NJS_OK) ? NXT_OK : NXT_ERROR; } +nxt_int_t nxt_js_test(nxt_js_conf_t *jcf, nxt_str_t *str, u_char *error) { + u_char *start; + njs_vm_t *vm; + njs_int_t ret; -nxt_int_t -nxt_js_test(nxt_js_conf_t *jcf, nxt_str_t *str, u_char *error) -{ - u_char *start; - njs_vm_t *vm; - njs_int_t ret; + vm = nxt_js_vm_create(jcf); + if (nxt_slow_path(vm == NULL)) { + return NXT_ERROR; + } - vm = nxt_js_vm_create(jcf); - if (nxt_slow_path(vm == NULL)) { - return NXT_ERROR; - } + start = nxt_mp_nget(jcf->pool, str->length); + if (nxt_slow_path(start == NULL)) { + goto fail; + } - start = nxt_mp_nget(jcf->pool, str->length); - if (nxt_slow_path(start == NULL)) { - goto fail; - } + nxt_memcpy(start, str->start, str->length); - nxt_memcpy(start, str->start, str->length); + ret = njs_vm_compile(vm, &start, start + str->length); - ret = njs_vm_compile(vm, &start, start + str->length); + if (nxt_slow_path(ret != NJS_OK)) { + (void)nxt_js_error(vm, error); + goto fail; + } - if (nxt_slow_path(ret != NJS_OK)) { - (void) nxt_js_error(vm, error); - goto fail; - } + njs_vm_destroy(vm); - njs_vm_destroy(vm); - - return NXT_OK; + return NXT_OK; fail: - njs_vm_destroy(vm); + njs_vm_destroy(vm); - return NXT_ERROR; + return NXT_ERROR; } - -nxt_int_t -nxt_js_call(nxt_task_t *task, nxt_js_conf_t *jcf, nxt_js_cache_t *cache, - nxt_js_t *js, nxt_str_t *str, void *ctx) -{ - njs_vm_t *vm; - njs_int_t ret; - njs_str_t res; - njs_uint_t i, n; - njs_value_t *value; - njs_function_t *func; - njs_opaque_value_t retval, opaque_value, arguments[7]; - - static const njs_str_t js_args[] = { - njs_str("uri"), - njs_str("host"), - njs_str("remoteAddr"), - njs_str("args"), - njs_str("headers"), - njs_str("cookies"), - njs_str("vars"), - }; - - vm = cache->vm; - - if (vm == NULL) { - vm = njs_vm_clone(jcf->vm, ctx); - if (nxt_slow_path(vm == NULL)) { - return NXT_ERROR; - } - - cache->vm = vm; - - ret = njs_vm_start(vm, &cache->array); - if (ret != NJS_OK) { - return NXT_ERROR; - } +nxt_int_t nxt_js_call(nxt_task_t *task, nxt_js_conf_t *jcf, + nxt_js_cache_t *cache, nxt_js_t *js, nxt_str_t *str, + void *ctx) { + njs_vm_t *vm; + njs_int_t ret; + njs_str_t res; + njs_uint_t i, n; + njs_value_t *value; + njs_function_t *func; + njs_opaque_value_t retval, opaque_value, arguments[7]; + + static const njs_str_t js_args[] = { + njs_str("uri"), njs_str("host"), njs_str("remoteAddr"), + njs_str("args"), njs_str("headers"), njs_str("cookies"), + njs_str("vars"), + }; + + vm = cache->vm; + + if (vm == NULL) { + vm = njs_vm_clone(jcf->vm, ctx); + if (nxt_slow_path(vm == NULL)) { + return NXT_ERROR; } - value = njs_vm_array_prop(vm, &cache->array, js->index, &opaque_value); - func = njs_value_function(value); + cache->vm = vm; - ret = njs_vm_external_create(vm, njs_value_arg(&opaque_value), - nxt_js_proto_id, ctx, 0); - if (nxt_slow_path(ret != NJS_OK)) { - return NXT_ERROR; + ret = njs_vm_start(vm, &cache->array); + if (ret != NJS_OK) { + return NXT_ERROR; } + } - n = nxt_nitems(js_args); + value = njs_vm_array_prop(vm, &cache->array, js->index, &opaque_value); + func = njs_value_function(value); - for (i = 0; i < n; i++) { - value = njs_vm_object_prop(vm, njs_value_arg(&opaque_value), - &js_args[i], &arguments[i]); - if (nxt_slow_path(value == NULL)) { - return NXT_ERROR; - } - } + ret = njs_vm_external_create(vm, njs_value_arg(&opaque_value), + nxt_js_proto_id, ctx, 0); + if (nxt_slow_path(ret != NJS_OK)) { + return NXT_ERROR; + } - ret = njs_vm_invoke(vm, func, njs_value_arg(&arguments), n, - njs_value_arg(&retval)); + n = nxt_nitems(js_args); - if (ret != NJS_OK) { - ret = njs_vm_exception_string(vm, &res); - if (ret == NJS_OK) { - nxt_alert(task, "js exception: %V", &res); - } - - return NXT_ERROR; + for (i = 0; i < n; i++) { + value = njs_vm_object_prop(vm, njs_value_arg(&opaque_value), &js_args[i], + &arguments[i]); + if (nxt_slow_path(value == NULL)) { + return NXT_ERROR; } + } - ret = njs_vm_value_string(vm, &res, njs_value_arg(&retval)); + ret = njs_vm_invoke(vm, func, njs_value_arg(&arguments), n, + njs_value_arg(&retval)); - str->length = res.length; - str->start = res.start; + if (ret != NJS_OK) { + ret = njs_vm_exception_string(vm, &res); + if (ret == NJS_OK) { + nxt_alert(task, "js exception: %V", &res); + } - return NXT_OK; -} + return NXT_ERROR; + } + ret = njs_vm_value_string(vm, &res, njs_value_arg(&retval)); -void -nxt_js_release(nxt_js_cache_t *cache) -{ - if (cache->vm != NULL) { - njs_vm_destroy(cache->vm); - } + str->length = res.length; + str->start = res.start; + + return NXT_OK; } +void nxt_js_release(nxt_js_cache_t *cache) { + if (cache->vm != NULL) { + njs_vm_destroy(cache->vm); + } +} -nxt_int_t -nxt_js_error(njs_vm_t *vm, u_char *error) -{ - njs_int_t ret; - njs_str_t res; - nxt_str_t err; +nxt_int_t nxt_js_error(njs_vm_t *vm, u_char *error) { + njs_int_t ret; + njs_str_t res; + nxt_str_t err; - ret = njs_vm_exception_string(vm, &res); - if (nxt_slow_path(ret != NJS_OK)) { - return NXT_ERROR; - } + ret = njs_vm_exception_string(vm, &res); + if (nxt_slow_path(ret != NJS_OK)) { + return NXT_ERROR; + } - err.start = res.start; - err.length = res.length; + err.start = res.start; + err.length = res.length; - nxt_sprintf(error, error + NXT_MAX_ERROR_STR, "\"%V\"%Z", &err); + nxt_sprintf(error, error + NXT_MAX_ERROR_STR, "\"%V\"%Z", &err); - return NXT_OK; + return NXT_OK; } diff --git a/src/nxt_js.h b/src/nxt_js.h index 53262563e..c53a2cf33 100644 --- a/src/nxt_js.h +++ b/src/nxt_js.h @@ -10,35 +10,31 @@ #include - -typedef struct nxt_js_s nxt_js_t; -typedef struct nxt_js_conf_s nxt_js_conf_t; - +typedef struct nxt_js_s nxt_js_t; +typedef struct nxt_js_conf_s nxt_js_conf_t; typedef struct { - njs_vm_t *vm; - njs_value_t array; + njs_vm_t *vm; + njs_value_t array; } nxt_js_cache_t; - njs_mod_t *nxt_js_module_loader(njs_vm_t *vm, njs_external_ptr_t external, - njs_str_t *name); + njs_str_t *name); nxt_js_conf_t *nxt_js_conf_new(nxt_mp_t *mp, nxt_bool_t test); void nxt_js_conf_release(nxt_js_conf_t *jcf); void nxt_js_set_proto(nxt_js_conf_t *jcf, njs_external_t *proto, nxt_uint_t n); nxt_int_t nxt_js_add_module(nxt_js_conf_t *jcf, nxt_str_t *name, - nxt_str_t *text); + nxt_str_t *text); nxt_js_t *nxt_js_add_tpl(nxt_js_conf_t *jcf, nxt_str_t *str, nxt_uint_t flags); nxt_int_t nxt_js_compile(nxt_js_conf_t *jcf); nxt_int_t nxt_js_test(nxt_js_conf_t *jcf, nxt_str_t *str, u_char *error); nxt_int_t nxt_js_call(nxt_task_t *task, nxt_js_conf_t *jcf, - nxt_js_cache_t *cache, nxt_js_t *js, nxt_str_t *str, void *ctx); + nxt_js_cache_t *cache, nxt_js_t *js, nxt_str_t *str, + void *ctx); void nxt_js_release(nxt_js_cache_t *cache); nxt_int_t nxt_js_error(njs_vm_t *vm, u_char *error); - -extern njs_int_t nxt_js_proto_id; - +extern njs_int_t nxt_js_proto_id; #endif /* NXT_HAVE_NJS */ diff --git a/src/nxt_kqueue_engine.c b/src/nxt_kqueue_engine.c index a7a5a29ed..221d89d9e 100644 --- a/src/nxt_kqueue_engine.c +++ b/src/nxt_kqueue_engine.c @@ -6,7 +6,6 @@ #include - /* * kqueue() has been introduced in FreeBSD 4.1 and then was ported * to OpenBSD 2.9, MacOSX 10.3 (Panther), and NetBSD 2.0. @@ -26,91 +25,83 @@ * libdispatch support. */ - /* * EV_DISPATCH is better because it just disables an event on delivery * whilst EV_ONESHOT deletes the event. This eliminates in-kernel memory * deallocation and probable subsequent allocation with a lock acquiring. */ #ifdef EV_DISPATCH -#define NXT_KEVENT_ONESHOT EV_DISPATCH +#define NXT_KEVENT_ONESHOT EV_DISPATCH #else -#define NXT_KEVENT_ONESHOT EV_ONESHOT +#define NXT_KEVENT_ONESHOT EV_ONESHOT #endif - #if (NXT_NETBSD) /* NetBSD defines the kevent.udata field as intptr_t. */ -#define nxt_kevent_set_udata(udata) (intptr_t) (udata) -#define nxt_kevent_get_udata(udata) (void *) (udata) +#define nxt_kevent_set_udata(udata) (intptr_t)(udata) +#define nxt_kevent_get_udata(udata) (void *)(udata) #else -#define nxt_kevent_set_udata(udata) (void *) (udata) -#define nxt_kevent_get_udata(udata) (udata) +#define nxt_kevent_set_udata(udata) (void *)(udata) +#define nxt_kevent_get_udata(udata) (udata) #endif - static nxt_int_t nxt_kqueue_create(nxt_event_engine_t *engine, - nxt_uint_t mchanges, nxt_uint_t mevents); + nxt_uint_t mchanges, nxt_uint_t mevents); static void nxt_kqueue_free(nxt_event_engine_t *engine); static void nxt_kqueue_enable(nxt_event_engine_t *engine, nxt_fd_event_t *ev); static void nxt_kqueue_disable(nxt_event_engine_t *engine, nxt_fd_event_t *ev); static void nxt_kqueue_delete(nxt_event_engine_t *engine, nxt_fd_event_t *ev); static nxt_bool_t nxt_kqueue_close(nxt_event_engine_t *engine, - nxt_fd_event_t *ev); + nxt_fd_event_t *ev); static void nxt_kqueue_enable_read(nxt_event_engine_t *engine, - nxt_fd_event_t *ev); + nxt_fd_event_t *ev); static void nxt_kqueue_enable_write(nxt_event_engine_t *engine, - nxt_fd_event_t *ev); + nxt_fd_event_t *ev); static void nxt_kqueue_disable_read(nxt_event_engine_t *engine, - nxt_fd_event_t *ev); + nxt_fd_event_t *ev); static void nxt_kqueue_disable_write(nxt_event_engine_t *engine, - nxt_fd_event_t *ev); + nxt_fd_event_t *ev); static void nxt_kqueue_block_read(nxt_event_engine_t *engine, - nxt_fd_event_t *ev); + nxt_fd_event_t *ev); static void nxt_kqueue_block_write(nxt_event_engine_t *engine, - nxt_fd_event_t *ev); + nxt_fd_event_t *ev); static void nxt_kqueue_oneshot_read(nxt_event_engine_t *engine, - nxt_fd_event_t *ev); + nxt_fd_event_t *ev); static void nxt_kqueue_oneshot_write(nxt_event_engine_t *engine, - nxt_fd_event_t *ev); + nxt_fd_event_t *ev); static void nxt_kqueue_enable_accept(nxt_event_engine_t *engine, - nxt_fd_event_t *ev); + nxt_fd_event_t *ev); static void nxt_kqueue_enable_file(nxt_event_engine_t *engine, - nxt_file_event_t *ev); + nxt_file_event_t *ev); static void nxt_kqueue_close_file(nxt_event_engine_t *engine, - nxt_file_event_t *ev); + nxt_file_event_t *ev); static void nxt_kqueue_fd_set(nxt_event_engine_t *engine, nxt_fd_event_t *ev, - nxt_int_t filter, nxt_uint_t flags); + nxt_int_t filter, nxt_uint_t flags); static struct kevent *nxt_kqueue_get_kevent(nxt_event_engine_t *engine); static void nxt_kqueue_error(nxt_event_engine_t *engine); static void nxt_kqueue_fd_error_handler(nxt_task_t *task, void *obj, - void *data); + void *data); static void nxt_kqueue_file_error_handler(nxt_task_t *task, void *obj, - void *data); + void *data); static nxt_int_t nxt_kqueue_add_signal(nxt_event_engine_t *engine, - const nxt_sig_event_t *sigev); + const nxt_sig_event_t *sigev); #if (NXT_HAVE_EVFILT_USER) static nxt_int_t nxt_kqueue_enable_post(nxt_event_engine_t *engine, - nxt_work_handler_t handler); + nxt_work_handler_t handler); static void nxt_kqueue_signal(nxt_event_engine_t *engine, nxt_uint_t signo); #endif static void nxt_kqueue_poll(nxt_event_engine_t *engine, nxt_msec_t timeout); -static void nxt_kqueue_conn_io_connect(nxt_task_t *task, void *obj, - void *data); -static void nxt_kqueue_conn_connected(nxt_task_t *task, void *obj, - void *data); +static void nxt_kqueue_conn_io_connect(nxt_task_t *task, void *obj, void *data); +static void nxt_kqueue_conn_connected(nxt_task_t *task, void *obj, void *data); static void nxt_kqueue_listen_handler(nxt_task_t *task, void *obj, void *data); -static void nxt_kqueue_conn_io_accept(nxt_task_t *task, void *obj, - void *data); -static void nxt_kqueue_conn_io_read(nxt_task_t *task, void *obj, - void *data); +static void nxt_kqueue_conn_io_accept(nxt_task_t *task, void *obj, void *data); +static void nxt_kqueue_conn_io_read(nxt_task_t *task, void *obj, void *data); static ssize_t nxt_kqueue_conn_io_recvbuf(nxt_conn_t *c, nxt_buf_t *b); - -static nxt_conn_io_t nxt_kqueue_conn_io = { +static nxt_conn_io_t nxt_kqueue_conn_io = { .connect = nxt_kqueue_conn_io_connect, .accept = nxt_kqueue_conn_io_accept, @@ -133,8 +124,7 @@ static nxt_conn_io_t nxt_kqueue_conn_io = { .send = nxt_event_conn_io_send, }; - -const nxt_event_interface_t nxt_kqueue_engine = { +const nxt_event_interface_t nxt_kqueue_engine = { "kqueue", nxt_kqueue_create, nxt_kqueue_free, @@ -168,122 +158,105 @@ const nxt_event_interface_t nxt_kqueue_engine = { NXT_SIGNAL_EVENTS, }; - -static nxt_int_t -nxt_kqueue_create(nxt_event_engine_t *engine, nxt_uint_t mchanges, - nxt_uint_t mevents) -{ - const nxt_sig_event_t *sigev; - - engine->u.kqueue.fd = -1; - engine->u.kqueue.mchanges = mchanges; - engine->u.kqueue.mevents = mevents; - engine->u.kqueue.pid = nxt_pid; - - engine->u.kqueue.changes = nxt_malloc(sizeof(struct kevent) * mchanges); - if (engine->u.kqueue.changes == NULL) { - goto fail; - } - - engine->u.kqueue.events = nxt_malloc(sizeof(struct kevent) * mevents); - if (engine->u.kqueue.events == NULL) { - goto fail; - } - - engine->u.kqueue.fd = kqueue(); - if (engine->u.kqueue.fd == -1) { - nxt_alert(&engine->task, "kqueue() failed %E", nxt_errno); +static nxt_int_t nxt_kqueue_create(nxt_event_engine_t *engine, + nxt_uint_t mchanges, nxt_uint_t mevents) { + const nxt_sig_event_t *sigev; + + engine->u.kqueue.fd = -1; + engine->u.kqueue.mchanges = mchanges; + engine->u.kqueue.mevents = mevents; + engine->u.kqueue.pid = nxt_pid; + + engine->u.kqueue.changes = nxt_malloc(sizeof(struct kevent) * mchanges); + if (engine->u.kqueue.changes == NULL) { + goto fail; + } + + engine->u.kqueue.events = nxt_malloc(sizeof(struct kevent) * mevents); + if (engine->u.kqueue.events == NULL) { + goto fail; + } + + engine->u.kqueue.fd = kqueue(); + if (engine->u.kqueue.fd == -1) { + nxt_alert(&engine->task, "kqueue() failed %E", nxt_errno); + goto fail; + } + + nxt_debug(&engine->task, "kqueue(): %d", engine->u.kqueue.fd); + + if (engine->signals != NULL) { + for (sigev = engine->signals->sigev; sigev->signo != 0; sigev++) { + if (nxt_kqueue_add_signal(engine, sigev) != NXT_OK) { goto fail; + } } + } - nxt_debug(&engine->task, "kqueue(): %d", engine->u.kqueue.fd); - - if (engine->signals != NULL) { - for (sigev = engine->signals->sigev; sigev->signo != 0; sigev++) { - if (nxt_kqueue_add_signal(engine, sigev) != NXT_OK) { - goto fail; - } - } - } - - return NXT_OK; + return NXT_OK; fail: - nxt_kqueue_free(engine); + nxt_kqueue_free(engine); - return NXT_ERROR; + return NXT_ERROR; } +static void nxt_kqueue_free(nxt_event_engine_t *engine) { + nxt_fd_t fd; -static void -nxt_kqueue_free(nxt_event_engine_t *engine) -{ - nxt_fd_t fd; + fd = engine->u.kqueue.fd; - fd = engine->u.kqueue.fd; + nxt_debug(&engine->task, "kqueue %d free", fd); - nxt_debug(&engine->task, "kqueue %d free", fd); + if (fd != -1 && engine->u.kqueue.pid == nxt_pid) { + /* kqueue is not inherited by fork() */ - if (fd != -1 && engine->u.kqueue.pid == nxt_pid) { - /* kqueue is not inherited by fork() */ - - if (close(fd) != 0) { - nxt_alert(&engine->task, "kqueue close(%d) failed %E", - fd, nxt_errno); - } + if (close(fd) != 0) { + nxt_alert(&engine->task, "kqueue close(%d) failed %E", fd, nxt_errno); } + } - nxt_free(engine->u.kqueue.events); - nxt_free(engine->u.kqueue.changes); + nxt_free(engine->u.kqueue.events); + nxt_free(engine->u.kqueue.changes); - nxt_memzero(&engine->u.kqueue, sizeof(nxt_kqueue_engine_t)); + nxt_memzero(&engine->u.kqueue, sizeof(nxt_kqueue_engine_t)); } - -static void -nxt_kqueue_enable(nxt_event_engine_t *engine, nxt_fd_event_t *ev) -{ - nxt_kqueue_enable_read(engine, ev); - nxt_kqueue_enable_write(engine, ev); +static void nxt_kqueue_enable(nxt_event_engine_t *engine, nxt_fd_event_t *ev) { + nxt_kqueue_enable_read(engine, ev); + nxt_kqueue_enable_write(engine, ev); } - /* * EV_DISABLE is better because it eliminates in-kernel memory * deallocation and probable subsequent allocation with a lock acquiring. */ -static void -nxt_kqueue_disable(nxt_event_engine_t *engine, nxt_fd_event_t *ev) -{ - if (ev->read != NXT_EVENT_INACTIVE) { - ev->read = NXT_EVENT_INACTIVE; - nxt_kqueue_fd_set(engine, ev, EVFILT_READ, EV_DISABLE); - } +static void nxt_kqueue_disable(nxt_event_engine_t *engine, nxt_fd_event_t *ev) { + if (ev->read != NXT_EVENT_INACTIVE) { + ev->read = NXT_EVENT_INACTIVE; + nxt_kqueue_fd_set(engine, ev, EVFILT_READ, EV_DISABLE); + } - if (ev->write != NXT_EVENT_INACTIVE) { - ev->write = NXT_EVENT_INACTIVE; - nxt_kqueue_fd_set(engine, ev, EVFILT_WRITE, EV_DISABLE); - } + if (ev->write != NXT_EVENT_INACTIVE) { + ev->write = NXT_EVENT_INACTIVE; + nxt_kqueue_fd_set(engine, ev, EVFILT_WRITE, EV_DISABLE); + } } +static void nxt_kqueue_delete(nxt_event_engine_t *engine, nxt_fd_event_t *ev) { + if (ev->read != NXT_EVENT_INACTIVE) { + ev->read = NXT_EVENT_INACTIVE; + nxt_kqueue_fd_set(engine, ev, EVFILT_READ, EV_DELETE); + } -static void -nxt_kqueue_delete(nxt_event_engine_t *engine, nxt_fd_event_t *ev) -{ - if (ev->read != NXT_EVENT_INACTIVE) { - ev->read = NXT_EVENT_INACTIVE; - nxt_kqueue_fd_set(engine, ev, EVFILT_READ, EV_DELETE); - } - - if (ev->write != NXT_EVENT_INACTIVE) { - ev->write = NXT_EVENT_INACTIVE; - nxt_kqueue_fd_set(engine, ev, EVFILT_WRITE, EV_DELETE); - } + if (ev->write != NXT_EVENT_INACTIVE) { + ev->write = NXT_EVENT_INACTIVE; + nxt_kqueue_fd_set(engine, ev, EVFILT_WRITE, EV_DELETE); + } } - /* * kqueue(2): * @@ -293,26 +266,24 @@ nxt_kqueue_delete(nxt_event_engine_t *engine, nxt_fd_event_t *ev) * So nxt_kqueue_close() returns true only if there are pending events. */ -static nxt_bool_t -nxt_kqueue_close(nxt_event_engine_t *engine, nxt_fd_event_t *ev) -{ - struct kevent *kev, *end; +static nxt_bool_t nxt_kqueue_close(nxt_event_engine_t *engine, + nxt_fd_event_t *ev) { + struct kevent *kev, *end; - ev->read = NXT_EVENT_INACTIVE; - ev->write = NXT_EVENT_INACTIVE; + ev->read = NXT_EVENT_INACTIVE; + ev->write = NXT_EVENT_INACTIVE; - end = &engine->u.kqueue.changes[engine->u.kqueue.nchanges]; + end = &engine->u.kqueue.changes[engine->u.kqueue.nchanges]; - for (kev = engine->u.kqueue.changes; kev < end; kev++) { - if (kev->ident == (uintptr_t) ev->fd) { - return 1; - } + for (kev = engine->u.kqueue.changes; kev < end; kev++) { + if (kev->ident == (uintptr_t)ev->fd) { + return 1; } + } - return 0; + return 0; } - /* * The kqueue event engine uses only three states: inactive, blocked, and * active. An active oneshot event is marked as it is in the default @@ -320,709 +291,643 @@ nxt_kqueue_close(nxt_event_engine_t *engine, nxt_fd_event_t *ev) * mode after it will become inactive after delivery. */ -static void -nxt_kqueue_enable_read(nxt_event_engine_t *engine, nxt_fd_event_t *ev) -{ - if (ev->read == NXT_EVENT_INACTIVE) { - nxt_kqueue_fd_set(engine, ev, EVFILT_READ, - EV_ADD | EV_ENABLE | EV_CLEAR); - } +static void nxt_kqueue_enable_read(nxt_event_engine_t *engine, + nxt_fd_event_t *ev) { + if (ev->read == NXT_EVENT_INACTIVE) { + nxt_kqueue_fd_set(engine, ev, EVFILT_READ, EV_ADD | EV_ENABLE | EV_CLEAR); + } - ev->read = NXT_EVENT_ACTIVE; + ev->read = NXT_EVENT_ACTIVE; } +static void nxt_kqueue_enable_write(nxt_event_engine_t *engine, + nxt_fd_event_t *ev) { + if (ev->write == NXT_EVENT_INACTIVE) { + nxt_kqueue_fd_set(engine, ev, EVFILT_WRITE, EV_ADD | EV_ENABLE | EV_CLEAR); + } -static void -nxt_kqueue_enable_write(nxt_event_engine_t *engine, nxt_fd_event_t *ev) -{ - if (ev->write == NXT_EVENT_INACTIVE) { - nxt_kqueue_fd_set(engine, ev, EVFILT_WRITE, - EV_ADD | EV_ENABLE | EV_CLEAR); - } + ev->write = NXT_EVENT_ACTIVE; +} - ev->write = NXT_EVENT_ACTIVE; +static void nxt_kqueue_disable_read(nxt_event_engine_t *engine, + nxt_fd_event_t *ev) { + ev->read = NXT_EVENT_INACTIVE; + + nxt_kqueue_fd_set(engine, ev, EVFILT_READ, EV_DISABLE); } +static void nxt_kqueue_disable_write(nxt_event_engine_t *engine, + nxt_fd_event_t *ev) { + ev->write = NXT_EVENT_INACTIVE; -static void -nxt_kqueue_disable_read(nxt_event_engine_t *engine, nxt_fd_event_t *ev) -{ - ev->read = NXT_EVENT_INACTIVE; + nxt_kqueue_fd_set(engine, ev, EVFILT_WRITE, EV_DISABLE); +} - nxt_kqueue_fd_set(engine, ev, EVFILT_READ, EV_DISABLE); +static void nxt_kqueue_block_read(nxt_event_engine_t *engine, + nxt_fd_event_t *ev) { + if (ev->read != NXT_EVENT_INACTIVE) { + ev->read = NXT_EVENT_BLOCKED; + } } +static void nxt_kqueue_block_write(nxt_event_engine_t *engine, + nxt_fd_event_t *ev) { + if (ev->write != NXT_EVENT_INACTIVE) { + ev->write = NXT_EVENT_BLOCKED; + } +} -static void -nxt_kqueue_disable_write(nxt_event_engine_t *engine, nxt_fd_event_t *ev) -{ - ev->write = NXT_EVENT_INACTIVE; +static void nxt_kqueue_oneshot_read(nxt_event_engine_t *engine, + nxt_fd_event_t *ev) { + ev->write = NXT_EVENT_ACTIVE; - nxt_kqueue_fd_set(engine, ev, EVFILT_WRITE, EV_DISABLE); + nxt_kqueue_fd_set(engine, ev, EVFILT_WRITE, + EV_ADD | EV_ENABLE | NXT_KEVENT_ONESHOT); } +static void nxt_kqueue_oneshot_write(nxt_event_engine_t *engine, + nxt_fd_event_t *ev) { + ev->write = NXT_EVENT_ACTIVE; -static void -nxt_kqueue_block_read(nxt_event_engine_t *engine, nxt_fd_event_t *ev) -{ - if (ev->read != NXT_EVENT_INACTIVE) { - ev->read = NXT_EVENT_BLOCKED; - } + nxt_kqueue_fd_set(engine, ev, EVFILT_WRITE, + EV_ADD | EV_ENABLE | NXT_KEVENT_ONESHOT); } +static void nxt_kqueue_enable_accept(nxt_event_engine_t *engine, + nxt_fd_event_t *ev) { + ev->read = NXT_EVENT_ACTIVE; + ev->read_handler = nxt_kqueue_listen_handler; -static void -nxt_kqueue_block_write(nxt_event_engine_t *engine, nxt_fd_event_t *ev) -{ - if (ev->write != NXT_EVENT_INACTIVE) { - ev->write = NXT_EVENT_BLOCKED; - } + nxt_kqueue_fd_set(engine, ev, EVFILT_READ, EV_ADD | EV_ENABLE); } +static void nxt_kqueue_enable_file(nxt_event_engine_t *engine, + nxt_file_event_t *ev) { + struct kevent *kev; -static void -nxt_kqueue_oneshot_read(nxt_event_engine_t *engine, nxt_fd_event_t *ev) -{ - ev->write = NXT_EVENT_ACTIVE; + const nxt_int_t flags = EV_ADD | EV_ENABLE | EV_ONESHOT; + const nxt_uint_t fflags = NOTE_DELETE | NOTE_WRITE | NOTE_EXTEND | + NOTE_ATTRIB | NOTE_RENAME | NOTE_REVOKE; - nxt_kqueue_fd_set(engine, ev, EVFILT_WRITE, - EV_ADD | EV_ENABLE | NXT_KEVENT_ONESHOT); -} + nxt_debug(&engine->task, "kevent(%d) set: id:%d ft:%i fl:%04Xd, ff:%04XuD", + engine->u.kqueue.fd, ev->file->fd, EVFILT_VNODE, flags, fflags); + kev = nxt_kqueue_get_kevent(engine); -static void -nxt_kqueue_oneshot_write(nxt_event_engine_t *engine, nxt_fd_event_t *ev) -{ - ev->write = NXT_EVENT_ACTIVE; + kev->ident = ev->file->fd; + kev->filter = EVFILT_VNODE; + kev->flags = flags; + kev->fflags = fflags; + kev->data = 0; + kev->udata = nxt_kevent_set_udata(ev); +} - nxt_kqueue_fd_set(engine, ev, EVFILT_WRITE, - EV_ADD | EV_ENABLE | NXT_KEVENT_ONESHOT); +static void nxt_kqueue_close_file(nxt_event_engine_t *engine, + nxt_file_event_t *ev) { + /* TODO: pending event. */ } +static void nxt_kqueue_fd_set(nxt_event_engine_t *engine, nxt_fd_event_t *ev, + nxt_int_t filter, nxt_uint_t flags) { + struct kevent *kev; + + nxt_debug(ev->task, "kevent(%d) set event: id:%d ft:%i fl:%04Xui", + engine->u.kqueue.fd, ev->fd, filter, flags); -static void -nxt_kqueue_enable_accept(nxt_event_engine_t *engine, nxt_fd_event_t *ev) -{ - ev->read = NXT_EVENT_ACTIVE; - ev->read_handler = nxt_kqueue_listen_handler; + kev = nxt_kqueue_get_kevent(engine); - nxt_kqueue_fd_set(engine, ev, EVFILT_READ, EV_ADD | EV_ENABLE); + kev->ident = ev->fd; + kev->filter = filter; + kev->flags = flags; + kev->fflags = 0; + kev->data = 0; + kev->udata = nxt_kevent_set_udata(ev); } +static struct kevent *nxt_kqueue_get_kevent(nxt_event_engine_t *engine) { + int ret, nchanges; -static void -nxt_kqueue_enable_file(nxt_event_engine_t *engine, nxt_file_event_t *ev) -{ - struct kevent *kev; + nchanges = engine->u.kqueue.nchanges; - const nxt_int_t flags = EV_ADD | EV_ENABLE | EV_ONESHOT; - const nxt_uint_t fflags = NOTE_DELETE | NOTE_WRITE | NOTE_EXTEND - | NOTE_ATTRIB | NOTE_RENAME | NOTE_REVOKE; + if (nxt_slow_path(nchanges >= engine->u.kqueue.mchanges)) { - nxt_debug(&engine->task, "kevent(%d) set: id:%d ft:%i fl:%04Xd, ff:%04XuD", - engine->u.kqueue.fd, ev->file->fd, EVFILT_VNODE, flags, fflags); + nxt_debug(&engine->task, "kevent(%d) changes:%d", engine->u.kqueue.fd, + nchanges); - kev = nxt_kqueue_get_kevent(engine); + ret = kevent(engine->u.kqueue.fd, engine->u.kqueue.changes, nchanges, NULL, + 0, NULL); - kev->ident = ev->file->fd; - kev->filter = EVFILT_VNODE; - kev->flags = flags; - kev->fflags = fflags; - kev->data = 0; - kev->udata = nxt_kevent_set_udata(ev); -} + if (nxt_slow_path(ret != 0)) { + nxt_alert(&engine->task, "kevent(%d) failed %E", engine->u.kqueue.fd, + nxt_errno); + + nxt_kqueue_error(engine); + } + engine->u.kqueue.nchanges = 0; + } -static void -nxt_kqueue_close_file(nxt_event_engine_t *engine, nxt_file_event_t *ev) -{ - /* TODO: pending event. */ + return &engine->u.kqueue.changes[engine->u.kqueue.nchanges++]; } +static void nxt_kqueue_error(nxt_event_engine_t *engine) { + struct kevent *kev, *end; + nxt_fd_event_t *ev; + nxt_file_event_t *fev; + nxt_work_queue_t *wq; -static void -nxt_kqueue_fd_set(nxt_event_engine_t *engine, nxt_fd_event_t *ev, - nxt_int_t filter, nxt_uint_t flags) -{ - struct kevent *kev; + wq = &engine->fast_work_queue; + end = &engine->u.kqueue.changes[engine->u.kqueue.nchanges]; - nxt_debug(ev->task, "kevent(%d) set event: id:%d ft:%i fl:%04Xui", - engine->u.kqueue.fd, ev->fd, filter, flags); + for (kev = engine->u.kqueue.changes; kev < end; kev++) { - kev = nxt_kqueue_get_kevent(engine); + switch (kev->filter) { - kev->ident = ev->fd; - kev->filter = filter; - kev->flags = flags; - kev->fflags = 0; - kev->data = 0; - kev->udata = nxt_kevent_set_udata(ev); + case EVFILT_READ: + case EVFILT_WRITE: + ev = nxt_kevent_get_udata(kev->udata); + nxt_work_queue_add(wq, nxt_kqueue_fd_error_handler, ev->task, ev, + ev->data); + break; + + case EVFILT_VNODE: + fev = nxt_kevent_get_udata(kev->udata); + nxt_work_queue_add(wq, nxt_kqueue_file_error_handler, fev->task, fev, + fev->data); + break; + } + } } +static void nxt_kqueue_fd_error_handler(nxt_task_t *task, void *obj, + void *data) { + nxt_fd_event_t *ev; -static struct kevent * -nxt_kqueue_get_kevent(nxt_event_engine_t *engine) -{ - int ret, nchanges; + ev = obj; - nchanges = engine->u.kqueue.nchanges; + nxt_debug(task, "kqueue fd error handler fd:%d", ev->fd); - if (nxt_slow_path(nchanges >= engine->u.kqueue.mchanges)) { + if (ev->kq_eof && ev->kq_errno != 0) { + ev->error = ev->kq_errno; + nxt_log(task, nxt_socket_error_level(ev->kq_errno), + "kevent() reported error on descriptor %d %E", ev->fd, + ev->kq_errno); + } - nxt_debug(&engine->task, "kevent(%d) changes:%d", - engine->u.kqueue.fd, nchanges); + ev->read = NXT_EVENT_INACTIVE; + ev->write = NXT_EVENT_INACTIVE; + ev->error = ev->kq_errno; - ret = kevent(engine->u.kqueue.fd, engine->u.kqueue.changes, nchanges, - NULL, 0, NULL); + ev->error_handler(task, ev, data); +} - if (nxt_slow_path(ret != 0)) { - nxt_alert(&engine->task, "kevent(%d) failed %E", - engine->u.kqueue.fd, nxt_errno); +static void nxt_kqueue_file_error_handler(nxt_task_t *task, void *obj, + void *data) { + nxt_file_event_t *ev; - nxt_kqueue_error(engine); - } + ev = obj; - engine->u.kqueue.nchanges = 0; - } + nxt_debug(task, "kqueue file error handler fd:%d", ev->file->fd); - return &engine->u.kqueue.changes[engine->u.kqueue.nchanges++]; + ev->handler(task, ev, data); } +static nxt_int_t nxt_kqueue_add_signal(nxt_event_engine_t *engine, + const nxt_sig_event_t *sigev) { + int signo; + struct kevent kev; + struct sigaction sa; -static void -nxt_kqueue_error(nxt_event_engine_t *engine) -{ - struct kevent *kev, *end; - nxt_fd_event_t *ev; - nxt_file_event_t *fev; - nxt_work_queue_t *wq; - - wq = &engine->fast_work_queue; - end = &engine->u.kqueue.changes[engine->u.kqueue.nchanges]; - - for (kev = engine->u.kqueue.changes; kev < end; kev++) { + signo = sigev->signo; - switch (kev->filter) { + nxt_memzero(&sa, sizeof(struct sigaction)); + sigemptyset(&sa.sa_mask); - case EVFILT_READ: - case EVFILT_WRITE: - ev = nxt_kevent_get_udata(kev->udata); - nxt_work_queue_add(wq, nxt_kqueue_fd_error_handler, - ev->task, ev, ev->data); - break; + /* + * SIGCHLD must not be set to SIG_IGN, since kqueue cannot catch + * this signal. It should be set to SIG_DFL instead. And although + * SIGCHLD default action is also ignoring, nevertheless SIG_DFL + * allows kqueue to catch the signal. + */ + sa.sa_handler = (signo == SIGCHLD) ? SIG_DFL : SIG_IGN; - case EVFILT_VNODE: - fev = nxt_kevent_get_udata(kev->udata); - nxt_work_queue_add(wq, nxt_kqueue_file_error_handler, - fev->task, fev, fev->data); - break; - } - } -} + if (sigaction(signo, &sa, NULL) != 0) { + nxt_alert(&engine->task, "sigaction(%d) failed %E", signo, nxt_errno); + return NXT_ERROR; + } -static void -nxt_kqueue_fd_error_handler(nxt_task_t *task, void *obj, void *data) -{ - nxt_fd_event_t *ev; + nxt_debug(&engine->task, "kevent(%d) signo:%d (%s)", engine->u.kqueue.fd, + signo, sigev->name); - ev = obj; + kev.ident = signo; + kev.filter = EVFILT_SIGNAL; + kev.flags = EV_ADD; + kev.fflags = 0; + kev.data = 0; + kev.udata = nxt_kevent_set_udata(sigev); - nxt_debug(task, "kqueue fd error handler fd:%d", ev->fd); + if (kevent(engine->u.kqueue.fd, &kev, 1, NULL, 0, NULL) == 0) { + return NXT_OK; + } - if (ev->kq_eof && ev->kq_errno != 0) { - ev->error = ev->kq_errno; - nxt_log(task, nxt_socket_error_level(ev->kq_errno), - "kevent() reported error on descriptor %d %E", - ev->fd, ev->kq_errno); - } + nxt_alert(&engine->task, "kevent(%d) failed %E", kqueue, nxt_errno); - ev->read = NXT_EVENT_INACTIVE; - ev->write = NXT_EVENT_INACTIVE; - ev->error = ev->kq_errno; - - ev->error_handler(task, ev, data); + return NXT_ERROR; } +#if (NXT_HAVE_EVFILT_USER) -static void -nxt_kqueue_file_error_handler(nxt_task_t *task, void *obj, void *data) -{ - nxt_file_event_t *ev; +static nxt_int_t nxt_kqueue_enable_post(nxt_event_engine_t *engine, + nxt_work_handler_t handler) { + struct kevent kev; - ev = obj; + /* EVFILT_USER must be added to a kqueue before it can be triggered. */ - nxt_debug(task, "kqueue file error handler fd:%d", ev->file->fd); + kev.ident = 0; + kev.filter = EVFILT_USER; + kev.flags = EV_ADD | EV_CLEAR; + kev.fflags = 0; + kev.data = 0; + kev.udata = NULL; - ev->handler(task, ev, data); -} + engine->u.kqueue.post_handler = handler; + if (kevent(engine->u.kqueue.fd, &kev, 1, NULL, 0, NULL) == 0) { + return NXT_OK; + } -static nxt_int_t -nxt_kqueue_add_signal(nxt_event_engine_t *engine, const nxt_sig_event_t *sigev) -{ - int signo; - struct kevent kev; - struct sigaction sa; + nxt_alert(&engine->task, "kevent(%d) failed %E", engine->u.kqueue.fd, + nxt_errno); - signo = sigev->signo; + return NXT_ERROR; +} - nxt_memzero(&sa, sizeof(struct sigaction)); - sigemptyset(&sa.sa_mask); +static void nxt_kqueue_signal(nxt_event_engine_t *engine, nxt_uint_t signo) { + struct kevent kev; - /* - * SIGCHLD must not be set to SIG_IGN, since kqueue cannot catch - * this signal. It should be set to SIG_DFL instead. And although - * SIGCHLD default action is also ignoring, nevertheless SIG_DFL - * allows kqueue to catch the signal. - */ - sa.sa_handler = (signo == SIGCHLD) ? SIG_DFL : SIG_IGN; + /* + * kqueue has a builtin signal processing support, so the function + * is used only to post events and the signo argument is ignored. + */ - if (sigaction(signo, &sa, NULL) != 0) { - nxt_alert(&engine->task, "sigaction(%d) failed %E", signo, nxt_errno); + kev.ident = 0; + kev.filter = EVFILT_USER; + kev.flags = 0; + kev.fflags = NOTE_TRIGGER; + kev.data = 0; + kev.udata = NULL; - return NXT_ERROR; - } + if (kevent(engine->u.kqueue.fd, &kev, 1, NULL, 0, NULL) != 0) { + nxt_alert(&engine->task, "kevent(%d) failed %E", engine->u.kqueue.fd, + nxt_errno); + } +} - nxt_debug(&engine->task, "kevent(%d) signo:%d (%s)", - engine->u.kqueue.fd, signo, sigev->name); +#endif - kev.ident = signo; - kev.filter = EVFILT_SIGNAL; - kev.flags = EV_ADD; - kev.fflags = 0; - kev.data = 0; - kev.udata = nxt_kevent_set_udata(sigev); +static void nxt_kqueue_poll(nxt_event_engine_t *engine, nxt_msec_t timeout) { + int nevents; + void *obj, *data; + nxt_int_t i; + nxt_err_t err; + nxt_uint_t level; + nxt_bool_t error, eof; + nxt_task_t *task; + struct kevent *kev; + nxt_fd_event_t *ev; + nxt_sig_event_t *sigev; + struct timespec ts, *tp; + nxt_file_event_t *fev; + nxt_work_queue_t *wq; + nxt_work_handler_t handler; - if (kevent(engine->u.kqueue.fd, &kev, 1, NULL, 0, NULL) == 0) { - return NXT_OK; - } + if (timeout == NXT_INFINITE_MSEC) { + tp = NULL; - nxt_alert(&engine->task, "kevent(%d) failed %E", kqueue, nxt_errno); + } else { + ts.tv_sec = timeout / 1000; + ts.tv_nsec = (timeout % 1000) * 1000000; + tp = &ts; + } - return NXT_ERROR; -} + nxt_debug(&engine->task, "kevent(%d) changes:%d timeout:%M", + engine->u.kqueue.fd, engine->u.kqueue.nchanges, timeout); + nevents = kevent(engine->u.kqueue.fd, engine->u.kqueue.changes, + engine->u.kqueue.nchanges, engine->u.kqueue.events, + engine->u.kqueue.mevents, tp); -#if (NXT_HAVE_EVFILT_USER) + err = (nevents == -1) ? nxt_errno : 0; -static nxt_int_t -nxt_kqueue_enable_post(nxt_event_engine_t *engine, nxt_work_handler_t handler) -{ - struct kevent kev; + nxt_thread_time_update(engine->task.thread); - /* EVFILT_USER must be added to a kqueue before it can be triggered. */ + nxt_debug(&engine->task, "kevent(%d): %d", engine->u.kqueue.fd, nevents); - kev.ident = 0; - kev.filter = EVFILT_USER; - kev.flags = EV_ADD | EV_CLEAR; - kev.fflags = 0; - kev.data = 0; - kev.udata = NULL; + if (nevents == -1) { + level = (err == NXT_EINTR) ? NXT_LOG_INFO : NXT_LOG_ALERT; - engine->u.kqueue.post_handler = handler; + nxt_log(&engine->task, level, "kevent(%d) failed %E", engine->u.kqueue.fd, + err); - if (kevent(engine->u.kqueue.fd, &kev, 1, NULL, 0, NULL) == 0) { - return NXT_OK; + if (err != NXT_EINTR) { + nxt_kqueue_error(engine); } - nxt_alert(&engine->task, "kevent(%d) failed %E", - engine->u.kqueue.fd, nxt_errno); + return; + } - return NXT_ERROR; -} + engine->u.kqueue.nchanges = 0; + for (i = 0; i < nevents; i++) { -static void -nxt_kqueue_signal(nxt_event_engine_t *engine, nxt_uint_t signo) -{ - struct kevent kev; + error = 0; - /* - * kqueue has a builtin signal processing support, so the function - * is used only to post events and the signo argument is ignored. - */ + kev = &engine->u.kqueue.events[i]; - kev.ident = 0; - kev.filter = EVFILT_USER; - kev.flags = 0; - kev.fflags = NOTE_TRIGGER; - kev.data = 0; - kev.udata = NULL; + nxt_debug(&engine->task, + (kev->ident > 0x8000000 && kev->ident != (uintptr_t)-1) + ? "kevent: id:%p ft:%d fl:%04Xd ff:%d d:%d ud:%p" + : "kevent: id:%d ft:%d fl:%04Xd ff:%d d:%d ud:%p", + kev->ident, kev->filter, kev->flags, kev->fflags, kev->data, + kev->udata); - if (kevent(engine->u.kqueue.fd, &kev, 1, NULL, 0, NULL) != 0) { - nxt_alert(&engine->task, "kevent(%d) failed %E", - engine->u.kqueue.fd, nxt_errno); + if (nxt_slow_path(kev->flags & EV_ERROR)) { + nxt_alert(&engine->task, "kevent(%d) error %E on ident:%d filter:%d", + engine->u.kqueue.fd, kev->data, kev->ident, kev->filter); + error = 1; } -} -#endif + task = &engine->task; + wq = &engine->fast_work_queue; + handler = nxt_kqueue_fd_error_handler; + obj = nxt_kevent_get_udata(kev->udata); + + switch (kev->filter) { + + case EVFILT_READ: + ev = obj; + ev->read_ready = 1; + ev->kq_available = (int32_t)kev->data; + err = kev->fflags; + eof = (kev->flags & EV_EOF) != 0; + ev->kq_errno = err; + ev->kq_eof |= eof; + + if (ev->read <= NXT_EVENT_BLOCKED) { + nxt_debug(ev->task, "blocked read event fd:%d", ev->fd); + continue; + } + + if ((kev->flags & NXT_KEVENT_ONESHOT) != 0) { + ev->read = NXT_EVENT_INACTIVE; + } + if (nxt_slow_path(ev->kq_available == 0 && eof && err != 0)) { + error = 1; + } -static void -nxt_kqueue_poll(nxt_event_engine_t *engine, nxt_msec_t timeout) -{ - int nevents; - void *obj, *data; - nxt_int_t i; - nxt_err_t err; - nxt_uint_t level; - nxt_bool_t error, eof; - nxt_task_t *task; - struct kevent *kev; - nxt_fd_event_t *ev; - nxt_sig_event_t *sigev; - struct timespec ts, *tp; - nxt_file_event_t *fev; - nxt_work_queue_t *wq; - nxt_work_handler_t handler; - - if (timeout == NXT_INFINITE_MSEC) { - tp = NULL; - - } else { - ts.tv_sec = timeout / 1000; - ts.tv_nsec = (timeout % 1000) * 1000000; - tp = &ts; - } + if (nxt_fast_path(!error)) { + handler = ev->read_handler; + wq = ev->read_work_queue; + } - nxt_debug(&engine->task, "kevent(%d) changes:%d timeout:%M", - engine->u.kqueue.fd, engine->u.kqueue.nchanges, timeout); + task = ev->task; + data = ev->data; - nevents = kevent(engine->u.kqueue.fd, - engine->u.kqueue.changes, engine->u.kqueue.nchanges, - engine->u.kqueue.events, engine->u.kqueue.mevents, tp); + break; - err = (nevents == -1) ? nxt_errno : 0; + case EVFILT_WRITE: + ev = obj; + ev->write_ready = 1; + err = kev->fflags; + eof = (kev->flags & EV_EOF) != 0; + ev->kq_errno = err; + ev->kq_eof |= eof; - nxt_thread_time_update(engine->task.thread); + if (ev->write <= NXT_EVENT_BLOCKED) { + nxt_debug(ev->task, "blocked write event fd:%d", ev->fd); + continue; + } - nxt_debug(&engine->task, "kevent(%d): %d", engine->u.kqueue.fd, nevents); + if ((kev->flags & NXT_KEVENT_ONESHOT) != 0) { + ev->write = NXT_EVENT_INACTIVE; + } - if (nevents == -1) { - level = (err == NXT_EINTR) ? NXT_LOG_INFO : NXT_LOG_ALERT; + if (nxt_slow_path(eof && err != 0)) { + error = 1; + } - nxt_log(&engine->task, level, "kevent(%d) failed %E", - engine->u.kqueue.fd, err); + if (nxt_fast_path(!error)) { + handler = ev->write_handler; + wq = ev->write_work_queue; + } - if (err != NXT_EINTR) { - nxt_kqueue_error(engine); - } + task = ev->task; + data = ev->data; - return; - } + break; - engine->u.kqueue.nchanges = 0; + case EVFILT_VNODE: + fev = obj; + handler = fev->handler; + task = fev->task; + data = fev->data; + break; - for (i = 0; i < nevents; i++) { - - error = 0; - - kev = &engine->u.kqueue.events[i]; - - nxt_debug(&engine->task, - (kev->ident > 0x8000000 && kev->ident != (uintptr_t) -1) ? - "kevent: id:%p ft:%d fl:%04Xd ff:%d d:%d ud:%p": - "kevent: id:%d ft:%d fl:%04Xd ff:%d d:%d ud:%p", - kev->ident, kev->filter, kev->flags, kev->fflags, - kev->data, kev->udata); - - if (nxt_slow_path(kev->flags & EV_ERROR)) { - nxt_alert(&engine->task, - "kevent(%d) error %E on ident:%d filter:%d", - engine->u.kqueue.fd, kev->data, kev->ident, kev->filter); - error = 1; - } - - task = &engine->task; - wq = &engine->fast_work_queue; - handler = nxt_kqueue_fd_error_handler; - obj = nxt_kevent_get_udata(kev->udata); - - switch (kev->filter) { - - case EVFILT_READ: - ev = obj; - ev->read_ready = 1; - ev->kq_available = (int32_t) kev->data; - err = kev->fflags; - eof = (kev->flags & EV_EOF) != 0; - ev->kq_errno = err; - ev->kq_eof |= eof; - - if (ev->read <= NXT_EVENT_BLOCKED) { - nxt_debug(ev->task, "blocked read event fd:%d", ev->fd); - continue; - } - - if ((kev->flags & NXT_KEVENT_ONESHOT) != 0) { - ev->read = NXT_EVENT_INACTIVE; - } - - if (nxt_slow_path(ev->kq_available == 0 && eof && err != 0)) { - error = 1; - } - - if (nxt_fast_path(!error)) { - handler = ev->read_handler; - wq = ev->read_work_queue; - } - - task = ev->task; - data = ev->data; - - break; - - case EVFILT_WRITE: - ev = obj; - ev->write_ready = 1; - err = kev->fflags; - eof = (kev->flags & EV_EOF) != 0; - ev->kq_errno = err; - ev->kq_eof |= eof; - - if (ev->write <= NXT_EVENT_BLOCKED) { - nxt_debug(ev->task, "blocked write event fd:%d", ev->fd); - continue; - } - - if ((kev->flags & NXT_KEVENT_ONESHOT) != 0) { - ev->write = NXT_EVENT_INACTIVE; - } - - if (nxt_slow_path(eof && err != 0)) { - error = 1; - } - - if (nxt_fast_path(!error)) { - handler = ev->write_handler; - wq = ev->write_work_queue; - } - - task = ev->task; - data = ev->data; - - break; - - case EVFILT_VNODE: - fev = obj; - handler = fev->handler; - task = fev->task; - data = fev->data; - break; - - case EVFILT_SIGNAL: - sigev = obj; - obj = (void *) kev->ident; - handler = sigev->handler; - data = (void *) sigev->name; - break; + case EVFILT_SIGNAL: + sigev = obj; + obj = (void *)kev->ident; + handler = sigev->handler; + data = (void *)sigev->name; + break; #if (NXT_HAVE_EVFILT_USER) - case EVFILT_USER: - handler = engine->u.kqueue.post_handler; - data = NULL; - break; + case EVFILT_USER: + handler = engine->u.kqueue.post_handler; + data = NULL; + break; #endif - default: + default: #if (NXT_DEBUG) - nxt_alert(&engine->task, - "unexpected kevent(%d) filter %d on ident %d", - engine->u.kqueue.fd, kev->filter, kev->ident); + nxt_alert(&engine->task, "unexpected kevent(%d) filter %d on ident %d", + engine->u.kqueue.fd, kev->filter, kev->ident); #endif - continue; - } - - nxt_work_queue_add(wq, handler, task, obj, data); + continue; } -} + nxt_work_queue_add(wq, handler, task, obj, data); + } +} /* * nxt_kqueue_event_conn_io_connect() eliminates the * getsockopt() syscall to test pending connect() error. */ -static void -nxt_kqueue_conn_io_connect(nxt_task_t *task, void *obj, void *data) -{ - nxt_conn_t *c; - nxt_event_engine_t *engine; - nxt_work_handler_t handler; - const nxt_event_conn_state_t *state; +static void nxt_kqueue_conn_io_connect(nxt_task_t *task, void *obj, + void *data) { + nxt_conn_t *c; + nxt_event_engine_t *engine; + nxt_work_handler_t handler; + const nxt_event_conn_state_t *state; - c = obj; + c = obj; - state = c->write_state; + state = c->write_state; - switch (nxt_socket_connect(task, c->socket.fd, c->remote)) { + switch (nxt_socket_connect(task, c->socket.fd, c->remote)) { - case NXT_OK: - c->socket.write_ready = 1; - handler = state->ready_handler; - break; + case NXT_OK: + c->socket.write_ready = 1; + handler = state->ready_handler; + break; - case NXT_AGAIN: - c->socket.write_handler = nxt_kqueue_conn_connected; - c->socket.error_handler = nxt_conn_connect_error; + case NXT_AGAIN: + c->socket.write_handler = nxt_kqueue_conn_connected; + c->socket.error_handler = nxt_conn_connect_error; - engine = task->thread->engine; - nxt_conn_timer(engine, c, state, &c->write_timer); + engine = task->thread->engine; + nxt_conn_timer(engine, c, state, &c->write_timer); - nxt_kqueue_enable_write(engine, &c->socket); - return; + nxt_kqueue_enable_write(engine, &c->socket); + return; - case NXT_DECLINED: - handler = state->close_handler; - break; + case NXT_DECLINED: + handler = state->close_handler; + break; - default: /* NXT_ERROR */ - handler = state->error_handler; - break; - } + default: /* NXT_ERROR */ + handler = state->error_handler; + break; + } - nxt_work_queue_add(c->write_work_queue, handler, task, c, data); + nxt_work_queue_add(c->write_work_queue, handler, task, c, data); } +static void nxt_kqueue_conn_connected(nxt_task_t *task, void *obj, void *data) { + nxt_conn_t *c; -static void -nxt_kqueue_conn_connected(nxt_task_t *task, void *obj, void *data) -{ - nxt_conn_t *c; + c = obj; - c = obj; + nxt_debug(task, "kqueue conn connected fd:%d", c->socket.fd); - nxt_debug(task, "kqueue conn connected fd:%d", c->socket.fd); + c->socket.write = NXT_EVENT_BLOCKED; - c->socket.write = NXT_EVENT_BLOCKED; + if (c->write_state->timer_autoreset) { + nxt_timer_disable(task->thread->engine, &c->write_timer); + } - if (c->write_state->timer_autoreset) { - nxt_timer_disable(task->thread->engine, &c->write_timer); - } - - nxt_work_queue_add(c->write_work_queue, c->write_state->ready_handler, - task, c, data); + nxt_work_queue_add(c->write_work_queue, c->write_state->ready_handler, task, + c, data); } +static void nxt_kqueue_listen_handler(nxt_task_t *task, void *obj, void *data) { + nxt_listen_event_t *lev; -static void -nxt_kqueue_listen_handler(nxt_task_t *task, void *obj, void *data) -{ - nxt_listen_event_t *lev; + lev = obj; - lev = obj; + nxt_debug(task, "kevent fd:%d avail:%D", lev->socket.fd, + lev->socket.kq_available); - nxt_debug(task, "kevent fd:%d avail:%D", - lev->socket.fd, lev->socket.kq_available); + lev->ready = nxt_min(lev->batch, (uint32_t)lev->socket.kq_available); - lev->ready = nxt_min(lev->batch, (uint32_t) lev->socket.kq_available); - - nxt_kqueue_conn_io_accept(task, lev, data); + nxt_kqueue_conn_io_accept(task, lev, data); } +static void nxt_kqueue_conn_io_accept(nxt_task_t *task, void *obj, void *data) { + socklen_t socklen; + nxt_conn_t *c; + nxt_socket_t s; + struct sockaddr *sa; + nxt_listen_event_t *lev; -static void -nxt_kqueue_conn_io_accept(nxt_task_t *task, void *obj, void *data) -{ - socklen_t socklen; - nxt_conn_t *c; - nxt_socket_t s; - struct sockaddr *sa; - nxt_listen_event_t *lev; + lev = obj; + c = lev->next; - lev = obj; - c = lev->next; + lev->ready--; + lev->socket.read_ready = (lev->ready != 0); - lev->ready--; - lev->socket.read_ready = (lev->ready != 0); + lev->socket.kq_available--; + lev->socket.read_ready = (lev->socket.kq_available != 0); - lev->socket.kq_available--; - lev->socket.read_ready = (lev->socket.kq_available != 0); + sa = &c->remote->u.sockaddr; + socklen = c->remote->socklen; + /* + * The returned socklen is ignored here, + * see comment in nxt_conn_io_accept(). + */ + s = accept(lev->socket.fd, sa, &socklen); - sa = &c->remote->u.sockaddr; - socklen = c->remote->socklen; - /* - * The returned socklen is ignored here, - * see comment in nxt_conn_io_accept(). - */ - s = accept(lev->socket.fd, sa, &socklen); + if (s != -1) { + c->socket.fd = s; - if (s != -1) { - c->socket.fd = s; + nxt_debug(task, "accept(%d): %d", lev->socket.fd, s); - nxt_debug(task, "accept(%d): %d", lev->socket.fd, s); + nxt_conn_accept(task, lev, c); + return; + } - nxt_conn_accept(task, lev, c); - return; - } - - nxt_conn_accept_error(task, lev, "accept", nxt_errno); + nxt_conn_accept_error(task, lev, "accept", nxt_errno); } - /* * nxt_kqueue_conn_io_read() is just a wrapper to eliminate the * readv() or recv() syscall if a remote side just closed connection. */ -static void -nxt_kqueue_conn_io_read(nxt_task_t *task, void *obj, void *data) -{ - nxt_conn_t *c; +static void nxt_kqueue_conn_io_read(nxt_task_t *task, void *obj, void *data) { + nxt_conn_t *c; - c = obj; + c = obj; - nxt_debug(task, "kqueue conn read fd:%d", c->socket.fd); + nxt_debug(task, "kqueue conn read fd:%d", c->socket.fd); - if (c->socket.kq_available == 0 && c->socket.kq_eof) { - nxt_debug(task, "kevent fd:%d eof", c->socket.fd); + if (c->socket.kq_available == 0 && c->socket.kq_eof) { + nxt_debug(task, "kevent fd:%d eof", c->socket.fd); - c->socket.closed = 1; - nxt_work_queue_add(c->read_work_queue, c->read_state->close_handler, - task, c, data); - return; - } + c->socket.closed = 1; + nxt_work_queue_add(c->read_work_queue, c->read_state->close_handler, task, + c, data); + return; + } - nxt_conn_io_read(task, c, data); + nxt_conn_io_read(task, c, data); } - /* * nxt_kqueue_conn_io_recvbuf() is just wrapper around standard * nxt_conn_io_recvbuf() to eliminate the readv() or recv() syscalls * if there is no pending data or a remote side closed connection. */ -static ssize_t -nxt_kqueue_conn_io_recvbuf(nxt_conn_t *c, nxt_buf_t *b) -{ - ssize_t n; +static ssize_t nxt_kqueue_conn_io_recvbuf(nxt_conn_t *c, nxt_buf_t *b) { + ssize_t n; - if (c->socket.kq_available == 0 && c->socket.kq_eof) { - c->socket.closed = 1; - return 0; - } + if (c->socket.kq_available == 0 && c->socket.kq_eof) { + c->socket.closed = 1; + return 0; + } - n = nxt_conn_io_recvbuf(c, b); + n = nxt_conn_io_recvbuf(c, b); - if (n > 0) { - c->socket.kq_available -= n; + if (n > 0) { + c->socket.kq_available -= n; - if (c->socket.kq_available < 0) { - c->socket.kq_available = 0; - } + if (c->socket.kq_available < 0) { + c->socket.kq_available = 0; + } - nxt_debug(c->socket.task, "kevent fd:%d avail:%D eof:%d", - c->socket.fd, c->socket.kq_available, c->socket.kq_eof); + nxt_debug(c->socket.task, "kevent fd:%d avail:%D eof:%d", c->socket.fd, + c->socket.kq_available, c->socket.kq_eof); - c->socket.read_ready = (c->socket.kq_available != 0 - || c->socket.kq_eof); - } + c->socket.read_ready = (c->socket.kq_available != 0 || c->socket.kq_eof); + } - return n; + return n; } diff --git a/src/nxt_lib.c b/src/nxt_lib.c index de23ce0ab..f24700d14 100644 --- a/src/nxt_lib.c +++ b/src/nxt_lib.c @@ -6,15 +6,13 @@ #include - -nxt_uint_t nxt_ncpu = 1; -nxt_uint_t nxt_pagesize; -nxt_task_t nxt_main_task; -nxt_atomic_t nxt_task_ident; +nxt_uint_t nxt_ncpu = 1; +nxt_uint_t nxt_pagesize; +nxt_task_t nxt_main_task; +nxt_atomic_t nxt_task_ident; nxt_thread_declare_data(nxt_thread_t, nxt_thread_context); - #if (NXT_DEBUG && NXT_FREEBSD) /* * Fill memory with 0xA5 after malloc() and with 0x5A before free(). @@ -28,125 +26,119 @@ const char *malloc_conf = "junk:true"; #endif #endif +nxt_int_t nxt_lib_start(const char *app, char **argv, char ***envp) { + int n = 0; + nxt_int_t flags; + nxt_bool_t update; + nxt_thread_t *thread; -nxt_int_t -nxt_lib_start(const char *app, char **argv, char ***envp) -{ - int n = 0; - nxt_int_t flags; - nxt_bool_t update; - nxt_thread_t *thread; + flags = nxt_stderr_start(); - flags = nxt_stderr_start(); + nxt_log_start(app); - nxt_log_start(app); - - nxt_pid = getpid(); - nxt_ppid = getppid(); - nxt_euid = geteuid(); - nxt_egid = getegid(); + nxt_pid = getpid(); + nxt_ppid = getppid(); + nxt_euid = geteuid(); + nxt_egid = getegid(); #if (NXT_DEBUG) - nxt_main_log.level = NXT_LOG_DEBUG; + nxt_main_log.level = NXT_LOG_DEBUG; #if (NXT_HAVE_MALLOPT) - /* Fill memory with 0xAA after malloc() and with 0x55 before free(). */ - mallopt(M_PERTURB, 0x55); + /* Fill memory with 0xAA after malloc() and with 0x55 before free(). */ + mallopt(M_PERTURB, 0x55); #endif #if (NXT_MACOSX) - /* Fill memory with 0xAA after malloc() and with 0x55 before free(). */ - setenv("MallocScribble", "1", 0); + /* Fill memory with 0xAA after malloc() and with 0x55 before free(). */ + setenv("MallocScribble", "1", 0); #endif #endif /* NXT_DEBUG */ - /* Thread log is required for nxt_malloc() in nxt_strerror_start(). */ + /* Thread log is required for nxt_malloc() in nxt_strerror_start(). */ - nxt_thread_init_data(nxt_thread_context); - thread = nxt_thread(); - thread->log = &nxt_main_log; + nxt_thread_init_data(nxt_thread_context); + thread = nxt_thread(); + thread->log = &nxt_main_log; - thread->handle = nxt_thread_handle(); - thread->time.signal = -1; - nxt_thread_time_update(thread); + thread->handle = nxt_thread_handle(); + thread->time.signal = -1; + nxt_thread_time_update(thread); - nxt_main_task.thread = thread; - nxt_main_task.log = thread->log; - nxt_main_task.ident = nxt_task_next_ident(); + nxt_main_task.thread = thread; + nxt_main_task.log = thread->log; + nxt_main_task.ident = nxt_task_next_ident(); - if (nxt_strerror_start() != NXT_OK) { - return NXT_ERROR; - } + if (nxt_strerror_start() != NXT_OK) { + return NXT_ERROR; + } - if (flags != -1) { - nxt_debug(&nxt_main_task, "stderr flags: 0x%04Xd", flags); - } + if (flags != -1) { + nxt_debug(&nxt_main_task, "stderr flags: 0x%04Xd", flags); + } #ifdef _SC_NPROCESSORS_ONLN - /* Linux, FreeBSD, Solaris, MacOSX. */ - n = sysconf(_SC_NPROCESSORS_ONLN); + /* Linux, FreeBSD, Solaris, MacOSX. */ + n = sysconf(_SC_NPROCESSORS_ONLN); #endif #if (NXT_HAVE_LINUX_SCHED_GETAFFINITY) - if (n > 0) { - int err; - size_t size; - cpu_set_t *set; - - set = CPU_ALLOC(n); - if (set == NULL) { - return NXT_ERROR; - } - - size = CPU_ALLOC_SIZE(n); + if (n > 0) { + int err; + size_t size; + cpu_set_t *set; + + set = CPU_ALLOC(n); + if (set == NULL) { + return NXT_ERROR; + } - err = sched_getaffinity(0, size, set); - if (err == 0) { - n = CPU_COUNT_S(size, set); - } + size = CPU_ALLOC_SIZE(n); - CPU_FREE(set); + err = sched_getaffinity(0, size, set); + if (err == 0) { + n = CPU_COUNT_S(size, set); } + CPU_FREE(set); + } + #elif (NXT_HPUX) - n = mpctl(MPC_GETNUMSPUS, NULL, NULL); + n = mpctl(MPC_GETNUMSPUS, NULL, NULL); #endif - nxt_debug(&nxt_main_task, "ncpu: %d", n); + nxt_debug(&nxt_main_task, "ncpu: %d", n); - if (n > 1) { - nxt_ncpu = n; - } + if (n > 1) { + nxt_ncpu = n; + } - nxt_thread_spin_init(nxt_ncpu, 0); + nxt_thread_spin_init(nxt_ncpu, 0); - nxt_random_init(&thread->random); + nxt_random_init(&thread->random); - nxt_pagesize = getpagesize(); + nxt_pagesize = getpagesize(); - nxt_debug(&nxt_main_task, "pagesize: %ui", nxt_pagesize); + nxt_debug(&nxt_main_task, "pagesize: %ui", nxt_pagesize); - if (argv != NULL) { - update = (argv[0] == app); + if (argv != NULL) { + update = (argv[0] == app); - nxt_process_arguments(&nxt_main_task, argv, envp); + nxt_process_arguments(&nxt_main_task, argv, envp); - if (update) { - nxt_log_start(nxt_process_argv[0]); - } + if (update) { + nxt_log_start(nxt_process_argv[0]); } + } - return NXT_OK; + return NXT_OK; } - -void -nxt_lib_stop(void) -{ - /* TODO: stop engines */ +void nxt_lib_stop(void) { + /* TODO: stop engines */ #if 0 @@ -169,8 +161,8 @@ nxt_lib_stop(void) #else - exit(0); - nxt_unreachable(); + exit(0); + nxt_unreachable(); #endif } diff --git a/src/nxt_linux_sendfile.c b/src/nxt_linux_sendfile.c index 0e772ffb3..28db2d6d7 100644 --- a/src/nxt_linux_sendfile.c +++ b/src/nxt_linux_sendfile.c @@ -6,7 +6,6 @@ #include - /* * sendfile() has been introduced in Linux 2.2. * It supported 32-bit offsets only. @@ -19,221 +18,212 @@ #ifdef NXT_TEST_BUILD_LINUX_SENDFILE -#define MSG_NOSIGNAL 0x4000 -#define MSG_MORE 0x8000 +#define MSG_NOSIGNAL 0x4000 +#define MSG_MORE 0x8000 ssize_t nxt_linux_event_conn_io_sendfile(nxt_event_conn_t *c, nxt_buf_t *b, - size_t limit); + size_t limit); static ssize_t nxt_sys_sendfile(int out_fd, int in_fd, off_t *offset, - size_t count) -{ - return -1; + size_t count) { + return -1; } #else -#define nxt_sys_sendfile sendfile +#define nxt_sys_sendfile sendfile #endif - static ssize_t nxt_linux_send(nxt_event_conn_t *c, void *buf, size_t size, - nxt_uint_t flags); + nxt_uint_t flags); static ssize_t nxt_linux_sendmsg(nxt_event_conn_t *c, - nxt_sendbuf_coalesce_t *sb, nxt_uint_t niov, nxt_uint_t flags); - - -ssize_t -nxt_linux_event_conn_io_sendfile(nxt_event_conn_t *c, nxt_buf_t *b, - size_t limit) -{ - size_t size; - ssize_t n; - nxt_buf_t *fb; - nxt_err_t err; - nxt_off_t offset; - nxt_uint_t niov, flags; - struct iovec iov[NXT_IOBUF_MAX]; - nxt_sendbuf_coalesce_t sb; - - sb.buf = b; - sb.iobuf = iov; - sb.nmax = NXT_IOBUF_MAX; - sb.sync = 0; - sb.size = 0; - sb.limit = limit; - - niov = nxt_sendbuf_mem_coalesce(c->socket.task, &sb); - - if (niov == 0 && sb.sync) { - return 0; - } - - fb = (sb.buf != NULL && nxt_buf_is_file(sb.buf)) ? sb.buf : NULL; - - if (niov != 0) { - - flags = MSG_NOSIGNAL; + nxt_sendbuf_coalesce_t *sb, nxt_uint_t niov, + nxt_uint_t flags); - if (fb != NULL) { - /* - * The Linux-specific MSG_MORE flag is cheaper - * than additional setsockopt(TCP_CORK) syscall. - */ - flags |= MSG_MORE; - } - - if (niov == 1) { - /* - * Disposal of surplus kernel msghdr - * and iovec copy-in operations. - */ - return nxt_linux_send(c, iov->iov_base, iov->iov_len, flags); - } - - return nxt_linux_sendmsg(c, &sb, niov, flags); +ssize_t nxt_linux_event_conn_io_sendfile(nxt_event_conn_t *c, nxt_buf_t *b, + size_t limit) { + size_t size; + ssize_t n; + nxt_buf_t *fb; + nxt_err_t err; + nxt_off_t offset; + nxt_uint_t niov, flags; + struct iovec iov[NXT_IOBUF_MAX]; + nxt_sendbuf_coalesce_t sb; + + sb.buf = b; + sb.iobuf = iov; + sb.nmax = NXT_IOBUF_MAX; + sb.sync = 0; + sb.size = 0; + sb.limit = limit; + + niov = nxt_sendbuf_mem_coalesce(c->socket.task, &sb); + + if (niov == 0 && sb.sync) { + return 0; + } + + fb = (sb.buf != NULL && nxt_buf_is_file(sb.buf)) ? sb.buf : NULL; + + if (niov != 0) { + + flags = MSG_NOSIGNAL; + + if (fb != NULL) { + /* + * The Linux-specific MSG_MORE flag is cheaper + * than additional setsockopt(TCP_CORK) syscall. + */ + flags |= MSG_MORE; } - size = nxt_sendbuf_file_coalesce(&sb); + if (niov == 1) { + /* + * Disposal of surplus kernel msghdr + * and iovec copy-in operations. + */ + return nxt_linux_send(c, iov->iov_base, iov->iov_len, flags); + } - nxt_debug(c->socket.task, "sendfile(%d, %FD, @%O, %uz)", - c->socket.fd, fb->file->fd, fb->file_pos, size); + return nxt_linux_sendmsg(c, &sb, niov, flags); + } - offset = fb->file_pos; + size = nxt_sendbuf_file_coalesce(&sb); - n = nxt_sys_sendfile(c->socket.fd, fb->file->fd, &offset, size); + nxt_debug(c->socket.task, "sendfile(%d, %FD, @%O, %uz)", c->socket.fd, + fb->file->fd, fb->file_pos, size); - err = (n == -1) ? nxt_errno : 0; + offset = fb->file_pos; - nxt_debug(c->socket.task, "sendfile(): %z", n); + n = nxt_sys_sendfile(c->socket.fd, fb->file->fd, &offset, size); - if (n == -1) { - switch (err) { + err = (n == -1) ? nxt_errno : 0; - case NXT_EAGAIN: - c->socket.write_ready = 0; - break; + nxt_debug(c->socket.task, "sendfile(): %z", n); - case NXT_EINTR: - break; + if (n == -1) { + switch (err) { - default: - c->socket.error = err; - nxt_log(c->socket.task, nxt_socket_error_level(err), - "sendfile(%d, %FD, %O, %uz) failed %E \"%FN\"", - c->socket.fd, fb->file->fd, fb->file_pos, size, - err, fb->file->name); + case NXT_EAGAIN: + c->socket.write_ready = 0; + break; - return NXT_ERROR; - } + case NXT_EINTR: + break; - nxt_debug(c->socket.task, "sendfile() %E", err); + default: + c->socket.error = err; + nxt_log(c->socket.task, nxt_socket_error_level(err), + "sendfile(%d, %FD, %O, %uz) failed %E \"%FN\"", c->socket.fd, + fb->file->fd, fb->file_pos, size, err, fb->file->name); - return 0; + return NXT_ERROR; } - if (n < (ssize_t) size) { - c->socket.write_ready = 0; - } + nxt_debug(c->socket.task, "sendfile() %E", err); - return n; -} + return 0; + } + if (n < (ssize_t)size) { + c->socket.write_ready = 0; + } -static ssize_t -nxt_linux_send(nxt_event_conn_t *c, void *buf, size_t size, nxt_uint_t flags) -{ - ssize_t n; - nxt_err_t err; - - n = send(c->socket.fd, buf, size, flags); - - err = (n == -1) ? nxt_errno : 0; + return n; +} - nxt_debug(c->socket.task, "send(%d, %p, %uz, 0x%uXi): %z", - c->socket.fd, buf, size, flags, n); +static ssize_t nxt_linux_send(nxt_event_conn_t *c, void *buf, size_t size, + nxt_uint_t flags) { + ssize_t n; + nxt_err_t err; - if (n == -1) { - switch (err) { + n = send(c->socket.fd, buf, size, flags); - case NXT_EAGAIN: - c->socket.write_ready = 0; - break; + err = (n == -1) ? nxt_errno : 0; - case NXT_EINTR: - break; + nxt_debug(c->socket.task, "send(%d, %p, %uz, 0x%uXi): %z", c->socket.fd, buf, + size, flags, n); - default: - c->socket.error = err; - nxt_log(c->socket.task, nxt_socket_error_level(err), - "send(%d, %p, %uz, 0x%uXi) failed %E", - c->socket.fd, buf, size, flags, err); + if (n == -1) { + switch (err) { - return NXT_ERROR; - } + case NXT_EAGAIN: + c->socket.write_ready = 0; + break; - nxt_debug(c->socket.task, "send() %E", err); + case NXT_EINTR: + break; - return 0; - } + default: + c->socket.error = err; + nxt_log(c->socket.task, nxt_socket_error_level(err), + "send(%d, %p, %uz, 0x%uXi) failed %E", c->socket.fd, buf, size, + flags, err); - if (n < (ssize_t) size) { - c->socket.write_ready = 0; + return NXT_ERROR; } - return n; -} + nxt_debug(c->socket.task, "send() %E", err); + return 0; + } -static ssize_t -nxt_linux_sendmsg(nxt_event_conn_t *c, nxt_sendbuf_coalesce_t *sb, - nxt_uint_t niov, nxt_uint_t flags) -{ - ssize_t n; - nxt_err_t err; - struct msghdr msg; + if (n < (ssize_t)size) { + c->socket.write_ready = 0; + } - msg.msg_name = NULL; - msg.msg_namelen = 0; - msg.msg_iov = sb->iobuf; - msg.msg_iovlen = niov; - msg.msg_control = NULL; - msg.msg_controllen = 0; - msg.msg_flags = 0; + return n; +} - n = sendmsg(c->socket.fd, &msg, flags); +static ssize_t nxt_linux_sendmsg(nxt_event_conn_t *c, + nxt_sendbuf_coalesce_t *sb, nxt_uint_t niov, + nxt_uint_t flags) { + ssize_t n; + nxt_err_t err; + struct msghdr msg; - err = (n == -1) ? nxt_errno : 0; + msg.msg_name = NULL; + msg.msg_namelen = 0; + msg.msg_iov = sb->iobuf; + msg.msg_iovlen = niov; + msg.msg_control = NULL; + msg.msg_controllen = 0; + msg.msg_flags = 0; - nxt_debug(c->socket.task, "sendmsg(%d, %ui, 0x%uXi): %z", - c->socket.fd, niov, flags, n); + n = sendmsg(c->socket.fd, &msg, flags); - if (n == -1) { - switch (err) { + err = (n == -1) ? nxt_errno : 0; - case NXT_EAGAIN: - c->socket.write_ready = 0; - break; + nxt_debug(c->socket.task, "sendmsg(%d, %ui, 0x%uXi): %z", c->socket.fd, niov, + flags, n); - case NXT_EINTR: - break; + if (n == -1) { + switch (err) { - default: - c->socket.error = err; - nxt_log(c->socket.task, nxt_socket_error_level(err), - "sendmsg(%d, %ui, 0x%uXi) failed %E", - c->socket.fd, niov, flags, err); + case NXT_EAGAIN: + c->socket.write_ready = 0; + break; - return NXT_ERROR; - } + case NXT_EINTR: + break; - nxt_debug(c->socket.task, "sendmsg() %E", err); + default: + c->socket.error = err; + nxt_log(c->socket.task, nxt_socket_error_level(err), + "sendmsg(%d, %ui, 0x%uXi) failed %E", c->socket.fd, niov, flags, + err); - return 0; + return NXT_ERROR; } - if (n < (ssize_t) sb->size) { - c->socket.write_ready = 0; - } + nxt_debug(c->socket.task, "sendmsg() %E", err); + + return 0; + } + + if (n < (ssize_t)sb->size) { + c->socket.write_ready = 0; + } - return n; + return n; } diff --git a/src/nxt_list.c b/src/nxt_list.c index cab925cbd..5589b94a6 100644 --- a/src/nxt_list.c +++ b/src/nxt_list.c @@ -6,103 +6,90 @@ #include +nxt_list_t *nxt_list_create(nxt_mp_t *mp, nxt_uint_t n, size_t size) { + nxt_list_t *list; -nxt_list_t * -nxt_list_create(nxt_mp_t *mp, nxt_uint_t n, size_t size) -{ - nxt_list_t *list; + list = nxt_mp_get(mp, sizeof(nxt_list_t) + n * size); - list = nxt_mp_get(mp, sizeof(nxt_list_t) + n * size); + if (nxt_fast_path(list != NULL)) { + list->last = &list->part; + list->size = size; + list->nalloc = n; + list->mem_pool = mp; + list->part.next = NULL; + list->part.nelts = 0; + } - if (nxt_fast_path(list != NULL)) { - list->last = &list->part; - list->size = size; - list->nalloc = n; - list->mem_pool = mp; - list->part.next = NULL; - list->part.nelts = 0; - } - - return list; + return list; } +void *nxt_list_add(nxt_list_t *list) { + void *elt; + nxt_list_part_t *last; -void * -nxt_list_add(nxt_list_t *list) -{ - void *elt; - nxt_list_part_t *last; + last = list->last; - last = list->last; + if (last->nelts == list->nalloc) { - if (last->nelts == list->nalloc) { + /* The last list part is filled up, allocating a new list part. */ - /* The last list part is filled up, allocating a new list part. */ + last = nxt_mp_get(list->mem_pool, + sizeof(nxt_list_part_t) + list->nalloc * list->size); - last = nxt_mp_get(list->mem_pool, - sizeof(nxt_list_part_t) + list->nalloc * list->size); + if (nxt_slow_path(last == NULL)) { + return NULL; + } - if (nxt_slow_path(last == NULL)) { - return NULL; - } + last->next = NULL; + last->nelts = 0; - last->next = NULL; - last->nelts = 0; + list->last->next = last; + list->last = last; + } - list->last->next = last; - list->last = last; - } + elt = nxt_pointer_to(nxt_list_data(last), last->nelts * list->size); + last->nelts++; - elt = nxt_pointer_to(nxt_list_data(last), last->nelts * list->size); - last->nelts++; - - return elt; + return elt; } +void *nxt_list_zero_add(nxt_list_t *list) { + void *p; -void * -nxt_list_zero_add(nxt_list_t *list) -{ - void *p; - - p = nxt_list_add(list); + p = nxt_list_add(list); - if (nxt_fast_path(p != NULL)) { - nxt_memzero(p, list->size); - } + if (nxt_fast_path(p != NULL)) { + nxt_memzero(p, list->size); + } - return p; + return p; } +void *nxt_list_next(nxt_list_t *list, nxt_list_next_t *next) { + if (next->part != NULL) { + next->elt++; -void * -nxt_list_next(nxt_list_t *list, nxt_list_next_t *next) -{ - if (next->part != NULL) { - next->elt++; - - if (next->elt < next->part->nelts) { - return nxt_list_next_value(list, next); - } - - next->part = next->part->next; + if (next->elt < next->part->nelts) { + return nxt_list_next_value(list, next); + } - if (next->part != NULL) { - next->elt = 0; - return nxt_list_data(next->part); - } + next->part = next->part->next; - } else { - next->part = nxt_list_part(list); - /* - * The first list part is allocated together with - * a nxt_list_t itself and it may never be NULL. - */ - if (next->part->nelts != 0) { - return nxt_list_data(next->part); - } + if (next->part != NULL) { + next->elt = 0; + return nxt_list_data(next->part); + } + } else { + next->part = nxt_list_part(list); + /* + * The first list part is allocated together with + * a nxt_list_t itself and it may never be NULL. + */ + if (next->part->nelts != 0) { + return nxt_list_data(next->part); } + } - return NULL; + return NULL; } diff --git a/src/nxt_list.h b/src/nxt_list.h index dc948e038..9dec24a8e 100644 --- a/src/nxt_list.h +++ b/src/nxt_list.h @@ -7,90 +7,78 @@ #ifndef _NXT_LIST_H_INCLUDED_ #define _NXT_LIST_H_INCLUDED_ - -typedef struct nxt_list_part_s nxt_list_part_t; +typedef struct nxt_list_part_s nxt_list_part_t; struct nxt_list_part_s { - nxt_list_part_t *next; - uintptr_t nelts; - char data[]; + nxt_list_part_t *next; + uintptr_t nelts; + char data[]; }; - typedef struct { - nxt_list_part_t *last; + nxt_list_part_t *last; #if (NXT_64BIT) - uint32_t size; - uint32_t nalloc; + uint32_t size; + uint32_t nalloc; #else - uint16_t size; - uint16_t nalloc; + uint16_t size; + uint16_t nalloc; #endif - nxt_mp_t *mem_pool; - nxt_list_part_t part; + nxt_mp_t *mem_pool; + nxt_list_part_t part; } nxt_list_t; - typedef struct { - nxt_list_part_t *part; - uintptr_t elt; + nxt_list_part_t *part; + uintptr_t elt; } nxt_list_next_t; +#define nxt_list_part(list) (&(list)->part) -#define nxt_list_part(list) \ - (&(list)->part) - - -#define nxt_list_data(part) \ - ((void *) part->data) - - -#define nxt_list_first(list) \ - nxt_list_data(nxt_list_part(list)) +#define nxt_list_data(part) ((void *)part->data) +#define nxt_list_first(list) nxt_list_data(nxt_list_part(list)) -nxt_inline void * -nxt_list_elt(nxt_list_t *list, nxt_uint_t n) -{ - nxt_list_part_t *part; +nxt_inline void *nxt_list_elt(nxt_list_t *list, nxt_uint_t n) { + nxt_list_part_t *part; - if (nxt_fast_path((list) != NULL)) { - part = nxt_list_part(list); + if (nxt_fast_path((list) != NULL)) { + part = nxt_list_part(list); - while (part != NULL) { - if (n < (nxt_uint_t) part->nelts) { - return nxt_pointer_to(nxt_list_data(part), n * (list)->size); - } + while (part != NULL) { + if (n < (nxt_uint_t)part->nelts) { + return nxt_pointer_to(nxt_list_data(part), n * (list)->size); + } - n -= (nxt_uint_t) part->nelts; - part = part->next; - } + n -= (nxt_uint_t)part->nelts; + part = part->next; } + } - return NULL; + return NULL; } - -#define nxt_list_each(elt, list) \ - do { \ - if (nxt_fast_path((list) != NULL)) { \ - void *_end; \ - nxt_list_part_t *_part = nxt_list_part(list); \ - \ - do { \ - elt = nxt_list_data(_part); \ - \ - for (_end = (elt + _part->nelts); elt != _end; elt++) { \ - -#define nxt_list_loop \ - } \ - \ - _part = _part->next; \ - \ - } while (_part != NULL); \ - } \ - } while (0) - +#define nxt_list_each(elt, list) \ + do { \ + if (nxt_fast_path((list) != NULL)) { \ + void *_end; \ + nxt_list_part_t *_part = nxt_list_part(list); \ + \ + do { \ + elt = nxt_list_data(_part); \ + \ + for (_end = (elt + _part->nelts); elt != _end; elt++) { + +#define nxt_list_loop \ + } \ + \ + _part = _part->next; \ + } \ + while (_part != NULL) \ + ; \ + } \ + } \ + while (0) NXT_EXPORT nxt_list_t *nxt_list_create(nxt_mp_t *mp, nxt_uint_t n, size_t size); NXT_EXPORT void *nxt_list_add(nxt_list_t *list); @@ -98,30 +86,25 @@ NXT_EXPORT void *nxt_list_zero_add(nxt_list_t *list); NXT_EXPORT void *nxt_list_next(nxt_list_t *list, nxt_list_next_t *next); +#define nxt_list_next_value(list, next) \ + (nxt_pointer_to(nxt_list_data((next)->part), (next)->elt * (list)->size)) -#define nxt_list_next_value(list, next) \ - (nxt_pointer_to(nxt_list_data((next)->part), (next)->elt * (list)->size)) - +nxt_inline nxt_uint_t nxt_list_nelts(nxt_list_t *list) { + nxt_uint_t n; + nxt_list_part_t *part; -nxt_inline nxt_uint_t -nxt_list_nelts(nxt_list_t *list) -{ - nxt_uint_t n; - nxt_list_part_t *part; + n = 0; - n = 0; + if (nxt_fast_path((list) != NULL)) { + part = nxt_list_part(list); - if (nxt_fast_path((list) != NULL)) { - part = nxt_list_part(list); + do { + n += (nxt_uint_t)part->nelts; + part = part->next; + } while (part != NULL); + } - do { - n += (nxt_uint_t) part->nelts; - part = part->next; - } while (part != NULL); - } - - return n; + return n; } - #endif /* _NXT_LIST_H_INCLUDED_ */ diff --git a/src/nxt_listen_socket.c b/src/nxt_listen_socket.c index 4fe3e20b6..a9dcf0b99 100644 --- a/src/nxt_listen_socket.c +++ b/src/nxt_listen_socket.c @@ -6,76 +6,68 @@ #include - static u_char *nxt_listen_socket_log_handler(void *ctx, u_char *pos, - u_char *last); - + u_char *last); -nxt_int_t -nxt_listen_socket(nxt_task_t *task, nxt_socket_t s, int backlog) -{ - nxt_debug(task, "listen(%d, %d)", s, backlog); +nxt_int_t nxt_listen_socket(nxt_task_t *task, nxt_socket_t s, int backlog) { + nxt_debug(task, "listen(%d, %d)", s, backlog); - if (nxt_fast_path(listen(s, backlog) == 0)) { - return NXT_OK; - } + if (nxt_fast_path(listen(s, backlog) == 0)) { + return NXT_OK; + } - nxt_alert(task, "listen(%d, %d) failed %E", s, backlog, nxt_socket_errno); + nxt_alert(task, "listen(%d, %d) failed %E", s, backlog, nxt_socket_errno); - return NXT_ERROR; + return NXT_ERROR; } - -nxt_int_t -nxt_listen_socket_create(nxt_task_t *task, nxt_mp_t *mp, - nxt_listen_socket_t *ls) -{ - nxt_log_t log, *old; - nxt_uint_t family; - nxt_socket_t s; - nxt_thread_t *thr; - nxt_sockaddr_t *sa; +nxt_int_t nxt_listen_socket_create(nxt_task_t *task, nxt_mp_t *mp, + nxt_listen_socket_t *ls) { + nxt_log_t log, *old; + nxt_uint_t family; + nxt_socket_t s; + nxt_thread_t *thr; + nxt_sockaddr_t *sa; #if (NXT_HAVE_UNIX_DOMAIN) - int ret; - u_char *p; - nxt_err_t err; - nxt_socket_t ts; - nxt_sockaddr_t *orig_sa; - nxt_file_name_t *name, *tmp; - nxt_file_access_t access; + int ret; + u_char *p; + nxt_err_t err; + nxt_socket_t ts; + nxt_sockaddr_t *orig_sa; + nxt_file_name_t *name, *tmp; + nxt_file_access_t access; #endif - sa = ls->sockaddr; + sa = ls->sockaddr; - thr = nxt_thread(); - old = thr->log; - log = *thr->log; - log.ctx_handler = nxt_listen_socket_log_handler; - log.ctx = sa; - thr->log = &log; + thr = nxt_thread(); + old = thr->log; + log = *thr->log; + log.ctx_handler = nxt_listen_socket_log_handler; + log.ctx = sa; + thr->log = &log; - family = sa->u.sockaddr.sa_family; + family = sa->u.sockaddr.sa_family; - s = nxt_socket_create(task, family, sa->type, 0, ls->flags); - if (s == -1) { - goto fail; - } + s = nxt_socket_create(task, family, sa->type, 0, ls->flags); + if (s == -1) { + goto fail; + } - if (nxt_socket_setsockopt(task, s, SOL_SOCKET, SO_REUSEADDR, 1) != NXT_OK) { - goto fail; - } + if (nxt_socket_setsockopt(task, s, SOL_SOCKET, SO_REUSEADDR, 1) != NXT_OK) { + goto fail; + } #if (NXT_INET6 && defined IPV6_V6ONLY) - if (family == AF_INET6 && ls->ipv6only) { - int ipv6only; + if (family == AF_INET6 && ls->ipv6only) { + int ipv6only; - ipv6only = (ls->ipv6only == 1); + ipv6only = (ls->ipv6only == 1); - /* Ignore possible error. TODO: why? */ - (void) nxt_socket_setsockopt(task, s, IPPROTO_IPV6, IPV6_V6ONLY, - ipv6only); - } + /* Ignore possible error. TODO: why? */ + (void)nxt_socket_setsockopt(task, s, IPPROTO_IPV6, IPV6_V6ONLY, ipv6only); + } #endif @@ -86,309 +78,292 @@ nxt_listen_socket_create(nxt_task_t *task, nxt_mp_t *mp, #endif - if (ls->read_after_accept) { - nxt_socket_defer_accept(task, s, sa); - } + if (ls->read_after_accept) { + nxt_socket_defer_accept(task, s, sa); + } #if (NXT_HAVE_UNIX_DOMAIN) - if (family == AF_UNIX - && sa->type == SOCK_STREAM - && sa->u.sockaddr_un.sun_path[0] != '\0') - { - orig_sa = sa; + if (family == AF_UNIX && sa->type == SOCK_STREAM && + sa->u.sockaddr_un.sun_path[0] != '\0') { + orig_sa = sa; - sa = nxt_sockaddr_alloc(mp, sa->socklen + 4, sa->length + 4); - if (sa == NULL) { - goto fail; - } + sa = nxt_sockaddr_alloc(mp, sa->socklen + 4, sa->length + 4); + if (sa == NULL) { + goto fail; + } - sa->type = SOCK_STREAM; - sa->u.sockaddr_un.sun_family = AF_UNIX; + sa->type = SOCK_STREAM; + sa->u.sockaddr_un.sun_family = AF_UNIX; - p = nxt_cpystr((u_char *) sa->u.sockaddr_un.sun_path, - (u_char *) orig_sa->u.sockaddr_un.sun_path); - nxt_memcpy(p, ".tmp", 4); + p = nxt_cpystr((u_char *)sa->u.sockaddr_un.sun_path, + (u_char *)orig_sa->u.sockaddr_un.sun_path); + nxt_memcpy(p, ".tmp", 4); - nxt_sockaddr_text(sa); + nxt_sockaddr_text(sa); - (void) unlink(sa->u.sockaddr_un.sun_path); + (void)unlink(sa->u.sockaddr_un.sun_path); - } else { - orig_sa = NULL; - } + } else { + orig_sa = NULL; + } #endif - if (nxt_socket_bind(task, s, sa) != NXT_OK) { - goto fail; - } + if (nxt_socket_bind(task, s, sa) != NXT_OK) { + goto fail; + } #if (NXT_HAVE_UNIX_DOMAIN) - if (family == AF_UNIX) { - const char *user; - const char *group; - nxt_runtime_t *rt = thr->runtime; + if (family == AF_UNIX) { + const char *user; + const char *group; + nxt_runtime_t *rt = thr->runtime; - name = (nxt_file_name_t *) sa->u.sockaddr_un.sun_path; - access = rt->control_mode > 0 ? rt->control_mode : 0600; + name = (nxt_file_name_t *)sa->u.sockaddr_un.sun_path; + access = rt->control_mode > 0 ? rt->control_mode : 0600; - if (nxt_file_set_access(name, access) != NXT_OK) { - goto listen_fail; - } + if (nxt_file_set_access(name, access) != NXT_OK) { + goto listen_fail; + } - user = rt->control_user; - group = rt->control_group; + user = rt->control_user; + group = rt->control_group; - if (nxt_file_chown(name, user, group) != NXT_OK) { - goto listen_fail; - } + if (nxt_file_chown(name, user, group) != NXT_OK) { + goto listen_fail; } + } #endif - nxt_debug(task, "listen(%d, %d)", s, ls->backlog); + nxt_debug(task, "listen(%d, %d)", s, ls->backlog); - if (listen(s, ls->backlog) != 0) { - nxt_alert(task, "listen(%d, %d) failed %E", - s, ls->backlog, nxt_socket_errno); - goto listen_fail; - } + if (listen(s, ls->backlog) != 0) { + nxt_alert(task, "listen(%d, %d) failed %E", s, ls->backlog, + nxt_socket_errno); + goto listen_fail; + } #if (NXT_HAVE_UNIX_DOMAIN) - if (orig_sa != NULL) { - ts = nxt_socket_create(task, AF_UNIX, SOCK_STREAM, 0, 0); - if (ts == -1) { - goto listen_fail; - } + if (orig_sa != NULL) { + ts = nxt_socket_create(task, AF_UNIX, SOCK_STREAM, 0, 0); + if (ts == -1) { + goto listen_fail; + } - ret = connect(ts, &orig_sa->u.sockaddr, orig_sa->socklen); + ret = connect(ts, &orig_sa->u.sockaddr, orig_sa->socklen); - err = nxt_socket_errno; + err = nxt_socket_errno; - nxt_socket_close(task, ts); + nxt_socket_close(task, ts); - if (ret == 0) { - nxt_alert(task, "connect(%d, %*s) socket already in use", - ts, (size_t) orig_sa->length, - nxt_sockaddr_start(orig_sa)); + if (ret == 0) { + nxt_alert(task, "connect(%d, %*s) socket already in use", ts, + (size_t)orig_sa->length, nxt_sockaddr_start(orig_sa)); - goto listen_fail; - } + goto listen_fail; + } - if (err != NXT_ENOENT && err != NXT_ECONNREFUSED) { - nxt_alert(task, "connect(%d, %*s) failed %E", - ts, (size_t) orig_sa->length, - nxt_sockaddr_start(orig_sa), err); + if (err != NXT_ENOENT && err != NXT_ECONNREFUSED) { + nxt_alert(task, "connect(%d, %*s) failed %E", ts, (size_t)orig_sa->length, + nxt_sockaddr_start(orig_sa), err); - goto listen_fail; - } + goto listen_fail; + } - tmp = (nxt_file_name_t *) sa->u.sockaddr_un.sun_path; - name = (nxt_file_name_t *) orig_sa->u.sockaddr_un.sun_path; + tmp = (nxt_file_name_t *)sa->u.sockaddr_un.sun_path; + name = (nxt_file_name_t *)orig_sa->u.sockaddr_un.sun_path; - if (nxt_file_rename(tmp, name) != NXT_OK) { - goto listen_fail; - } + if (nxt_file_rename(tmp, name) != NXT_OK) { + goto listen_fail; } + } #endif - ls->socket = s; - thr->log = old; + ls->socket = s; + thr->log = old; - return NXT_OK; + return NXT_OK; listen_fail: #if (NXT_HAVE_UNIX_DOMAIN) - if (family == AF_UNIX) { - name = (nxt_file_name_t *) sa->u.sockaddr_un.sun_path; + if (family == AF_UNIX) { + name = (nxt_file_name_t *)sa->u.sockaddr_un.sun_path; - (void) nxt_file_delete(name); - } + (void)nxt_file_delete(name); + } #endif fail: - if (s != -1) { - nxt_socket_close(task, s); - } + if (s != -1) { + nxt_socket_close(task, s); + } - thr->log = old; + thr->log = old; - return NXT_ERROR; + return NXT_ERROR; } +nxt_int_t nxt_listen_socket_update(nxt_task_t *task, nxt_listen_socket_t *ls, + nxt_listen_socket_t *prev) { + nxt_log_t log, *old; + nxt_thread_t *thr; -nxt_int_t -nxt_listen_socket_update(nxt_task_t *task, nxt_listen_socket_t *ls, - nxt_listen_socket_t *prev) -{ - nxt_log_t log, *old; - nxt_thread_t *thr; + ls->socket = prev->socket; - ls->socket = prev->socket; + thr = nxt_thread(); + old = thr->log; + log = *thr->log; + log.ctx_handler = nxt_listen_socket_log_handler; + log.ctx = ls->sockaddr; + thr->log = &log; - thr = nxt_thread(); - old = thr->log; - log = *thr->log; - log.ctx_handler = nxt_listen_socket_log_handler; - log.ctx = ls->sockaddr; - thr->log = &log; + nxt_debug(task, "listen(%d, %d)", ls->socket, ls->backlog); - nxt_debug(task, "listen(%d, %d)", ls->socket, ls->backlog); + if (listen(ls->socket, ls->backlog) != 0) { + nxt_alert(task, "listen(%d, %d) failed %E", ls->socket, ls->backlog, + nxt_socket_errno); + goto fail; + } - if (listen(ls->socket, ls->backlog) != 0) { - nxt_alert(task, "listen(%d, %d) failed %E", - ls->socket, ls->backlog, nxt_socket_errno); - goto fail; - } + thr->log = old; - thr->log = old; - - return NXT_OK; + return NXT_OK; fail: - thr->log = old; + thr->log = old; - return NXT_ERROR; + return NXT_ERROR; } - -void -nxt_listen_socket_remote_size(nxt_listen_socket_t *ls) -{ - switch (ls->sockaddr->u.sockaddr.sa_family) { +void nxt_listen_socket_remote_size(nxt_listen_socket_t *ls) { + switch (ls->sockaddr->u.sockaddr.sa_family) { #if (NXT_INET6) - case AF_INET6: - ls->socklen = sizeof(struct sockaddr_in6); - ls->address_length = NXT_INET6_ADDR_STR_LEN; + case AF_INET6: + ls->socklen = sizeof(struct sockaddr_in6); + ls->address_length = NXT_INET6_ADDR_STR_LEN; - break; + break; #endif #if (NXT_HAVE_UNIX_DOMAIN) - case AF_UNIX: - /* - * A remote socket is usually unbound and thus has unspecified Unix - * domain sockaddr_un which can be shortcut to 3 bytes. To handle - * a bound remote socket correctly ls->socklen should be larger, see - * comment in nxt_socket.h. - */ - ls->socklen = offsetof(struct sockaddr_un, sun_path) + 1; - ls->address_length = nxt_length("unix:"); + case AF_UNIX: + /* + * A remote socket is usually unbound and thus has unspecified Unix + * domain sockaddr_un which can be shortcut to 3 bytes. To handle + * a bound remote socket correctly ls->socklen should be larger, see + * comment in nxt_socket.h. + */ + ls->socklen = offsetof(struct sockaddr_un, sun_path) + 1; + ls->address_length = nxt_length("unix:"); - break; + break; #endif - default: - case AF_INET: - ls->socklen = sizeof(struct sockaddr_in); - ls->address_length = NXT_INET_ADDR_STR_LEN; + default: + case AF_INET: + ls->socklen = sizeof(struct sockaddr_in); + ls->address_length = NXT_INET_ADDR_STR_LEN; - break; - } + break; + } } +size_t nxt_listen_socket_pool_min_size(nxt_listen_socket_t *ls) { + size_t size; -size_t -nxt_listen_socket_pool_min_size(nxt_listen_socket_t *ls) -{ - size_t size; + /* + * The first nxt_sockaddr_t is intended for mandatory remote sockaddr + * and textual representaion with port. The second nxt_sockaddr_t + * is intended for local sockaddr without textual representaion which + * may be required to get specific address of connection received on + * wildcard AF_INET and AF_INET6 addresses. For AF_UNIX addresses + * the local sockaddr is not required. + */ - /* - * The first nxt_sockaddr_t is intended for mandatory remote sockaddr - * and textual representaion with port. The second nxt_sockaddr_t - * is intended for local sockaddr without textual representaion which - * may be required to get specific address of connection received on - * wildcard AF_INET and AF_INET6 addresses. For AF_UNIX addresses - * the local sockaddr is not required. - */ - - switch (ls->sockaddr->u.sockaddr.sa_family) { + switch (ls->sockaddr->u.sockaddr.sa_family) { #if (NXT_INET6) - case AF_INET6: - ls->socklen = sizeof(struct sockaddr_in6); - ls->address_length = NXT_INET6_ADDR_STR_LEN; + case AF_INET6: + ls->socklen = sizeof(struct sockaddr_in6); + ls->address_length = NXT_INET6_ADDR_STR_LEN; - size = offsetof(nxt_sockaddr_t, u) + sizeof(struct sockaddr_in6) - + NXT_INET6_ADDR_STR_LEN + nxt_length(":65535"); + size = offsetof(nxt_sockaddr_t, u) + sizeof(struct sockaddr_in6) + + NXT_INET6_ADDR_STR_LEN + nxt_length(":65535"); - if (IN6_IS_ADDR_UNSPECIFIED(&ls->sockaddr->u.sockaddr_in6.sin6_addr)) { - size += offsetof(nxt_sockaddr_t, u) + sizeof(struct sockaddr_in6); - } + if (IN6_IS_ADDR_UNSPECIFIED(&ls->sockaddr->u.sockaddr_in6.sin6_addr)) { + size += offsetof(nxt_sockaddr_t, u) + sizeof(struct sockaddr_in6); + } - break; + break; #endif #if (NXT_HAVE_UNIX_DOMAIN) - case AF_UNIX: - /* - * A remote socket is usually unbound and thus has unspecified Unix - * domain sockaddr_un which can be shortcut to 3 bytes. To handle - * a bound remote socket correctly ls->socklen should be at least - * sizeof(struct sockaddr_un), see comment in nxt_socket.h. - */ - ls->socklen = 3; - size = ls->socklen + nxt_length("unix:"); - ls->address_length = nxt_length("unix:"); + case AF_UNIX: + /* + * A remote socket is usually unbound and thus has unspecified Unix + * domain sockaddr_un which can be shortcut to 3 bytes. To handle + * a bound remote socket correctly ls->socklen should be at least + * sizeof(struct sockaddr_un), see comment in nxt_socket.h. + */ + ls->socklen = 3; + size = ls->socklen + nxt_length("unix:"); + ls->address_length = nxt_length("unix:"); - break; + break; #endif - default: - ls->socklen = sizeof(struct sockaddr_in); - ls->address_length = NXT_INET_ADDR_STR_LEN; - - size = offsetof(nxt_sockaddr_t, u) + sizeof(struct sockaddr_in) - + NXT_INET_ADDR_STR_LEN + nxt_length(":65535"); + default: + ls->socklen = sizeof(struct sockaddr_in); + ls->address_length = NXT_INET_ADDR_STR_LEN; - if (ls->sockaddr->u.sockaddr_in.sin_addr.s_addr == INADDR_ANY) { - size += offsetof(nxt_sockaddr_t, u) + sizeof(struct sockaddr_in); - } + size = offsetof(nxt_sockaddr_t, u) + sizeof(struct sockaddr_in) + + NXT_INET_ADDR_STR_LEN + nxt_length(":65535"); - break; + if (ls->sockaddr->u.sockaddr_in.sin_addr.s_addr == INADDR_ANY) { + size += offsetof(nxt_sockaddr_t, u) + sizeof(struct sockaddr_in); } + break; + } + #if (NXT_TLS) - if (ls->tls) { - size += 4 * sizeof(void *) /* SSL/TLS connection */ - + sizeof(nxt_buf_mem_t) - + sizeof(nxt_work_t); /* nxt_mp_cleanup */ - } + if (ls->tls) { + size += 4 * sizeof(void *) /* SSL/TLS connection */ + + sizeof(nxt_buf_mem_t) + sizeof(nxt_work_t); /* nxt_mp_cleanup */ + } #endif - return size // + sizeof(nxt_mem_pool_t) - + sizeof(nxt_conn_t) - + sizeof(nxt_log_t); + return size // + sizeof(nxt_mem_pool_t) + + sizeof(nxt_conn_t) + sizeof(nxt_log_t); } +static u_char *nxt_listen_socket_log_handler(void *ctx, u_char *pos, + u_char *end) { + nxt_sockaddr_t *sa; -static u_char * -nxt_listen_socket_log_handler(void *ctx, u_char *pos, u_char *end) -{ - nxt_sockaddr_t *sa; - - sa = ctx; + sa = ctx; - return nxt_sprintf(pos, end, " while creating listening socket on %*s", - (size_t) sa->length, nxt_sockaddr_start(sa)); + return nxt_sprintf(pos, end, " while creating listening socket on %*s", + (size_t)sa->length, nxt_sockaddr_start(sa)); } diff --git a/src/nxt_listen_socket.h b/src/nxt_listen_socket.h index 8bf320bc1..c13b6378f 100644 --- a/src/nxt_listen_socket.h +++ b/src/nxt_listen_socket.h @@ -7,59 +7,56 @@ #ifndef _NXT_LISTEN_SOCKET_H_INCLUDED_ #define _NXT_LISTEN_SOCKET_H_INCLUDED_ - typedef struct { - /* nxt_socket_t is int. */ - nxt_socket_t socket; - int backlog; + /* nxt_socket_t is int. */ + nxt_socket_t socket; + int backlog; - nxt_work_queue_t *work_queue; - nxt_work_handler_t handler; + nxt_work_queue_t *work_queue; + nxt_work_handler_t handler; - nxt_sockaddr_t *sockaddr; + nxt_sockaddr_t *sockaddr; - uint32_t count; + uint32_t count; - uint8_t flags; - uint8_t read_after_accept; /* 1 bit */ + uint8_t flags; + uint8_t read_after_accept; /* 1 bit */ #if (NXT_TLS) - uint8_t tls; /* 1 bit */ + uint8_t tls; /* 1 bit */ #endif #if (NXT_INET6 && defined IPV6_V6ONLY) - uint8_t ipv6only; /* 2 bits */ + uint8_t ipv6only; /* 2 bits */ #endif - uint8_t socklen; - uint8_t address_length; + uint8_t socklen; + uint8_t address_length; } nxt_listen_socket_t; - #if (NXT_LINUX || NXT_FREEBSD || NXT_MACOSX || NXT_OPENBSD) /* * A backlog is limited by system-wide sysctl {net.core,kern.ipc}.somaxconn. * This is supported by Linux, FreeBSD 2.2, OpenBSD 2.0, and MacOSX. */ -#define NXT_LISTEN_BACKLOG -1 +#define NXT_LISTEN_BACKLOG -1 #else /* * Solaris and NetBSD treat negative value as 0. * 511 is a safe default. */ -#define NXT_LISTEN_BACKLOG 511 +#define NXT_LISTEN_BACKLOG 511 #endif - NXT_EXPORT nxt_int_t nxt_listen_socket(nxt_task_t *task, nxt_socket_t s, - int backlog); + int backlog); NXT_EXPORT nxt_int_t nxt_listen_socket_create(nxt_task_t *task, nxt_mp_t *mp, - nxt_listen_socket_t *ls); + nxt_listen_socket_t *ls); NXT_EXPORT nxt_int_t nxt_listen_socket_update(nxt_task_t *task, - nxt_listen_socket_t *ls, nxt_listen_socket_t *prev); + nxt_listen_socket_t *ls, + nxt_listen_socket_t *prev); NXT_EXPORT void nxt_listen_socket_remote_size(nxt_listen_socket_t *ls); NXT_EXPORT size_t nxt_listen_socket_pool_min_size(nxt_listen_socket_t *ls); - #endif /* _NXT_LISTEN_SOCKET_H_INCLUDED_ */ diff --git a/src/nxt_log.c b/src/nxt_log.c index 587568164..861cd035e 100644 --- a/src/nxt_log.c +++ b/src/nxt_log.c @@ -6,104 +6,82 @@ #include +nxt_uint_t nxt_debug; +nxt_uint_t nxt_trace; -nxt_uint_t nxt_debug; -nxt_uint_t nxt_trace; +nxt_log_t nxt_main_log = {NXT_LOG_INFO, 0, nxt_log_handler, NULL, NULL}; +nxt_str_t nxt_log_levels[6] = {nxt_string("alert"), nxt_string("error"), + nxt_string("warn"), nxt_string("notice"), + nxt_string("info"), nxt_string("debug")}; -nxt_log_t nxt_main_log = { - NXT_LOG_INFO, - 0, - nxt_log_handler, - NULL, - NULL -}; +static const u_char *nxt_log_prefix; - -nxt_str_t nxt_log_levels[6] = { - nxt_string("alert"), - nxt_string("error"), - nxt_string("warn"), - nxt_string("notice"), - nxt_string("info"), - nxt_string("debug") -}; - - -static const u_char *nxt_log_prefix; - - -void -nxt_log_start(const char *prefix) -{ - if (prefix != NULL && *prefix != '\0') { - nxt_log_prefix = (u_char *) prefix; - } +void nxt_log_start(const char *prefix) { + if (prefix != NULL && *prefix != '\0') { + nxt_log_prefix = (u_char *)prefix; + } } - /* STUB */ -nxt_log_t * -nxt_log_set_ctx(nxt_log_t *log, nxt_log_ctx_handler_t handler, void *ctx) -{ - nxt_log_t *old; - nxt_thread_t *thr; +nxt_log_t *nxt_log_set_ctx(nxt_log_t *log, nxt_log_ctx_handler_t handler, + void *ctx) { + nxt_log_t *old; + nxt_thread_t *thr; - thr = nxt_thread(); - old = thr->log; + thr = nxt_thread(); + old = thr->log; - log->level = old->level; - log->handler = old->handler; - log->ctx_handler = handler; - log->ctx = ctx; + log->level = old->level; + log->handler = old->handler; + log->ctx_handler = handler; + log->ctx = ctx; - thr->log = log; + thr->log = log; - return old; + return old; } - -void nxt_cdecl -nxt_log_handler(nxt_uint_t level, nxt_log_t *log, const char *fmt, ...) -{ - u_char *p, *end; +void nxt_cdecl nxt_log_handler(nxt_uint_t level, nxt_log_t *log, + const char *fmt, ...) { + u_char *p, *end; #if 0 u_char *syslogmsg; #endif - va_list args; - u_char msg[NXT_MAX_ERROR_STR]; + va_list args; + u_char msg[NXT_MAX_ERROR_STR]; - p = msg; - end = msg + NXT_MAX_ERROR_STR; + p = msg; + end = msg + NXT_MAX_ERROR_STR; - if (nxt_log_prefix != NULL) { - p = nxt_cpystrn(p, nxt_log_prefix, end - p); - *p++ = ':'; - *p++ = ' '; - } + if (nxt_log_prefix != NULL) { + p = nxt_cpystrn(p, nxt_log_prefix, end - p); + *p++ = ':'; + *p++ = ' '; + } #if 0 syslogmsg = p; #endif - p = nxt_sprintf(p, end, (log->ident != 0) ? "[%V] *%D " : "[%V] ", - &nxt_log_levels[level], log->ident); + p = nxt_sprintf(p, end, (log->ident != 0) ? "[%V] *%D " : "[%V] ", + &nxt_log_levels[level], log->ident); - va_start(args, fmt); - p = nxt_vsprintf(p, end, fmt, args); - va_end(args); + va_start(args, fmt); + p = nxt_vsprintf(p, end, fmt, args); + va_end(args); - if (level != NXT_LOG_DEBUG && log->ctx_handler != NULL) { - p = log->ctx_handler(log->ctx, p, end); - } + if (level != NXT_LOG_DEBUG && log->ctx_handler != NULL) { + p = log->ctx_handler(log->ctx, p, end); + } - if (p > end - nxt_length("\n")) { - p = end - nxt_length("\n"); - } + if (p > end - nxt_length("\n")) { + p = end - nxt_length("\n"); + } - *p++ = '\n'; + *p++ = '\n'; - (void) nxt_write_console(nxt_stderr, msg, p - msg); + (void)nxt_write_console(nxt_stderr, msg, p - msg); #if 0 if (level == NXT_LOG_ALERT) { diff --git a/src/nxt_log.h b/src/nxt_log.h index aa2fe673e..28d079d66 100644 --- a/src/nxt_log.h +++ b/src/nxt_log.h @@ -7,122 +7,107 @@ #ifndef _NXT_LOG_H_INCLUDED_ #define _NXT_LOG_H_INCLUDED_ +#define NXT_LOG_ALERT 0 +#define NXT_LOG_ERR 1 +#define NXT_LOG_WARN 2 +#define NXT_LOG_NOTICE 3 +#define NXT_LOG_INFO 4 +#define NXT_LOG_DEBUG 5 -#define NXT_LOG_ALERT 0 -#define NXT_LOG_ERR 1 -#define NXT_LOG_WARN 2 -#define NXT_LOG_NOTICE 3 -#define NXT_LOG_INFO 4 -#define NXT_LOG_DEBUG 5 - - -#define NXT_MAX_ERROR_STR 2048 - +#define NXT_MAX_ERROR_STR 2048 typedef void nxt_cdecl (*nxt_log_handler_t)(nxt_uint_t level, nxt_log_t *log, - const char *fmt, ...); + const char *fmt, ...); typedef u_char *(*nxt_log_ctx_handler_t)(void *ctx, u_char *pos, u_char *end); - struct nxt_log_s { - uint32_t level; - uint32_t ident; - nxt_log_handler_t handler; - nxt_log_ctx_handler_t ctx_handler; - void *ctx; + uint32_t level; + uint32_t ident; + nxt_log_handler_t handler; + nxt_log_ctx_handler_t ctx_handler; + void *ctx; }; - NXT_EXPORT void nxt_log_start(const char *name); NXT_EXPORT nxt_log_t *nxt_log_set_ctx(nxt_log_t *log, - nxt_log_ctx_handler_t handler, void *ctx); + nxt_log_ctx_handler_t handler, void *ctx); NXT_EXPORT void nxt_cdecl nxt_log_handler(nxt_uint_t level, nxt_log_t *log, - const char *fmt, ...); - - -#define nxt_log_level_enough(log, level) \ - ((log)->level >= (level)) - - -#define nxt_alert(task, ...) \ - do { \ - nxt_log_t *_log = (task)->log; \ - \ - _log->handler(NXT_LOG_ALERT, _log, __VA_ARGS__); \ - } while (0) - - -#define nxt_log(task, _level, ...) \ - do { \ - nxt_log_t *_log = (task)->log; \ - nxt_uint_t _level_ = (_level); \ - \ - if (nxt_slow_path(_log->level >= _level_)) { \ - _log->handler(_level_, _log, __VA_ARGS__); \ - } \ - } while (0) - - -#define nxt_trace(task, ...) \ - do { \ - nxt_log_t *_log = (task)->log; \ - \ - if (nxt_slow_path(_log->level >= NXT_LOG_NOTICE || nxt_trace)) { \ - _log->handler(NXT_LOG_NOTICE, _log, __VA_ARGS__); \ - } \ - } while (0) - - -#define nxt_log_alert(_log, ...) \ - do { \ - nxt_log_t *_log_ = (_log); \ - \ - _log_->handler(NXT_LOG_ALERT, _log_, __VA_ARGS__); \ - } while (0) - - -#define nxt_log_error(_level, _log, ...) \ - do { \ - nxt_log_t *_log_ = (_log); \ - nxt_uint_t _level_ = (_level); \ - \ - if (nxt_slow_path(_log_->level >= _level_)) { \ - _log_->handler(_level_, _log_, __VA_ARGS__); \ - } \ - } while (0) - + const char *fmt, ...); + +#define nxt_log_level_enough(log, level) ((log)->level >= (level)) + +#define nxt_alert(task, ...) \ + do { \ + nxt_log_t *_log = (task)->log; \ + \ + _log->handler(NXT_LOG_ALERT, _log, __VA_ARGS__); \ + } while (0) + +#define nxt_log(task, _level, ...) \ + do { \ + nxt_log_t *_log = (task)->log; \ + nxt_uint_t _level_ = (_level); \ + \ + if (nxt_slow_path(_log->level >= _level_)) { \ + _log->handler(_level_, _log, __VA_ARGS__); \ + } \ + } while (0) + +#define nxt_trace(task, ...) \ + do { \ + nxt_log_t *_log = (task)->log; \ + \ + if (nxt_slow_path(_log->level >= NXT_LOG_NOTICE || nxt_trace)) { \ + _log->handler(NXT_LOG_NOTICE, _log, __VA_ARGS__); \ + } \ + } while (0) + +#define nxt_log_alert(_log, ...) \ + do { \ + nxt_log_t *_log_ = (_log); \ + \ + _log_->handler(NXT_LOG_ALERT, _log_, __VA_ARGS__); \ + } while (0) + +#define nxt_log_error(_level, _log, ...) \ + do { \ + nxt_log_t *_log_ = (_log); \ + nxt_uint_t _level_ = (_level); \ + \ + if (nxt_slow_path(_log_->level >= _level_)) { \ + _log_->handler(_level_, _log_, __VA_ARGS__); \ + } \ + } while (0) #if (NXT_DEBUG) -#define nxt_debug(task, ...) \ - do { \ - nxt_log_t *_log = (task)->log; \ - \ - if (nxt_slow_path(_log->level == NXT_LOG_DEBUG || nxt_debug)) { \ - _log->handler(NXT_LOG_DEBUG, _log, __VA_ARGS__); \ - } \ - } while (0) - - -#define nxt_log_debug(_log, ...) \ - do { \ - nxt_log_t *_log_ = (_log); \ - \ - if (nxt_slow_path(_log_->level == NXT_LOG_DEBUG || nxt_debug)) { \ - _log_->handler(NXT_LOG_DEBUG, _log_, __VA_ARGS__); \ - } \ - } while (0) - - -#define nxt_assert(c) \ - do { \ - if (nxt_slow_path(!(c))) { \ - nxt_thread_log_alert("%s:%d assertion failed: %s", \ - __FILE__, __LINE__, #c); \ - nxt_abort(); \ - } \ - } while (0) +#define nxt_debug(task, ...) \ + do { \ + nxt_log_t *_log = (task)->log; \ + \ + if (nxt_slow_path(_log->level == NXT_LOG_DEBUG || nxt_debug)) { \ + _log->handler(NXT_LOG_DEBUG, _log, __VA_ARGS__); \ + } \ + } while (0) + +#define nxt_log_debug(_log, ...) \ + do { \ + nxt_log_t *_log_ = (_log); \ + \ + if (nxt_slow_path(_log_->level == NXT_LOG_DEBUG || nxt_debug)) { \ + _log_->handler(NXT_LOG_DEBUG, _log_, __VA_ARGS__); \ + } \ + } while (0) + +#define nxt_assert(c) \ + do { \ + if (nxt_slow_path(!(c))) { \ + nxt_thread_log_alert("%s:%d assertion failed: %s", __FILE__, __LINE__, \ + #c); \ + nxt_abort(); \ + } \ + } while (0) #else @@ -134,11 +119,9 @@ NXT_EXPORT void nxt_cdecl nxt_log_handler(nxt_uint_t level, nxt_log_t *log, #endif - #if (NXT_DEBUG_ALLOC) -#define nxt_debug_alloc(...) \ - nxt_thread_log_debug(__VA_ARGS__) +#define nxt_debug_alloc(...) nxt_thread_log_debug(__VA_ARGS__) #else @@ -146,23 +129,16 @@ NXT_EXPORT void nxt_cdecl nxt_log_handler(nxt_uint_t level, nxt_log_t *log, #endif +#define nxt_main_log_alert(...) nxt_log_alert(&nxt_main_log, __VA_ARGS__) -#define nxt_main_log_alert(...) \ - nxt_log_alert(&nxt_main_log, __VA_ARGS__) - - -#define nxt_main_log_error(level, ...) \ - nxt_log_error(level, &nxt_main_log, __VA_ARGS__) - - -#define nxt_main_log_debug(...) \ - nxt_log_debug(&nxt_main_log, __VA_ARGS__) - +#define nxt_main_log_error(level, ...) \ + nxt_log_error(level, &nxt_main_log, __VA_ARGS__) -NXT_EXPORT extern nxt_uint_t nxt_debug; -NXT_EXPORT extern nxt_uint_t nxt_trace; -NXT_EXPORT extern nxt_log_t nxt_main_log; -NXT_EXPORT extern nxt_str_t nxt_log_levels[]; +#define nxt_main_log_debug(...) nxt_log_debug(&nxt_main_log, __VA_ARGS__) +NXT_EXPORT extern nxt_uint_t nxt_debug; +NXT_EXPORT extern nxt_uint_t nxt_trace; +NXT_EXPORT extern nxt_log_t nxt_main_log; +NXT_EXPORT extern nxt_str_t nxt_log_levels[]; #endif /* _NXT_LOG_H_INCLUDED_ */ diff --git a/src/nxt_log_moderation.c b/src/nxt_log_moderation.c index 95f9cbfec..52690c75a 100644 --- a/src/nxt_log_moderation.c +++ b/src/nxt_log_moderation.c @@ -6,92 +6,86 @@ #include - static void nxt_log_moderate_timer_handler(nxt_task_t *task, void *obj, - void *data); - + void *data); -nxt_bool_t -nxt_log_moderate_allow(nxt_log_moderation_t *mod) -{ - nxt_uint_t n; - nxt_time_t now; - nxt_bool_t allow, timer; - nxt_thread_t *thr; +nxt_bool_t nxt_log_moderate_allow(nxt_log_moderation_t *mod) { + nxt_uint_t n; + nxt_time_t now; + nxt_bool_t allow, timer; + nxt_thread_t *thr; - thr = nxt_thread(); - now = nxt_thread_time(thr); + thr = nxt_thread(); + now = nxt_thread_time(thr); - allow = 0; - timer = 0; + allow = 0; + timer = 0; - nxt_thread_spin_lock(&mod->lock); + nxt_thread_spin_lock(&mod->lock); - n = mod->count++; + n = mod->count++; - if (now != mod->last) { + if (now != mod->last) { - if (n <= mod->limit) { - mod->last = now; - mod->count = 1; - allow = 1; - } + if (n <= mod->limit) { + mod->last = now; + mod->count = 1; + allow = 1; + } - /* "n > mod->limit" means that timer has already been set. */ + /* "n > mod->limit" means that timer has already been set. */ - } else { + } else { - if (n < mod->limit) { - allow = 1; + if (n < mod->limit) { + allow = 1; - } else if (n == mod->limit) { - /* - * There is a race condition on 32-bit many core system - * capable to fail an operation 2^32 times per second. - * This can be fixed by storing mod->count as uint64_t. - */ - timer = 1; - mod->pid = nxt_pid; - } + } else if (n == mod->limit) { + /* + * There is a race condition on 32-bit many core system + * capable to fail an operation 2^32 times per second. + * This can be fixed by storing mod->count as uint64_t. + */ + timer = 1; + mod->pid = nxt_pid; } + } - nxt_thread_spin_unlock(&mod->lock); + nxt_thread_spin_unlock(&mod->lock); - if (timer) { - mod->timer.work_queue = &thr->engine->fast_work_queue; - mod->timer.handler = nxt_log_moderate_timer_handler; - mod->timer.log = &nxt_main_log; - mod->timer.task = &nxt_main_task; + if (timer) { + mod->timer.work_queue = &thr->engine->fast_work_queue; + mod->timer.handler = nxt_log_moderate_timer_handler; + mod->timer.log = &nxt_main_log; + mod->timer.task = &nxt_main_task; - nxt_timer_add(thr->engine, &mod->timer, 1000); - } + nxt_timer_add(thr->engine, &mod->timer, 1000); + } - return allow; + return allow; } +static void nxt_log_moderate_timer_handler(nxt_task_t *task, void *obj, + void *data) { + nxt_bool_t msg; + nxt_timer_t *ev; + nxt_atomic_uint_t n; + nxt_log_moderation_t *mod; -static void -nxt_log_moderate_timer_handler(nxt_task_t *task, void *obj, void *data) -{ - nxt_bool_t msg; - nxt_timer_t *ev; - nxt_atomic_uint_t n; - nxt_log_moderation_t *mod; - - ev = obj; - mod = nxt_timer_data(ev, nxt_log_moderation_t, timer); + ev = obj; + mod = nxt_timer_data(ev, nxt_log_moderation_t, timer); - nxt_thread_spin_lock(&mod->lock); + nxt_thread_spin_lock(&mod->lock); - mod->last = nxt_thread_time(task->thread); - n = mod->count; - mod->count = 0; - msg = (mod->pid == nxt_pid); + mod->last = nxt_thread_time(task->thread); + n = mod->count; + mod->count = 0; + msg = (mod->pid == nxt_pid); - nxt_thread_spin_unlock(&mod->lock); + nxt_thread_spin_unlock(&mod->lock); - if (msg) { - nxt_log_error(mod->level, &nxt_main_log, "%s %uA times", - mod->msg, n - mod->limit); - } + if (msg) { + nxt_log_error(mod->level, &nxt_main_log, "%s %uA times", mod->msg, + n - mod->limit); + } } diff --git a/src/nxt_log_moderation.h b/src/nxt_log_moderation.h index c6033201f..37fa1c665 100644 --- a/src/nxt_log_moderation.h +++ b/src/nxt_log_moderation.h @@ -7,43 +7,37 @@ #ifndef _NXT_LOG_MODERATION_H_INCLUDED_ #define _NXT_LOG_MODERATION_H_INCLUDED_ - typedef struct { - uint32_t level; - uint32_t limit; - const char *msg; - nxt_thread_spinlock_t lock; - nxt_pid_t pid; - nxt_uint_t count; - nxt_time_t last; - nxt_timer_t timer; + uint32_t level; + uint32_t limit; + const char *msg; + nxt_thread_spinlock_t lock; + nxt_pid_t pid; + nxt_uint_t count; + nxt_time_t last; + nxt_timer_t timer; } nxt_log_moderation_t; - -#define NXT_LOG_MODERATION 0, -1, 0, 0, NXT_TIMER - - -#define nxt_log_alert_moderate(_mod, _log, ...) \ - do { \ - nxt_log_t *_log_ = _log; \ - \ - if (nxt_log_moderate_allow(_mod)) { \ - _log_->handler(NXT_LOG_ALERT, _log_, __VA_ARGS__); \ - } \ - } while (0) - - -#define nxt_log_moderate(_mod, _level, _log, ...) \ - do { \ - nxt_log_t *_log_ = _log; \ - \ - if (_log_->level >= (_level) && nxt_log_moderate_allow(_mod)) { \ - _log_->handler(_level, _log_, __VA_ARGS__); \ - } \ - } while (0) - +#define NXT_LOG_MODERATION 0, -1, 0, 0, NXT_TIMER + +#define nxt_log_alert_moderate(_mod, _log, ...) \ + do { \ + nxt_log_t *_log_ = _log; \ + \ + if (nxt_log_moderate_allow(_mod)) { \ + _log_->handler(NXT_LOG_ALERT, _log_, __VA_ARGS__); \ + } \ + } while (0) + +#define nxt_log_moderate(_mod, _level, _log, ...) \ + do { \ + nxt_log_t *_log_ = _log; \ + \ + if (_log_->level >= (_level) && nxt_log_moderate_allow(_mod)) { \ + _log_->handler(_level, _log_, __VA_ARGS__); \ + } \ + } while (0) nxt_bool_t nxt_log_moderate_allow(nxt_log_moderation_t *mod); - #endif /* _NXT_LOG_MODERATION_H_INCLUDED_ */ diff --git a/src/nxt_lvlhsh.c b/src/nxt_lvlhsh.c index 7a8b3ddae..295d0e7d0 100644 --- a/src/nxt_lvlhsh.c +++ b/src/nxt_lvlhsh.c @@ -6,7 +6,6 @@ #include - /* * The level hash consists of hierarchical levels of arrays of pointers. * The pointers may point to another level, a bucket, or NULL. @@ -43,501 +42,438 @@ * several levels. */ -#define nxt_lvlhsh_is_bucket(p) \ - ((uintptr_t) (p) & 1) - - -#define nxt_lvlhsh_count_inc(n) \ - n = (void *) ((uintptr_t) (n) + 2) - - -#define nxt_lvlhsh_count_dec(n) \ - n = (void *) ((uintptr_t) (n) - 2) - - -#define nxt_lvlhsh_level_size(proto, nlvl) \ - ((uintptr_t) 1 << proto->shift[nlvl]) - - -#define nxt_lvlhsh_level(lvl, mask) \ - (void **) ((uintptr_t) lvl & (~mask << 2)) - - -#define nxt_lvlhsh_level_entries(lvl, mask) \ - ((uintptr_t) lvl & (mask << 1)) +#define nxt_lvlhsh_is_bucket(p) ((uintptr_t)(p) & 1) +#define nxt_lvlhsh_count_inc(n) n = (void *)((uintptr_t)(n) + 2) -#define nxt_lvlhsh_store_bucket(slot, bkt) \ - slot = (void **) ((uintptr_t) bkt | 2 | 1) +#define nxt_lvlhsh_count_dec(n) n = (void *)((uintptr_t)(n) - 2) +#define nxt_lvlhsh_level_size(proto, nlvl) ((uintptr_t)1 << proto->shift[nlvl]) -#define nxt_lvlhsh_bucket_size(proto) \ - proto->bucket_size +#define nxt_lvlhsh_level(lvl, mask) (void **)((uintptr_t)lvl & (~mask << 2)) +#define nxt_lvlhsh_level_entries(lvl, mask) ((uintptr_t)lvl & (mask << 1)) -#define nxt_lvlhsh_bucket(proto, bkt) \ - (uint32_t *) ((uintptr_t) bkt & ~(uintptr_t) proto->bucket_mask) +#define nxt_lvlhsh_store_bucket(slot, bkt) \ + slot = (void **)((uintptr_t)bkt | 2 | 1) +#define nxt_lvlhsh_bucket_size(proto) proto->bucket_size -#define nxt_lvlhsh_bucket_entries(proto, bkt) \ - (((uintptr_t) bkt & (uintptr_t) proto->bucket_mask) >> 1) +#define nxt_lvlhsh_bucket(proto, bkt) \ + (uint32_t *)((uintptr_t)bkt & ~(uintptr_t)proto->bucket_mask) +#define nxt_lvlhsh_bucket_entries(proto, bkt) \ + (((uintptr_t)bkt & (uintptr_t)proto->bucket_mask) >> 1) -#define nxt_lvlhsh_bucket_end(proto, bkt) \ - &bkt[proto->bucket_end] +#define nxt_lvlhsh_bucket_end(proto, bkt) &bkt[proto->bucket_end] +#define nxt_lvlhsh_free_entry(e) (!(nxt_lvlhsh_valid_entry(e))) -#define nxt_lvlhsh_free_entry(e) \ - (!(nxt_lvlhsh_valid_entry(e))) - - -#define nxt_lvlhsh_next_bucket(proto, bkt) \ - ((void **) &bkt[proto->bucket_end]) +#define nxt_lvlhsh_next_bucket(proto, bkt) ((void **)&bkt[proto->bucket_end]) #if (NXT_64BIT) -#define nxt_lvlhsh_valid_entry(e) \ - (((e)[0] | (e)[1]) != 0) - - -#define nxt_lvlhsh_entry_value(e) \ - (void *) (((uintptr_t) (e)[1] << 32) + (e)[0]) - - -#define nxt_lvlhsh_set_entry_value(e, n) \ - (e)[0] = (uint32_t) (uintptr_t) n; \ - (e)[1] = (uint32_t) ((uintptr_t) n >> 32) +#define nxt_lvlhsh_valid_entry(e) (((e)[0] | (e)[1]) != 0) +#define nxt_lvlhsh_entry_value(e) (void *)(((uintptr_t)(e)[1] << 32) + (e)[0]) -#define nxt_lvlhsh_entry_key(e) \ - (e)[2] +#define nxt_lvlhsh_set_entry_value(e, n) \ + (e)[0] = (uint32_t)(uintptr_t)n; \ + (e)[1] = (uint32_t)((uintptr_t)n >> 32) +#define nxt_lvlhsh_entry_key(e) (e)[2] -#define nxt_lvlhsh_set_entry_key(e, n) \ - (e)[2] = n +#define nxt_lvlhsh_set_entry_key(e, n) (e)[2] = n #else -#define nxt_lvlhsh_valid_entry(e) \ - ((e)[0] != 0) +#define nxt_lvlhsh_valid_entry(e) ((e)[0] != 0) +#define nxt_lvlhsh_entry_value(e) (void *)(e)[0] -#define nxt_lvlhsh_entry_value(e) \ - (void *) (e)[0] +#define nxt_lvlhsh_set_entry_value(e, n) (e)[0] = (uint32_t)n +#define nxt_lvlhsh_entry_key(e) (e)[1] -#define nxt_lvlhsh_set_entry_value(e, n) \ - (e)[0] = (uint32_t) n - - -#define nxt_lvlhsh_entry_key(e) \ - (e)[1] - - -#define nxt_lvlhsh_set_entry_key(e, n) \ - (e)[1] = n +#define nxt_lvlhsh_set_entry_key(e, n) (e)[1] = n #endif - -#define NXT_LVLHSH_BUCKET_DONE ((void *) -1) - +#define NXT_LVLHSH_BUCKET_DONE ((void *)-1) typedef struct { - const nxt_lvlhsh_proto_t *proto; - void *pool; - uint32_t retrieve; /* 1 bit */ + const nxt_lvlhsh_proto_t *proto; + void *pool; + uint32_t retrieve; /* 1 bit */ } nxt_lvlhsh_peek_t; - static nxt_int_t nxt_lvlhsh_level_find(nxt_lvlhsh_query_t *lhq, void **lvl, - uint32_t key, nxt_uint_t nlvl); + uint32_t key, nxt_uint_t nlvl); static nxt_int_t nxt_lvlhsh_bucket_find(nxt_lvlhsh_query_t *lhq, void **bkt); static nxt_int_t nxt_lvlhsh_new_bucket(nxt_lvlhsh_query_t *lhq, void **slot); -static nxt_int_t nxt_lvlhsh_level_insert(nxt_lvlhsh_query_t *lhq, - void **slot, uint32_t key, nxt_uint_t nlvl); -static nxt_int_t nxt_lvlhsh_bucket_insert(nxt_lvlhsh_query_t *lhq, - void **slot, uint32_t key, nxt_int_t nlvl); +static nxt_int_t nxt_lvlhsh_level_insert(nxt_lvlhsh_query_t *lhq, void **slot, + uint32_t key, nxt_uint_t nlvl); +static nxt_int_t nxt_lvlhsh_bucket_insert(nxt_lvlhsh_query_t *lhq, void **slot, + uint32_t key, nxt_int_t nlvl); static nxt_int_t nxt_lvlhsh_convert_bucket_to_level(nxt_lvlhsh_query_t *lhq, - void **slot, nxt_uint_t nlvl, uint32_t *bucket); + void **slot, + nxt_uint_t nlvl, + uint32_t *bucket); static nxt_int_t nxt_lvlhsh_level_convertion_insert(nxt_lvlhsh_query_t *lhq, - void **parent, uint32_t key, nxt_uint_t nlvl); + void **parent, uint32_t key, + nxt_uint_t nlvl); static nxt_int_t nxt_lvlhsh_bucket_convertion_insert(nxt_lvlhsh_query_t *lhq, - void **slot, uint32_t key, nxt_int_t nlvl); + void **slot, uint32_t key, + nxt_int_t nlvl); static nxt_int_t nxt_lvlhsh_free_level(nxt_lvlhsh_query_t *lhq, void **level, - nxt_uint_t size); + nxt_uint_t size); static nxt_int_t nxt_lvlhsh_level_delete(nxt_lvlhsh_query_t *lhq, void **slot, - uint32_t key, nxt_uint_t nlvl); + uint32_t key, nxt_uint_t nlvl); static nxt_int_t nxt_lvlhsh_bucket_delete(nxt_lvlhsh_query_t *lhq, void **bkt); static void *nxt_lvlhsh_level_each(nxt_lvlhsh_each_t *lhe, void **level, - nxt_uint_t nlvl, nxt_uint_t shift); + nxt_uint_t nlvl, nxt_uint_t shift); static void *nxt_lvlhsh_bucket_each(nxt_lvlhsh_each_t *lhe); static void *nxt_lvlhsh_level_peek(nxt_lvlhsh_peek_t *peek, void **level, - nxt_uint_t nlvl); + nxt_uint_t nlvl); static void *nxt_lvlhsh_bucket_peek(nxt_lvlhsh_peek_t *peek, void **bkt); +nxt_int_t nxt_lvlhsh_find(nxt_lvlhsh_t *lh, nxt_lvlhsh_query_t *lhq) { + void *slot; -nxt_int_t -nxt_lvlhsh_find(nxt_lvlhsh_t *lh, nxt_lvlhsh_query_t *lhq) -{ - void *slot; - - slot = lh->slot; - - if (nxt_fast_path(slot != NULL)) { + slot = lh->slot; - if (nxt_lvlhsh_is_bucket(slot)) { - return nxt_lvlhsh_bucket_find(lhq, slot); - } + if (nxt_fast_path(slot != NULL)) { - return nxt_lvlhsh_level_find(lhq, slot, lhq->key_hash, 0); + if (nxt_lvlhsh_is_bucket(slot)) { + return nxt_lvlhsh_bucket_find(lhq, slot); } - return NXT_DECLINED; -} - + return nxt_lvlhsh_level_find(lhq, slot, lhq->key_hash, 0); + } -static nxt_int_t -nxt_lvlhsh_level_find(nxt_lvlhsh_query_t *lhq, void **lvl, uint32_t key, - nxt_uint_t nlvl) -{ - void **slot; - uintptr_t mask; - nxt_uint_t shift; + return NXT_DECLINED; +} - shift = lhq->proto->shift[nlvl]; - mask = ((uintptr_t) 1 << shift) - 1; +static nxt_int_t nxt_lvlhsh_level_find(nxt_lvlhsh_query_t *lhq, void **lvl, + uint32_t key, nxt_uint_t nlvl) { + void **slot; + uintptr_t mask; + nxt_uint_t shift; - lvl = nxt_lvlhsh_level(lvl, mask); - slot = lvl[key & mask]; + shift = lhq->proto->shift[nlvl]; + mask = ((uintptr_t)1 << shift) - 1; - if (slot != NULL) { + lvl = nxt_lvlhsh_level(lvl, mask); + slot = lvl[key & mask]; - if (nxt_lvlhsh_is_bucket(slot)) { - return nxt_lvlhsh_bucket_find(lhq, slot); - } + if (slot != NULL) { - return nxt_lvlhsh_level_find(lhq, slot, key >> shift, nlvl + 1); + if (nxt_lvlhsh_is_bucket(slot)) { + return nxt_lvlhsh_bucket_find(lhq, slot); } - return NXT_DECLINED; + return nxt_lvlhsh_level_find(lhq, slot, key >> shift, nlvl + 1); + } + + return NXT_DECLINED; } +static nxt_int_t nxt_lvlhsh_bucket_find(nxt_lvlhsh_query_t *lhq, void **bkt) { + void *value; + uint32_t *bucket, *e; + nxt_uint_t n; -static nxt_int_t -nxt_lvlhsh_bucket_find(nxt_lvlhsh_query_t *lhq, void **bkt) -{ - void *value; - uint32_t *bucket, *e; - nxt_uint_t n; + do { + bucket = nxt_lvlhsh_bucket(lhq->proto, bkt); + n = nxt_lvlhsh_bucket_entries(lhq->proto, bkt); + e = bucket; do { - bucket = nxt_lvlhsh_bucket(lhq->proto, bkt); - n = nxt_lvlhsh_bucket_entries(lhq->proto, bkt); - e = bucket; - - do { - if (nxt_lvlhsh_valid_entry(e)) { - n--; + if (nxt_lvlhsh_valid_entry(e)) { + n--; - if (nxt_lvlhsh_entry_key(e) == lhq->key_hash) { + if (nxt_lvlhsh_entry_key(e) == lhq->key_hash) { - value = nxt_lvlhsh_entry_value(e); + value = nxt_lvlhsh_entry_value(e); - if (lhq->proto->test(lhq, value) == NXT_OK) { - lhq->value = value; + if (lhq->proto->test(lhq, value) == NXT_OK) { + lhq->value = value; - return NXT_OK; - } - } - } + return NXT_OK; + } + } + } - e += NXT_LVLHSH_ENTRY_SIZE; + e += NXT_LVLHSH_ENTRY_SIZE; - } while (n != 0); + } while (n != 0); - bkt = *nxt_lvlhsh_next_bucket(lhq->proto, bucket); + bkt = *nxt_lvlhsh_next_bucket(lhq->proto, bucket); - } while (bkt != NULL); + } while (bkt != NULL); - return NXT_DECLINED; + return NXT_DECLINED; } +nxt_int_t nxt_lvlhsh_insert(nxt_lvlhsh_t *lh, nxt_lvlhsh_query_t *lhq) { + uint32_t key; -nxt_int_t -nxt_lvlhsh_insert(nxt_lvlhsh_t *lh, nxt_lvlhsh_query_t *lhq) -{ - uint32_t key; - - if (nxt_fast_path(lh->slot != NULL)) { + if (nxt_fast_path(lh->slot != NULL)) { - key = lhq->key_hash; + key = lhq->key_hash; - if (nxt_lvlhsh_is_bucket(lh->slot)) { - return nxt_lvlhsh_bucket_insert(lhq, &lh->slot, key, -1); - } - - return nxt_lvlhsh_level_insert(lhq, &lh->slot, key, 0); + if (nxt_lvlhsh_is_bucket(lh->slot)) { + return nxt_lvlhsh_bucket_insert(lhq, &lh->slot, key, -1); } - return nxt_lvlhsh_new_bucket(lhq, &lh->slot); -} + return nxt_lvlhsh_level_insert(lhq, &lh->slot, key, 0); + } + return nxt_lvlhsh_new_bucket(lhq, &lh->slot); +} -static nxt_int_t -nxt_lvlhsh_new_bucket(nxt_lvlhsh_query_t *lhq, void **slot) -{ - uint32_t *bucket; +static nxt_int_t nxt_lvlhsh_new_bucket(nxt_lvlhsh_query_t *lhq, void **slot) { + uint32_t *bucket; - bucket = lhq->proto->alloc(lhq->pool, nxt_lvlhsh_bucket_size(lhq->proto)); + bucket = lhq->proto->alloc(lhq->pool, nxt_lvlhsh_bucket_size(lhq->proto)); - if (nxt_fast_path(bucket != NULL)) { + if (nxt_fast_path(bucket != NULL)) { - nxt_lvlhsh_set_entry_value(bucket, lhq->value); - nxt_lvlhsh_set_entry_key(bucket, lhq->key_hash); + nxt_lvlhsh_set_entry_value(bucket, lhq->value); + nxt_lvlhsh_set_entry_key(bucket, lhq->key_hash); - *nxt_lvlhsh_next_bucket(lhq->proto, bucket) = NULL; + *nxt_lvlhsh_next_bucket(lhq->proto, bucket) = NULL; - nxt_lvlhsh_store_bucket(*slot, bucket); + nxt_lvlhsh_store_bucket(*slot, bucket); - return NXT_OK; - } + return NXT_OK; + } - return NXT_ERROR; + return NXT_ERROR; } +static nxt_int_t nxt_lvlhsh_level_insert(nxt_lvlhsh_query_t *lhq, void **parent, + uint32_t key, nxt_uint_t nlvl) { + void **slot, **lvl; + nxt_int_t ret; + uintptr_t mask; + nxt_uint_t shift; -static nxt_int_t -nxt_lvlhsh_level_insert(nxt_lvlhsh_query_t *lhq, void **parent, uint32_t key, - nxt_uint_t nlvl) -{ - void **slot, **lvl; - nxt_int_t ret; - uintptr_t mask; - nxt_uint_t shift; - - shift = lhq->proto->shift[nlvl]; - mask = ((uintptr_t) 1 << shift) - 1; + shift = lhq->proto->shift[nlvl]; + mask = ((uintptr_t)1 << shift) - 1; - lvl = nxt_lvlhsh_level(*parent, mask); - slot = &lvl[key & mask]; + lvl = nxt_lvlhsh_level(*parent, mask); + slot = &lvl[key & mask]; - if (*slot != NULL) { - key >>= shift; + if (*slot != NULL) { + key >>= shift; - if (nxt_lvlhsh_is_bucket(*slot)) { - return nxt_lvlhsh_bucket_insert(lhq, slot, key, nlvl); - } - - return nxt_lvlhsh_level_insert(lhq, slot, key, nlvl + 1); + if (nxt_lvlhsh_is_bucket(*slot)) { + return nxt_lvlhsh_bucket_insert(lhq, slot, key, nlvl); } - ret = nxt_lvlhsh_new_bucket(lhq, slot); + return nxt_lvlhsh_level_insert(lhq, slot, key, nlvl + 1); + } - if (nxt_fast_path(ret == NXT_OK)) { - nxt_lvlhsh_count_inc(*parent); - } + ret = nxt_lvlhsh_new_bucket(lhq, slot); - return ret; + if (nxt_fast_path(ret == NXT_OK)) { + nxt_lvlhsh_count_inc(*parent); + } + + return ret; } +static nxt_int_t nxt_lvlhsh_bucket_insert(nxt_lvlhsh_query_t *lhq, void **slot, + uint32_t key, nxt_int_t nlvl) { + void **bkt, **vacant_bucket, *value; + uint32_t *bucket, *e, *vacant_entry; + nxt_int_t ret; + uintptr_t n; + const void *new_value; + const nxt_lvlhsh_proto_t *proto; -static nxt_int_t -nxt_lvlhsh_bucket_insert(nxt_lvlhsh_query_t *lhq, void **slot, uint32_t key, - nxt_int_t nlvl) -{ - void **bkt, **vacant_bucket, *value; - uint32_t *bucket, *e, *vacant_entry; - nxt_int_t ret; - uintptr_t n; - const void *new_value; - const nxt_lvlhsh_proto_t *proto; + bkt = slot; + vacant_entry = NULL; + vacant_bucket = NULL; + proto = lhq->proto; - bkt = slot; - vacant_entry = NULL; - vacant_bucket = NULL; - proto = lhq->proto; + /* Search for duplicate entry in bucket chain. */ - /* Search for duplicate entry in bucket chain. */ + do { + bucket = nxt_lvlhsh_bucket(proto, *bkt); + n = nxt_lvlhsh_bucket_entries(proto, *bkt); + e = bucket; do { - bucket = nxt_lvlhsh_bucket(proto, *bkt); - n = nxt_lvlhsh_bucket_entries(proto, *bkt); - e = bucket; - - do { - if (nxt_lvlhsh_valid_entry(e)) { - - if (nxt_lvlhsh_entry_key(e) == lhq->key_hash) { - - value = nxt_lvlhsh_entry_value(e); - - if (proto->test(lhq, value) == NXT_OK) { + if (nxt_lvlhsh_valid_entry(e)) { - new_value = lhq->value; - lhq->value = value; + if (nxt_lvlhsh_entry_key(e) == lhq->key_hash) { - if (lhq->replace) { - nxt_lvlhsh_set_entry_value(e, new_value); + value = nxt_lvlhsh_entry_value(e); - return NXT_OK; - } + if (proto->test(lhq, value) == NXT_OK) { - return NXT_DECLINED; - } - } + new_value = lhq->value; + lhq->value = value; - n--; + if (lhq->replace) { + nxt_lvlhsh_set_entry_value(e, new_value); - } else { - /* - * Save a hole vacant position in bucket - * and continue to search for duplicate entry. - */ - if (vacant_entry == NULL) { - vacant_entry = e; - vacant_bucket = bkt; - } + return NXT_OK; } - e += NXT_LVLHSH_ENTRY_SIZE; + return NXT_DECLINED; + } + } - } while (n != 0); + n--; - if (e < nxt_lvlhsh_bucket_end(proto, bucket)) { - /* - * Save a vacant position on incomplete bucket's end - * and continue to search for duplicate entry. - */ - if (vacant_entry == NULL) { - vacant_entry = e; - vacant_bucket = bkt; - } + } else { + /* + * Save a hole vacant position in bucket + * and continue to search for duplicate entry. + */ + if (vacant_entry == NULL) { + vacant_entry = e; + vacant_bucket = bkt; } + } - bkt = nxt_lvlhsh_next_bucket(proto, bucket); + e += NXT_LVLHSH_ENTRY_SIZE; - } while (*bkt != NULL); - - if (vacant_entry != NULL) { - nxt_lvlhsh_set_entry_value(vacant_entry, lhq->value); - nxt_lvlhsh_set_entry_key(vacant_entry, lhq->key_hash); - nxt_lvlhsh_count_inc(*vacant_bucket); + } while (n != 0); - return NXT_OK; + if (e < nxt_lvlhsh_bucket_end(proto, bucket)) { + /* + * Save a vacant position on incomplete bucket's end + * and continue to search for duplicate entry. + */ + if (vacant_entry == NULL) { + vacant_entry = e; + vacant_bucket = bkt; + } } - /* All buckets are full. */ + bkt = nxt_lvlhsh_next_bucket(proto, bucket); - nlvl++; + } while (*bkt != NULL); - if (nxt_fast_path(proto->shift[nlvl] != 0)) { + if (vacant_entry != NULL) { + nxt_lvlhsh_set_entry_value(vacant_entry, lhq->value); + nxt_lvlhsh_set_entry_key(vacant_entry, lhq->key_hash); + nxt_lvlhsh_count_inc(*vacant_bucket); - ret = nxt_lvlhsh_convert_bucket_to_level(lhq, slot, nlvl, bucket); + return NXT_OK; + } - if (nxt_fast_path(ret == NXT_OK)) { - return nxt_lvlhsh_level_insert(lhq, slot, key, nlvl); - } + /* All buckets are full. */ - return ret; - } + nlvl++; - /* The last allowed level, only buckets may be allocated here. */ + if (nxt_fast_path(proto->shift[nlvl] != 0)) { - return nxt_lvlhsh_new_bucket(lhq, bkt); -} + ret = nxt_lvlhsh_convert_bucket_to_level(lhq, slot, nlvl, bucket); + if (nxt_fast_path(ret == NXT_OK)) { + return nxt_lvlhsh_level_insert(lhq, slot, key, nlvl); + } -static nxt_int_t -nxt_lvlhsh_convert_bucket_to_level(nxt_lvlhsh_query_t *lhq, void **slot, - nxt_uint_t nlvl, uint32_t *bucket) -{ - void *lvl, **level; - uint32_t *e, *end, key; - nxt_int_t ret; - nxt_uint_t i, shift, size; - nxt_lvlhsh_query_t q; - const nxt_lvlhsh_proto_t *proto; + return ret; + } - proto = lhq->proto; - size = nxt_lvlhsh_level_size(proto, nlvl); + /* The last allowed level, only buckets may be allocated here. */ - lvl = proto->alloc(lhq->pool, size * (sizeof(void *))); + return nxt_lvlhsh_new_bucket(lhq, bkt); +} - if (nxt_slow_path(lvl == NULL)) { - return NXT_ERROR; - } +static nxt_int_t nxt_lvlhsh_convert_bucket_to_level(nxt_lvlhsh_query_t *lhq, + void **slot, + nxt_uint_t nlvl, + uint32_t *bucket) { + void *lvl, **level; + uint32_t *e, *end, key; + nxt_int_t ret; + nxt_uint_t i, shift, size; + nxt_lvlhsh_query_t q; + const nxt_lvlhsh_proto_t *proto; + + proto = lhq->proto; + size = nxt_lvlhsh_level_size(proto, nlvl); + + lvl = proto->alloc(lhq->pool, size * (sizeof(void *))); + + if (nxt_slow_path(lvl == NULL)) { + return NXT_ERROR; + } - nxt_memzero(lvl, size * (sizeof(void *))); + nxt_memzero(lvl, size * (sizeof(void *))); - level = lvl; - shift = 0; + level = lvl; + shift = 0; - for (i = 0; i < nlvl; i++) { - /* - * Using SIMD operations in this trivial loop with maximum - * 8 iterations may increase code size by 170 bytes. - */ - nxt_pragma_loop_disable_vectorization; + for (i = 0; i < nlvl; i++) { + /* + * Using SIMD operations in this trivial loop with maximum + * 8 iterations may increase code size by 170 bytes. + */ + nxt_pragma_loop_disable_vectorization; - shift += proto->shift[i]; - } + shift += proto->shift[i]; + } - end = nxt_lvlhsh_bucket_end(proto, bucket); + end = nxt_lvlhsh_bucket_end(proto, bucket); - for (e = bucket; e < end; e += NXT_LVLHSH_ENTRY_SIZE) { + for (e = bucket; e < end; e += NXT_LVLHSH_ENTRY_SIZE) { - q.proto = proto; - q.pool = lhq->pool; - q.value = nxt_lvlhsh_entry_value(e); - key = nxt_lvlhsh_entry_key(e); - q.key_hash = key; + q.proto = proto; + q.pool = lhq->pool; + q.value = nxt_lvlhsh_entry_value(e); + key = nxt_lvlhsh_entry_key(e); + q.key_hash = key; - ret = nxt_lvlhsh_level_convertion_insert(&q, &lvl, key >> shift, nlvl); + ret = nxt_lvlhsh_level_convertion_insert(&q, &lvl, key >> shift, nlvl); - if (nxt_slow_path(ret != NXT_OK)) { - return nxt_lvlhsh_free_level(lhq, level, size); - } + if (nxt_slow_path(ret != NXT_OK)) { + return nxt_lvlhsh_free_level(lhq, level, size); } + } - *slot = lvl; + *slot = lvl; - proto->free(lhq->pool, bucket); + proto->free(lhq->pool, bucket); - return NXT_OK; + return NXT_OK; } +static nxt_int_t nxt_lvlhsh_level_convertion_insert(nxt_lvlhsh_query_t *lhq, + void **parent, uint32_t key, + nxt_uint_t nlvl) { + void **slot, **lvl; + nxt_int_t ret; + uintptr_t mask; + nxt_uint_t shift; -static nxt_int_t -nxt_lvlhsh_level_convertion_insert(nxt_lvlhsh_query_t *lhq, void **parent, - uint32_t key, nxt_uint_t nlvl) -{ - void **slot, **lvl; - nxt_int_t ret; - uintptr_t mask; - nxt_uint_t shift; - - shift = lhq->proto->shift[nlvl]; - mask = ((uintptr_t) 1 << shift) - 1; - - lvl = nxt_lvlhsh_level(*parent, mask); - slot = &lvl[key & mask]; + shift = lhq->proto->shift[nlvl]; + mask = ((uintptr_t)1 << shift) - 1; - if (*slot == NULL) { - ret = nxt_lvlhsh_new_bucket(lhq, slot); + lvl = nxt_lvlhsh_level(*parent, mask); + slot = &lvl[key & mask]; - if (nxt_fast_path(ret == NXT_OK)) { - nxt_lvlhsh_count_inc(*parent); - } + if (*slot == NULL) { + ret = nxt_lvlhsh_new_bucket(lhq, slot); - return ret; + if (nxt_fast_path(ret == NXT_OK)) { + nxt_lvlhsh_count_inc(*parent); } - /* Only backets can be here. */ + return ret; + } - return nxt_lvlhsh_bucket_convertion_insert(lhq, slot, key >> shift, nlvl); -} + /* Only backets can be here. */ + return nxt_lvlhsh_bucket_convertion_insert(lhq, slot, key >> shift, nlvl); +} /* * The special bucket insertion procedure is required because during @@ -546,449 +482,415 @@ nxt_lvlhsh_level_convertion_insert(nxt_lvlhsh_query_t *lhq, void **parent, * a new entry is inserted just after occupied entries. */ -static nxt_int_t -nxt_lvlhsh_bucket_convertion_insert(nxt_lvlhsh_query_t *lhq, void **slot, - uint32_t key, nxt_int_t nlvl) -{ - void **bkt; - uint32_t *bucket, *e; - nxt_int_t ret; - uintptr_t n; - const nxt_lvlhsh_proto_t *proto; +static nxt_int_t nxt_lvlhsh_bucket_convertion_insert(nxt_lvlhsh_query_t *lhq, + void **slot, uint32_t key, + nxt_int_t nlvl) { + void **bkt; + uint32_t *bucket, *e; + nxt_int_t ret; + uintptr_t n; + const nxt_lvlhsh_proto_t *proto; - bkt = slot; - proto = lhq->proto; + bkt = slot; + proto = lhq->proto; - do { - bucket = nxt_lvlhsh_bucket(proto, *bkt); - n = nxt_lvlhsh_bucket_entries(proto, *bkt); - e = bucket + n * NXT_LVLHSH_ENTRY_SIZE; + do { + bucket = nxt_lvlhsh_bucket(proto, *bkt); + n = nxt_lvlhsh_bucket_entries(proto, *bkt); + e = bucket + n * NXT_LVLHSH_ENTRY_SIZE; - if (nxt_fast_path(e < nxt_lvlhsh_bucket_end(proto, bucket))) { + if (nxt_fast_path(e < nxt_lvlhsh_bucket_end(proto, bucket))) { - nxt_lvlhsh_set_entry_value(e, lhq->value); - nxt_lvlhsh_set_entry_key(e, lhq->key_hash); - nxt_lvlhsh_count_inc(*bkt); - - return NXT_OK; - } + nxt_lvlhsh_set_entry_value(e, lhq->value); + nxt_lvlhsh_set_entry_key(e, lhq->key_hash); + nxt_lvlhsh_count_inc(*bkt); - bkt = nxt_lvlhsh_next_bucket(proto, bucket); + return NXT_OK; + } - } while (*bkt != NULL); + bkt = nxt_lvlhsh_next_bucket(proto, bucket); - /* All buckets are full. */ + } while (*bkt != NULL); - nlvl++; + /* All buckets are full. */ - if (nxt_fast_path(proto->shift[nlvl] != 0)) { + nlvl++; - ret = nxt_lvlhsh_convert_bucket_to_level(lhq, slot, nlvl, bucket); + if (nxt_fast_path(proto->shift[nlvl] != 0)) { - if (nxt_fast_path(ret == NXT_OK)) { - return nxt_lvlhsh_level_insert(lhq, slot, key, nlvl); - } + ret = nxt_lvlhsh_convert_bucket_to_level(lhq, slot, nlvl, bucket); - return ret; + if (nxt_fast_path(ret == NXT_OK)) { + return nxt_lvlhsh_level_insert(lhq, slot, key, nlvl); } - /* The last allowed level, only buckets may be allocated here. */ + return ret; + } - return nxt_lvlhsh_new_bucket(lhq, bkt); -} + /* The last allowed level, only buckets may be allocated here. */ + return nxt_lvlhsh_new_bucket(lhq, bkt); +} -static nxt_int_t -nxt_lvlhsh_free_level(nxt_lvlhsh_query_t *lhq, void **level, nxt_uint_t size) -{ - nxt_uint_t i; - const nxt_lvlhsh_proto_t *proto; +static nxt_int_t nxt_lvlhsh_free_level(nxt_lvlhsh_query_t *lhq, void **level, + nxt_uint_t size) { + nxt_uint_t i; + const nxt_lvlhsh_proto_t *proto; - proto = lhq->proto; + proto = lhq->proto; - for (i = 0; i < size; i++) { + for (i = 0; i < size; i++) { - if (level[i] != NULL) { - /* - * Chained buckets are not possible here, since even - * in the worst case one bucket cannot be converted - * in two chained buckets but remains the same bucket. - */ - proto->free(lhq->pool, nxt_lvlhsh_bucket(proto, level[i])); - } + if (level[i] != NULL) { + /* + * Chained buckets are not possible here, since even + * in the worst case one bucket cannot be converted + * in two chained buckets but remains the same bucket. + */ + proto->free(lhq->pool, nxt_lvlhsh_bucket(proto, level[i])); } + } - proto->free(lhq->pool, level); + proto->free(lhq->pool, level); - return NXT_ERROR; + return NXT_ERROR; } +nxt_int_t nxt_lvlhsh_delete(nxt_lvlhsh_t *lh, nxt_lvlhsh_query_t *lhq) { + if (nxt_fast_path(lh->slot != NULL)) { -nxt_int_t -nxt_lvlhsh_delete(nxt_lvlhsh_t *lh, nxt_lvlhsh_query_t *lhq) -{ - if (nxt_fast_path(lh->slot != NULL)) { - - if (nxt_lvlhsh_is_bucket(lh->slot)) { - return nxt_lvlhsh_bucket_delete(lhq, &lh->slot); - } - - return nxt_lvlhsh_level_delete(lhq, &lh->slot, lhq->key_hash, 0); + if (nxt_lvlhsh_is_bucket(lh->slot)) { + return nxt_lvlhsh_bucket_delete(lhq, &lh->slot); } - return NXT_DECLINED; -} + return nxt_lvlhsh_level_delete(lhq, &lh->slot, lhq->key_hash, 0); + } + return NXT_DECLINED; +} -static nxt_int_t -nxt_lvlhsh_level_delete(nxt_lvlhsh_query_t *lhq, void **parent, uint32_t key, - nxt_uint_t nlvl) -{ - void **slot, **lvl; - uintptr_t mask; - nxt_int_t ret; - nxt_uint_t shift; +static nxt_int_t nxt_lvlhsh_level_delete(nxt_lvlhsh_query_t *lhq, void **parent, + uint32_t key, nxt_uint_t nlvl) { + void **slot, **lvl; + uintptr_t mask; + nxt_int_t ret; + nxt_uint_t shift; - shift = lhq->proto->shift[nlvl]; - mask = ((uintptr_t) 1 << shift) - 1; + shift = lhq->proto->shift[nlvl]; + mask = ((uintptr_t)1 << shift) - 1; - lvl = nxt_lvlhsh_level(*parent, mask); - slot = &lvl[key & mask]; + lvl = nxt_lvlhsh_level(*parent, mask); + slot = &lvl[key & mask]; - if (*slot != NULL) { + if (*slot != NULL) { - if (nxt_lvlhsh_is_bucket(*slot)) { - ret = nxt_lvlhsh_bucket_delete(lhq, slot); + if (nxt_lvlhsh_is_bucket(*slot)) { + ret = nxt_lvlhsh_bucket_delete(lhq, slot); - } else { - key >>= shift; - ret = nxt_lvlhsh_level_delete(lhq, slot, key, nlvl + 1); - } - - if (*slot == NULL) { - nxt_lvlhsh_count_dec(*parent); + } else { + key >>= shift; + ret = nxt_lvlhsh_level_delete(lhq, slot, key, nlvl + 1); + } - if (nxt_lvlhsh_level_entries(*parent, mask) == 0) { - *parent = NULL; - lhq->proto->free(lhq->pool, lvl); - } - } + if (*slot == NULL) { + nxt_lvlhsh_count_dec(*parent); - return ret; + if (nxt_lvlhsh_level_entries(*parent, mask) == 0) { + *parent = NULL; + lhq->proto->free(lhq->pool, lvl); + } } - return NXT_DECLINED; + return ret; + } + + return NXT_DECLINED; } +static nxt_int_t nxt_lvlhsh_bucket_delete(nxt_lvlhsh_query_t *lhq, void **bkt) { + void *value; + uint32_t *bucket, *e; + uintptr_t n; + const nxt_lvlhsh_proto_t *proto; -static nxt_int_t -nxt_lvlhsh_bucket_delete(nxt_lvlhsh_query_t *lhq, void **bkt) -{ - void *value; - uint32_t *bucket, *e; - uintptr_t n; - const nxt_lvlhsh_proto_t *proto; + proto = lhq->proto; - proto = lhq->proto; + do { + bucket = nxt_lvlhsh_bucket(proto, *bkt); + n = nxt_lvlhsh_bucket_entries(proto, *bkt); + e = bucket; do { - bucket = nxt_lvlhsh_bucket(proto, *bkt); - n = nxt_lvlhsh_bucket_entries(proto, *bkt); - e = bucket; + if (nxt_lvlhsh_valid_entry(e)) { - do { - if (nxt_lvlhsh_valid_entry(e)) { + if (nxt_lvlhsh_entry_key(e) == lhq->key_hash) { - if (nxt_lvlhsh_entry_key(e) == lhq->key_hash) { + value = nxt_lvlhsh_entry_value(e); - value = nxt_lvlhsh_entry_value(e); + if (proto->test(lhq, value) == NXT_OK) { - if (proto->test(lhq, value) == NXT_OK) { + if (nxt_lvlhsh_bucket_entries(proto, *bkt) == 1) { + *bkt = *nxt_lvlhsh_next_bucket(proto, bucket); + proto->free(lhq->pool, bucket); - if (nxt_lvlhsh_bucket_entries(proto, *bkt) == 1) { - *bkt = *nxt_lvlhsh_next_bucket(proto, bucket); - proto->free(lhq->pool, bucket); - - } else { - nxt_lvlhsh_count_dec(*bkt); - nxt_lvlhsh_set_entry_value(e, NULL); - } + } else { + nxt_lvlhsh_count_dec(*bkt); + nxt_lvlhsh_set_entry_value(e, NULL); + } - lhq->value = value; + lhq->value = value; - return NXT_OK; - } - } + return NXT_OK; + } + } - n--; - } + n--; + } - e += NXT_LVLHSH_ENTRY_SIZE; + e += NXT_LVLHSH_ENTRY_SIZE; - } while (n != 0); + } while (n != 0); - bkt = nxt_lvlhsh_next_bucket(proto, bucket); + bkt = nxt_lvlhsh_next_bucket(proto, bucket); - } while (*bkt != NULL); + } while (*bkt != NULL); - return NXT_DECLINED; + return NXT_DECLINED; } +void *nxt_lvlhsh_each(nxt_lvlhsh_t *lh, nxt_lvlhsh_each_t *lhe) { + void **slot; -void * -nxt_lvlhsh_each(nxt_lvlhsh_t *lh, nxt_lvlhsh_each_t *lhe) -{ - void **slot; - - if (lhe->bucket == NXT_LVLHSH_BUCKET_DONE) { - slot = lh->slot; + if (lhe->bucket == NXT_LVLHSH_BUCKET_DONE) { + slot = lh->slot; - if (nxt_lvlhsh_is_bucket(slot)) { - return NULL; - } + if (nxt_lvlhsh_is_bucket(slot)) { + return NULL; + } - } else { - if (nxt_slow_path(lhe->bucket == NULL)) { + } else { + if (nxt_slow_path(lhe->bucket == NULL)) { - /* The first iteration only. */ + /* The first iteration only. */ - slot = lh->slot; + slot = lh->slot; - if (slot == NULL) { - return NULL; - } + if (slot == NULL) { + return NULL; + } - if (!nxt_lvlhsh_is_bucket(slot)) { - lhe->current = 0; - goto level; - } + if (!nxt_lvlhsh_is_bucket(slot)) { + lhe->current = 0; + goto level; + } - lhe->bucket = nxt_lvlhsh_bucket(lhe->proto, slot); - lhe->entries = nxt_lvlhsh_bucket_entries(lhe->proto, slot); - lhe->entry = 0; - } - - return nxt_lvlhsh_bucket_each(lhe); + lhe->bucket = nxt_lvlhsh_bucket(lhe->proto, slot); + lhe->entries = nxt_lvlhsh_bucket_entries(lhe->proto, slot); + lhe->entry = 0; } + return nxt_lvlhsh_bucket_each(lhe); + } + level: - return nxt_lvlhsh_level_each(lhe, slot, 0, 0); + return nxt_lvlhsh_level_each(lhe, slot, 0, 0); } +static void *nxt_lvlhsh_level_each(nxt_lvlhsh_each_t *lhe, void **level, + nxt_uint_t nlvl, nxt_uint_t shift) { + void **slot, *value; + uintptr_t mask; + nxt_uint_t n, level_shift; -static void * -nxt_lvlhsh_level_each(nxt_lvlhsh_each_t *lhe, void **level, nxt_uint_t nlvl, - nxt_uint_t shift) -{ - void **slot, *value; - uintptr_t mask; - nxt_uint_t n, level_shift; - - level_shift = lhe->proto->shift[nlvl]; - mask = ((uintptr_t) 1 << level_shift) - 1; + level_shift = lhe->proto->shift[nlvl]; + mask = ((uintptr_t)1 << level_shift) - 1; - level = nxt_lvlhsh_level(level, mask); + level = nxt_lvlhsh_level(level, mask); - do { - n = (lhe->current >> shift) & mask; - slot = level[n]; + do { + n = (lhe->current >> shift) & mask; + slot = level[n]; - if (slot != NULL) { - if (nxt_lvlhsh_is_bucket(slot)) { + if (slot != NULL) { + if (nxt_lvlhsh_is_bucket(slot)) { - if (lhe->bucket != NXT_LVLHSH_BUCKET_DONE) { + if (lhe->bucket != NXT_LVLHSH_BUCKET_DONE) { - lhe->bucket = nxt_lvlhsh_bucket(lhe->proto, slot); - lhe->entries = nxt_lvlhsh_bucket_entries(lhe->proto, slot); - lhe->entry = 0; + lhe->bucket = nxt_lvlhsh_bucket(lhe->proto, slot); + lhe->entries = nxt_lvlhsh_bucket_entries(lhe->proto, slot); + lhe->entry = 0; - return nxt_lvlhsh_bucket_each(lhe); - } + return nxt_lvlhsh_bucket_each(lhe); + } - lhe->bucket = NULL; + lhe->bucket = NULL; - } else { - value = nxt_lvlhsh_level_each(lhe, slot, nlvl + 1, - shift + level_shift); - if (value != NULL) { - return value; - } - } + } else { + value = nxt_lvlhsh_level_each(lhe, slot, nlvl + 1, shift + level_shift); + if (value != NULL) { + return value; } + } + } - lhe->current &= ~(mask << shift); - n = ((n + 1) & mask) << shift; - lhe->current |= n; + lhe->current &= ~(mask << shift); + n = ((n + 1) & mask) << shift; + lhe->current |= n; - } while (n != 0); + } while (n != 0); - return NULL; + return NULL; } +static nxt_noinline void *nxt_lvlhsh_bucket_each(nxt_lvlhsh_each_t *lhe) { + void *value, **next; + uint32_t *bucket; -static nxt_noinline void * -nxt_lvlhsh_bucket_each(nxt_lvlhsh_each_t *lhe) -{ - void *value, **next; - uint32_t *bucket; + /* At least one valid entry must present here. */ + do { + bucket = &lhe->bucket[lhe->entry]; + lhe->entry += NXT_LVLHSH_ENTRY_SIZE; - /* At least one valid entry must present here. */ - do { - bucket = &lhe->bucket[lhe->entry]; - lhe->entry += NXT_LVLHSH_ENTRY_SIZE; + } while (nxt_lvlhsh_free_entry(bucket)); - } while (nxt_lvlhsh_free_entry(bucket)); + value = nxt_lvlhsh_entry_value(bucket); - value = nxt_lvlhsh_entry_value(bucket); + lhe->entries--; - lhe->entries--; + if (lhe->entries == 0) { + next = *nxt_lvlhsh_next_bucket(lhe->proto, lhe->bucket); - if (lhe->entries == 0) { - next = *nxt_lvlhsh_next_bucket(lhe->proto, lhe->bucket); + lhe->bucket = (next == NULL) ? NXT_LVLHSH_BUCKET_DONE + : nxt_lvlhsh_bucket(lhe->proto, next); - lhe->bucket = (next == NULL) ? NXT_LVLHSH_BUCKET_DONE - : nxt_lvlhsh_bucket(lhe->proto, next); + lhe->entries = nxt_lvlhsh_bucket_entries(lhe->proto, next); + lhe->entry = 0; + } - lhe->entries = nxt_lvlhsh_bucket_entries(lhe->proto, next); - lhe->entry = 0; - } - - return value; + return value; } +void *nxt_lvlhsh_peek(nxt_lvlhsh_t *lh, const nxt_lvlhsh_proto_t *proto) { + void **slot; + nxt_lvlhsh_peek_t peek; -void * -nxt_lvlhsh_peek(nxt_lvlhsh_t *lh, const nxt_lvlhsh_proto_t *proto) -{ - void **slot; - nxt_lvlhsh_peek_t peek; + slot = lh->slot; - slot = lh->slot; + if (slot != NULL) { - if (slot != NULL) { - - peek.proto = proto; - peek.retrieve = 0; - - if (nxt_lvlhsh_is_bucket(slot)) { - return nxt_lvlhsh_bucket_peek(&peek, &lh->slot); - } + peek.proto = proto; + peek.retrieve = 0; - return nxt_lvlhsh_level_peek(&peek, &lh->slot, 0); + if (nxt_lvlhsh_is_bucket(slot)) { + return nxt_lvlhsh_bucket_peek(&peek, &lh->slot); } - return NULL; -} + return nxt_lvlhsh_level_peek(&peek, &lh->slot, 0); + } + return NULL; +} -static void * -nxt_lvlhsh_level_peek(nxt_lvlhsh_peek_t *peek, void **parent, nxt_uint_t nlvl) -{ - void **slot, **level, *value; - uintptr_t mask; - nxt_uint_t n, shift; +static void *nxt_lvlhsh_level_peek(nxt_lvlhsh_peek_t *peek, void **parent, + nxt_uint_t nlvl) { + void **slot, **level, *value; + uintptr_t mask; + nxt_uint_t n, shift; - shift = peek->proto->shift[nlvl]; - mask = ((uintptr_t) 1 << shift) - 1; + shift = peek->proto->shift[nlvl]; + mask = ((uintptr_t)1 << shift) - 1; - level = nxt_lvlhsh_level(*parent, mask); + level = nxt_lvlhsh_level(*parent, mask); - n = 0; + n = 0; - /* At least one valid level slot must present here. */ + /* At least one valid level slot must present here. */ - for ( ;; ) { - slot = &level[n]; + for (;;) { + slot = &level[n]; - if (*slot != NULL) { + if (*slot != NULL) { - if (nxt_lvlhsh_is_bucket(*slot)) { - value = nxt_lvlhsh_bucket_peek(peek, slot); + if (nxt_lvlhsh_is_bucket(*slot)) { + value = nxt_lvlhsh_bucket_peek(peek, slot); - } else { - value = nxt_lvlhsh_level_peek(peek, slot, nlvl + 1); - } + } else { + value = nxt_lvlhsh_level_peek(peek, slot, nlvl + 1); + } - /* - * Checking peek->retrieve is not required here because - * there can not be empty slots during peeking. - */ - if (*slot == NULL) { - nxt_lvlhsh_count_dec(*parent); - - if (nxt_lvlhsh_level_entries(*parent, mask) == 0) { - *parent = NULL; - peek->proto->free(peek->pool, level); - } - } + /* + * Checking peek->retrieve is not required here because + * there can not be empty slots during peeking. + */ + if (*slot == NULL) { + nxt_lvlhsh_count_dec(*parent); - return value; + if (nxt_lvlhsh_level_entries(*parent, mask) == 0) { + *parent = NULL; + peek->proto->free(peek->pool, level); } + } - n++; + return value; } -} + n++; + } +} -static nxt_noinline void * -nxt_lvlhsh_bucket_peek(nxt_lvlhsh_peek_t *peek, void **bkt) -{ - void *value; - uint32_t *bucket, *entry; - const nxt_lvlhsh_proto_t *proto; +static nxt_noinline void *nxt_lvlhsh_bucket_peek(nxt_lvlhsh_peek_t *peek, + void **bkt) { + void *value; + uint32_t *bucket, *entry; + const nxt_lvlhsh_proto_t *proto; - bucket = nxt_lvlhsh_bucket(peek->proto, *bkt); + bucket = nxt_lvlhsh_bucket(peek->proto, *bkt); - /* At least one valid entry must present here. */ + /* At least one valid entry must present here. */ - for (entry = bucket; - nxt_lvlhsh_free_entry(entry); - entry += NXT_LVLHSH_ENTRY_SIZE) - { - /* void */ - } + for (entry = bucket; nxt_lvlhsh_free_entry(entry); + entry += NXT_LVLHSH_ENTRY_SIZE) { + /* void */ + } - value = nxt_lvlhsh_entry_value(entry); + value = nxt_lvlhsh_entry_value(entry); - if (peek->retrieve) { - proto = peek->proto; + if (peek->retrieve) { + proto = peek->proto; - if (nxt_lvlhsh_bucket_entries(proto, *bkt) == 1) { - *bkt = *nxt_lvlhsh_next_bucket(proto, bucket); - proto->free(peek->pool, bucket); + if (nxt_lvlhsh_bucket_entries(proto, *bkt) == 1) { + *bkt = *nxt_lvlhsh_next_bucket(proto, bucket); + proto->free(peek->pool, bucket); - } else { - nxt_lvlhsh_count_dec(*bkt); - nxt_lvlhsh_set_entry_value(entry, NULL); - } + } else { + nxt_lvlhsh_count_dec(*bkt); + nxt_lvlhsh_set_entry_value(entry, NULL); } + } - return value; + return value; } +void *nxt_lvlhsh_retrieve(nxt_lvlhsh_t *lh, const nxt_lvlhsh_proto_t *proto, + void *pool) { + void **slot; + nxt_lvlhsh_peek_t peek; -void * -nxt_lvlhsh_retrieve(nxt_lvlhsh_t *lh, const nxt_lvlhsh_proto_t *proto, - void *pool) -{ - void **slot; - nxt_lvlhsh_peek_t peek; - - slot = lh->slot; + slot = lh->slot; - if (slot != NULL) { + if (slot != NULL) { - peek.proto = proto; - peek.pool = pool; - peek.retrieve = 1; + peek.proto = proto; + peek.pool = pool; + peek.retrieve = 1; - if (nxt_lvlhsh_is_bucket(slot)) { - return nxt_lvlhsh_bucket_peek(&peek, &lh->slot); - } - - return nxt_lvlhsh_level_peek(&peek, &lh->slot, 0); + if (nxt_lvlhsh_is_bucket(slot)) { + return nxt_lvlhsh_bucket_peek(&peek, &lh->slot); } - return NULL; + return nxt_lvlhsh_level_peek(&peek, &lh->slot, 0); + } + + return NULL; } diff --git a/src/nxt_lvlhsh.h b/src/nxt_lvlhsh.h index c051081c3..089e67c38 100644 --- a/src/nxt_lvlhsh.h +++ b/src/nxt_lvlhsh.h @@ -7,119 +7,102 @@ #ifndef _NXT_LEVEL_HASH_H_INCLUDED_ #define _NXT_LEVEL_HASH_H_INCLUDED_ - -typedef struct nxt_lvlhsh_query_s nxt_lvlhsh_query_t; +typedef struct nxt_lvlhsh_query_s nxt_lvlhsh_query_t; typedef nxt_int_t (*nxt_lvlhsh_test_t)(nxt_lvlhsh_query_t *lhq, void *data); typedef void *(*nxt_lvlhsh_alloc_t)(void *ctx, size_t size); typedef void (*nxt_lvlhsh_free_t)(void *ctx, void *p); - #if (NXT_64BIT) -#define NXT_LVLHSH_DEFAULT_BUCKET_SIZE 128 -#define NXT_LVLHSH_ENTRY_SIZE 3 -#define NXT_LVLHSH_BATCH_ALLOC 16 +#define NXT_LVLHSH_DEFAULT_BUCKET_SIZE 128 +#define NXT_LVLHSH_ENTRY_SIZE 3 +#define NXT_LVLHSH_BATCH_ALLOC 16 /* 3 is shift of 64-bit pointer. */ -#define NXT_LVLHSH_MEMALIGN_SHIFT (NXT_MAX_MEMALIGN_SHIFT - 3) +#define NXT_LVLHSH_MEMALIGN_SHIFT (NXT_MAX_MEMALIGN_SHIFT - 3) #else -#define NXT_LVLHSH_DEFAULT_BUCKET_SIZE 64 -#define NXT_LVLHSH_ENTRY_SIZE 2 -#define NXT_LVLHSH_BATCH_ALLOC 8 +#define NXT_LVLHSH_DEFAULT_BUCKET_SIZE 64 +#define NXT_LVLHSH_ENTRY_SIZE 2 +#define NXT_LVLHSH_BATCH_ALLOC 8 /* 2 is shift of 32-bit pointer. */ -#define NXT_LVLHSH_MEMALIGN_SHIFT (NXT_MAX_MEMALIGN_SHIFT - 2) +#define NXT_LVLHSH_MEMALIGN_SHIFT (NXT_MAX_MEMALIGN_SHIFT - 2) #endif - #if (NXT_LVLHSH_MEMALIGN_SHIFT < 10) -#define NXT_LVLHSH_MAX_MEMALIGN_SHIFT NXT_LVLHSH_MEMALIGN_SHIFT +#define NXT_LVLHSH_MAX_MEMALIGN_SHIFT NXT_LVLHSH_MEMALIGN_SHIFT #else -#define NXT_LVLHSH_MAX_MEMALIGN_SHIFT 10 +#define NXT_LVLHSH_MAX_MEMALIGN_SHIFT 10 #endif +#define NXT_LVLHSH_BUCKET_END(bucket_size) \ + (((bucket_size) - sizeof(void *)) / \ + (NXT_LVLHSH_ENTRY_SIZE * sizeof(uint32_t)) * NXT_LVLHSH_ENTRY_SIZE) -#define NXT_LVLHSH_BUCKET_END(bucket_size) \ - (((bucket_size) - sizeof(void *)) \ - / (NXT_LVLHSH_ENTRY_SIZE * sizeof(uint32_t)) \ - * NXT_LVLHSH_ENTRY_SIZE) - - -#define NXT_LVLHSH_BUCKET_SIZE(bucket_size) \ - NXT_LVLHSH_BUCKET_END(bucket_size), bucket_size, (bucket_size - 1) - - -#define NXT_LVLHSH_DEFAULT \ - NXT_LVLHSH_BUCKET_SIZE(NXT_LVLHSH_DEFAULT_BUCKET_SIZE), \ - { 4, 4, 4, 4, 4, 4, 4, 0 } - +#define NXT_LVLHSH_BUCKET_SIZE(bucket_size) \ + NXT_LVLHSH_BUCKET_END(bucket_size), bucket_size, (bucket_size - 1) -#define NXT_LVLHSH_LARGE_SLAB \ - NXT_LVLHSH_BUCKET_SIZE(NXT_LVLHSH_DEFAULT_BUCKET_SIZE), \ - { 10, 4, 4, 4, 4, 4, 4, 0 } +#define NXT_LVLHSH_DEFAULT \ + NXT_LVLHSH_BUCKET_SIZE(NXT_LVLHSH_DEFAULT_BUCKET_SIZE), \ + {4, 4, 4, 4, 4, 4, 4, 0} +#define NXT_LVLHSH_LARGE_SLAB \ + NXT_LVLHSH_BUCKET_SIZE(NXT_LVLHSH_DEFAULT_BUCKET_SIZE), \ + {10, 4, 4, 4, 4, 4, 4, 0} -#define NXT_LVLHSH_LARGE_MEMALIGN \ - NXT_LVLHSH_BUCKET_SIZE(NXT_LVLHSH_DEFAULT_BUCKET_SIZE), \ - { NXT_LVLHSH_MAX_MEMALIGN_SHIFT, 4, 4, 4, 4, 0, 0, 0 } - +#define NXT_LVLHSH_LARGE_MEMALIGN \ + NXT_LVLHSH_BUCKET_SIZE(NXT_LVLHSH_DEFAULT_BUCKET_SIZE), \ + {NXT_LVLHSH_MAX_MEMALIGN_SHIFT, 4, 4, 4, 4, 0, 0, 0} typedef struct { - uint32_t bucket_end; - uint32_t bucket_size; - uint32_t bucket_mask; - uint8_t shift[8]; - - nxt_lvlhsh_test_t test; - nxt_lvlhsh_alloc_t alloc; - nxt_lvlhsh_free_t free; + uint32_t bucket_end; + uint32_t bucket_size; + uint32_t bucket_mask; + uint8_t shift[8]; + + nxt_lvlhsh_test_t test; + nxt_lvlhsh_alloc_t alloc; + nxt_lvlhsh_free_t free; } nxt_lvlhsh_proto_t; - typedef struct { - void *slot; + void *slot; } nxt_lvlhsh_t; - struct nxt_lvlhsh_query_s { - uint32_t key_hash; - uint32_t replace; /* 1 bit */ - nxt_str_t key; - void *value; + uint32_t key_hash; + uint32_t replace; /* 1 bit */ + nxt_str_t key; + void *value; - const nxt_lvlhsh_proto_t *proto; - void *pool; + const nxt_lvlhsh_proto_t *proto; + void *pool; - /* Opaque data passed for the test function. */ - void *data; + /* Opaque data passed for the test function. */ + void *data; }; - typedef struct { - const nxt_lvlhsh_proto_t *proto; - /* - * Fields to store current bucket entry position. They cannot be - * combined in a single bucket pointer with number of entries in low - * bits, because entry positions are not aligned. A current level is - * stored as key bit path from the root. - */ - uint32_t *bucket; - uint32_t current; - uint32_t entry; - uint32_t entries; + const nxt_lvlhsh_proto_t *proto; + /* + * Fields to store current bucket entry position. They cannot be + * combined in a single bucket pointer with number of entries in low + * bits, because entry positions are not aligned. A current level is + * stored as key bit path from the root. + */ + uint32_t *bucket; + uint32_t current; + uint32_t entry; + uint32_t entries; } nxt_lvlhsh_each_t; +#define nxt_lvlhsh_is_empty(lh) ((lh)->slot == NULL) -#define nxt_lvlhsh_is_empty(lh) \ - ((lh)->slot == NULL) - - -#define nxt_lvlhsh_init(lh) \ - (lh)->slot = NULL +#define nxt_lvlhsh_init(lh) (lh)->slot = NULL /* * nxt_lvlhsh_find() finds a hash element. If the element has been @@ -145,7 +128,7 @@ NXT_EXPORT nxt_int_t nxt_lvlhsh_find(nxt_lvlhsh_t *lh, nxt_lvlhsh_query_t *lhq); * The optional nxt_lvlhsh_query_t fields: pool. */ NXT_EXPORT nxt_int_t nxt_lvlhsh_insert(nxt_lvlhsh_t *lh, - nxt_lvlhsh_query_t *lhq); + nxt_lvlhsh_query_t *lhq); /* * nxt_lvlhsh_delete() deletes a hash element. If the element has been @@ -156,17 +139,17 @@ NXT_EXPORT nxt_int_t nxt_lvlhsh_insert(nxt_lvlhsh_t *lh, * The optional nxt_lvlhsh_query_t fields: pool. */ NXT_EXPORT nxt_int_t nxt_lvlhsh_delete(nxt_lvlhsh_t *lh, - nxt_lvlhsh_query_t *lhq); + nxt_lvlhsh_query_t *lhq); /* * nxt_lvlhsh_each_init() initializes iterator. * It must be called before the first nxt_lvlhsh_each() call. */ -#define nxt_lvlhsh_each_init(lhe, _proto) \ - do { \ - (lhe)->proto = _proto; \ - (lhe)->bucket = NULL; \ - } while (0) +#define nxt_lvlhsh_each_init(lhe, _proto) \ + do { \ + (lhe)->proto = _proto; \ + (lhe)->bucket = NULL; \ + } while (0) /* * nxt_lvlhsh_each() iterates over a lvlhsh. @@ -181,7 +164,7 @@ NXT_EXPORT void *nxt_lvlhsh_each(nxt_lvlhsh_t *lh, nxt_lvlhsh_each_t *lhe); * The function returns NULL if there is no more elements in the lvlhsh. */ NXT_EXPORT void *nxt_lvlhsh_peek(nxt_lvlhsh_t *lh, - const nxt_lvlhsh_proto_t *proto); + const nxt_lvlhsh_proto_t *proto); /* * nxt_lvlhsh_retrieve() is used to iterate over a lvlhsh during the lvlhsh @@ -190,11 +173,10 @@ NXT_EXPORT void *nxt_lvlhsh_peek(nxt_lvlhsh_t *lh, * more elements in the lvlhsh. */ NXT_EXPORT void *nxt_lvlhsh_retrieve(nxt_lvlhsh_t *lh, - const nxt_lvlhsh_proto_t *proto, void *pool); - + const nxt_lvlhsh_proto_t *proto, + void *pool); NXT_EXPORT void *nxt_lvlhsh_alloc(void *data, size_t size); NXT_EXPORT void nxt_lvlhsh_free(void *data, void *p); - #endif /* _NXT_LEVEL_HASH_H_INCLUDED_ */ diff --git a/src/nxt_macosx_sendfile.c b/src/nxt_macosx_sendfile.c index 2c6ea954c..781a35a30 100644 --- a/src/nxt_macosx_sendfile.c +++ b/src/nxt_macosx_sendfile.c @@ -6,148 +6,142 @@ #include - /* sendfile() has been introduced in MacOSX 10.5 (Leopard) */ #ifdef NXT_TEST_BUILD_MACOSX_SENDFILE ssize_t nxt_macosx_event_conn_io_sendfile(nxt_event_conn_t *c, nxt_buf_t *b, - size_t limit); + size_t limit); static int nxt_sys_sendfile(int fd, int s, off_t offset, off_t *len, - struct sf_hdtr *hdtr, int flags) -{ - return -1; + struct sf_hdtr *hdtr, int flags) { + return -1; } #else -#define nxt_sys_sendfile sendfile +#define nxt_sys_sendfile sendfile #endif - -ssize_t -nxt_macosx_event_conn_io_sendfile(nxt_conn_t *c, nxt_buf_t *b, size_t limit) -{ - size_t hd_size, file_size; - ssize_t n; - nxt_buf_t *fb; - nxt_err_t err; - nxt_off_t sent; - nxt_uint_t nhd, ntr; - struct iovec hd[NXT_IOBUF_MAX], tr[NXT_IOBUF_MAX]; - struct sf_hdtr hdtr, *ht; - nxt_sendbuf_coalesce_t sb; - - sb.buf = b; - sb.iobuf = hd; - sb.nmax = NXT_IOBUF_MAX; - sb.sync = 0; - sb.size = 0; - sb.limit = limit; - - nhd = nxt_sendbuf_mem_coalesce(c->socket.task, &sb); - - if (nhd == 0 && sb.sync) { - return 0; - } - - if (sb.buf == NULL || !nxt_buf_is_file(sb.buf)) { - return nxt_event_conn_io_writev(c, hd, nhd); - } - - hd_size = sb.size; - fb = sb.buf; - - file_size = nxt_sendbuf_file_coalesce(&sb); - - if (file_size == 0) { - return nxt_event_conn_io_writev(c, hd, nhd); - } - - sb.iobuf = tr; - - ntr = nxt_sendbuf_mem_coalesce(c->socket.task, &sb); - - /* - * Disposal of surplus kernel operations if there are no headers - * and trailers. Besides sendfile() returns EINVAL if a sf_hdtr's - * count is 0, but corresponding pointer is not NULL. - */ - - nxt_memzero(&hdtr, sizeof(struct sf_hdtr)); - ht = NULL; - - if (nhd != 0) { - ht = &hdtr; - hdtr.headers = hd; - hdtr.hdr_cnt = nhd; - } - - if (ntr != 0) { - ht = &hdtr; - hdtr.trailers = tr; - hdtr.trl_cnt = ntr; +ssize_t nxt_macosx_event_conn_io_sendfile(nxt_conn_t *c, nxt_buf_t *b, + size_t limit) { + size_t hd_size, file_size; + ssize_t n; + nxt_buf_t *fb; + nxt_err_t err; + nxt_off_t sent; + nxt_uint_t nhd, ntr; + struct iovec hd[NXT_IOBUF_MAX], tr[NXT_IOBUF_MAX]; + struct sf_hdtr hdtr, *ht; + nxt_sendbuf_coalesce_t sb; + + sb.buf = b; + sb.iobuf = hd; + sb.nmax = NXT_IOBUF_MAX; + sb.sync = 0; + sb.size = 0; + sb.limit = limit; + + nhd = nxt_sendbuf_mem_coalesce(c->socket.task, &sb); + + if (nhd == 0 && sb.sync) { + return 0; + } + + if (sb.buf == NULL || !nxt_buf_is_file(sb.buf)) { + return nxt_event_conn_io_writev(c, hd, nhd); + } + + hd_size = sb.size; + fb = sb.buf; + + file_size = nxt_sendbuf_file_coalesce(&sb); + + if (file_size == 0) { + return nxt_event_conn_io_writev(c, hd, nhd); + } + + sb.iobuf = tr; + + ntr = nxt_sendbuf_mem_coalesce(c->socket.task, &sb); + + /* + * Disposal of surplus kernel operations if there are no headers + * and trailers. Besides sendfile() returns EINVAL if a sf_hdtr's + * count is 0, but corresponding pointer is not NULL. + */ + + nxt_memzero(&hdtr, sizeof(struct sf_hdtr)); + ht = NULL; + + if (nhd != 0) { + ht = &hdtr; + hdtr.headers = hd; + hdtr.hdr_cnt = nhd; + } + + if (ntr != 0) { + ht = &hdtr; + hdtr.trailers = tr; + hdtr.trl_cnt = ntr; + } + + /* + * MacOSX has the same bug as old FreeBSD (http://bugs.freebsd.org/33771). + * However this bug has never been fixed and instead of this it has been + * documented as a feature in MacOSX 10.7 (Lion) sendfile(2): + * + * When a header or trailer is specified, the value of len argument + * indicates the maximum number of bytes in the header and/or file + * to be sent. It does not control the trailer; if a trailer exists, + * all of it will be sent. + */ + sent = hd_size + file_size; + + nxt_log_debug(c->socket.log, + "sendfile(%FD, %d, @%O, %O) hd:%ui tr:%ui hs:%uz", fb->file->fd, + c->socket.fd, fb->file_pos, sent, nhd, ntr, hd_size); + + n = nxt_sys_sendfile(fb->file->fd, c->socket.fd, fb->file_pos, &sent, ht, 0); + + err = (n == -1) ? nxt_errno : 0; + + nxt_debug(c->socket.task, "sendfile(): %d sent:%O", n, sent); + + if (n == -1) { + switch (err) { + + case NXT_EAGAIN: + c->socket.write_ready = 0; + break; + + case NXT_EINTR: + break; + + default: + c->socket.error = err; + nxt_log(c->socket.task, nxt_socket_error_level(err), + "sendfile(%FD, %d, %O, %O) failed %E \"%FN\" hd:%ui tr:%ui", + fb->file->fd, c->socket.fd, fb->file_pos, sent, err, + fb->file->name, nhd, ntr); + + return NXT_ERROR; } - /* - * MacOSX has the same bug as old FreeBSD (http://bugs.freebsd.org/33771). - * However this bug has never been fixed and instead of this it has been - * documented as a feature in MacOSX 10.7 (Lion) sendfile(2): - * - * When a header or trailer is specified, the value of len argument - * indicates the maximum number of bytes in the header and/or file - * to be sent. It does not control the trailer; if a trailer exists, - * all of it will be sent. - */ - sent = hd_size + file_size; + nxt_debug(c->socket.task, "sendfile() %E", err); - nxt_log_debug(c->socket.log, - "sendfile(%FD, %d, @%O, %O) hd:%ui tr:%ui hs:%uz", - fb->file->fd, c->socket.fd, fb->file_pos, sent, - nhd, ntr, hd_size); - - n = nxt_sys_sendfile(fb->file->fd, c->socket.fd, - fb->file_pos, &sent, ht, 0); - - err = (n == -1) ? nxt_errno : 0; - - nxt_debug(c->socket.task, "sendfile(): %d sent:%O", n, sent); - - if (n == -1) { - switch (err) { - - case NXT_EAGAIN: - c->socket.write_ready = 0; - break; - - case NXT_EINTR: - break; - - default: - c->socket.error = err; - nxt_log(c->socket.task, nxt_socket_error_level(err), - "sendfile(%FD, %d, %O, %O) failed %E \"%FN\" hd:%ui tr:%ui", - fb->file->fd, c->socket.fd, fb->file_pos, sent, err, - fb->file->name, nhd, ntr); - - return NXT_ERROR; - } - - nxt_debug(c->socket.task, "sendfile() %E", err); + return sent; + } - return sent; - } + if (sent == 0) { + nxt_log(c->socket.task, NXT_LOG_ERR, + "file \"%FN\" was truncated while sendfile()", fb->file->name); - if (sent == 0) { - nxt_log(c->socket.task, NXT_LOG_ERR, - "file \"%FN\" was truncated while sendfile()", fb->file->name); + return NXT_ERROR; + } - return NXT_ERROR; - } + if (sent < (nxt_off_t)sb.size) { + c->socket.write_ready = 0; + } - if (sent < (nxt_off_t) sb.size) { - c->socket.write_ready = 0; - } - - return sent; + return sent; } diff --git a/src/nxt_main.c b/src/nxt_main.c index 26bee8732..ee1bca17e 100644 --- a/src/nxt_main.c +++ b/src/nxt_main.c @@ -7,33 +7,29 @@ #include #include +extern char **environ; -extern char **environ; +int nxt_cdecl main(int argc, char **argv) { + nxt_int_t ret; + if (nxt_lib_start("unit", argv, &environ) != NXT_OK) { + return 1; + } -int nxt_cdecl -main(int argc, char **argv) -{ - nxt_int_t ret; + // nxt_main_log.level = NXT_LOG_INFO; - if (nxt_lib_start("unit", argv, &environ) != NXT_OK) { - return 1; - } + nxt_main_log.handler = nxt_log_time_handler; -// nxt_main_log.level = NXT_LOG_INFO; + ret = nxt_runtime_create(&nxt_main_task); - nxt_main_log.handler = nxt_log_time_handler; + if (ret != NXT_OK) { + return 1; + } - ret = nxt_runtime_create(&nxt_main_task); + nxt_log(&nxt_main_task, NXT_LOG_INFO, "unit " NXT_VERSION " started"); - if (ret != NXT_OK) { - return 1; - } + nxt_event_engine_start(nxt_main_task.thread->engine); - nxt_log(&nxt_main_task, NXT_LOG_INFO, "unit " NXT_VERSION " started"); - - nxt_event_engine_start(nxt_main_task.thread->engine); - - nxt_unreachable(); - return 0; + nxt_unreachable(); + return 0; } diff --git a/src/nxt_main.h b/src/nxt_main.h index 7880e55f8..8aded42ad 100644 --- a/src/nxt_main.h +++ b/src/nxt_main.h @@ -7,25 +7,24 @@ #ifndef _NXT_LIB_H_INCLUDED_ #define _NXT_LIB_H_INCLUDED_ - #include #include -#define NXT_NAME "Unit" -#define NXT_SERVER NXT_NAME "/" NXT_VERSION +#define NXT_NAME "Unit" +#define NXT_SERVER NXT_NAME "/" NXT_VERSION -typedef struct nxt_port_s nxt_port_t; -typedef struct nxt_task_s nxt_task_t; -typedef struct nxt_port_recv_msg_s nxt_port_recv_msg_t; +typedef struct nxt_port_s nxt_port_t; +typedef struct nxt_task_s nxt_task_t; +typedef struct nxt_port_recv_msg_s nxt_port_recv_msg_t; typedef void (*nxt_port_handler_t)(nxt_task_t *task, nxt_port_recv_msg_t *msg); -typedef struct nxt_port_handlers_s nxt_port_handlers_t; -typedef struct nxt_sig_event_s nxt_sig_event_t; -typedef struct nxt_runtime_s nxt_runtime_t; +typedef struct nxt_port_handlers_s nxt_port_handlers_t; +typedef struct nxt_sig_event_s nxt_sig_event_t; +typedef struct nxt_runtime_s nxt_runtime_t; -typedef struct nxt_thread_s nxt_thread_t; -typedef struct nxt_event_engine_s nxt_event_engine_t; -typedef struct nxt_log_s nxt_log_t; -typedef struct nxt_thread_pool_s nxt_thread_pool_t; +typedef struct nxt_thread_s nxt_thread_t; +typedef struct nxt_event_engine_s nxt_event_engine_t; +typedef struct nxt_log_s nxt_log_t; +typedef struct nxt_thread_pool_s nxt_thread_pool_t; typedef void (*nxt_work_handler_t)(nxt_task_t *task, void *obj, void *data); @@ -36,7 +35,7 @@ typedef void (*nxt_work_handler_t)(nxt_task_t *task, void *obj, void *data); #include #include -typedef uint16_t nxt_port_id_t; +typedef uint16_t nxt_port_id_t; #include @@ -69,32 +68,28 @@ typedef uint16_t nxt_port_id_t; #include #include -typedef struct nxt_tstr_state_s nxt_tstr_state_t; +typedef struct nxt_tstr_state_s nxt_tstr_state_t; #include #include - /* TODO: remove unused */ -typedef struct nxt_fd_event_s nxt_fd_event_t; -typedef struct nxt_sockaddr_s nxt_sockaddr_t; - +typedef struct nxt_fd_event_s nxt_fd_event_t; +typedef struct nxt_sockaddr_s nxt_sockaddr_t; #include #include #include #include - typedef void *(*nxt_mem_proto_alloc_t)(void *pool, size_t size); typedef void (*nxt_mem_proto_free_t)(void *pool, void *p); typedef struct { - nxt_mem_proto_alloc_t alloc; - nxt_mem_proto_free_t free; + nxt_mem_proto_alloc_t alloc; + nxt_mem_proto_free_t free; } nxt_mem_proto_t; - #include #include #include @@ -108,12 +103,12 @@ typedef struct { #include -typedef struct nxt_buf_s nxt_buf_t; +typedef struct nxt_buf_s nxt_buf_t; #include #include #include -typedef struct nxt_conn_s nxt_conn_t; +typedef struct nxt_conn_s nxt_conn_t; #include #include @@ -122,13 +117,10 @@ typedef struct nxt_conn_s nxt_conn_t; #include #endif - -#define nxt_thread() \ - (nxt_thread_t *) nxt_thread_get_data(nxt_thread_context) +#define nxt_thread() (nxt_thread_t *)nxt_thread_get_data(nxt_thread_context) nxt_thread_extern_data(nxt_thread_t, nxt_thread_context); - #include #include @@ -139,7 +131,6 @@ nxt_thread_extern_data(nxt_thread_t, nxt_thread_context); #include #include - typedef void (*nxt_event_conn_handler_t)(nxt_thread_t *thr, nxt_conn_t *c); #include @@ -154,7 +145,6 @@ typedef void (*nxt_event_conn_handler_t)(nxt_thread_t *thr, nxt_conn_t *c); #include #include - /* * The envp argument must be &environ if application may * change its process title with nxt_process_title(). @@ -162,11 +152,9 @@ typedef void (*nxt_event_conn_handler_t)(nxt_thread_t *thr, nxt_conn_t *c); NXT_EXPORT nxt_int_t nxt_lib_start(const char *app, char **argv, char ***envp); NXT_EXPORT void nxt_lib_stop(void); - -NXT_EXPORT extern nxt_uint_t nxt_ncpu; -NXT_EXPORT extern nxt_uint_t nxt_pagesize; -NXT_EXPORT extern nxt_task_t nxt_main_task; -NXT_EXPORT extern nxt_atomic_t nxt_task_ident; - +NXT_EXPORT extern nxt_uint_t nxt_ncpu; +NXT_EXPORT extern nxt_uint_t nxt_pagesize; +NXT_EXPORT extern nxt_task_t nxt_main_task; +NXT_EXPORT extern nxt_atomic_t nxt_task_ident; #endif /* _NXT_LIB_H_INCLUDED_ */ diff --git a/src/nxt_main_process.c b/src/nxt_main_process.c index 00318226b..ea5e347f2 100644 --- a/src/nxt_main_process.c +++ b/src/nxt_main_process.c @@ -20,56 +20,54 @@ #include - typedef struct { - nxt_socket_t socket; - nxt_socket_error_t error; - u_char *start; - u_char *end; + nxt_socket_t socket; + nxt_socket_error_t error; + u_char *start; + u_char *end; } nxt_listening_socket_t; - typedef struct { - nxt_uint_t size; - nxt_conf_map_t *map; + nxt_uint_t size; + nxt_conf_map_t *map; } nxt_conf_app_map_t; - static nxt_int_t nxt_main_process_port_create(nxt_task_t *task, - nxt_runtime_t *rt); + nxt_runtime_t *rt); static void nxt_main_process_title(nxt_task_t *task); static void nxt_main_process_sigterm_handler(nxt_task_t *task, void *obj, - void *data); + void *data); static void nxt_main_process_sigquit_handler(nxt_task_t *task, void *obj, - void *data); + void *data); static void nxt_main_process_sigusr1_handler(nxt_task_t *task, void *obj, - void *data); + void *data); static void nxt_main_process_sigchld_handler(nxt_task_t *task, void *obj, - void *data); + void *data); static void nxt_main_process_signal_handler(nxt_task_t *task, void *obj, - void *data); + void *data); static void nxt_main_process_cleanup(nxt_task_t *task, nxt_process_t *process); static void nxt_main_port_socket_handler(nxt_task_t *task, - nxt_port_recv_msg_t *msg); + nxt_port_recv_msg_t *msg); static void nxt_main_port_socket_unlink_handler(nxt_task_t *task, - nxt_port_recv_msg_t *msg); + nxt_port_recv_msg_t *msg); static nxt_int_t nxt_main_listening_socket(nxt_sockaddr_t *sa, - nxt_listening_socket_t *ls); + nxt_listening_socket_t *ls); static void nxt_main_port_modules_handler(nxt_task_t *task, - nxt_port_recv_msg_t *msg); + nxt_port_recv_msg_t *msg); static int nxt_cdecl nxt_app_lang_compare(const void *v1, const void *v2); static void nxt_main_process_whoami_handler(nxt_task_t *task, - nxt_port_recv_msg_t *msg); + nxt_port_recv_msg_t *msg); static void nxt_main_port_conf_store_handler(nxt_task_t *task, - nxt_port_recv_msg_t *msg); + nxt_port_recv_msg_t *msg); static nxt_int_t nxt_main_file_store(nxt_task_t *task, const char *tmp_name, - const char *name, u_char *buf, size_t size); + const char *name, u_char *buf, + size_t size); static void nxt_main_port_access_log_handler(nxt_task_t *task, - nxt_port_recv_msg_t *msg); + nxt_port_recv_msg_t *msg); -const nxt_sig_event_t nxt_main_process_signals[] = { - nxt_event_signal(SIGHUP, nxt_main_process_signal_handler), - nxt_event_signal(SIGINT, nxt_main_process_sigterm_handler), +const nxt_sig_event_t nxt_main_process_signals[] = { + nxt_event_signal(SIGHUP, nxt_main_process_signal_handler), + nxt_event_signal(SIGINT, nxt_main_process_sigterm_handler), nxt_event_signal(SIGQUIT, nxt_main_process_sigquit_handler), nxt_event_signal(SIGTERM, nxt_main_process_sigterm_handler), nxt_event_signal(SIGCHLD, nxt_main_process_sigchld_handler), @@ -77,34 +75,29 @@ const nxt_sig_event_t nxt_main_process_signals[] = { nxt_event_signal_end, }; +nxt_uint_t nxt_conf_ver; -nxt_uint_t nxt_conf_ver; - -static nxt_bool_t nxt_exiting; - +static nxt_bool_t nxt_exiting; -nxt_int_t -nxt_main_process_start(nxt_thread_t *thr, nxt_task_t *task, - nxt_runtime_t *rt) -{ - rt->type = NXT_PROCESS_MAIN; +nxt_int_t nxt_main_process_start(nxt_thread_t *thr, nxt_task_t *task, + nxt_runtime_t *rt) { + rt->type = NXT_PROCESS_MAIN; - if (nxt_main_process_port_create(task, rt) != NXT_OK) { - return NXT_ERROR; - } + if (nxt_main_process_port_create(task, rt) != NXT_OK) { + return NXT_ERROR; + } - nxt_main_process_title(task); + nxt_main_process_title(task); - /* - * The discovery process will send a message processed by - * nxt_main_port_modules_handler() which starts the controller - * and router processes. - */ - return nxt_process_init_start(task, nxt_discovery_process); + /* + * The discovery process will send a message processed by + * nxt_main_port_modules_handler() which starts the controller + * and router processes. + */ + return nxt_process_init_start(task, nxt_discovery_process); } - -static nxt_conf_map_t nxt_common_app_conf[] = { +static nxt_conf_map_t nxt_common_app_conf[] = { { nxt_string("type"), NXT_CONF_MAP_STR, @@ -161,8 +154,7 @@ static nxt_conf_map_t nxt_common_app_conf[] = { }; - -static nxt_conf_map_t nxt_common_app_limits_conf[] = { +static nxt_conf_map_t nxt_common_app_limits_conf[] = { { nxt_string("shm"), NXT_CONF_MAP_SIZE, @@ -177,8 +169,7 @@ static nxt_conf_map_t nxt_common_app_limits_conf[] = { }; - -static nxt_conf_map_t nxt_external_app_conf[] = { +static nxt_conf_map_t nxt_external_app_conf[] = { { nxt_string("executable"), NXT_CONF_MAP_CSTRZ, @@ -193,8 +184,7 @@ static nxt_conf_map_t nxt_external_app_conf[] = { }; - -static nxt_conf_map_t nxt_python_app_conf[] = { +static nxt_conf_map_t nxt_python_app_conf[] = { { nxt_string("home"), NXT_CONF_MAP_CSTRZ, @@ -232,8 +222,7 @@ static nxt_conf_map_t nxt_python_app_conf[] = { }, }; - -static nxt_conf_map_t nxt_php_app_conf[] = { +static nxt_conf_map_t nxt_php_app_conf[] = { { nxt_string("targets"), NXT_CONF_MAP_PTR, @@ -247,8 +236,7 @@ static nxt_conf_map_t nxt_php_app_conf[] = { }, }; - -static nxt_conf_map_t nxt_perl_app_conf[] = { +static nxt_conf_map_t nxt_perl_app_conf[] = { { nxt_string("script"), NXT_CONF_MAP_CSTRZ, @@ -268,8 +256,7 @@ static nxt_conf_map_t nxt_perl_app_conf[] = { }, }; - -static nxt_conf_map_t nxt_ruby_app_conf[] = { +static nxt_conf_map_t nxt_ruby_app_conf[] = { { nxt_string("script"), NXT_CONF_MAP_STR, @@ -284,11 +271,9 @@ static nxt_conf_map_t nxt_ruby_app_conf[] = { nxt_string("hooks"), NXT_CONF_MAP_STR, offsetof(nxt_common_app_conf_t, u.ruby.hooks), - } -}; - + }}; -static nxt_conf_map_t nxt_java_app_conf[] = { +static nxt_conf_map_t nxt_java_app_conf[] = { { nxt_string("classpath"), NXT_CONF_MAP_PTR, @@ -322,8 +307,7 @@ static nxt_conf_map_t nxt_java_app_conf[] = { }; - -static nxt_conf_map_t nxt_wasm_app_conf[] = { +static nxt_conf_map_t nxt_wasm_app_conf[] = { { nxt_string("module"), NXT_CONF_MAP_CSTRZ, @@ -376,8 +360,7 @@ static nxt_conf_map_t nxt_wasm_app_conf[] = { }, }; - -static nxt_conf_map_t nxt_wasm_wc_app_conf[] = { +static nxt_conf_map_t nxt_wasm_wc_app_conf[] = { { nxt_string("component"), NXT_CONF_MAP_CSTRZ, @@ -390,964 +373,905 @@ static nxt_conf_map_t nxt_wasm_wc_app_conf[] = { }, }; - -static nxt_conf_app_map_t nxt_app_maps[] = { - { nxt_nitems(nxt_external_app_conf), nxt_external_app_conf }, - { nxt_nitems(nxt_python_app_conf), nxt_python_app_conf }, - { nxt_nitems(nxt_php_app_conf), nxt_php_app_conf }, - { nxt_nitems(nxt_perl_app_conf), nxt_perl_app_conf }, - { nxt_nitems(nxt_ruby_app_conf), nxt_ruby_app_conf }, - { nxt_nitems(nxt_java_app_conf), nxt_java_app_conf }, - { nxt_nitems(nxt_wasm_app_conf), nxt_wasm_app_conf }, - { nxt_nitems(nxt_wasm_wc_app_conf), nxt_wasm_wc_app_conf }, +static nxt_conf_app_map_t nxt_app_maps[] = { + {nxt_nitems(nxt_external_app_conf), nxt_external_app_conf}, + {nxt_nitems(nxt_python_app_conf), nxt_python_app_conf}, + {nxt_nitems(nxt_php_app_conf), nxt_php_app_conf}, + {nxt_nitems(nxt_perl_app_conf), nxt_perl_app_conf}, + {nxt_nitems(nxt_ruby_app_conf), nxt_ruby_app_conf}, + {nxt_nitems(nxt_java_app_conf), nxt_java_app_conf}, + {nxt_nitems(nxt_wasm_app_conf), nxt_wasm_app_conf}, + {nxt_nitems(nxt_wasm_wc_app_conf), nxt_wasm_wc_app_conf}, }; - -static void -nxt_main_data_handler(nxt_task_t *task, nxt_port_recv_msg_t *msg) -{ - nxt_debug(task, "main data: %*s", - nxt_buf_mem_used_size(&msg->buf->mem), msg->buf->mem.pos); +static void nxt_main_data_handler(nxt_task_t *task, nxt_port_recv_msg_t *msg) { + nxt_debug(task, "main data: %*s", nxt_buf_mem_used_size(&msg->buf->mem), + msg->buf->mem.pos); } +static void nxt_main_new_port_handler(nxt_task_t *task, + nxt_port_recv_msg_t *msg) { + void *mem; + nxt_port_t *port; -static void -nxt_main_new_port_handler(nxt_task_t *task, nxt_port_recv_msg_t *msg) -{ - void *mem; - nxt_port_t *port; - - nxt_port_new_port_handler(task, msg); + nxt_port_new_port_handler(task, msg); - port = msg->u.new_port; + port = msg->u.new_port; - if (port != NULL - && port->type == NXT_PROCESS_APP - && msg->fd[1] != -1) - { - mem = nxt_mem_mmap(NULL, sizeof(nxt_port_queue_t), - PROT_READ | PROT_WRITE, MAP_SHARED, msg->fd[1], 0); - if (nxt_fast_path(mem != MAP_FAILED)) { - port->queue = mem; - } - - nxt_fd_close(msg->fd[1]); - msg->fd[1] = -1; + if (port != NULL && port->type == NXT_PROCESS_APP && msg->fd[1] != -1) { + mem = nxt_mem_mmap(NULL, sizeof(nxt_port_queue_t), PROT_READ | PROT_WRITE, + MAP_SHARED, msg->fd[1], 0); + if (nxt_fast_path(mem != MAP_FAILED)) { + port->queue = mem; } -} + nxt_fd_close(msg->fd[1]); + msg->fd[1] = -1; + } +} -static void -nxt_main_start_process_handler(nxt_task_t *task, nxt_port_recv_msg_t *msg) -{ - u_char *start, *p, ch; - size_t type_len; - nxt_int_t ret; - nxt_buf_t *b; - nxt_port_t *port; - nxt_runtime_t *rt; - nxt_process_t *process; - nxt_app_type_t idx; - nxt_conf_value_t *conf; - nxt_process_init_t *init; - nxt_common_app_conf_t *app_conf; - - rt = task->thread->runtime; - - port = rt->port_by_type[NXT_PROCESS_ROUTER]; - if (nxt_slow_path(port == NULL)) { - nxt_alert(task, "router port not found"); - goto close_fds; - } - - if (nxt_slow_path(port->pid != nxt_recv_msg_cmsg_pid(msg))) { - nxt_alert(task, "process %PI cannot start processes", - nxt_recv_msg_cmsg_pid(msg)); - - goto close_fds; - } +static void nxt_main_start_process_handler(nxt_task_t *task, + nxt_port_recv_msg_t *msg) { + u_char *start, *p, ch; + size_t type_len; + nxt_int_t ret; + nxt_buf_t *b; + nxt_port_t *port; + nxt_runtime_t *rt; + nxt_process_t *process; + nxt_app_type_t idx; + nxt_conf_value_t *conf; + nxt_process_init_t *init; + nxt_common_app_conf_t *app_conf; + + rt = task->thread->runtime; + + port = rt->port_by_type[NXT_PROCESS_ROUTER]; + if (nxt_slow_path(port == NULL)) { + nxt_alert(task, "router port not found"); + goto close_fds; + } + + if (nxt_slow_path(port->pid != nxt_recv_msg_cmsg_pid(msg))) { + nxt_alert(task, "process %PI cannot start processes", + nxt_recv_msg_cmsg_pid(msg)); + + goto close_fds; + } + + process = nxt_process_new(rt); + if (nxt_slow_path(process == NULL)) { + goto close_fds; + } + + process->mem_pool = nxt_mp_create(1024, 128, 256, 32); + if (process->mem_pool == NULL) { + nxt_process_use(task, process, -1); + goto close_fds; + } - process = nxt_process_new(rt); - if (nxt_slow_path(process == NULL)) { - goto close_fds; - } + process->parent_port = rt->port_by_type[NXT_PROCESS_MAIN]; - process->mem_pool = nxt_mp_create(1024, 128, 256, 32); - if (process->mem_pool == NULL) { - nxt_process_use(task, process, -1); - goto close_fds; - } + init = nxt_process_init(process); - process->parent_port = rt->port_by_type[NXT_PROCESS_MAIN]; + *init = nxt_proto_process; - init = nxt_process_init(process); + b = nxt_buf_chk_make_plain(process->mem_pool, msg->buf, msg->size); + if (b == NULL) { + goto failed; + } - *init = nxt_proto_process; + nxt_debug(task, "main start prototype: %*s", b->mem.free - b->mem.pos, + b->mem.pos); - b = nxt_buf_chk_make_plain(process->mem_pool, msg->buf, msg->size); - if (b == NULL) { - goto failed; - } + app_conf = nxt_mp_zalloc(process->mem_pool, sizeof(nxt_common_app_conf_t)); + if (nxt_slow_path(app_conf == NULL)) { + goto failed; + } - nxt_debug(task, "main start prototype: %*s", b->mem.free - b->mem.pos, - b->mem.pos); + app_conf->shared_port_fd = msg->fd[0]; + app_conf->shared_queue_fd = msg->fd[1]; - app_conf = nxt_mp_zalloc(process->mem_pool, sizeof(nxt_common_app_conf_t)); - if (nxt_slow_path(app_conf == NULL)) { - goto failed; - } + start = b->mem.pos; - app_conf->shared_port_fd = msg->fd[0]; - app_conf->shared_queue_fd = msg->fd[1]; + app_conf->name.start = start; + app_conf->name.length = nxt_strlen(start); - start = b->mem.pos; + init->name = (const char *)start; - app_conf->name.start = start; - app_conf->name.length = nxt_strlen(start); + process->name = nxt_mp_alloc( + process->mem_pool, app_conf->name.length + sizeof("\"\" prototype") + 1); - init->name = (const char *) start; + if (nxt_slow_path(process->name == NULL)) { + goto failed; + } - process->name = nxt_mp_alloc(process->mem_pool, app_conf->name.length - + sizeof("\"\" prototype") + 1); + p = (u_char *)process->name; + *p++ = '"'; + p = nxt_cpymem(p, init->name, app_conf->name.length); + p = nxt_cpymem(p, "\" prototype", 11); + *p = '\0'; - if (nxt_slow_path(process->name == NULL)) { - goto failed; - } + app_conf->shm_limit = 100 * 1024 * 1024; + app_conf->request_limit = 0; - p = (u_char *) process->name; - *p++ = '"'; - p = nxt_cpymem(p, init->name, app_conf->name.length); - p = nxt_cpymem(p, "\" prototype", 11); - *p = '\0'; + start += app_conf->name.length + 1; - app_conf->shm_limit = 100 * 1024 * 1024; - app_conf->request_limit = 0; + conf = nxt_conf_json_parse(process->mem_pool, start, b->mem.free, NULL); + if (conf == NULL) { + nxt_alert(task, "router app configuration parsing error"); - start += app_conf->name.length + 1; + goto failed; + } - conf = nxt_conf_json_parse(process->mem_pool, start, b->mem.free, NULL); - if (conf == NULL) { - nxt_alert(task, "router app configuration parsing error"); + rt = task->thread->runtime; - goto failed; - } + app_conf->user.start = (u_char *)rt->user_cred.user; + app_conf->user.length = nxt_strlen(rt->user_cred.user); - rt = task->thread->runtime; + ret = nxt_conf_map_object(process->mem_pool, conf, nxt_common_app_conf, + nxt_nitems(nxt_common_app_conf), app_conf); - app_conf->user.start = (u_char*)rt->user_cred.user; - app_conf->user.length = nxt_strlen(rt->user_cred.user); + if (ret != NXT_OK) { + nxt_alert(task, "failed to map common app conf received from router"); + goto failed; + } - ret = nxt_conf_map_object(process->mem_pool, conf, nxt_common_app_conf, - nxt_nitems(nxt_common_app_conf), app_conf); + for (type_len = 0; type_len != app_conf->type.length; type_len++) { + ch = app_conf->type.start[type_len]; - if (ret != NXT_OK) { - nxt_alert(task, "failed to map common app conf received from router"); - goto failed; + if (ch == ' ' || nxt_isdigit(ch)) { + break; } + } - for (type_len = 0; type_len != app_conf->type.length; type_len++) { - ch = app_conf->type.start[type_len]; + idx = nxt_app_parse_type(app_conf->type.start, type_len); - if (ch == ' ' || nxt_isdigit(ch)) { - break; - } - } + if (nxt_slow_path(idx >= nxt_nitems(nxt_app_maps))) { + nxt_alert(task, "invalid app type %d received from router", (int)idx); + goto failed; + } - idx = nxt_app_parse_type(app_conf->type.start, type_len); + ret = nxt_conf_map_object(process->mem_pool, conf, nxt_app_maps[idx].map, + nxt_app_maps[idx].size, app_conf); - if (nxt_slow_path(idx >= nxt_nitems(nxt_app_maps))) { - nxt_alert(task, "invalid app type %d received from router", (int) idx); - goto failed; - } + if (nxt_slow_path(ret != NXT_OK)) { + nxt_alert(task, "failed to map app conf received from router"); + goto failed; + } - ret = nxt_conf_map_object(process->mem_pool, conf, nxt_app_maps[idx].map, - nxt_app_maps[idx].size, app_conf); + if (app_conf->limits != NULL) { + ret = nxt_conf_map_object(process->mem_pool, app_conf->limits, + nxt_common_app_limits_conf, + nxt_nitems(nxt_common_app_limits_conf), app_conf); if (nxt_slow_path(ret != NXT_OK)) { - nxt_alert(task, "failed to map app conf received from router"); - goto failed; - } - - if (app_conf->limits != NULL) { - ret = nxt_conf_map_object(process->mem_pool, app_conf->limits, - nxt_common_app_limits_conf, - nxt_nitems(nxt_common_app_limits_conf), - app_conf); - - if (nxt_slow_path(ret != NXT_OK)) { - nxt_alert(task, "failed to map app limits received from router"); - goto failed; - } + nxt_alert(task, "failed to map app limits received from router"); + goto failed; } + } - app_conf->self = conf; + app_conf->self = conf; - process->stream = msg->port_msg.stream; - process->data.app = app_conf; + process->stream = msg->port_msg.stream; + process->data.app = app_conf; - ret = nxt_process_start(task, process); - if (nxt_fast_path(ret == NXT_OK || ret == NXT_AGAIN)) { + ret = nxt_process_start(task, process); + if (nxt_fast_path(ret == NXT_OK || ret == NXT_AGAIN)) { - /* Close shared port fds only in main process. */ - if (ret == NXT_OK) { - nxt_fd_close(app_conf->shared_port_fd); - nxt_fd_close(app_conf->shared_queue_fd); - } + /* Close shared port fds only in main process. */ + if (ret == NXT_OK) { + nxt_fd_close(app_conf->shared_port_fd); + nxt_fd_close(app_conf->shared_queue_fd); + } - /* Avoid fds close in caller. */ - msg->fd[0] = -1; - msg->fd[1] = -1; + /* Avoid fds close in caller. */ + msg->fd[0] = -1; + msg->fd[1] = -1; - return; - } + return; + } failed: - nxt_process_use(task, process, -1); + nxt_process_use(task, process, -1); - port = nxt_runtime_port_find(rt, msg->port_msg.pid, - msg->port_msg.reply_port); + port = nxt_runtime_port_find(rt, msg->port_msg.pid, msg->port_msg.reply_port); - if (nxt_fast_path(port != NULL)) { - nxt_port_socket_write(task, port, NXT_PORT_MSG_RPC_ERROR, - -1, msg->port_msg.stream, 0, NULL); - } + if (nxt_fast_path(port != NULL)) { + nxt_port_socket_write(task, port, NXT_PORT_MSG_RPC_ERROR, -1, + msg->port_msg.stream, 0, NULL); + } close_fds: - nxt_fd_close(msg->fd[0]); - msg->fd[0] = -1; + nxt_fd_close(msg->fd[0]); + msg->fd[0] = -1; - nxt_fd_close(msg->fd[1]); - msg->fd[1] = -1; + nxt_fd_close(msg->fd[1]); + msg->fd[1] = -1; } +static void nxt_main_process_created_handler(nxt_task_t *task, + nxt_port_recv_msg_t *msg) { + nxt_port_t *port; + nxt_process_t *process; + nxt_runtime_t *rt; -static void -nxt_main_process_created_handler(nxt_task_t *task, nxt_port_recv_msg_t *msg) -{ - nxt_port_t *port; - nxt_process_t *process; - nxt_runtime_t *rt; - - rt = task->thread->runtime; + rt = task->thread->runtime; - port = nxt_runtime_port_find(rt, msg->port_msg.pid, - msg->port_msg.reply_port); - if (nxt_slow_path(port == NULL)) { - return; - } + port = nxt_runtime_port_find(rt, msg->port_msg.pid, msg->port_msg.reply_port); + if (nxt_slow_path(port == NULL)) { + return; + } - process = port->process; + process = port->process; - nxt_assert(process != NULL); - nxt_assert(process->state == NXT_PROCESS_STATE_CREATING); + nxt_assert(process != NULL); + nxt_assert(process->state == NXT_PROCESS_STATE_CREATING); #if (NXT_HAVE_LINUX_NS && NXT_HAVE_CLONE_NEWUSER) - if (nxt_is_clone_flag_set(process->isolation.clone.flags, NEWUSER)) { - if (nxt_slow_path(nxt_clone_credential_map(task, process->pid, - process->user_cred, - &process->isolation.clone) - != NXT_OK)) - { - (void) nxt_port_socket_write(task, port, NXT_PORT_MSG_RPC_ERROR, - -1, msg->port_msg.stream, 0, NULL); - return; - } + if (nxt_is_clone_flag_set(process->isolation.clone.flags, NEWUSER)) { + if (nxt_slow_path( + nxt_clone_credential_map(task, process->pid, process->user_cred, + &process->isolation.clone) != NXT_OK)) { + (void)nxt_port_socket_write(task, port, NXT_PORT_MSG_RPC_ERROR, -1, + msg->port_msg.stream, 0, NULL); + return; } + } #endif - process->state = NXT_PROCESS_STATE_CREATED; + process->state = NXT_PROCESS_STATE_CREATED; - (void) nxt_port_socket_write(task, port, NXT_PORT_MSG_RPC_READY_LAST, - -1, msg->port_msg.stream, 0, NULL); + (void)nxt_port_socket_write(task, port, NXT_PORT_MSG_RPC_READY_LAST, -1, + msg->port_msg.stream, 0, NULL); } - -static nxt_port_handlers_t nxt_main_process_port_handlers = { - .data = nxt_main_data_handler, - .new_port = nxt_main_new_port_handler, - .process_created = nxt_main_process_created_handler, - .process_ready = nxt_port_process_ready_handler, - .whoami = nxt_main_process_whoami_handler, - .remove_pid = nxt_port_remove_pid_handler, - .start_process = nxt_main_start_process_handler, - .socket = nxt_main_port_socket_handler, - .socket_unlink = nxt_main_port_socket_unlink_handler, - .modules = nxt_main_port_modules_handler, - .conf_store = nxt_main_port_conf_store_handler, +static nxt_port_handlers_t nxt_main_process_port_handlers = { + .data = nxt_main_data_handler, + .new_port = nxt_main_new_port_handler, + .process_created = nxt_main_process_created_handler, + .process_ready = nxt_port_process_ready_handler, + .whoami = nxt_main_process_whoami_handler, + .remove_pid = nxt_port_remove_pid_handler, + .start_process = nxt_main_start_process_handler, + .socket = nxt_main_port_socket_handler, + .socket_unlink = nxt_main_port_socket_unlink_handler, + .modules = nxt_main_port_modules_handler, + .conf_store = nxt_main_port_conf_store_handler, #if (NXT_TLS) - .cert_get = nxt_cert_store_get_handler, - .cert_delete = nxt_cert_store_delete_handler, + .cert_get = nxt_cert_store_get_handler, + .cert_delete = nxt_cert_store_delete_handler, #endif #if (NXT_HAVE_NJS) - .script_get = nxt_script_store_get_handler, - .script_delete = nxt_script_store_delete_handler, + .script_get = nxt_script_store_get_handler, + .script_delete = nxt_script_store_delete_handler, #endif - .access_log = nxt_main_port_access_log_handler, - .rpc_ready = nxt_port_rpc_handler, - .rpc_error = nxt_port_rpc_handler, + .access_log = nxt_main_port_access_log_handler, + .rpc_ready = nxt_port_rpc_handler, + .rpc_error = nxt_port_rpc_handler, }; +static void nxt_main_process_whoami_handler(nxt_task_t *task, + nxt_port_recv_msg_t *msg) { + nxt_buf_t *buf; + nxt_pid_t pid, ppid; + nxt_port_t *port; + nxt_runtime_t *rt; + nxt_process_t *pprocess; -static void -nxt_main_process_whoami_handler(nxt_task_t *task, nxt_port_recv_msg_t *msg) -{ - nxt_buf_t *buf; - nxt_pid_t pid, ppid; - nxt_port_t *port; - nxt_runtime_t *rt; - nxt_process_t *pprocess; + nxt_assert(msg->port_msg.reply_port == 0); - nxt_assert(msg->port_msg.reply_port == 0); + if (nxt_slow_path(msg->buf == NULL || + nxt_buf_used_size(msg->buf) != sizeof(nxt_pid_t))) { + nxt_alert(task, "whoami: buffer is NULL or unexpected size"); + goto fail; + } - if (nxt_slow_path(msg->buf == NULL - || nxt_buf_used_size(msg->buf) != sizeof(nxt_pid_t))) - { - nxt_alert(task, "whoami: buffer is NULL or unexpected size"); - goto fail; - } + nxt_memcpy(&ppid, msg->buf->mem.pos, sizeof(nxt_pid_t)); - nxt_memcpy(&ppid, msg->buf->mem.pos, sizeof(nxt_pid_t)); + rt = task->thread->runtime; - rt = task->thread->runtime; + pprocess = nxt_runtime_process_find(rt, ppid); + if (nxt_slow_path(pprocess == NULL)) { + nxt_alert(task, "whoami: parent process %PI not found", ppid); + goto fail; + } - pprocess = nxt_runtime_process_find(rt, ppid); - if (nxt_slow_path(pprocess == NULL)) { - nxt_alert(task, "whoami: parent process %PI not found", ppid); - goto fail; - } + pid = nxt_recv_msg_cmsg_pid(msg); - pid = nxt_recv_msg_cmsg_pid(msg); + nxt_debug(task, "whoami: from %PI, parent %PI, fd %d", pid, ppid, msg->fd[0]); - nxt_debug(task, "whoami: from %PI, parent %PI, fd %d", pid, ppid, - msg->fd[0]); - - if (msg->fd[0] != -1) { - port = nxt_runtime_process_port_create(task, rt, pid, 0, - NXT_PROCESS_APP); - if (nxt_slow_path(port == NULL)) { - goto fail; - } + if (msg->fd[0] != -1) { + port = nxt_runtime_process_port_create(task, rt, pid, 0, NXT_PROCESS_APP); + if (nxt_slow_path(port == NULL)) { + goto fail; + } - nxt_fd_nonblocking(task, msg->fd[0]); + nxt_fd_nonblocking(task, msg->fd[0]); - port->pair[0] = -1; - port->pair[1] = msg->fd[0]; - msg->fd[0] = -1; + port->pair[0] = -1; + port->pair[1] = msg->fd[0]; + msg->fd[0] = -1; - port->max_size = 16 * 1024; - port->max_share = 64 * 1024; - port->socket.task = task; + port->max_size = 16 * 1024; + port->max_share = 64 * 1024; + port->socket.task = task; - nxt_port_write_enable(task, port); + nxt_port_write_enable(task, port); - } else { - port = nxt_runtime_port_find(rt, pid, 0); - if (nxt_slow_path(port == NULL)) { - goto fail; - } + } else { + port = nxt_runtime_port_find(rt, pid, 0); + if (nxt_slow_path(port == NULL)) { + goto fail; } + } - if (ppid != nxt_pid) { - nxt_queue_insert_tail(&pprocess->children, &port->process->link); - } + if (ppid != nxt_pid) { + nxt_queue_insert_tail(&pprocess->children, &port->process->link); + } - buf = nxt_buf_mem_alloc(task->thread->engine->mem_pool, - sizeof(nxt_pid_t), 0); - if (nxt_slow_path(buf == NULL)) { - goto fail; - } + buf = nxt_buf_mem_alloc(task->thread->engine->mem_pool, sizeof(nxt_pid_t), 0); + if (nxt_slow_path(buf == NULL)) { + goto fail; + } - buf->mem.free = nxt_cpymem(buf->mem.free, &pid, sizeof(nxt_pid_t)); + buf->mem.free = nxt_cpymem(buf->mem.free, &pid, sizeof(nxt_pid_t)); - (void) nxt_port_socket_write(task, port, NXT_PORT_MSG_RPC_READY_LAST, -1, - msg->port_msg.stream, 0, buf); + (void)nxt_port_socket_write(task, port, NXT_PORT_MSG_RPC_READY_LAST, -1, + msg->port_msg.stream, 0, buf); fail: - if (msg->fd[0] != -1) { - nxt_fd_close(msg->fd[0]); - } + if (msg->fd[0] != -1) { + nxt_fd_close(msg->fd[0]); + } } +static nxt_int_t nxt_main_process_port_create(nxt_task_t *task, + nxt_runtime_t *rt) { + nxt_int_t ret; + nxt_port_t *port; + nxt_process_t *process; + + port = + nxt_runtime_process_port_create(task, rt, nxt_pid, 0, NXT_PROCESS_MAIN); + if (nxt_slow_path(port == NULL)) { + return NXT_ERROR; + } -static nxt_int_t -nxt_main_process_port_create(nxt_task_t *task, nxt_runtime_t *rt) -{ - nxt_int_t ret; - nxt_port_t *port; - nxt_process_t *process; - - port = nxt_runtime_process_port_create(task, rt, nxt_pid, 0, - NXT_PROCESS_MAIN); - if (nxt_slow_path(port == NULL)) { - return NXT_ERROR; - } - - process = port->process; + process = port->process; - ret = nxt_port_socket_init(task, port, 0); - if (nxt_slow_path(ret != NXT_OK)) { - nxt_port_use(task, port, -1); - return ret; - } + ret = nxt_port_socket_init(task, port, 0); + if (nxt_slow_path(ret != NXT_OK)) { + nxt_port_use(task, port, -1); + return ret; + } - /* - * A main process port. A write port is not closed - * since it should be inherited by processes. - */ - nxt_port_enable(task, port, &nxt_main_process_port_handlers); + /* + * A main process port. A write port is not closed + * since it should be inherited by processes. + */ + nxt_port_enable(task, port, &nxt_main_process_port_handlers); - process->state = NXT_PROCESS_STATE_READY; + process->state = NXT_PROCESS_STATE_READY; - return NXT_OK; + return NXT_OK; } +static void nxt_main_process_title(nxt_task_t *task) { + u_char *p, *end; + nxt_uint_t i; + u_char title[2048]; -static void -nxt_main_process_title(nxt_task_t *task) -{ - u_char *p, *end; - nxt_uint_t i; - u_char title[2048]; - - end = title + sizeof(title) - 1; + end = title + sizeof(title) - 1; - p = nxt_sprintf(title, end, "unit: main v" NXT_VERSION " [%s", - nxt_process_argv[0]); + p = nxt_sprintf(title, end, "unit: main v" NXT_VERSION " [%s", + nxt_process_argv[0]); - for (i = 1; nxt_process_argv[i] != NULL; i++) { - p = nxt_sprintf(p, end, " %s", nxt_process_argv[i]); - } + for (i = 1; nxt_process_argv[i] != NULL; i++) { + p = nxt_sprintf(p, end, " %s", nxt_process_argv[i]); + } - if (p < end) { - *p++ = ']'; - } + if (p < end) { + *p++ = ']'; + } - *p = '\0'; + *p = '\0'; - nxt_process_title(task, "%s", title); + nxt_process_title(task, "%s", title); } +static void nxt_main_process_sigterm_handler(nxt_task_t *task, void *obj, + void *data) { + nxt_debug(task, "sigterm handler signo:%d (%s)", (int)(uintptr_t)obj, data); -static void -nxt_main_process_sigterm_handler(nxt_task_t *task, void *obj, void *data) -{ - nxt_debug(task, "sigterm handler signo:%d (%s)", - (int) (uintptr_t) obj, data); - - /* TODO: fast exit. */ + /* TODO: fast exit. */ - nxt_exiting = 1; + nxt_exiting = 1; - nxt_runtime_quit(task, 0); + nxt_runtime_quit(task, 0); } +static void nxt_main_process_sigquit_handler(nxt_task_t *task, void *obj, + void *data) { + nxt_debug(task, "sigquit handler signo:%d (%s)", (int)(uintptr_t)obj, data); -static void -nxt_main_process_sigquit_handler(nxt_task_t *task, void *obj, void *data) -{ - nxt_debug(task, "sigquit handler signo:%d (%s)", - (int) (uintptr_t) obj, data); + /* TODO: graceful exit. */ - /* TODO: graceful exit. */ + nxt_exiting = 1; - nxt_exiting = 1; - - nxt_runtime_quit(task, 0); + nxt_runtime_quit(task, 0); } +static void nxt_main_process_sigusr1_handler(nxt_task_t *task, void *obj, + void *data) { + nxt_mp_t *mp; + nxt_int_t ret; + nxt_uint_t n; + nxt_port_t *port; + nxt_file_t *file, *new_file; + nxt_array_t *new_files; + nxt_runtime_t *rt; -static void -nxt_main_process_sigusr1_handler(nxt_task_t *task, void *obj, void *data) -{ - nxt_mp_t *mp; - nxt_int_t ret; - nxt_uint_t n; - nxt_port_t *port; - nxt_file_t *file, *new_file; - nxt_array_t *new_files; - nxt_runtime_t *rt; - - nxt_log(task, NXT_LOG_NOTICE, "signal %d (%s) received, %s", - (int) (uintptr_t) obj, data, "log files rotation"); + nxt_log(task, NXT_LOG_NOTICE, "signal %d (%s) received, %s", + (int)(uintptr_t)obj, data, "log files rotation"); - rt = task->thread->runtime; + rt = task->thread->runtime; - port = rt->port_by_type[NXT_PROCESS_ROUTER]; + port = rt->port_by_type[NXT_PROCESS_ROUTER]; - if (nxt_fast_path(port != NULL)) { - (void) nxt_port_socket_write(task, port, NXT_PORT_MSG_ACCESS_LOG, - -1, 0, 0, NULL); - } + if (nxt_fast_path(port != NULL)) { + (void)nxt_port_socket_write(task, port, NXT_PORT_MSG_ACCESS_LOG, -1, 0, 0, + NULL); + } - mp = nxt_mp_create(1024, 128, 256, 32); - if (mp == NULL) { - return; - } + mp = nxt_mp_create(1024, 128, 256, 32); + if (mp == NULL) { + return; + } - n = nxt_list_nelts(rt->log_files); + n = nxt_list_nelts(rt->log_files); - new_files = nxt_array_create(mp, n, sizeof(nxt_file_t)); - if (new_files == NULL) { - nxt_mp_destroy(mp); - return; - } - - nxt_list_each(file, rt->log_files) { - - /* This allocation cannot fail. */ - new_file = nxt_array_add(new_files); - - new_file->name = file->name; - new_file->fd = NXT_FILE_INVALID; - new_file->log_level = NXT_LOG_ALERT; + new_files = nxt_array_create(mp, n, sizeof(nxt_file_t)); + if (new_files == NULL) { + nxt_mp_destroy(mp); + return; + } - ret = nxt_file_open(task, new_file, O_WRONLY | O_APPEND, O_CREAT, - NXT_FILE_OWNER_ACCESS); + nxt_list_each(file, rt->log_files) { - if (ret != NXT_OK) { - goto fail; - } + /* This allocation cannot fail. */ + new_file = nxt_array_add(new_files); - } nxt_list_loop; + new_file->name = file->name; + new_file->fd = NXT_FILE_INVALID; + new_file->log_level = NXT_LOG_ALERT; - new_file = new_files->elts; + ret = nxt_file_open(task, new_file, O_WRONLY | O_APPEND, O_CREAT, + NXT_FILE_OWNER_ACCESS); - ret = nxt_file_stderr(&new_file[0]); + if (ret != NXT_OK) { + goto fail; + } + } + nxt_list_loop; - if (ret == NXT_OK) { - n = 0; + new_file = new_files->elts; - nxt_list_each(file, rt->log_files) { + ret = nxt_file_stderr(&new_file[0]); - nxt_port_change_log_file(task, rt, n, new_file[n].fd); - /* - * The old log file descriptor must be closed at the moment - * when no other threads use it. dup2() allows to use the - * old file descriptor for new log file. This change is - * performed atomically in the kernel. - */ - (void) nxt_file_redirect(file, new_file[n].fd); + if (ret == NXT_OK) { + n = 0; - n++; + nxt_list_each(file, rt->log_files) { - } nxt_list_loop; + nxt_port_change_log_file(task, rt, n, new_file[n].fd); + /* + * The old log file descriptor must be closed at the moment + * when no other threads use it. dup2() allows to use the + * old file descriptor for new log file. This change is + * performed atomically in the kernel. + */ + (void)nxt_file_redirect(file, new_file[n].fd); - nxt_mp_destroy(mp); - return; + n++; } + nxt_list_loop; -fail: + nxt_mp_destroy(mp); + return; + } - new_file = new_files->elts; - n = new_files->nelts; +fail: - while (n != 0) { - if (new_file->fd != NXT_FILE_INVALID) { - nxt_file_close(task, new_file); - } + new_file = new_files->elts; + n = new_files->nelts; - new_file++; - n--; + while (n != 0) { + if (new_file->fd != NXT_FILE_INVALID) { + nxt_file_close(task, new_file); } - nxt_mp_destroy(mp); -} + new_file++; + n--; + } + nxt_mp_destroy(mp); +} -static void -nxt_main_process_sigchld_handler(nxt_task_t *task, void *obj, void *data) -{ - int status; - nxt_int_t ret; - nxt_err_t err; - nxt_pid_t pid; - nxt_port_t *port; - nxt_queue_t children; - nxt_runtime_t *rt; - nxt_process_t *process, *child; - nxt_process_init_t init; +static void nxt_main_process_sigchld_handler(nxt_task_t *task, void *obj, + void *data) { + int status; + nxt_int_t ret; + nxt_err_t err; + nxt_pid_t pid; + nxt_port_t *port; + nxt_queue_t children; + nxt_runtime_t *rt; + nxt_process_t *process, *child; + nxt_process_init_t init; - nxt_debug(task, "sigchld handler signo:%d (%s)", - (int) (uintptr_t) obj, data); + nxt_debug(task, "sigchld handler signo:%d (%s)", (int)(uintptr_t)obj, data); - rt = task->thread->runtime; + rt = task->thread->runtime; - for ( ;; ) { - pid = waitpid(-1, &status, WNOHANG); + for (;;) { + pid = waitpid(-1, &status, WNOHANG); - if (pid == -1) { + if (pid == -1) { - switch (err = nxt_errno) { + switch (err = nxt_errno) { - case NXT_ECHILD: - return; + case NXT_ECHILD: + return; - case NXT_EINTR: - continue; + case NXT_EINTR: + continue; - default: - nxt_alert(task, "waitpid() failed: %E", err); - return; - } - } + default: + nxt_alert(task, "waitpid() failed: %E", err); + return; + } + } - nxt_debug(task, "waitpid(): %PI", pid); + nxt_debug(task, "waitpid(): %PI", pid); - if (pid == 0) { - return; - } + if (pid == 0) { + return; + } - if (WTERMSIG(status)) { + if (WTERMSIG(status)) { #ifdef WCOREDUMP - nxt_alert(task, "process %PI exited on signal %d%s", - pid, WTERMSIG(status), - WCOREDUMP(status) ? " (core dumped)" : ""); + nxt_alert(task, "process %PI exited on signal %d%s", pid, + WTERMSIG(status), WCOREDUMP(status) ? " (core dumped)" : ""); #else - nxt_alert(task, "process %PI exited on signal %d", - pid, WTERMSIG(status)); + nxt_alert(task, "process %PI exited on signal %d", pid, WTERMSIG(status)); #endif - } else { - nxt_trace(task, "process %PI exited with code %d", - pid, WEXITSTATUS(status)); - } + } else { + nxt_trace(task, "process %PI exited with code %d", pid, + WEXITSTATUS(status)); + } - process = nxt_runtime_process_find(rt, pid); + process = nxt_runtime_process_find(rt, pid); - if (process != NULL) { - nxt_main_process_cleanup(task, process); + if (process != NULL) { + nxt_main_process_cleanup(task, process); - if (process->state == NXT_PROCESS_STATE_READY) { - process->stream = 0; - } + if (process->state == NXT_PROCESS_STATE_READY) { + process->stream = 0; + } - nxt_queue_init(&children); + nxt_queue_init(&children); - if (!nxt_queue_is_empty(&process->children)) { - nxt_queue_add(&children, &process->children); + if (!nxt_queue_is_empty(&process->children)) { + nxt_queue_add(&children, &process->children); - nxt_queue_init(&process->children); + nxt_queue_init(&process->children); - nxt_queue_each(child, &children, nxt_process_t, link) { - port = nxt_process_port_first(child); + nxt_queue_each(child, &children, nxt_process_t, link) { + port = nxt_process_port_first(child); - (void) nxt_port_socket_write(task, port, NXT_PORT_MSG_QUIT, - -1, 0, 0, NULL); - } nxt_queue_loop; - } + (void)nxt_port_socket_write(task, port, NXT_PORT_MSG_QUIT, -1, 0, 0, + NULL); + } + nxt_queue_loop; + } - if (nxt_exiting) { - nxt_process_close_ports(task, process); + if (nxt_exiting) { + nxt_process_close_ports(task, process); - nxt_queue_each(child, &children, nxt_process_t, link) { - nxt_queue_remove(&child->link); - child->link.next = NULL; + nxt_queue_each(child, &children, nxt_process_t, link) { + nxt_queue_remove(&child->link); + child->link.next = NULL; - nxt_process_close_ports(task, child); - } nxt_queue_loop; + nxt_process_close_ports(task, child); + } + nxt_queue_loop; - if (rt->nprocesses <= 1) { - nxt_runtime_quit(task, 0); + if (rt->nprocesses <= 1) { + nxt_runtime_quit(task, 0); - return; - } + return; + } - continue; - } + continue; + } - nxt_port_remove_notify_others(task, process); + nxt_port_remove_notify_others(task, process); - nxt_queue_each(child, &children, nxt_process_t, link) { - nxt_port_remove_notify_others(task, child); + nxt_queue_each(child, &children, nxt_process_t, link) { + nxt_port_remove_notify_others(task, child); - nxt_queue_remove(&child->link); - child->link.next = NULL; + nxt_queue_remove(&child->link); + child->link.next = NULL; - nxt_process_close_ports(task, child); - } nxt_queue_loop; + nxt_process_close_ports(task, child); + } + nxt_queue_loop; - init = *(nxt_process_init_t *) nxt_process_init(process); + init = *(nxt_process_init_t *)nxt_process_init(process); - nxt_process_close_ports(task, process); + nxt_process_close_ports(task, process); - if (init.restart) { - ret = nxt_process_init_start(task, init); - if (nxt_slow_path(ret == NXT_ERROR)) { - nxt_alert(task, "failed to restart %s", init.name); - } - } + if (init.restart) { + ret = nxt_process_init_start(task, init); + if (nxt_slow_path(ret == NXT_ERROR)) { + nxt_alert(task, "failed to restart %s", init.name); } + } } + } } - -static void -nxt_main_process_signal_handler(nxt_task_t *task, void *obj, void *data) -{ - nxt_trace(task, "signal signo:%d (%s) received, ignored", - (int) (uintptr_t) obj, data); +static void nxt_main_process_signal_handler(nxt_task_t *task, void *obj, + void *data) { + nxt_trace(task, "signal signo:%d (%s) received, ignored", (int)(uintptr_t)obj, + data); } +static void nxt_main_process_cleanup(nxt_task_t *task, nxt_process_t *process) { + if (process->isolation.cleanup != NULL) { + process->isolation.cleanup(task, process); + } -static void -nxt_main_process_cleanup(nxt_task_t *task, nxt_process_t *process) -{ - if (process->isolation.cleanup != NULL) { - process->isolation.cleanup(task, process); - } - - if (process->isolation.cgroup_cleanup != NULL) { - process->isolation.cgroup_cleanup(task, process); - } + if (process->isolation.cgroup_cleanup != NULL) { + process->isolation.cgroup_cleanup(task, process); + } } +static void nxt_main_port_socket_handler(nxt_task_t *task, + nxt_port_recv_msg_t *msg) { + size_t size; + nxt_int_t ret; + nxt_buf_t *b, *out; + nxt_port_t *port; + nxt_sockaddr_t *sa; + nxt_port_msg_type_t type; + nxt_listening_socket_t ls; + u_char message[2048]; -static void -nxt_main_port_socket_handler(nxt_task_t *task, nxt_port_recv_msg_t *msg) -{ - size_t size; - nxt_int_t ret; - nxt_buf_t *b, *out; - nxt_port_t *port; - nxt_sockaddr_t *sa; - nxt_port_msg_type_t type; - nxt_listening_socket_t ls; - u_char message[2048]; - - port = nxt_runtime_port_find(task->thread->runtime, msg->port_msg.pid, - msg->port_msg.reply_port); - if (nxt_slow_path(port == NULL)) { - return; - } - - if (nxt_slow_path(port->type != NXT_PROCESS_ROUTER)) { - nxt_alert(task, "process %PI cannot create listener sockets", - msg->port_msg.pid); + port = nxt_runtime_port_find(task->thread->runtime, msg->port_msg.pid, + msg->port_msg.reply_port); + if (nxt_slow_path(port == NULL)) { + return; + } - return; - } + if (nxt_slow_path(port->type != NXT_PROCESS_ROUTER)) { + nxt_alert(task, "process %PI cannot create listener sockets", + msg->port_msg.pid); - b = msg->buf; - sa = (nxt_sockaddr_t *) b->mem.pos; + return; + } - /* TODO check b size and make plain */ + b = msg->buf; + sa = (nxt_sockaddr_t *)b->mem.pos; - ls.socket = -1; - ls.error = NXT_SOCKET_ERROR_SYSTEM; - ls.start = message; - ls.end = message + sizeof(message); + /* TODO check b size and make plain */ - nxt_debug(task, "listening socket \"%*s\"", - (size_t) sa->length, nxt_sockaddr_start(sa)); + ls.socket = -1; + ls.error = NXT_SOCKET_ERROR_SYSTEM; + ls.start = message; + ls.end = message + sizeof(message); - ret = nxt_main_listening_socket(sa, &ls); + nxt_debug(task, "listening socket \"%*s\"", (size_t)sa->length, + nxt_sockaddr_start(sa)); - if (ret == NXT_OK) { - nxt_debug(task, "socket(\"%*s\"): %d", - (size_t) sa->length, nxt_sockaddr_start(sa), ls.socket); + ret = nxt_main_listening_socket(sa, &ls); - out = NULL; + if (ret == NXT_OK) { + nxt_debug(task, "socket(\"%*s\"): %d", (size_t)sa->length, + nxt_sockaddr_start(sa), ls.socket); - type = NXT_PORT_MSG_RPC_READY_LAST | NXT_PORT_MSG_CLOSE_FD; + out = NULL; - } else { - size = ls.end - ls.start; + type = NXT_PORT_MSG_RPC_READY_LAST | NXT_PORT_MSG_CLOSE_FD; - nxt_alert(task, "%*s", size, ls.start); + } else { + size = ls.end - ls.start; - out = nxt_buf_mem_ts_alloc(task, task->thread->engine->mem_pool, - size + 1); - if (nxt_fast_path(out != NULL)) { - *out->mem.free++ = (uint8_t) ls.error; + nxt_alert(task, "%*s", size, ls.start); - out->mem.free = nxt_cpymem(out->mem.free, ls.start, size); - } + out = nxt_buf_mem_ts_alloc(task, task->thread->engine->mem_pool, size + 1); + if (nxt_fast_path(out != NULL)) { + *out->mem.free++ = (uint8_t)ls.error; - type = NXT_PORT_MSG_RPC_ERROR; + out->mem.free = nxt_cpymem(out->mem.free, ls.start, size); } - nxt_port_socket_write(task, port, type, ls.socket, msg->port_msg.stream, - 0, out); -} + type = NXT_PORT_MSG_RPC_ERROR; + } + nxt_port_socket_write(task, port, type, ls.socket, msg->port_msg.stream, 0, + out); +} -static nxt_int_t -nxt_main_listening_socket(nxt_sockaddr_t *sa, nxt_listening_socket_t *ls) -{ - nxt_err_t err; - nxt_socket_t s; +static nxt_int_t nxt_main_listening_socket(nxt_sockaddr_t *sa, + nxt_listening_socket_t *ls) { + nxt_err_t err; + nxt_socket_t s; - const socklen_t length = sizeof(int); - static const int enable = 1; + const socklen_t length = sizeof(int); + static const int enable = 1; - s = socket(sa->u.sockaddr.sa_family, sa->type, 0); + s = socket(sa->u.sockaddr.sa_family, sa->type, 0); - if (nxt_slow_path(s == -1)) { - err = nxt_errno; + if (nxt_slow_path(s == -1)) { + err = nxt_errno; #if (NXT_INET6) - if (err == EAFNOSUPPORT && sa->u.sockaddr.sa_family == AF_INET6) { - ls->error = NXT_SOCKET_ERROR_NOINET6; - } + if (err == EAFNOSUPPORT && sa->u.sockaddr.sa_family == AF_INET6) { + ls->error = NXT_SOCKET_ERROR_NOINET6; + } #endif - ls->end = nxt_sprintf(ls->start, ls->end, - "socket(\\\"%*s\\\") failed %E", - (size_t) sa->length, nxt_sockaddr_start(sa), err); + ls->end = nxt_sprintf(ls->start, ls->end, "socket(\\\"%*s\\\") failed %E", + (size_t)sa->length, nxt_sockaddr_start(sa), err); - return NXT_ERROR; - } + return NXT_ERROR; + } - if (setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &enable, length) != 0) { - ls->end = nxt_sprintf(ls->start, ls->end, - "setsockopt(\\\"%*s\\\", SO_REUSEADDR) failed %E", - (size_t) sa->length, nxt_sockaddr_start(sa), - nxt_errno); - goto fail; - } + if (setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &enable, length) != 0) { + ls->end = nxt_sprintf( + ls->start, ls->end, "setsockopt(\\\"%*s\\\", SO_REUSEADDR) failed %E", + (size_t)sa->length, nxt_sockaddr_start(sa), nxt_errno); + goto fail; + } #if (NXT_INET6) - if (sa->u.sockaddr.sa_family == AF_INET6) { + if (sa->u.sockaddr.sa_family == AF_INET6) { - if (setsockopt(s, IPPROTO_IPV6, IPV6_V6ONLY, &enable, length) != 0) { - ls->end = nxt_sprintf(ls->start, ls->end, - "setsockopt(\\\"%*s\\\", IPV6_V6ONLY) failed %E", - (size_t) sa->length, nxt_sockaddr_start(sa), - nxt_errno); - goto fail; - } + if (setsockopt(s, IPPROTO_IPV6, IPV6_V6ONLY, &enable, length) != 0) { + ls->end = nxt_sprintf( + ls->start, ls->end, "setsockopt(\\\"%*s\\\", IPV6_V6ONLY) failed %E", + (size_t)sa->length, nxt_sockaddr_start(sa), nxt_errno); + goto fail; } + } #endif - if (bind(s, &sa->u.sockaddr, sa->socklen) != 0) { - err = nxt_errno; + if (bind(s, &sa->u.sockaddr, sa->socklen) != 0) { + err = nxt_errno; #if (NXT_HAVE_UNIX_DOMAIN) - if (sa->u.sockaddr.sa_family == AF_UNIX) { - switch (err) { + if (sa->u.sockaddr.sa_family == AF_UNIX) { + switch (err) { - case EACCES: - ls->error = NXT_SOCKET_ERROR_ACCESS; - break; + case EACCES: + ls->error = NXT_SOCKET_ERROR_ACCESS; + break; - case ENOENT: - case ENOTDIR: - ls->error = NXT_SOCKET_ERROR_PATH; - break; - } + case ENOENT: + case ENOTDIR: + ls->error = NXT_SOCKET_ERROR_PATH; + break; + } - } else + } else #endif - { - switch (err) { - - case EACCES: - ls->error = NXT_SOCKET_ERROR_PORT; - break; + { + switch (err) { - case EADDRINUSE: - ls->error = NXT_SOCKET_ERROR_INUSE; - break; + case EACCES: + ls->error = NXT_SOCKET_ERROR_PORT; + break; - case EADDRNOTAVAIL: - ls->error = NXT_SOCKET_ERROR_NOADDR; - break; - } - } + case EADDRINUSE: + ls->error = NXT_SOCKET_ERROR_INUSE; + break; - ls->end = nxt_sprintf(ls->start, ls->end, "bind(\\\"%*s\\\") failed %E", - (size_t) sa->length, nxt_sockaddr_start(sa), err); - goto fail; + case EADDRNOTAVAIL: + ls->error = NXT_SOCKET_ERROR_NOADDR; + break; + } } -#if (NXT_HAVE_UNIX_DOMAIN) + ls->end = nxt_sprintf(ls->start, ls->end, "bind(\\\"%*s\\\") failed %E", + (size_t)sa->length, nxt_sockaddr_start(sa), err); + goto fail; + } - if (sa->u.sockaddr.sa_family == AF_UNIX - && sa->u.sockaddr_un.sun_path[0] != '\0') - { - char *filename; - nxt_thread_t *thr; +#if (NXT_HAVE_UNIX_DOMAIN) - filename = sa->u.sockaddr_un.sun_path; + if (sa->u.sockaddr.sa_family == AF_UNIX && + sa->u.sockaddr_un.sun_path[0] != '\0') { + char *filename; + nxt_thread_t *thr; - if (chmod(filename, 0666) != 0) { - ls->end = nxt_sprintf(ls->start, ls->end, - "chmod(\\\"%s\\\") failed %E", - filename, nxt_errno); - goto fail; - } + filename = sa->u.sockaddr_un.sun_path; - thr = nxt_thread(); - nxt_runtime_listen_socket_add(thr->runtime, sa); + if (chmod(filename, 0666) != 0) { + ls->end = nxt_sprintf(ls->start, ls->end, "chmod(\\\"%s\\\") failed %E", + filename, nxt_errno); + goto fail; } + thr = nxt_thread(); + nxt_runtime_listen_socket_add(thr->runtime, sa); + } + #endif - ls->socket = s; + ls->socket = s; - return NXT_OK; + return NXT_OK; fail: - (void) close(s); + (void)close(s); - return NXT_ERROR; + return NXT_ERROR; } - -static void -nxt_main_port_socket_unlink_handler(nxt_task_t *task, nxt_port_recv_msg_t *msg) -{ +static void nxt_main_port_socket_unlink_handler(nxt_task_t *task, + nxt_port_recv_msg_t *msg) { #if (NXT_HAVE_UNIX_DOMAIN) - size_t i; - nxt_buf_t *b; - const char *filename; - nxt_runtime_t *rt; - nxt_sockaddr_t *sa; - nxt_listen_socket_t *ls; + size_t i; + nxt_buf_t *b; + const char *filename; + nxt_runtime_t *rt; + nxt_sockaddr_t *sa; + nxt_listen_socket_t *ls; - b = msg->buf; - sa = (nxt_sockaddr_t *) b->mem.pos; - - filename = sa->u.sockaddr_un.sun_path; - unlink(filename); + b = msg->buf; + sa = (nxt_sockaddr_t *)b->mem.pos; - rt = task->thread->runtime; + filename = sa->u.sockaddr_un.sun_path; + unlink(filename); - for (i = 0; i < rt->listen_sockets->nelts; i++) { - const char *name; + rt = task->thread->runtime; - ls = (nxt_listen_socket_t *) rt->listen_sockets->elts + i; - sa = ls->sockaddr; + for (i = 0; i < rt->listen_sockets->nelts; i++) { + const char *name; - if (sa->u.sockaddr.sa_family != AF_UNIX - || sa->u.sockaddr_un.sun_path[0] == '\0') - { - continue; - } + ls = (nxt_listen_socket_t *)rt->listen_sockets->elts + i; + sa = ls->sockaddr; - name = sa->u.sockaddr_un.sun_path; - if (strcmp(name, filename) != 0) { - continue; - } + if (sa->u.sockaddr.sa_family != AF_UNIX || + sa->u.sockaddr_un.sun_path[0] == '\0') { + continue; + } - nxt_array_remove(rt->listen_sockets, ls); - break; + name = sa->u.sockaddr_un.sun_path; + if (strcmp(name, filename) != 0) { + continue; } + + nxt_array_remove(rt->listen_sockets, ls); + break; + } #endif } - -static nxt_conf_map_t nxt_app_lang_module_map[] = { +static nxt_conf_map_t nxt_app_lang_module_map[] = { { nxt_string("type"), NXT_CONF_MAP_INT, @@ -1373,8 +1297,7 @@ static nxt_conf_map_t nxt_app_lang_module_map[] = { }, }; - -static nxt_conf_map_t nxt_app_lang_mounts_map[] = { +static nxt_conf_map_t nxt_app_lang_mounts_map[] = { { nxt_string("src"), NXT_CONF_MAP_CSTRZ, @@ -1407,328 +1330,316 @@ static nxt_conf_map_t nxt_app_lang_mounts_map[] = { }, }; +static void nxt_main_port_modules_handler(nxt_task_t *task, + nxt_port_recv_msg_t *msg) { + uint32_t index, jindex, nmounts; + nxt_mp_t *mp; + nxt_int_t ret; + nxt_buf_t *b; + nxt_port_t *port; + nxt_runtime_t *rt; + nxt_fs_mount_t *mnt; + nxt_conf_value_t *conf, *root, *value, *mounts; + nxt_app_lang_module_t *lang; -static void -nxt_main_port_modules_handler(nxt_task_t *task, nxt_port_recv_msg_t *msg) -{ - uint32_t index, jindex, nmounts; - nxt_mp_t *mp; - nxt_int_t ret; - nxt_buf_t *b; - nxt_port_t *port; - nxt_runtime_t *rt; - nxt_fs_mount_t *mnt; - nxt_conf_value_t *conf, *root, *value, *mounts; - nxt_app_lang_module_t *lang; + static nxt_str_t root_path = nxt_string("/"); + static nxt_str_t mounts_name = nxt_string("mounts"); - static nxt_str_t root_path = nxt_string("/"); - static nxt_str_t mounts_name = nxt_string("mounts"); + rt = task->thread->runtime; - rt = task->thread->runtime; + if (msg->port_msg.pid != rt->port_by_type[NXT_PROCESS_DISCOVERY]->pid) { + nxt_alert(task, "process %PI cannot send modules", msg->port_msg.pid); + return; + } - if (msg->port_msg.pid != rt->port_by_type[NXT_PROCESS_DISCOVERY]->pid) { - nxt_alert(task, "process %PI cannot send modules", msg->port_msg.pid); - return; - } + if (nxt_exiting) { + nxt_debug(task, "ignoring discovered modules, exiting"); + return; + } - if (nxt_exiting) { - nxt_debug(task, "ignoring discovered modules, exiting"); - return; - } + port = nxt_runtime_port_find(task->thread->runtime, msg->port_msg.pid, + msg->port_msg.reply_port); - port = nxt_runtime_port_find(task->thread->runtime, msg->port_msg.pid, - msg->port_msg.reply_port); + if (nxt_fast_path(port != NULL)) { + (void)nxt_port_socket_write(task, port, NXT_PORT_MSG_RPC_ERROR, -1, + msg->port_msg.stream, 0, NULL); + } - if (nxt_fast_path(port != NULL)) { - (void) nxt_port_socket_write(task, port, NXT_PORT_MSG_RPC_ERROR, -1, - msg->port_msg.stream, 0, NULL); - } + b = msg->buf; - b = msg->buf; + if (b == NULL) { + return; + } - if (b == NULL) { - return; - } + mp = nxt_mp_create(1024, 128, 256, 32); + if (mp == NULL) { + return; + } - mp = nxt_mp_create(1024, 128, 256, 32); - if (mp == NULL) { - return; - } + b = nxt_buf_chk_make_plain(mp, b, msg->size); - b = nxt_buf_chk_make_plain(mp, b, msg->size); + if (b == NULL) { + return; + } - if (b == NULL) { - return; - } + nxt_debug(task, "application languages: \"%*s\"", b->mem.free - b->mem.pos, + b->mem.pos); - nxt_debug(task, "application languages: \"%*s\"", - b->mem.free - b->mem.pos, b->mem.pos); + conf = nxt_conf_json_parse(mp, b->mem.pos, b->mem.free, NULL); + if (conf == NULL) { + goto fail; + } - conf = nxt_conf_json_parse(mp, b->mem.pos, b->mem.free, NULL); - if (conf == NULL) { - goto fail; - } + root = nxt_conf_get_path(conf, &root_path); + if (root == NULL) { + goto fail; + } - root = nxt_conf_get_path(conf, &root_path); - if (root == NULL) { - goto fail; + for (index = 0; /* void */; index++) { + value = nxt_conf_get_array_element(root, index); + if (value == NULL) { + break; } - for (index = 0; /* void */ ; index++) { - value = nxt_conf_get_array_element(root, index); - if (value == NULL) { - break; - } - - lang = nxt_array_zero_add(rt->languages); - if (lang == NULL) { - goto fail; - } - - lang->module = NULL; + lang = nxt_array_zero_add(rt->languages); + if (lang == NULL) { + goto fail; + } - ret = nxt_conf_map_object(rt->mem_pool, value, nxt_app_lang_module_map, - nxt_nitems(nxt_app_lang_module_map), lang); + lang->module = NULL; - if (ret != NXT_OK) { - goto fail; - } + ret = nxt_conf_map_object(rt->mem_pool, value, nxt_app_lang_module_map, + nxt_nitems(nxt_app_lang_module_map), lang); - mounts = nxt_conf_get_object_member(value, &mounts_name, NULL); - if (mounts == NULL) { - nxt_alert(task, "missing mounts from discovery message."); - goto fail; - } + if (ret != NXT_OK) { + goto fail; + } - if (nxt_conf_type(mounts) != NXT_CONF_ARRAY) { - nxt_alert(task, "invalid mounts type from discovery message."); - goto fail; - } + mounts = nxt_conf_get_object_member(value, &mounts_name, NULL); + if (mounts == NULL) { + nxt_alert(task, "missing mounts from discovery message."); + goto fail; + } - nmounts = nxt_conf_array_elements_count(mounts); + if (nxt_conf_type(mounts) != NXT_CONF_ARRAY) { + nxt_alert(task, "invalid mounts type from discovery message."); + goto fail; + } - lang->mounts = nxt_array_create(rt->mem_pool, nmounts, - sizeof(nxt_fs_mount_t)); + nmounts = nxt_conf_array_elements_count(mounts); - if (lang->mounts == NULL) { - goto fail; - } + lang->mounts = + nxt_array_create(rt->mem_pool, nmounts, sizeof(nxt_fs_mount_t)); - for (jindex = 0; /* */; jindex++) { - value = nxt_conf_get_array_element(mounts, jindex); - if (value == NULL) { - break; - } + if (lang->mounts == NULL) { + goto fail; + } - mnt = nxt_array_zero_add(lang->mounts); - if (mnt == NULL) { - goto fail; - } + for (jindex = 0; /* */; jindex++) { + value = nxt_conf_get_array_element(mounts, jindex); + if (value == NULL) { + break; + } - mnt->builtin = 1; - mnt->deps = 1; + mnt = nxt_array_zero_add(lang->mounts); + if (mnt == NULL) { + goto fail; + } - ret = nxt_conf_map_object(rt->mem_pool, value, - nxt_app_lang_mounts_map, - nxt_nitems(nxt_app_lang_mounts_map), mnt); + mnt->builtin = 1; + mnt->deps = 1; - if (ret != NXT_OK) { - goto fail; - } - } + ret = nxt_conf_map_object(rt->mem_pool, value, nxt_app_lang_mounts_map, + nxt_nitems(nxt_app_lang_mounts_map), mnt); - nxt_debug(task, "lang %d %s \"%s\" (%d mounts)", - lang->type, lang->version, lang->file, lang->mounts->nelts); + if (ret != NXT_OK) { + goto fail; + } } - qsort(rt->languages->elts, rt->languages->nelts, - sizeof(nxt_app_lang_module_t), nxt_app_lang_compare); + nxt_debug(task, "lang %d %s \"%s\" (%d mounts)", lang->type, lang->version, + lang->file, lang->mounts->nelts); + } + + qsort(rt->languages->elts, rt->languages->nelts, + sizeof(nxt_app_lang_module_t), nxt_app_lang_compare); fail: - nxt_mp_destroy(mp); + nxt_mp_destroy(mp); - ret = nxt_process_init_start(task, nxt_controller_process); - if (ret == NXT_OK) { - ret = nxt_process_init_start(task, nxt_router_process); - } + ret = nxt_process_init_start(task, nxt_controller_process); + if (ret == NXT_OK) { + ret = nxt_process_init_start(task, nxt_router_process); + } - if (nxt_slow_path(ret == NXT_ERROR)) { - nxt_exiting = 1; + if (nxt_slow_path(ret == NXT_ERROR)) { + nxt_exiting = 1; - nxt_runtime_quit(task, 1); - } + nxt_runtime_quit(task, 1); + } } +static int nxt_cdecl nxt_app_lang_compare(const void *v1, const void *v2) { + int n; + const nxt_app_lang_module_t *lang1, *lang2; -static int nxt_cdecl -nxt_app_lang_compare(const void *v1, const void *v2) -{ - int n; - const nxt_app_lang_module_t *lang1, *lang2; - - lang1 = v1; - lang2 = v2; + lang1 = v1; + lang2 = v2; - n = lang1->type - lang2->type; + n = lang1->type - lang2->type; - if (n != 0) { - return n; - } + if (n != 0) { + return n; + } - n = nxt_strverscmp(lang1->version, lang2->version); + n = nxt_strverscmp(lang1->version, lang2->version); - /* Negate result to move higher versions to the beginning. */ + /* Negate result to move higher versions to the beginning. */ - return -n; + return -n; } +static void nxt_main_port_conf_store_handler(nxt_task_t *task, + nxt_port_recv_msg_t *msg) { + void *p; + size_t n, size; + nxt_int_t ret; + nxt_port_t *ctl_port; + nxt_runtime_t *rt; + u_char ver[NXT_INT_T_LEN]; -static void -nxt_main_port_conf_store_handler(nxt_task_t *task, nxt_port_recv_msg_t *msg) -{ - void *p; - size_t n, size; - nxt_int_t ret; - nxt_port_t *ctl_port; - nxt_runtime_t *rt; - u_char ver[NXT_INT_T_LEN]; + rt = task->thread->runtime; - rt = task->thread->runtime; + ctl_port = rt->port_by_type[NXT_PROCESS_CONTROLLER]; - ctl_port = rt->port_by_type[NXT_PROCESS_CONTROLLER]; + if (nxt_slow_path(msg->port_msg.pid != ctl_port->pid)) { + nxt_alert(task, "process %PI cannot store conf", msg->port_msg.pid); + return; + } - if (nxt_slow_path(msg->port_msg.pid != ctl_port->pid)) { - nxt_alert(task, "process %PI cannot store conf", msg->port_msg.pid); - return; - } + p = MAP_FAILED; - p = MAP_FAILED; + /* + * Ancient compilers like gcc 4.8.5 on CentOS 7 wants 'size' to be + * initialized in 'cleanup' section. + */ + size = 0; - /* - * Ancient compilers like gcc 4.8.5 on CentOS 7 wants 'size' to be - * initialized in 'cleanup' section. - */ - size = 0; + if (nxt_slow_path(msg->fd[0] == -1)) { + nxt_alert(task, "conf_store_handler: invalid shm fd"); + goto error; + } - if (nxt_slow_path(msg->fd[0] == -1)) { - nxt_alert(task, "conf_store_handler: invalid shm fd"); - goto error; - } + if (nxt_buf_mem_used_size(&msg->buf->mem) != sizeof(size_t)) { + nxt_alert(task, "conf_store_handler: unexpected buffer size (%d)", + (int)nxt_buf_mem_used_size(&msg->buf->mem)); + goto error; + } - if (nxt_buf_mem_used_size(&msg->buf->mem) != sizeof(size_t)) { - nxt_alert(task, "conf_store_handler: unexpected buffer size (%d)", - (int) nxt_buf_mem_used_size(&msg->buf->mem)); - goto error; - } + nxt_memcpy(&size, msg->buf->mem.pos, sizeof(size_t)); - nxt_memcpy(&size, msg->buf->mem.pos, sizeof(size_t)); + p = nxt_mem_mmap(NULL, size, PROT_READ, MAP_SHARED, msg->fd[0], 0); - p = nxt_mem_mmap(NULL, size, PROT_READ, MAP_SHARED, msg->fd[0], 0); + nxt_fd_close(msg->fd[0]); + msg->fd[0] = -1; - nxt_fd_close(msg->fd[0]); - msg->fd[0] = -1; - - if (nxt_slow_path(p == MAP_FAILED)) { - goto error; - } - - nxt_debug(task, "conf_store_handler(%uz): %*s", size, size, p); + if (nxt_slow_path(p == MAP_FAILED)) { + goto error; + } - if (nxt_conf_ver != NXT_VERNUM) { - n = nxt_sprintf(ver, ver + NXT_INT_T_LEN, "%d", NXT_VERNUM) - ver; + nxt_debug(task, "conf_store_handler(%uz): %*s", size, size, p); - ret = nxt_main_file_store(task, rt->ver_tmp, rt->ver, ver, n); - if (nxt_slow_path(ret != NXT_OK)) { - goto error; - } + if (nxt_conf_ver != NXT_VERNUM) { + n = nxt_sprintf(ver, ver + NXT_INT_T_LEN, "%d", NXT_VERNUM) - ver; - nxt_conf_ver = NXT_VERNUM; + ret = nxt_main_file_store(task, rt->ver_tmp, rt->ver, ver, n); + if (nxt_slow_path(ret != NXT_OK)) { + goto error; } - ret = nxt_main_file_store(task, rt->conf_tmp, rt->conf, p, size); + nxt_conf_ver = NXT_VERNUM; + } - if (nxt_fast_path(ret == NXT_OK)) { - goto cleanup; - } + ret = nxt_main_file_store(task, rt->conf_tmp, rt->conf, p, size); + + if (nxt_fast_path(ret == NXT_OK)) { + goto cleanup; + } error: - nxt_alert(task, "failed to store current configuration"); + nxt_alert(task, "failed to store current configuration"); cleanup: - if (p != MAP_FAILED) { - nxt_mem_munmap(p, size); - } + if (p != MAP_FAILED) { + nxt_mem_munmap(p, size); + } - if (msg->fd[0] != -1) { - nxt_fd_close(msg->fd[0]); - msg->fd[0] = -1; - } + if (msg->fd[0] != -1) { + nxt_fd_close(msg->fd[0]); + msg->fd[0] = -1; + } } +static nxt_int_t nxt_main_file_store(nxt_task_t *task, const char *tmp_name, + const char *name, u_char *buf, + size_t size) { + ssize_t n; + nxt_int_t ret; + nxt_file_t file; -static nxt_int_t -nxt_main_file_store(nxt_task_t *task, const char *tmp_name, const char *name, - u_char *buf, size_t size) -{ - ssize_t n; - nxt_int_t ret; - nxt_file_t file; - - nxt_memzero(&file, sizeof(nxt_file_t)); + nxt_memzero(&file, sizeof(nxt_file_t)); - file.name = (nxt_file_name_t *) name; + file.name = (nxt_file_name_t *)name; - ret = nxt_file_open(task, &file, NXT_FILE_WRONLY, NXT_FILE_TRUNCATE, - NXT_FILE_OWNER_ACCESS); - if (nxt_slow_path(ret != NXT_OK)) { - return NXT_ERROR; - } + ret = nxt_file_open(task, &file, NXT_FILE_WRONLY, NXT_FILE_TRUNCATE, + NXT_FILE_OWNER_ACCESS); + if (nxt_slow_path(ret != NXT_OK)) { + return NXT_ERROR; + } - n = nxt_file_write(&file, buf, size, 0); + n = nxt_file_write(&file, buf, size, 0); - nxt_file_close(task, &file); + nxt_file_close(task, &file); - if (nxt_slow_path(n != (ssize_t) size)) { - (void) nxt_file_delete(file.name); - return NXT_ERROR; - } + if (nxt_slow_path(n != (ssize_t)size)) { + (void)nxt_file_delete(file.name); + return NXT_ERROR; + } - return nxt_file_rename(file.name, (nxt_file_name_t *) name); + return nxt_file_rename(file.name, (nxt_file_name_t *)name); } +static void nxt_main_port_access_log_handler(nxt_task_t *task, + nxt_port_recv_msg_t *msg) { + u_char *path; + nxt_int_t ret; + nxt_file_t file; + nxt_port_t *port; + nxt_port_msg_type_t type; -static void -nxt_main_port_access_log_handler(nxt_task_t *task, nxt_port_recv_msg_t *msg) -{ - u_char *path; - nxt_int_t ret; - nxt_file_t file; - nxt_port_t *port; - nxt_port_msg_type_t type; - - nxt_debug(task, "opening access log file"); + nxt_debug(task, "opening access log file"); - path = msg->buf->mem.pos; + path = msg->buf->mem.pos; - nxt_memzero(&file, sizeof(nxt_file_t)); + nxt_memzero(&file, sizeof(nxt_file_t)); - file.name = (nxt_file_name_t *) path; - file.log_level = NXT_LOG_ERR; + file.name = (nxt_file_name_t *)path; + file.log_level = NXT_LOG_ERR; - ret = nxt_file_open(task, &file, O_WRONLY | O_APPEND, O_CREAT, - NXT_FILE_OWNER_ACCESS); + ret = nxt_file_open(task, &file, O_WRONLY | O_APPEND, O_CREAT, + NXT_FILE_OWNER_ACCESS); - type = (ret == NXT_OK) ? NXT_PORT_MSG_RPC_READY_LAST | NXT_PORT_MSG_CLOSE_FD - : NXT_PORT_MSG_RPC_ERROR; + type = (ret == NXT_OK) ? NXT_PORT_MSG_RPC_READY_LAST | NXT_PORT_MSG_CLOSE_FD + : NXT_PORT_MSG_RPC_ERROR; - port = nxt_runtime_port_find(task->thread->runtime, msg->port_msg.pid, - msg->port_msg.reply_port); + port = nxt_runtime_port_find(task->thread->runtime, msg->port_msg.pid, + msg->port_msg.reply_port); - if (nxt_fast_path(port != NULL)) { - (void) nxt_port_socket_write(task, port, type, file.fd, - msg->port_msg.stream, 0, NULL); - } + if (nxt_fast_path(port != NULL)) { + (void)nxt_port_socket_write(task, port, type, file.fd, msg->port_msg.stream, + 0, NULL); + } } diff --git a/src/nxt_main_process.h b/src/nxt_main_process.h index ef083d630..6ce64aa42 100644 --- a/src/nxt_main_process.h +++ b/src/nxt_main_process.h @@ -7,31 +7,27 @@ #ifndef _NXT_MAIN_PROCESS_H_INCLUDED_ #define _NXT_MAIN_PROCESS_H_INCLUDED_ - typedef enum { - NXT_SOCKET_ERROR_SYSTEM = 0, - NXT_SOCKET_ERROR_NOINET6, - NXT_SOCKET_ERROR_PORT, - NXT_SOCKET_ERROR_INUSE, - NXT_SOCKET_ERROR_NOADDR, - NXT_SOCKET_ERROR_ACCESS, - NXT_SOCKET_ERROR_PATH, + NXT_SOCKET_ERROR_SYSTEM = 0, + NXT_SOCKET_ERROR_NOINET6, + NXT_SOCKET_ERROR_PORT, + NXT_SOCKET_ERROR_INUSE, + NXT_SOCKET_ERROR_NOADDR, + NXT_SOCKET_ERROR_ACCESS, + NXT_SOCKET_ERROR_PATH, } nxt_socket_error_t; - nxt_int_t nxt_main_process_start(nxt_thread_t *thr, nxt_task_t *task, - nxt_runtime_t *runtime); - - -NXT_EXPORT extern nxt_uint_t nxt_conf_ver; -NXT_EXPORT extern const nxt_process_init_t nxt_discovery_process; -NXT_EXPORT extern const nxt_process_init_t nxt_controller_process; -NXT_EXPORT extern const nxt_process_init_t nxt_router_process; -NXT_EXPORT extern const nxt_process_init_t nxt_proto_process; -NXT_EXPORT extern const nxt_process_init_t nxt_app_process; + nxt_runtime_t *runtime); -extern const nxt_sig_event_t nxt_main_process_signals[]; -extern const nxt_sig_event_t nxt_process_signals[]; +NXT_EXPORT extern nxt_uint_t nxt_conf_ver; +NXT_EXPORT extern const nxt_process_init_t nxt_discovery_process; +NXT_EXPORT extern const nxt_process_init_t nxt_controller_process; +NXT_EXPORT extern const nxt_process_init_t nxt_router_process; +NXT_EXPORT extern const nxt_process_init_t nxt_proto_process; +NXT_EXPORT extern const nxt_process_init_t nxt_app_process; +extern const nxt_sig_event_t nxt_main_process_signals[]; +extern const nxt_sig_event_t nxt_process_signals[]; #endif /* _NXT_MAIN_PROCESS_H_INCLUDED_ */ diff --git a/src/nxt_malloc.c b/src/nxt_malloc.c index 5ea7322f6..92084c741 100644 --- a/src/nxt_malloc.c +++ b/src/nxt_malloc.c @@ -6,118 +6,90 @@ #include +static nxt_log_moderation_t nxt_malloc_log_moderation = { + NXT_LOG_ALERT, 2, "memory allocation failed", NXT_LOG_MODERATION}; -static nxt_log_moderation_t nxt_malloc_log_moderation = { - NXT_LOG_ALERT, 2, "memory allocation failed", NXT_LOG_MODERATION -}; +static nxt_log_t *nxt_malloc_log(void) { + nxt_thread_t *thr; + thr = nxt_thread(); -static nxt_log_t * -nxt_malloc_log(void) -{ - nxt_thread_t *thr; + if (thr != NULL && thr->log != NULL) { + return thr->log; + } - thr = nxt_thread(); - - if (thr != NULL && thr->log != NULL) { - return thr->log; - } - - return &nxt_main_log; + return &nxt_main_log; } +void *nxt_malloc(size_t size) { + void *p; -void * -nxt_malloc(size_t size) -{ - void *p; - - p = malloc(size); + p = malloc(size); - if (nxt_fast_path(p != NULL)) { - nxt_log_debug(nxt_malloc_log(), "malloc(%uz): %p", size, p); + if (nxt_fast_path(p != NULL)) { + nxt_log_debug(nxt_malloc_log(), "malloc(%uz): %p", size, p); - } else { - nxt_log_alert_moderate(&nxt_malloc_log_moderation, nxt_malloc_log(), - "malloc(%uz) failed %E", size, nxt_errno); - } + } else { + nxt_log_alert_moderate(&nxt_malloc_log_moderation, nxt_malloc_log(), + "malloc(%uz) failed %E", size, nxt_errno); + } - return p; + return p; } +void *nxt_zalloc(size_t size) { + void *p; -void * -nxt_zalloc(size_t size) -{ - void *p; - - p = nxt_malloc(size); + p = nxt_malloc(size); - if (nxt_fast_path(p != NULL)) { - nxt_memzero(p, size); - } + if (nxt_fast_path(p != NULL)) { + nxt_memzero(p, size); + } - return p; + return p; } +void *nxt_realloc(void *p, size_t size) { + void *n; + uintptr_t ptr; -void * -nxt_realloc(void *p, size_t size) -{ - void *n; - uintptr_t ptr; - - /* - * Workaround for a warning on GCC 12 about using "p" pointer in debug log - * after realloc(). - */ - ptr = (uintptr_t) p; + /* + * Workaround for a warning on GCC 12 about using "p" pointer in debug log + * after realloc(). + */ + ptr = (uintptr_t)p; - n = realloc(p, size); + n = realloc(p, size); - if (nxt_fast_path(n != NULL)) { - nxt_log_debug(nxt_malloc_log(), "realloc(%p, %uz): %p", ptr, size, n); + if (nxt_fast_path(n != NULL)) { + nxt_log_debug(nxt_malloc_log(), "realloc(%p, %uz): %p", ptr, size, n); - } else { - nxt_log_alert_moderate(&nxt_malloc_log_moderation, nxt_malloc_log(), - "realloc(%p, %uz) failed %E", - ptr, size, nxt_errno); - } + } else { + nxt_log_alert_moderate(&nxt_malloc_log_moderation, nxt_malloc_log(), + "realloc(%p, %uz) failed %E", ptr, size, nxt_errno); + } - return n; + return n; } - /* nxt_lvlhsh_* functions moved here to avoid references from nxt_lvlhsh.c. */ -void * -nxt_lvlhsh_alloc(void *data, size_t size) -{ - return nxt_memalign(size, size); -} - - -void -nxt_lvlhsh_free(void *data, void *p) -{ - nxt_free(p); +void *nxt_lvlhsh_alloc(void *data, size_t size) { + return nxt_memalign(size, size); } +void nxt_lvlhsh_free(void *data, void *p) { nxt_free(p); } #if (NXT_DEBUG) -void -nxt_free(void *p) -{ - nxt_log_debug(nxt_malloc_log(), "free(%p)", p); +void nxt_free(void *p) { + nxt_log_debug(nxt_malloc_log(), "free(%p)", p); - free(p); + free(p); } - #endif - #if (NXT_HAVE_POSIX_MEMALIGN) /* @@ -125,47 +97,41 @@ nxt_free(void *p) * Solaris 11, MacOSX 10.6 (Snow Leopard), NetBSD 5.0. */ -void * -nxt_memalign(size_t alignment, size_t size) -{ - void *p; - nxt_err_t err; +void *nxt_memalign(size_t alignment, size_t size) { + void *p; + nxt_err_t err; - err = posix_memalign(&p, alignment, size); + err = posix_memalign(&p, alignment, size); - if (nxt_fast_path(err == 0)) { - nxt_thread_log_debug("posix_memalign(%uz, %uz): %p", - alignment, size, p); - return p; - } + if (nxt_fast_path(err == 0)) { + nxt_thread_log_debug("posix_memalign(%uz, %uz): %p", alignment, size, p); + return p; + } - nxt_log_alert_moderate(&nxt_malloc_log_moderation, nxt_malloc_log(), - "posix_memalign(%uz, %uz) failed %E", - alignment, size, err); - return NULL; + nxt_log_alert_moderate(&nxt_malloc_log_moderation, nxt_malloc_log(), + "posix_memalign(%uz, %uz) failed %E", alignment, size, + err); + return NULL; } #elif (NXT_HAVE_MEMALIGN) /* memalign() presents in Solaris, HP-UX. */ -void * -nxt_memalign(size_t alignment, size_t size) -{ - void *p; +void *nxt_memalign(size_t alignment, size_t size) { + void *p; - p = memalign(alignment, size); + p = memalign(alignment, size); - if (nxt_fast_path(p != NULL)) { - nxt_thread_log_debug("memalign(%uz, %uz): %p", - alignment, size, p); - return p; - } + if (nxt_fast_path(p != NULL)) { + nxt_thread_log_debug("memalign(%uz, %uz): %p", alignment, size, p); + return p; + } - nxt_log_alert_moderate(&nxt_malloc_log_moderation, nxt_malloc_log(), - "memalign(%uz, %uz) failed %E", - alignment, size, nxt_errno); - return NULL; + nxt_log_alert_moderate(&nxt_malloc_log_moderation, nxt_malloc_log(), + "memalign(%uz, %uz) failed %E", alignment, size, + nxt_errno); + return NULL; } #elif (NXT_FREEBSD) @@ -177,49 +143,47 @@ nxt_memalign(size_t alignment, size_t size) * Allocations larger than 2K are always aligned to 4K. */ -void * -nxt_memalign(size_t alignment, size_t size) -{ - size_t aligned_size; - u_char *p; - nxt_err_t err; +void *nxt_memalign(size_t alignment, size_t size) { + size_t aligned_size; + u_char *p; + nxt_err_t err; - if (nxt_slow_path((alignment - 1) & alignment) != 0) { - /* Alignment must be a power of 2. */ - err = NXT_EINVAL; - goto fail; - } + if (nxt_slow_path((alignment - 1) & alignment) != 0) { + /* Alignment must be a power of 2. */ + err = NXT_EINVAL; + goto fail; + } - if (nxt_slow_path(alignment > 4096)) { - err = NXT_EOPNOTSUPP; - goto fail; - } + if (nxt_slow_path(alignment > 4096)) { + err = NXT_EOPNOTSUPP; + goto fail; + } - if (nxt_fast_path(size <= 2048)) { - aligned_size = nxt_max(size, alignment); + if (nxt_fast_path(size <= 2048)) { + aligned_size = nxt_max(size, alignment); - } else { - /* Align to 4096. */ - aligned_size = size; - } + } else { + /* Align to 4096. */ + aligned_size = size; + } - p = malloc(aligned_size); + p = malloc(aligned_size); - if (nxt_fast_path(p != NULL)) { - nxt_thread_log_debug("nxt_memalign(%uz, %uz): %p", alignment, size, p); + if (nxt_fast_path(p != NULL)) { + nxt_thread_log_debug("nxt_memalign(%uz, %uz): %p", alignment, size, p); - } else { - nxt_log_alert_moderate(&nxt_malloc_log_moderation, nxt_malloc_log(), - "malloc(%uz) failed %E", size, nxt_errno); - } + } else { + nxt_log_alert_moderate(&nxt_malloc_log_moderation, nxt_malloc_log(), + "malloc(%uz) failed %E", size, nxt_errno); + } - return p; + return p; fail: - nxt_thread_log_alert("nxt_memalign(%uz, %uz) failed %E", - alignment, size, err); - return NULL; + nxt_thread_log_alert("nxt_memalign(%uz, %uz) failed %E", alignment, size, + err); + return NULL; } #else diff --git a/src/nxt_malloc.h b/src/nxt_malloc.h index fd5493a57..410ce84e8 100644 --- a/src/nxt_malloc.h +++ b/src/nxt_malloc.h @@ -7,16 +7,10 @@ #ifndef _NXT_UNIX_MALLOC_H_INCLUDED_ #define _NXT_UNIX_MALLOC_H_INCLUDED_ - -NXT_EXPORT void *nxt_malloc(size_t size) - NXT_MALLOC_LIKE; -NXT_EXPORT void *nxt_zalloc(size_t size) - NXT_MALLOC_LIKE; -NXT_EXPORT void *nxt_realloc(void *p, size_t size) - NXT_MALLOC_LIKE; -NXT_EXPORT void *nxt_memalign(size_t alignment, size_t size) - NXT_MALLOC_LIKE; - +NXT_EXPORT void *nxt_malloc(size_t size) NXT_MALLOC_LIKE; +NXT_EXPORT void *nxt_zalloc(size_t size) NXT_MALLOC_LIKE; +NXT_EXPORT void *nxt_realloc(void *p, size_t size) NXT_MALLOC_LIKE; +NXT_EXPORT void *nxt_memalign(size_t alignment, size_t size) NXT_MALLOC_LIKE; #if (NXT_DEBUG) @@ -24,12 +18,10 @@ NXT_EXPORT void nxt_free(void *p); #else -#define nxt_free(p) \ - free(p) +#define nxt_free(p) free(p) #endif - #if (NXT_HAVE_MALLOC_USABLE_SIZE) /* @@ -53,11 +45,10 @@ NXT_EXPORT void nxt_free(void *p); * Glibc malloc_usable_size() is fast operation. */ -#define nxt_malloc_usable_size(p, size) \ - size = malloc_usable_size(p) +#define nxt_malloc_usable_size(p, size) size = malloc_usable_size(p) -#define nxt_malloc_cutback(cutback, size) \ - size = ((cutback) && size > 127 * 1024) ? size - 32 : size +#define nxt_malloc_cutback(cutback, size) \ + size = ((cutback) && size > 127 * 1024) ? size - 32 : size #elif (NXT_FREEBSD) @@ -78,8 +69,7 @@ NXT_EXPORT void nxt_free(void *p); * are lesser than 1M. Larger allocations require mutex acquiring. */ -#define nxt_malloc_usable_size(p, size) \ - size = malloc_usable_size(p) +#define nxt_malloc_usable_size(p, size) size = malloc_usable_size(p) #define nxt_malloc_cutback(cutback, size) @@ -98,8 +88,7 @@ NXT_EXPORT void nxt_free(void *p); * malloc_good_size() is faster than malloc_size() */ -#define nxt_malloc_usable_size(p, size) \ - size = malloc_good_size(size) +#define nxt_malloc_usable_size(p, size) size = malloc_good_size(size) #define nxt_malloc_cutback(cutback, size) @@ -111,16 +100,14 @@ NXT_EXPORT void nxt_free(void *p); #endif - #if (NXT_HAVE_POSIX_MEMALIGN || NXT_HAVE_MEMALIGN) -#define NXT_MAX_MEMALIGN_SHIFT 32 +#define NXT_MAX_MEMALIGN_SHIFT 32 #elif (NXT_FREEBSD) -#define NXT_MAX_MEMALIGN_SHIFT 12 +#define NXT_MAX_MEMALIGN_SHIFT 12 #else -#define NXT_MAX_MEMALIGN_SHIFT 3 +#define NXT_MAX_MEMALIGN_SHIFT 3 #endif - #endif /* _NXT_UNIX_MALLOC_H_INCLUDED_ */ diff --git a/src/nxt_mem_map.c b/src/nxt_mem_map.c index f9caf54f1..d5c689bb2 100644 --- a/src/nxt_mem_map.c +++ b/src/nxt_mem_map.c @@ -6,35 +6,29 @@ #include +void *nxt_mem_mmap(void *addr, size_t len, nxt_uint_t protection, + nxt_uint_t flags, nxt_fd_t fd, nxt_off_t offset) { + void *p; -void * -nxt_mem_mmap(void *addr, size_t len, nxt_uint_t protection, nxt_uint_t flags, - nxt_fd_t fd, nxt_off_t offset) -{ - void *p; + p = mmap(addr, len, protection, flags, fd, offset); - p = mmap(addr, len, protection, flags, fd, offset); + if (nxt_fast_path(p != MAP_FAILED)) { + nxt_thread_log_debug("mmap(%p, %uz, %uxi, %uxi, %FD, %O): %p", addr, len, + protection, flags, fd, offset, p); - if (nxt_fast_path(p != MAP_FAILED)) { - nxt_thread_log_debug("mmap(%p, %uz, %uxi, %uxi, %FD, %O): %p", - addr, len, protection, flags, fd, offset, p); + } else { + nxt_thread_log_alert("mmap(%p, %uz, %ui, %ui, %FD, %O) failed %E", addr, + len, protection, flags, fd, offset, nxt_errno); + } - } else { - nxt_thread_log_alert("mmap(%p, %uz, %ui, %ui, %FD, %O) failed %E", - addr, len, protection, flags, fd, offset, nxt_errno); - } - - return p; + return p; } +void nxt_mem_munmap(void *addr, size_t len) { + if (nxt_fast_path(munmap(addr, len) == 0)) { + nxt_thread_log_debug("munmap(%p, %uz)", addr, len); -void -nxt_mem_munmap(void *addr, size_t len) -{ - if (nxt_fast_path(munmap(addr, len) == 0)) { - nxt_thread_log_debug("munmap(%p, %uz)", addr, len); - - } else { - nxt_thread_log_alert("munmap(%p, %uz) failed %E", addr, len, nxt_errno); - } + } else { + nxt_thread_log_alert("munmap(%p, %uz) failed %E", addr, len, nxt_errno); + } } diff --git a/src/nxt_mem_map.h b/src/nxt_mem_map.h index e529aff8d..7ba147d5a 100644 --- a/src/nxt_mem_map.h +++ b/src/nxt_mem_map.h @@ -7,22 +7,18 @@ #ifndef _NXT_UNIX_MEM_MAP_H_INCLUDED_ #define _NXT_UNIX_MEM_MAP_H_INCLUDED_ +#define NXT_MEM_MAP_FAILED MAP_FAILED -#define NXT_MEM_MAP_FAILED MAP_FAILED - - -#define NXT_MEM_MAP_READ PROT_READ -#define NXT_MEM_MAP_WRITE PROT_WRITE - +#define NXT_MEM_MAP_READ PROT_READ +#define NXT_MEM_MAP_WRITE PROT_WRITE #if (NXT_HAVE_MAP_ANONYMOUS) -#define NXT_MEM_MAP_ANON MAP_ANONYMOUS +#define NXT_MEM_MAP_ANON MAP_ANONYMOUS #else -#define NXT_MEM_MAP_ANON MAP_ANON +#define NXT_MEM_MAP_ANON MAP_ANON #endif -#define NXT_MEM_MAP_SHARED (MAP_SHARED | NXT_MEM_MAP_ANON) - +#define NXT_MEM_MAP_SHARED (MAP_SHARED | NXT_MEM_MAP_ANON) #if (NXT_HAVE_MAP_POPULATE) /* @@ -30,33 +26,27 @@ * (MAP_POPULATE | MAP_NONBLOCK) wires only resident pages * without read ahead but it does not work since Linux 2.6.23. */ -#define NXT_MEM_MAP_PREFAULT MAP_POPULATE +#define NXT_MEM_MAP_PREFAULT MAP_POPULATE #elif (NXT_HAVE_MAP_PREFAULT_READ) /* FreeBSD MAP_PREFAULT_READ wires resident pages without read ahead. */ -#define NXT_MEM_MAP_PREFAULT MAP_PREFAULT_READ +#define NXT_MEM_MAP_PREFAULT MAP_PREFAULT_READ #else -#define NXT_MEM_MAP_PREFAULT 0 +#define NXT_MEM_MAP_PREFAULT 0 #endif -#define NXT_MEM_MAP_FILE (MAP_SHARED | NXT_MEM_MAP_PREFAULT) - +#define NXT_MEM_MAP_FILE (MAP_SHARED | NXT_MEM_MAP_PREFAULT) -#define nxt_mem_map_file_ctx_t(ctx) +#define nxt_mem_map_file_ctx_t(ctx) +#define nxt_mem_map(addr, ctx, len, protection, flags, fd, offset) \ + nxt_mem_mmap(addr, len, protection, flags, fd, offset) -#define nxt_mem_map(addr, ctx, len, protection, flags, fd, offset) \ - nxt_mem_mmap(addr, len, protection, flags, fd, offset) - - -#define nxt_mem_unmap(addr, ctx, len) \ - nxt_mem_munmap(addr, len) - +#define nxt_mem_unmap(addr, ctx, len) nxt_mem_munmap(addr, len) NXT_EXPORT void *nxt_mem_mmap(void *addr, size_t len, nxt_uint_t protection, - nxt_uint_t flags, nxt_fd_t fd, nxt_off_t offset); + nxt_uint_t flags, nxt_fd_t fd, nxt_off_t offset); NXT_EXPORT void nxt_mem_munmap(void *addr, size_t len); - #endif /* _NXT_UNIX_MEM_MAP_H_INCLUDED_ */ diff --git a/src/nxt_mem_zone.c b/src/nxt_mem_zone.c index a3ba37007..ec6cbd3ad 100644 --- a/src/nxt_mem_zone.c +++ b/src/nxt_mem_zone.c @@ -6,710 +6,663 @@ #include - -#define NXT_MEM_ZONE_PAGE_FREE 0 +#define NXT_MEM_ZONE_PAGE_FREE 0 /* * A page was never allocated before so it should be filled with * junk on the first time allocation if memory debugging is enabled. */ -#define NXT_MEM_ZONE_PAGE_FRESH 1 +#define NXT_MEM_ZONE_PAGE_FRESH 1 /* An entire page is currently used, no chunks inside the page. */ -#define NXT_MEM_ZONE_PAGE_USED 2 - +#define NXT_MEM_ZONE_PAGE_USED 2 -typedef struct nxt_mem_zone_page_s nxt_mem_zone_page_t; +typedef struct nxt_mem_zone_page_s nxt_mem_zone_page_t; struct nxt_mem_zone_page_s { + /* + * A size of page chunks if value is greater than or equal to 16. + * Otherwise it is used to mark page state: NXT_MEM_ZONE_PAGE_FREE, + * NXT_MEM_ZONE_PAGE_FRESH, and NXT_MEM_ZONE_PAGE_USED. + */ + uint16_t size; + + /* A number of free chunks of a chunked page. */ + uint16_t chunks; + + union { + /* A chunk bitmap if a number of chunks is lesser than 32. */ + uint8_t map[4]; /* - * A size of page chunks if value is greater than or equal to 16. - * Otherwise it is used to mark page state: NXT_MEM_ZONE_PAGE_FREE, - * NXT_MEM_ZONE_PAGE_FRESH, and NXT_MEM_ZONE_PAGE_USED. + * The count is a number of successive occupied pages in the first + * page. In the next occupied pages and in all free pages the count + * is zero, because a number of successive free pages is stored in + * free block size resided in beginning of the first free page. */ - uint16_t size; - - /* A number of free chunks of a chunked page. */ - uint16_t chunks; - - union { - /* A chunk bitmap if a number of chunks is lesser than 32. */ - uint8_t map[4]; - /* - * The count is a number of successive occupied pages in the first - * page. In the next occupied pages and in all free pages the count - * is zero, because a number of successive free pages is stored in - * free block size resided in beginning of the first free page. - */ - uint32_t count; - } u; - - /* Used for slot list of pages with free chunks. */ - nxt_mem_zone_page_t *next; + uint32_t count; + } u; - /* - * Used to link of all pages including free, chunked and occupied - * pages to coalesce free pages. - */ - nxt_queue_link_t link; -}; + /* Used for slot list of pages with free chunks. */ + nxt_mem_zone_page_t *next; + /* + * Used to link of all pages including free, chunked and occupied + * pages to coalesce free pages. + */ + nxt_queue_link_t link; +}; typedef struct { - uint32_t size; - uint32_t chunks; - uint32_t start; - uint32_t map_size; - nxt_mem_zone_page_t *pages; + uint32_t size; + uint32_t chunks; + uint32_t start; + uint32_t map_size; + nxt_mem_zone_page_t *pages; } nxt_mem_zone_slot_t; - typedef struct { - NXT_RBTREE_NODE (node); - uint32_t size; + NXT_RBTREE_NODE(node); + uint32_t size; } nxt_mem_zone_free_block_t; - struct nxt_mem_zone_s { - nxt_thread_spinlock_t lock; - nxt_mem_zone_page_t *pages; - nxt_mem_zone_page_t sentinel_page; - nxt_rbtree_t free_pages; + nxt_thread_spinlock_t lock; + nxt_mem_zone_page_t *pages; + nxt_mem_zone_page_t sentinel_page; + nxt_rbtree_t free_pages; - uint32_t page_size_shift; - uint32_t page_size_mask; - uint32_t max_chunk_size; - uint32_t small_bitmap_min_size; + uint32_t page_size_shift; + uint32_t page_size_mask; + uint32_t max_chunk_size; + uint32_t small_bitmap_min_size; - u_char *start; - u_char *end; + u_char *start; + u_char *end; - nxt_mem_zone_slot_t slots[]; + nxt_mem_zone_slot_t slots[]; }; +#define nxt_mem_zone_page_addr(zone, page) \ + (void *)(zone->start + ((page - zone->pages) << zone->page_size_shift)) -#define nxt_mem_zone_page_addr(zone, page) \ - (void *) (zone->start + ((page - zone->pages) << zone->page_size_shift)) - - -#define nxt_mem_zone_addr_page(zone, addr) \ - &zone->pages[((u_char *) addr - zone->start) >> zone->page_size_shift] - +#define nxt_mem_zone_addr_page(zone, addr) \ + &zone->pages[((u_char *)addr - zone->start) >> zone->page_size_shift] -#define nxt_mem_zone_page_is_free(page) \ - (page->size < NXT_MEM_ZONE_PAGE_USED) +#define nxt_mem_zone_page_is_free(page) (page->size < NXT_MEM_ZONE_PAGE_USED) +#define nxt_mem_zone_page_is_chunked(page) (page->size >= 16) -#define nxt_mem_zone_page_is_chunked(page) \ - (page->size >= 16) +#define nxt_mem_zone_page_bitmap(zone, slot) \ + (slot->size < zone->small_bitmap_min_size) +#define nxt_mem_zone_set_chunk_free(map, chunk) \ + map[chunk / 8] &= ~(0x80 >> (chunk & 7)) -#define nxt_mem_zone_page_bitmap(zone, slot) \ - (slot->size < zone->small_bitmap_min_size) +#define nxt_mem_zone_chunk_is_free(map, chunk) \ + ((map[chunk / 8] & (0x80 >> (chunk & 7))) == 0) +#define nxt_mem_zone_fresh_junk(p, size) nxt_memset((p), 0xA5, size) -#define nxt_mem_zone_set_chunk_free(map, chunk) \ - map[chunk / 8] &= ~(0x80 >> (chunk & 7)) - - -#define nxt_mem_zone_chunk_is_free(map, chunk) \ - ((map[chunk / 8] & (0x80 >> (chunk & 7))) == 0) - - -#define nxt_mem_zone_fresh_junk(p, size) \ - nxt_memset((p), 0xA5, size) - - -#define nxt_mem_zone_free_junk(p, size) \ - nxt_memset((p), 0x5A, size) - +#define nxt_mem_zone_free_junk(p, size) nxt_memset((p), 0x5A, size) static uint32_t nxt_mem_zone_pages(u_char *start, size_t zone_size, - nxt_uint_t page_size); + nxt_uint_t page_size); static void *nxt_mem_zone_slots_init(nxt_mem_zone_t *zone, - nxt_uint_t page_size); + nxt_uint_t page_size); static void nxt_mem_zone_slot_init(nxt_mem_zone_slot_t *slot, - nxt_uint_t page_size); + nxt_uint_t page_size); static intptr_t nxt_mem_zone_rbtree_compare(nxt_rbtree_node_t *node1, - nxt_rbtree_node_t *node2); + nxt_rbtree_node_t *node2); static void *nxt_mem_zone_alloc_small(nxt_mem_zone_t *zone, - nxt_mem_zone_slot_t *slot, size_t size); + nxt_mem_zone_slot_t *slot, size_t size); static nxt_uint_t nxt_mem_zone_alloc_chunk(uint8_t *map, nxt_uint_t offset, - nxt_uint_t size); + nxt_uint_t size); static void *nxt_mem_zone_alloc_large(nxt_mem_zone_t *zone, size_t alignment, - size_t size); + size_t size); static nxt_mem_zone_page_t *nxt_mem_zone_alloc_pages(nxt_mem_zone_t *zone, - size_t alignment, uint32_t pages); + size_t alignment, + uint32_t pages); static nxt_mem_zone_free_block_t * - nxt_mem_zone_find_free_block(nxt_mem_zone_t *zone, nxt_rbtree_node_t *node, - uint32_t alignment, uint32_t pages); +nxt_mem_zone_find_free_block(nxt_mem_zone_t *zone, nxt_rbtree_node_t *node, + uint32_t alignment, uint32_t pages); static const char *nxt_mem_zone_free_chunk(nxt_mem_zone_t *zone, - nxt_mem_zone_page_t *page, void *p); + nxt_mem_zone_page_t *page, void *p); static void nxt_mem_zone_free_pages(nxt_mem_zone_t *zone, - nxt_mem_zone_page_t *page, nxt_uint_t count); - + nxt_mem_zone_page_t *page, + nxt_uint_t count); -static nxt_log_moderation_t nxt_mem_zone_log_moderation = { +static nxt_log_moderation_t nxt_mem_zone_log_moderation = { NXT_LOG_ALERT, 2, "mem_zone_alloc() failed, not enough memory", - NXT_LOG_MODERATION -}; - + NXT_LOG_MODERATION}; + +nxt_mem_zone_t *nxt_mem_zone_init(u_char *start, size_t zone_size, + nxt_uint_t page_size) { + uint32_t pages; + nxt_uint_t n; + nxt_mem_zone_t *zone; + nxt_mem_zone_page_t *page; + nxt_mem_zone_free_block_t *block; + + if (nxt_slow_path((page_size & (page_size - 1)) != 0)) { + nxt_thread_log_alert("mem zone page size must be a power of 2"); + return NULL; + } -nxt_mem_zone_t * -nxt_mem_zone_init(u_char *start, size_t zone_size, nxt_uint_t page_size) -{ - uint32_t pages; - nxt_uint_t n; - nxt_mem_zone_t *zone; - nxt_mem_zone_page_t *page; - nxt_mem_zone_free_block_t *block; + pages = nxt_mem_zone_pages(start, zone_size, page_size); + if (pages == 0) { + return NULL; + } - if (nxt_slow_path((page_size & (page_size - 1)) != 0)) { - nxt_thread_log_alert("mem zone page size must be a power of 2"); - return NULL; - } + zone = (nxt_mem_zone_t *)start; - pages = nxt_mem_zone_pages(start, zone_size, page_size); - if (pages == 0) { - return NULL; - } + /* The function returns address after all slots. */ + page = nxt_mem_zone_slots_init(zone, page_size); - zone = (nxt_mem_zone_t *) start; + zone->pages = page; - /* The function returns address after all slots. */ - page = nxt_mem_zone_slots_init(zone, page_size); + for (n = 0; n < pages; n++) { + page[n].size = NXT_MEM_ZONE_PAGE_FRESH; + } - zone->pages = page; + /* + * A special sentinel page entry marked as used does not correspond + * to a real page. The entry simplifies neighbour queue nodes check + * in nxt_mem_zone_free_pages(). + */ + zone->sentinel_page.size = NXT_MEM_ZONE_PAGE_USED; + nxt_queue_sentinel(&zone->sentinel_page.link); + nxt_queue_insert_after(&zone->sentinel_page.link, &page->link); - for (n = 0; n < pages; n++) { - page[n].size = NXT_MEM_ZONE_PAGE_FRESH; - } + /* rbtree of free pages. */ - /* - * A special sentinel page entry marked as used does not correspond - * to a real page. The entry simplifies neighbour queue nodes check - * in nxt_mem_zone_free_pages(). - */ - zone->sentinel_page.size = NXT_MEM_ZONE_PAGE_USED; - nxt_queue_sentinel(&zone->sentinel_page.link); - nxt_queue_insert_after(&zone->sentinel_page.link, &page->link); - - /* rbtree of free pages. */ + nxt_rbtree_init(&zone->free_pages, nxt_mem_zone_rbtree_compare); - nxt_rbtree_init(&zone->free_pages, nxt_mem_zone_rbtree_compare); + block = (nxt_mem_zone_free_block_t *)zone->start; + block->size = pages; - block = (nxt_mem_zone_free_block_t *) zone->start; - block->size = pages; + nxt_rbtree_insert(&zone->free_pages, &block->node); - nxt_rbtree_insert(&zone->free_pages, &block->node); - - return zone; + return zone; } +static uint32_t nxt_mem_zone_pages(u_char *start, size_t zone_size, + nxt_uint_t page_size) { + u_char *end; + size_t reserved; + nxt_uint_t n, pages, size, chunks, last; + nxt_mem_zone_t *zone; + + /* + * Find all maximum chunk sizes which zone page can be split on + * with minimum 16-byte step. + */ + last = page_size / 16; + n = 0; + size = 32; + + do { + chunks = page_size / size; + + if (last != chunks) { + last = chunks; + n++; + } -static uint32_t -nxt_mem_zone_pages(u_char *start, size_t zone_size, nxt_uint_t page_size) -{ - u_char *end; - size_t reserved; - nxt_uint_t n, pages, size, chunks, last; - nxt_mem_zone_t *zone; - - /* - * Find all maximum chunk sizes which zone page can be split on - * with minimum 16-byte step. - */ - last = page_size / 16; - n = 0; - size = 32; + size += 16; - do { - chunks = page_size / size; + } while (chunks > 1); - if (last != chunks) { - last = chunks; - n++; - } + /* + * Find number of usable zone pages except zone bookkeeping data, + * slots, and pages entries. + */ + reserved = sizeof(nxt_mem_zone_t) + (n * sizeof(nxt_mem_zone_slot_t)); - size += 16; + end = nxt_trunc_ptr(start + zone_size, page_size); + zone_size = end - start; - } while (chunks > 1); + pages = (zone_size - reserved) / (page_size + sizeof(nxt_mem_zone_page_t)); - /* - * Find number of usable zone pages except zone bookkeeping data, - * slots, and pages entries. - */ - reserved = sizeof(nxt_mem_zone_t) + (n * sizeof(nxt_mem_zone_slot_t)); - - end = nxt_trunc_ptr(start + zone_size, page_size); - zone_size = end - start; + if (reserved > zone_size || pages == 0) { + nxt_thread_log_alert("mem zone size is too small: %uz", zone_size); + return 0; + } - pages = (zone_size - reserved) / (page_size + sizeof(nxt_mem_zone_page_t)); + reserved += pages * sizeof(nxt_mem_zone_page_t); + nxt_memzero(start, reserved); - if (reserved > zone_size || pages == 0) { - nxt_thread_log_alert("mem zone size is too small: %uz", zone_size); - return 0; - } + zone = (nxt_mem_zone_t *)start; - reserved += pages * sizeof(nxt_mem_zone_page_t); - nxt_memzero(start, reserved); + zone->start = nxt_align_ptr(start + reserved, page_size); + zone->end = end; - zone = (nxt_mem_zone_t *) start; + nxt_thread_log_debug("mem zone pages: %uD, unused:%z", pages, + end - (zone->start + pages * page_size)); - zone->start = nxt_align_ptr(start + reserved, page_size); - zone->end = end; + /* + * If a chunk size is lesser than zone->small_bitmap_min_size + * bytes, a page's chunk bitmap is larger than 32 bits and the + * bimap is placed at the start of the page. + */ + zone->small_bitmap_min_size = page_size / 32; - nxt_thread_log_debug("mem zone pages: %uD, unused:%z", pages, - end - (zone->start + pages * page_size)); + zone->page_size_mask = page_size - 1; + zone->max_chunk_size = page_size / 2; - /* - * If a chunk size is lesser than zone->small_bitmap_min_size - * bytes, a page's chunk bitmap is larger than 32 bits and the - * bimap is placed at the start of the page. - */ - zone->small_bitmap_min_size = page_size / 32; + n = zone->max_chunk_size; - zone->page_size_mask = page_size - 1; - zone->max_chunk_size = page_size / 2; + do { + zone->page_size_shift++; + n /= 2; + } while (n != 0); - n = zone->max_chunk_size; - - do { - zone->page_size_shift++; - n /= 2; - } while (n != 0); - - return (uint32_t) pages; + return (uint32_t)pages; } +static void *nxt_mem_zone_slots_init(nxt_mem_zone_t *zone, + nxt_uint_t page_size) { + nxt_uint_t n, size, chunks; + nxt_mem_zone_slot_t *slot; -static void * -nxt_mem_zone_slots_init(nxt_mem_zone_t *zone, nxt_uint_t page_size) -{ - nxt_uint_t n, size, chunks; - nxt_mem_zone_slot_t *slot; - - slot = zone->slots; + slot = zone->slots; - slot[0].chunks = page_size / 16; - slot[0].size = 16; + slot[0].chunks = page_size / 16; + slot[0].size = 16; - n = 0; - size = 32; + n = 0; + size = 32; - for ( ;; ) { - chunks = page_size / size; + for (;;) { + chunks = page_size / size; - if (slot[n].chunks != chunks) { + if (slot[n].chunks != chunks) { - nxt_mem_zone_slot_init(&slot[n], page_size); + nxt_mem_zone_slot_init(&slot[n], page_size); - nxt_thread_log_debug( - "mem zone size:%uD chunks:%uD start:%uD map:%uD", - slot[n].size, slot[n].chunks + 1, - slot[n].start, slot[n].map_size); + nxt_thread_log_debug("mem zone size:%uD chunks:%uD start:%uD map:%uD", + slot[n].size, slot[n].chunks + 1, slot[n].start, + slot[n].map_size); - n++; + n++; - if (chunks == 1) { - return &slot[n]; - } - } - - slot[n].chunks = chunks; - slot[n].size = size; - size += 16; + if (chunks == 1) { + return &slot[n]; + } } -} - -static void -nxt_mem_zone_slot_init(nxt_mem_zone_slot_t *slot, nxt_uint_t page_size) -{ - /* - * Calculate number of bytes required to store a chunk bitmap - * and align it to 4 bytes. - */ - slot->map_size = nxt_align_size(((slot->chunks + 7) / 8), 4); + slot[n].chunks = chunks; + slot[n].size = size; + size += 16; + } +} - /* If chunk size is not a multiple of zone page size, there - * is surplus space which can be used for the chunk's bitmap. - */ - slot->start = page_size - slot->chunks * slot->size; - - /* slot->chunks should be one less than actual number of chunks. */ - slot->chunks--; - - if (slot->map_size > 4) { - /* A page's chunks bitmap is placed at the start of the page. */ - - if (slot->start < slot->map_size) { - /* - * There is no surplus space or the space is too - * small for chunks bitmap, so use the first chunks. - */ - if (slot->size < slot->map_size) { - /* The first chunks are occupied by bitmap. */ - slot->chunks -= slot->map_size / slot->size; - slot->start = nxt_align_size(slot->map_size, 16); - - } else { - /* The first chunk is occupied by bitmap. */ - slot->chunks--; - slot->start = slot->size; - } - } +static void nxt_mem_zone_slot_init(nxt_mem_zone_slot_t *slot, + nxt_uint_t page_size) { + /* + * Calculate number of bytes required to store a chunk bitmap + * and align it to 4 bytes. + */ + slot->map_size = nxt_align_size(((slot->chunks + 7) / 8), 4); + + /* If chunk size is not a multiple of zone page size, there + * is surplus space which can be used for the chunk's bitmap. + */ + slot->start = page_size - slot->chunks * slot->size; + + /* slot->chunks should be one less than actual number of chunks. */ + slot->chunks--; + + if (slot->map_size > 4) { + /* A page's chunks bitmap is placed at the start of the page. */ + + if (slot->start < slot->map_size) { + /* + * There is no surplus space or the space is too + * small for chunks bitmap, so use the first chunks. + */ + if (slot->size < slot->map_size) { + /* The first chunks are occupied by bitmap. */ + slot->chunks -= slot->map_size / slot->size; + slot->start = nxt_align_size(slot->map_size, 16); + + } else { + /* The first chunk is occupied by bitmap. */ + slot->chunks--; + slot->start = slot->size; + } } + } } - /* * Round up to the next highest power of 2. The algorithm is * described in "Bit Twiddling Hacks" by Sean Eron Anderson. */ -nxt_inline uint32_t -nxt_next_highest_power_of_two(uint32_t n) -{ - n--; - n |= n >> 1; - n |= n >> 2; - n |= n >> 4; - n |= n >> 8; - n |= n >> 16; - n++; +nxt_inline uint32_t nxt_next_highest_power_of_two(uint32_t n) { + n--; + n |= n >> 1; + n |= n >> 2; + n |= n >> 4; + n |= n >> 8; + n |= n >> 16; + n++; - return n; + return n; } +static intptr_t nxt_mem_zone_rbtree_compare(nxt_rbtree_node_t *node1, + nxt_rbtree_node_t *node2) { + u_char *start1, *end1, *start2, *end2; + uint32_t n, size, size1, size2; + nxt_mem_zone_free_block_t *block1, *block2; -static intptr_t -nxt_mem_zone_rbtree_compare(nxt_rbtree_node_t *node1, nxt_rbtree_node_t *node2) -{ - u_char *start1, *end1, *start2, *end2; - uint32_t n, size, size1, size2; - nxt_mem_zone_free_block_t *block1, *block2; - - block1 = (nxt_mem_zone_free_block_t *) node1; - block2 = (nxt_mem_zone_free_block_t *) node2; + block1 = (nxt_mem_zone_free_block_t *)node1; + block2 = (nxt_mem_zone_free_block_t *)node2; - size1 = block1->size; - size2 = block2->size; + size1 = block1->size; + size2 = block2->size; - /* - * This subtractions do not overflow if number of pages of a free - * block is below 2^31-1. This allows to use blocks up to 128G if - * a zone page size is just 64 bytes. - */ - n = size1 - size2; + /* + * This subtractions do not overflow if number of pages of a free + * block is below 2^31-1. This allows to use blocks up to 128G if + * a zone page size is just 64 bytes. + */ + n = size1 - size2; - if (n != 0) { - return n; - } + if (n != 0) { + return n; + } - /* - * Sort equally sized blocks by their capability to allocate memory with - * alignment equal to the size rounded the previous higest power of 2. - */ + /* + * Sort equally sized blocks by their capability to allocate memory with + * alignment equal to the size rounded the previous higest power of 2. + */ - /* Round the size to the previous higest power of two. */ - size = nxt_next_highest_power_of_two(size1) >> 1; + /* Round the size to the previous higest power of two. */ + size = nxt_next_highest_power_of_two(size1) >> 1; - /* Align the blocks' start and end to the rounded size. */ - start1 = nxt_align_ptr(block1, size); - end1 = nxt_trunc_ptr((u_char *) block1 + size1, size); + /* Align the blocks' start and end to the rounded size. */ + start1 = nxt_align_ptr(block1, size); + end1 = nxt_trunc_ptr((u_char *)block1 + size1, size); - start2 = nxt_align_ptr(block2, size); - end2 = nxt_trunc_ptr((u_char *) block2 + size2, size); + start2 = nxt_align_ptr(block2, size); + end2 = nxt_trunc_ptr((u_char *)block2 + size2, size); - return (end1 - start1) - (end2 - start2); + return (end1 - start1) - (end2 - start2); } +void *nxt_mem_zone_zalloc(nxt_mem_zone_t *zone, size_t size) { + void *p; -void * -nxt_mem_zone_zalloc(nxt_mem_zone_t *zone, size_t size) -{ - void *p; - - p = nxt_mem_zone_align(zone, 1, size); + p = nxt_mem_zone_align(zone, 1, size); - if (nxt_fast_path(p != NULL)) { - nxt_memzero(p, size); - } + if (nxt_fast_path(p != NULL)) { + nxt_memzero(p, size); + } - return p; + return p; } +void *nxt_mem_zone_align(nxt_mem_zone_t *zone, size_t alignment, size_t size) { + void *p; + nxt_mem_zone_slot_t *slot; -void * -nxt_mem_zone_align(nxt_mem_zone_t *zone, size_t alignment, size_t size) -{ - void *p; - nxt_mem_zone_slot_t *slot; - - if (nxt_slow_path((alignment - 1) & alignment) != 0) { - /* Alignment must be a power of 2. */ - return NULL; + if (nxt_slow_path((alignment - 1) & alignment) != 0) { + /* Alignment must be a power of 2. */ + return NULL; + } + + if (size <= zone->max_chunk_size && alignment <= zone->max_chunk_size) { + /* All chunks are aligned to 16. */ + + if (alignment > 16) { + /* + * Chunks which size is power of 2 are aligned to the size. + * So allocation size should be increased to the next highest + * power of two. This can waste memory, but a main consumer + * of aligned allocations is lvlhsh which anyway allocates + * memory with alignment equal to size. + */ + size = nxt_next_highest_power_of_two(size); + size = nxt_max(size, alignment); } - if (size <= zone->max_chunk_size && alignment <= zone->max_chunk_size) { - /* All chunks are aligned to 16. */ - - if (alignment > 16) { - /* - * Chunks which size is power of 2 are aligned to the size. - * So allocation size should be increased to the next highest - * power of two. This can waste memory, but a main consumer - * of aligned allocations is lvlhsh which anyway allocates - * memory with alignment equal to size. - */ - size = nxt_next_highest_power_of_two(size); - size = nxt_max(size, alignment); - } - - /* - * Find a zone slot with appropriate chunk size. - * This operation can be performed without holding lock. - */ - for (slot = zone->slots; slot->size < size; slot++) { /* void */ } + /* + * Find a zone slot with appropriate chunk size. + * This operation can be performed without holding lock. + */ + for (slot = zone->slots; slot->size < size; slot++) { /* void */ + } - nxt_thread_log_debug("mem zone alloc: @%uz:%uz chunk:%uD", - alignment, size, slot->size); + nxt_thread_log_debug("mem zone alloc: @%uz:%uz chunk:%uD", alignment, size, + slot->size); - nxt_thread_spin_lock(&zone->lock); + nxt_thread_spin_lock(&zone->lock); - p = nxt_mem_zone_alloc_small(zone, slot, size); + p = nxt_mem_zone_alloc_small(zone, slot, size); - } else { + } else { - nxt_thread_log_debug("mem zone alloc: @%uz:%uz", alignment, size); + nxt_thread_log_debug("mem zone alloc: @%uz:%uz", alignment, size); - nxt_thread_spin_lock(&zone->lock); + nxt_thread_spin_lock(&zone->lock); - p = nxt_mem_zone_alloc_large(zone, alignment, size); - } + p = nxt_mem_zone_alloc_large(zone, alignment, size); + } - nxt_thread_spin_unlock(&zone->lock); + nxt_thread_spin_unlock(&zone->lock); - if (nxt_fast_path(p != NULL)) { - nxt_thread_log_debug("mem zone alloc: %p", p); + if (nxt_fast_path(p != NULL)) { + nxt_thread_log_debug("mem zone alloc: %p", p); - } else { - nxt_log_alert_moderate(&nxt_mem_zone_log_moderation, nxt_thread_log(), - "nxt_mem_zone_alloc(%uz, %uz) failed, not enough memory", - alignment, size); - } + } else { + nxt_log_alert_moderate( + &nxt_mem_zone_log_moderation, nxt_thread_log(), + "nxt_mem_zone_alloc(%uz, %uz) failed, not enough memory", alignment, + size); + } - return p; + return p; } +static void *nxt_mem_zone_alloc_small(nxt_mem_zone_t *zone, + nxt_mem_zone_slot_t *slot, size_t size) { + u_char *p; + uint8_t *map; + nxt_mem_zone_page_t *page; -static void * -nxt_mem_zone_alloc_small(nxt_mem_zone_t *zone, nxt_mem_zone_slot_t *slot, - size_t size) -{ - u_char *p; - uint8_t *map; - nxt_mem_zone_page_t *page; - - page = slot->pages; + page = slot->pages; - if (nxt_fast_path(page != NULL)) { + if (nxt_fast_path(page != NULL)) { - p = nxt_mem_zone_page_addr(zone, page); + p = nxt_mem_zone_page_addr(zone, page); - if (nxt_mem_zone_page_bitmap(zone, slot)) { - /* A page's chunks bitmap is placed at the start of the page. */ - map = p; + if (nxt_mem_zone_page_bitmap(zone, slot)) { + /* A page's chunks bitmap is placed at the start of the page. */ + map = p; - } else { - map = page->u.map; - } + } else { + map = page->u.map; + } - p += nxt_mem_zone_alloc_chunk(map, slot->start, slot->size); + p += nxt_mem_zone_alloc_chunk(map, slot->start, slot->size); - page->chunks--; + page->chunks--; - if (page->chunks == 0) { - /* - * Remove full page from the zone slot list of pages with - * free chunks. - */ - slot->pages = page->next; + if (page->chunks == 0) { + /* + * Remove full page from the zone slot list of pages with + * free chunks. + */ + slot->pages = page->next; #if (NXT_DEBUG) - page->next = NULL; + page->next = NULL; #endif - } - - return p; } - page = nxt_mem_zone_alloc_pages(zone, 1, 1); - - if (nxt_fast_path(page != NULL)) { + return p; + } - slot->pages = page; + page = nxt_mem_zone_alloc_pages(zone, 1, 1); - page->size = slot->size; - /* slot->chunks are already one less. */ - page->chunks = slot->chunks; - page->u.count = 0; - page->next = NULL; + if (nxt_fast_path(page != NULL)) { - p = nxt_mem_zone_page_addr(zone, page); + slot->pages = page; - if (nxt_mem_zone_page_bitmap(zone, slot)) { - /* A page's chunks bitmap is placed at the start of the page. */ - map = p; - nxt_memzero(map, slot->map_size); + page->size = slot->size; + /* slot->chunks are already one less. */ + page->chunks = slot->chunks; + page->u.count = 0; + page->next = NULL; - } else { - map = page->u.map; - } + p = nxt_mem_zone_page_addr(zone, page); - /* Mark the first chunk as busy. */ - map[0] = 0x80; + if (nxt_mem_zone_page_bitmap(zone, slot)) { + /* A page's chunks bitmap is placed at the start of the page. */ + map = p; + nxt_memzero(map, slot->map_size); - return p + slot->start; + } else { + map = page->u.map; } - return NULL; -} - + /* Mark the first chunk as busy. */ + map[0] = 0x80; -static nxt_uint_t -nxt_mem_zone_alloc_chunk(uint8_t *map, nxt_uint_t offset, nxt_uint_t size) -{ - uint8_t mask; - nxt_uint_t n; + return p + slot->start; + } - n = 0; - - /* The page must have at least one free chunk. */ + return NULL; +} - for ( ;; ) { - /* The bitmap is always aligned to uint32_t. */ +static nxt_uint_t nxt_mem_zone_alloc_chunk(uint8_t *map, nxt_uint_t offset, + nxt_uint_t size) { + uint8_t mask; + nxt_uint_t n; - if (*(uint32_t *) &map[n] != 0xFFFFFFFF) { + n = 0; - do { - if (map[n] != 0xFF) { + /* The page must have at least one free chunk. */ - mask = 0x80; + for (;;) { + /* The bitmap is always aligned to uint32_t. */ - do { - if ((map[n] & mask) == 0) { - /* The free chunk is found. */ - map[n] |= mask; - return offset; - } + if (*(uint32_t *)&map[n] != 0xFFFFFFFF) { - offset += size; - mask >>= 1; + do { + if (map[n] != 0xFF) { - } while (mask != 0); + mask = 0x80; - } else { - /* Fast-forward: all 8 chunks are occupied. */ - offset += size * 8; - } + do { + if ((map[n] & mask) == 0) { + /* The free chunk is found. */ + map[n] |= mask; + return offset; + } - n++; + offset += size; + mask >>= 1; - } while (n % 4 != 0); + } while (mask != 0); } else { - /* Fast-forward: all 32 chunks are occupied. */ - offset += size * 32; - n += 4; + /* Fast-forward: all 8 chunks are occupied. */ + offset += size * 8; } - } -} - - -static void * -nxt_mem_zone_alloc_large(nxt_mem_zone_t *zone, size_t alignment, size_t size) -{ - uint32_t pages; - nxt_mem_zone_page_t *page; - pages = (size + zone->page_size_mask) >> zone->page_size_shift; + n++; - page = nxt_mem_zone_alloc_pages(zone, alignment, pages); + } while (n % 4 != 0); - if (nxt_fast_path(page != NULL)) { - return nxt_mem_zone_page_addr(zone, page); + } else { + /* Fast-forward: all 32 chunks are occupied. */ + offset += size * 32; + n += 4; } - - return NULL; + } } +static void *nxt_mem_zone_alloc_large(nxt_mem_zone_t *zone, size_t alignment, + size_t size) { + uint32_t pages; + nxt_mem_zone_page_t *page; -static nxt_mem_zone_page_t * -nxt_mem_zone_alloc_pages(nxt_mem_zone_t *zone, size_t alignment, uint32_t pages) -{ - u_char *p; - size_t prev_size; - uint32_t prev_pages, node_pages, next_pages; - nxt_uint_t n; - nxt_mem_zone_page_t *prev_page, *page, *next_page; - nxt_mem_zone_free_block_t *block, *next_block; + pages = (size + zone->page_size_mask) >> zone->page_size_shift; - block = nxt_mem_zone_find_free_block(zone, - nxt_rbtree_root(&zone->free_pages), - alignment, pages); + page = nxt_mem_zone_alloc_pages(zone, alignment, pages); - if (nxt_slow_path(block == NULL)) { - return NULL; - } + if (nxt_fast_path(page != NULL)) { + return nxt_mem_zone_page_addr(zone, page); + } - node_pages = block->size; + return NULL; +} - nxt_rbtree_delete(&zone->free_pages, &block->node); +static nxt_mem_zone_page_t *nxt_mem_zone_alloc_pages(nxt_mem_zone_t *zone, + size_t alignment, + uint32_t pages) { + u_char *p; + size_t prev_size; + uint32_t prev_pages, node_pages, next_pages; + nxt_uint_t n; + nxt_mem_zone_page_t *prev_page, *page, *next_page; + nxt_mem_zone_free_block_t *block, *next_block; + + block = nxt_mem_zone_find_free_block(zone, nxt_rbtree_root(&zone->free_pages), + alignment, pages); + + if (nxt_slow_path(block == NULL)) { + return NULL; + } - p = nxt_align_ptr(block, alignment); - page = nxt_mem_zone_addr_page(zone, p); + node_pages = block->size; - prev_size = p - (u_char *) block; + nxt_rbtree_delete(&zone->free_pages, &block->node); - if (prev_size != 0) { - prev_pages = prev_size >> zone->page_size_shift; - node_pages -= prev_pages; + p = nxt_align_ptr(block, alignment); + page = nxt_mem_zone_addr_page(zone, p); - block->size = prev_pages; - nxt_rbtree_insert(&zone->free_pages, &block->node); + prev_size = p - (u_char *)block; - prev_page = nxt_mem_zone_addr_page(zone, block); - nxt_queue_insert_after(&prev_page->link, &page->link); - } + if (prev_size != 0) { + prev_pages = prev_size >> zone->page_size_shift; + node_pages -= prev_pages; - next_pages = node_pages - pages; + block->size = prev_pages; + nxt_rbtree_insert(&zone->free_pages, &block->node); - if (next_pages != 0) { - next_page = &page[pages]; - next_block = nxt_mem_zone_page_addr(zone, next_page); - next_block->size = next_pages; + prev_page = nxt_mem_zone_addr_page(zone, block); + nxt_queue_insert_after(&prev_page->link, &page->link); + } - nxt_rbtree_insert(&zone->free_pages, &next_block->node); - nxt_queue_insert_after(&page->link, &next_page->link); - } + next_pages = node_pages - pages; - /* Go through pages after all rbtree operations to not trash CPU cache. */ + if (next_pages != 0) { + next_page = &page[pages]; + next_block = nxt_mem_zone_page_addr(zone, next_page); + next_block->size = next_pages; - page[0].u.count = pages; + nxt_rbtree_insert(&zone->free_pages, &next_block->node); + nxt_queue_insert_after(&page->link, &next_page->link); + } - for (n = 0; n < pages; n++) { + /* Go through pages after all rbtree operations to not trash CPU cache. */ - if (page[n].size == NXT_MEM_ZONE_PAGE_FRESH) { - nxt_mem_zone_fresh_junk(nxt_mem_zone_page_addr(zone, &page[n]), - zone->page_size_mask + 1); - } + page[0].u.count = pages; + + for (n = 0; n < pages; n++) { - page[n].size = NXT_MEM_ZONE_PAGE_USED; + if (page[n].size == NXT_MEM_ZONE_PAGE_FRESH) { + nxt_mem_zone_fresh_junk(nxt_mem_zone_page_addr(zone, &page[n]), + zone->page_size_mask + 1); } - return page; -} + page[n].size = NXT_MEM_ZONE_PAGE_USED; + } + return page; +} /* * Free blocks are sorted by size and then if the sizes are equal @@ -725,224 +678,214 @@ nxt_mem_zone_alloc_pages(nxt_mem_zone_t *zone, size_t alignment, uint32_t pages) static nxt_mem_zone_free_block_t * nxt_mem_zone_find_free_block(nxt_mem_zone_t *zone, nxt_rbtree_node_t *node, - uint32_t alignment, uint32_t pages) -{ - u_char *aligned, *end; - nxt_mem_zone_free_block_t *block, *free_block; + uint32_t alignment, uint32_t pages) { + u_char *aligned, *end; + nxt_mem_zone_free_block_t *block, *free_block; - if (node == nxt_rbtree_sentinel(&zone->free_pages)) { - return NULL; - } + if (node == nxt_rbtree_sentinel(&zone->free_pages)) { + return NULL; + } - block = (nxt_mem_zone_free_block_t *) node; + block = (nxt_mem_zone_free_block_t *)node; - if (pages <= block->size) { + if (pages <= block->size) { - free_block = nxt_mem_zone_find_free_block(zone, block->node.left, - alignment, pages); - if (free_block != NULL) { - return free_block; - } + free_block = + nxt_mem_zone_find_free_block(zone, block->node.left, alignment, pages); + if (free_block != NULL) { + return free_block; + } - aligned = nxt_align_ptr(block, alignment); + aligned = nxt_align_ptr(block, alignment); - if (pages == block->size) { - if (aligned == (u_char *) block) { - /* Exact match. */ - return block; - } + if (pages == block->size) { + if (aligned == (u_char *)block) { + /* Exact match. */ + return block; + } - } else { /* pages < block->size */ - aligned += pages << zone->page_size_shift; - end = nxt_pointer_to(block, block->size << zone->page_size_shift); + } else { /* pages < block->size */ + aligned += pages << zone->page_size_shift; + end = nxt_pointer_to(block, block->size << zone->page_size_shift); - if (aligned <= end) { - return block; - } - } + if (aligned <= end) { + return block; + } } + } - return nxt_mem_zone_find_free_block(zone, block->node.right, - alignment, pages); + return nxt_mem_zone_find_free_block(zone, block->node.right, alignment, + pages); } +void nxt_mem_zone_free(nxt_mem_zone_t *zone, void *p) { + nxt_uint_t count; + const char *err; + nxt_mem_zone_page_t *page; -void -nxt_mem_zone_free(nxt_mem_zone_t *zone, void *p) -{ - nxt_uint_t count; - const char *err; - nxt_mem_zone_page_t *page; - - nxt_thread_log_debug("mem zone free: %p", p); + nxt_thread_log_debug("mem zone free: %p", p); - if (nxt_fast_path(zone->start <= (u_char *) p - && (u_char *) p < zone->end)) - { - page = nxt_mem_zone_addr_page(zone, p); + if (nxt_fast_path(zone->start <= (u_char *)p && (u_char *)p < zone->end)) { + page = nxt_mem_zone_addr_page(zone, p); - nxt_thread_spin_lock(&zone->lock); + nxt_thread_spin_lock(&zone->lock); - if (nxt_mem_zone_page_is_chunked(page)) { - err = nxt_mem_zone_free_chunk(zone, page, p); + if (nxt_mem_zone_page_is_chunked(page)) { + err = nxt_mem_zone_free_chunk(zone, page, p); - } else if (nxt_slow_path(nxt_mem_zone_page_is_free(page))) { - err = "page is already free"; + } else if (nxt_slow_path(nxt_mem_zone_page_is_free(page))) { + err = "page is already free"; - } else if (nxt_slow_path((uintptr_t) p & zone->page_size_mask) != 0) { - err = "invalid pointer to chunk"; + } else if (nxt_slow_path((uintptr_t)p & zone->page_size_mask) != 0) { + err = "invalid pointer to chunk"; - } else { - count = page->u.count; + } else { + count = page->u.count; - if (nxt_fast_path(count != 0)) { - nxt_mem_zone_free_junk(p, count * zone->page_size_mask + 1); - nxt_mem_zone_free_pages(zone, page, count); - err = NULL; + if (nxt_fast_path(count != 0)) { + nxt_mem_zone_free_junk(p, count * zone->page_size_mask + 1); + nxt_mem_zone_free_pages(zone, page, count); + err = NULL; - } else { - /* Not the first allocated page. */ - err = "pointer to wrong page"; - } - } + } else { + /* Not the first allocated page. */ + err = "pointer to wrong page"; + } + } - nxt_thread_spin_unlock(&zone->lock); + nxt_thread_spin_unlock(&zone->lock); - } else { - err = "pointer is out of zone"; - } + } else { + err = "pointer is out of zone"; + } - if (nxt_slow_path(err != NULL)) { - nxt_thread_log_alert("nxt_mem_zone_free(%p): %s", p, err); - } + if (nxt_slow_path(err != NULL)) { + nxt_thread_log_alert("nxt_mem_zone_free(%p): %s", p, err); + } } +static const char *nxt_mem_zone_free_chunk(nxt_mem_zone_t *zone, + nxt_mem_zone_page_t *page, void *p) { + u_char *map; + uint32_t size, offset, chunk; + nxt_mem_zone_page_t *pg, **ppg; + nxt_mem_zone_slot_t *slot; -static const char * -nxt_mem_zone_free_chunk(nxt_mem_zone_t *zone, nxt_mem_zone_page_t *page, - void *p) -{ - u_char *map; - uint32_t size, offset, chunk; - nxt_mem_zone_page_t *pg, **ppg; - nxt_mem_zone_slot_t *slot; + size = page->size; - size = page->size; + /* Find a zone slot with appropriate chunk size. */ + for (slot = zone->slots; slot->size < size; slot++) { /* void */ + } - /* Find a zone slot with appropriate chunk size. */ - for (slot = zone->slots; slot->size < size; slot++) { /* void */ } + offset = (uintptr_t)p & zone->page_size_mask; + offset -= slot->start; - offset = (uintptr_t) p & zone->page_size_mask; - offset -= slot->start; + chunk = offset / size; - chunk = offset / size; + if (nxt_slow_path(offset != chunk * size)) { + return "pointer to wrong chunk"; + } - if (nxt_slow_path(offset != chunk * size)) { - return "pointer to wrong chunk"; - } + if (nxt_mem_zone_page_bitmap(zone, slot)) { + /* A page's chunks bitmap is placed at the start of the page. */ + map = (u_char *)((uintptr_t)p & ~((uintptr_t)zone->page_size_mask)); - if (nxt_mem_zone_page_bitmap(zone, slot)) { - /* A page's chunks bitmap is placed at the start of the page. */ - map = (u_char *) ((uintptr_t) p & ~((uintptr_t) zone->page_size_mask)); + } else { + map = page->u.map; + } - } else { - map = page->u.map; - } - - if (nxt_mem_zone_chunk_is_free(map, chunk)) { - return "chunk is already free"; - } + if (nxt_mem_zone_chunk_is_free(map, chunk)) { + return "chunk is already free"; + } - nxt_mem_zone_set_chunk_free(map, chunk); + nxt_mem_zone_set_chunk_free(map, chunk); - nxt_mem_zone_free_junk(p, page->size); + nxt_mem_zone_free_junk(p, page->size); - if (page->chunks == 0) { - page->chunks = 1; + if (page->chunks == 0) { + page->chunks = 1; - /* Add the page to the head of slot list of pages with free chunks. */ - page->next = slot->pages; - slot->pages = page; + /* Add the page to the head of slot list of pages with free chunks. */ + page->next = slot->pages; + slot->pages = page; - } else if (page->chunks != slot->chunks) { - page->chunks++; + } else if (page->chunks != slot->chunks) { + page->chunks++; - } else { + } else { - if (map != page->u.map) { - nxt_mem_zone_free_junk(map, slot->map_size); - } + if (map != page->u.map) { + nxt_mem_zone_free_junk(map, slot->map_size); + } - /* - * All chunks are free, remove the page from the slot list of pages - * with free chunks and add the page to the free pages tree. - */ - ppg = &slot->pages; + /* + * All chunks are free, remove the page from the slot list of pages + * with free chunks and add the page to the free pages tree. + */ + ppg = &slot->pages; - for (pg = slot->pages; pg != NULL; pg = pg->next) { + for (pg = slot->pages; pg != NULL; pg = pg->next) { - if (pg == page) { - *ppg = page->next; - break; - } + if (pg == page) { + *ppg = page->next; + break; + } - ppg = &pg->next; - } - - nxt_mem_zone_free_pages(zone, page, 1); + ppg = &pg->next; } - return NULL; -} + nxt_mem_zone_free_pages(zone, page, 1); + } + return NULL; +} -static void -nxt_mem_zone_free_pages(nxt_mem_zone_t *zone, nxt_mem_zone_page_t *page, - nxt_uint_t count) -{ - nxt_mem_zone_page_t *prev_page, *next_page; - nxt_mem_zone_free_block_t *block, *prev_block, *next_block; +static void nxt_mem_zone_free_pages(nxt_mem_zone_t *zone, + nxt_mem_zone_page_t *page, + nxt_uint_t count) { + nxt_mem_zone_page_t *prev_page, *next_page; + nxt_mem_zone_free_block_t *block, *prev_block, *next_block; - page->size = NXT_MEM_ZONE_PAGE_FREE; - page->chunks = 0; - page->u.count = 0; - page->next = NULL; + page->size = NXT_MEM_ZONE_PAGE_FREE; + page->chunks = 0; + page->u.count = 0; + page->next = NULL; - nxt_memzero(&page[1], (count - 1) * sizeof(nxt_mem_zone_page_t)); + nxt_memzero(&page[1], (count - 1) * sizeof(nxt_mem_zone_page_t)); - next_page = nxt_queue_link_data(page->link.next, nxt_mem_zone_page_t, link); + next_page = nxt_queue_link_data(page->link.next, nxt_mem_zone_page_t, link); - if (nxt_mem_zone_page_is_free(next_page)) { + if (nxt_mem_zone_page_is_free(next_page)) { - /* Coalesce with the next free pages. */ + /* Coalesce with the next free pages. */ - nxt_queue_remove(&next_page->link); - nxt_memzero(next_page, sizeof(nxt_mem_zone_page_t)); + nxt_queue_remove(&next_page->link); + nxt_memzero(next_page, sizeof(nxt_mem_zone_page_t)); - next_block = nxt_mem_zone_page_addr(zone, next_page); - count += next_block->size; - nxt_rbtree_delete(&zone->free_pages, &next_block->node); - } + next_block = nxt_mem_zone_page_addr(zone, next_page); + count += next_block->size; + nxt_rbtree_delete(&zone->free_pages, &next_block->node); + } - prev_page = nxt_queue_link_data(page->link.prev, nxt_mem_zone_page_t, link); + prev_page = nxt_queue_link_data(page->link.prev, nxt_mem_zone_page_t, link); - if (nxt_mem_zone_page_is_free(prev_page)) { + if (nxt_mem_zone_page_is_free(prev_page)) { - /* Coalesce with the previous free pages. */ + /* Coalesce with the previous free pages. */ - nxt_queue_remove(&page->link); + nxt_queue_remove(&page->link); - prev_block = nxt_mem_zone_page_addr(zone, prev_page); - count += prev_block->size; - nxt_rbtree_delete(&zone->free_pages, &prev_block->node); + prev_block = nxt_mem_zone_page_addr(zone, prev_page); + count += prev_block->size; + nxt_rbtree_delete(&zone->free_pages, &prev_block->node); - prev_block->size = count; - nxt_rbtree_insert(&zone->free_pages, &prev_block->node); + prev_block->size = count; + nxt_rbtree_insert(&zone->free_pages, &prev_block->node); - return; - } + return; + } - block = nxt_mem_zone_page_addr(zone, page); - block->size = count; - nxt_rbtree_insert(&zone->free_pages, &block->node); + block = nxt_mem_zone_page_addr(zone, page); + block->size = count; + nxt_rbtree_insert(&zone->free_pages, &block->node); } diff --git a/src/nxt_mem_zone.h b/src/nxt_mem_zone.h index 89d73ca22..35eda79dc 100644 --- a/src/nxt_mem_zone.h +++ b/src/nxt_mem_zone.h @@ -7,22 +7,17 @@ #ifndef _NXT_MEM_ZONE_H_INCLUDED_ #define _NXT_MEM_ZONE_H_INCLUDED_ - -typedef struct nxt_mem_zone_s nxt_mem_zone_t; - +typedef struct nxt_mem_zone_s nxt_mem_zone_t; NXT_EXPORT nxt_mem_zone_t *nxt_mem_zone_init(u_char *start, size_t zone_size, - nxt_uint_t page_size); + nxt_uint_t page_size); -#define nxt_mem_zone_alloc(zone, size) \ - nxt_mem_zone_align((zone), 1, (size)) +#define nxt_mem_zone_alloc(zone, size) nxt_mem_zone_align((zone), 1, (size)) NXT_EXPORT void *nxt_mem_zone_align(nxt_mem_zone_t *zone, size_t alignment, - size_t size) - NXT_MALLOC_LIKE; -NXT_EXPORT void *nxt_mem_zone_zalloc(nxt_mem_zone_t *zone, size_t size) - NXT_MALLOC_LIKE; + size_t size) NXT_MALLOC_LIKE; +NXT_EXPORT void *nxt_mem_zone_zalloc(nxt_mem_zone_t *zone, + size_t size) NXT_MALLOC_LIKE; NXT_EXPORT void nxt_mem_zone_free(nxt_mem_zone_t *zone, void *p); - #endif /* _NXT_MEM_ZONE_H_INCLUDED_ */ diff --git a/src/nxt_mp.c b/src/nxt_mp.c index 2bd8cdee4..8f7a8b9e7 100644 --- a/src/nxt_mp.c +++ b/src/nxt_mp.c @@ -6,7 +6,6 @@ #include - /* * A memory pool allocates memory in clusters of specified size and aligned * to page_alignment. A cluster is divided on pages of specified size. Page @@ -21,47 +20,45 @@ * The rbtree is also used to destroy memory pool. */ - typedef struct { - /* - * Used to link - * *) pages with free chunks in pool chunk pages lists, - * *) pages with free space for non-freeable allocations, - * *) free pages in clusters. - */ - nxt_queue_link_t link; - - union { - /* Chunk bitmap. There can be no more than 32 chunks in a page. */ - uint32_t map; - - /* Size of taken non-freeable space. */ - uint32_t taken; - } u; - - /* - * Size of chunks or page shifted by pool->chunk_size_shift. Zero means - * that page is free, 0xFF means page with non-freeable allocations. - */ - uint8_t size; - - /* Number of free chunks of a chunked page. */ - uint8_t chunks; - - /* - * Number of allocation fails due to free space insufficiency - * in non-freeable page. - */ - uint8_t fails; - - /* - * Page number in page cluster. - * There can be no more than 256 pages in a cluster. - */ - uint8_t number; + /* + * Used to link + * *) pages with free chunks in pool chunk pages lists, + * *) pages with free space for non-freeable allocations, + * *) free pages in clusters. + */ + nxt_queue_link_t link; + + union { + /* Chunk bitmap. There can be no more than 32 chunks in a page. */ + uint32_t map; + + /* Size of taken non-freeable space. */ + uint32_t taken; + } u; + + /* + * Size of chunks or page shifted by pool->chunk_size_shift. Zero means + * that page is free, 0xFF means page with non-freeable allocations. + */ + uint8_t size; + + /* Number of free chunks of a chunked page. */ + uint8_t chunks; + + /* + * Number of allocation fails due to free space insufficiency + * in non-freeable page. + */ + uint8_t fails; + + /* + * Page number in page cluster. + * There can be no more than 256 pages in a cluster. + */ + uint8_t number; } nxt_mp_page_t; - /* * Some malloc implementations (e.g. jemalloc) allocates large enough * blocks (e.g. greater than 4K) with 4K alignment. So if a block @@ -71,79 +68,66 @@ typedef struct { */ typedef enum { - /* Block of cluster. The block is allocated apart of the cluster. */ - NXT_MP_CLUSTER_BLOCK = 0, - /* - * Block of large allocation. - * The block is allocated apart of the allocation. - */ - NXT_MP_DISCRETE_BLOCK, - /* - * Block of large allocation. - * The block is allocated just after of the allocation. - */ - NXT_MP_EMBEDDED_BLOCK, + /* Block of cluster. The block is allocated apart of the cluster. */ + NXT_MP_CLUSTER_BLOCK = 0, + /* + * Block of large allocation. + * The block is allocated apart of the allocation. + */ + NXT_MP_DISCRETE_BLOCK, + /* + * Block of large allocation. + * The block is allocated just after of the allocation. + */ + NXT_MP_EMBEDDED_BLOCK, } nxt_mp_block_type_t; - typedef struct { - NXT_RBTREE_NODE (node); - nxt_mp_block_type_t type:8; - uint8_t freeable; + NXT_RBTREE_NODE(node); + nxt_mp_block_type_t type : 8; + uint8_t freeable; - /* Block size must be less than 4G. */ - uint32_t size; + /* Block size must be less than 4G. */ + uint32_t size; - u_char *start; - nxt_mp_page_t pages[]; + u_char *start; + nxt_mp_page_t pages[]; } nxt_mp_block_t; - struct nxt_mp_s { - /* rbtree of nxt_mp_block_t. */ - nxt_rbtree_t blocks; + /* rbtree of nxt_mp_block_t. */ + nxt_rbtree_t blocks; - uint8_t chunk_size_shift; - uint8_t page_size_shift; - uint32_t page_size; - uint32_t page_alignment; - uint32_t cluster_size; - uint32_t retain; + uint8_t chunk_size_shift; + uint8_t page_size_shift; + uint32_t page_size; + uint32_t page_alignment; + uint32_t cluster_size; + uint32_t retain; #if (NXT_DEBUG) - nxt_pid_t pid; - nxt_tid_t tid; + nxt_pid_t pid; + nxt_tid_t tid; #endif - nxt_work_t *cleanup; + nxt_work_t *cleanup; - /* Lists of nxt_mp_page_t. */ - nxt_queue_t free_pages; - nxt_queue_t nget_pages; - nxt_queue_t get_pages; - nxt_queue_t chunk_pages[]; + /* Lists of nxt_mp_page_t. */ + nxt_queue_t free_pages; + nxt_queue_t nget_pages; + nxt_queue_t get_pages; + nxt_queue_t chunk_pages[]; }; +#define nxt_mp_chunk_get_free(map) (__builtin_ffs(map) - 1) -#define nxt_mp_chunk_get_free(map) \ - (__builtin_ffs(map) - 1) - - -#define nxt_mp_chunk_is_free(map, chunk) \ - ((map & (1 << chunk)) != 0) - - -#define nxt_mp_chunk_set_busy(map, chunk) \ - map &= ~(1 << chunk) - +#define nxt_mp_chunk_is_free(map, chunk) ((map & (1 << chunk)) != 0) -#define nxt_mp_chunk_set_free(map, chunk) \ - map |= (1 << chunk) +#define nxt_mp_chunk_set_busy(map, chunk) map &= ~(1 << chunk) +#define nxt_mp_chunk_set_free(map, chunk) map |= (1 << chunk) -#define nxt_mp_free_junk(p, size) \ - memset((p), 0x5A, size) - +#define nxt_mp_free_junk(p, size) memset((p), 0x5A, size) #if !(NXT_DEBUG_MEMORY) static void *nxt_mp_alloc_small(nxt_mp_t *mp, size_t size); @@ -152,73 +136,61 @@ static nxt_mp_page_t *nxt_mp_alloc_page(nxt_mp_t *mp); static nxt_mp_block_t *nxt_mp_alloc_cluster(nxt_mp_t *mp); #endif static void *nxt_mp_alloc_large(nxt_mp_t *mp, size_t alignment, size_t size, - nxt_bool_t freeable); + nxt_bool_t freeable); static intptr_t nxt_mp_rbtree_compare(nxt_rbtree_node_t *node1, - nxt_rbtree_node_t *node2); + nxt_rbtree_node_t *node2); static nxt_mp_block_t *nxt_mp_find_block(nxt_rbtree_t *tree, const u_char *p); static const char *nxt_mp_chunk_free(nxt_mp_t *mp, nxt_mp_block_t *cluster, - u_char *p); - + u_char *p); #if (NXT_HAVE_BUILTIN_CLZ) -#define nxt_lg2(value) \ - (31 - __builtin_clz(value)) +#define nxt_lg2(value) (31 - __builtin_clz(value)) #else static const int nxt_lg2_tab64[64] = { - 63, 0, 58, 1, 59, 47, 53, 2, - 60, 39, 48, 27, 54, 33, 42, 3, - 61, 51, 37, 40, 49, 18, 28, 20, - 55, 30, 34, 11, 43, 14, 22, 4, - 62, 57, 46, 52, 38, 26, 32, 41, - 50, 36, 17, 19, 29, 10, 13, 21, - 56, 45, 25, 31, 35, 16, 9, 12, - 44, 24, 15, 8, 23, 7, 6, 5 -}; + 63, 0, 58, 1, 59, 47, 53, 2, 60, 39, 48, 27, 54, 33, 42, 3, + 61, 51, 37, 40, 49, 18, 28, 20, 55, 30, 34, 11, 43, 14, 22, 4, + 62, 57, 46, 52, 38, 26, 32, 41, 50, 36, 17, 19, 29, 10, 13, 21, + 56, 45, 25, 31, 35, 16, 9, 12, 44, 24, 15, 8, 23, 7, 6, 5}; static const uint64_t nxt_lg2_magic = 0x07EDD5E59A4E28C2ULL; -static int -nxt_lg2(uint64_t v) -{ - v |= v >> 1; - v |= v >> 2; - v |= v >> 4; - v |= v >> 8; - v |= v >> 16; - v |= v >> 32; - return nxt_lg2_tab64[ ((v - (v >> 1)) * nxt_lg2_magic) >> 58 ]; +static int nxt_lg2(uint64_t v) { + v |= v >> 1; + v |= v >> 2; + v |= v >> 4; + v |= v >> 8; + v |= v >> 16; + v |= v >> 32; + return nxt_lg2_tab64[((v - (v >> 1)) * nxt_lg2_magic) >> 58]; } #endif - #if (NXT_DEBUG) -nxt_inline void -nxt_mp_thread_assert(nxt_mp_t *mp) -{ - nxt_tid_t tid; - nxt_thread_t *thread; +nxt_inline void nxt_mp_thread_assert(nxt_mp_t *mp) { + nxt_tid_t tid; + nxt_thread_t *thread; - thread = nxt_thread(); - tid = nxt_thread_tid(thread); + thread = nxt_thread(); + tid = nxt_thread_tid(thread); - if (nxt_fast_path(mp->tid == tid)) { - return; - } + if (nxt_fast_path(mp->tid == tid)) { + return; + } - if (nxt_slow_path(nxt_pid != mp->pid)) { - mp->pid = nxt_pid; - mp->tid = tid; + if (nxt_slow_path(nxt_pid != mp->pid)) { + mp->pid = nxt_pid; + mp->tid = tid; - return; - } + return; + } - nxt_log_alert(thread->log, "mem_pool locked by thread %PT", mp->tid); - nxt_abort(); + nxt_log_alert(thread->log, "mem_pool locked by thread %PT", mp->tid); + nxt_abort(); } #else @@ -227,849 +199,761 @@ nxt_mp_thread_assert(nxt_mp_t *mp) #endif - -void -nxt_mp_thread_adopt(nxt_mp_t *mp) -{ +void nxt_mp_thread_adopt(nxt_mp_t *mp) { #if (NXT_DEBUG) - mp->pid = nxt_pid; - mp->tid = nxt_thread_tid(nxt_thread()); + mp->pid = nxt_pid; + mp->tid = nxt_thread_tid(nxt_thread()); #endif } +nxt_mp_t *nxt_mp_create(size_t cluster_size, size_t page_alignment, + size_t page_size, size_t min_chunk_size) { + nxt_mp_t *mp; + uint32_t pages, chunk_size_shift, page_size_shift; + nxt_queue_t *chunk_pages; -nxt_mp_t * -nxt_mp_create(size_t cluster_size, size_t page_alignment, size_t page_size, - size_t min_chunk_size) -{ - nxt_mp_t *mp; - uint32_t pages, chunk_size_shift, page_size_shift; - nxt_queue_t *chunk_pages; - - chunk_size_shift = nxt_lg2(min_chunk_size); - page_size_shift = nxt_lg2(page_size); + chunk_size_shift = nxt_lg2(min_chunk_size); + page_size_shift = nxt_lg2(page_size); - pages = page_size_shift - chunk_size_shift; + pages = page_size_shift - chunk_size_shift; - mp = nxt_zalloc(sizeof(nxt_mp_t) + pages * sizeof(nxt_queue_t)); + mp = nxt_zalloc(sizeof(nxt_mp_t) + pages * sizeof(nxt_queue_t)); - if (nxt_fast_path(mp != NULL)) { - mp->retain = 1; - mp->chunk_size_shift = chunk_size_shift; - mp->page_size_shift = page_size_shift; - mp->page_size = page_size; - mp->page_alignment = nxt_max(page_alignment, NXT_MAX_ALIGNMENT); - mp->cluster_size = cluster_size; + if (nxt_fast_path(mp != NULL)) { + mp->retain = 1; + mp->chunk_size_shift = chunk_size_shift; + mp->page_size_shift = page_size_shift; + mp->page_size = page_size; + mp->page_alignment = nxt_max(page_alignment, NXT_MAX_ALIGNMENT); + mp->cluster_size = cluster_size; - chunk_pages = mp->chunk_pages; + chunk_pages = mp->chunk_pages; - while (pages != 0) { - nxt_queue_init(chunk_pages); - chunk_pages++; - pages--; - } + while (pages != 0) { + nxt_queue_init(chunk_pages); + chunk_pages++; + pages--; + } - nxt_queue_init(&mp->free_pages); - nxt_queue_init(&mp->nget_pages); - nxt_queue_init(&mp->get_pages); + nxt_queue_init(&mp->free_pages); + nxt_queue_init(&mp->nget_pages); + nxt_queue_init(&mp->get_pages); - nxt_rbtree_init(&mp->blocks, nxt_mp_rbtree_compare); - } + nxt_rbtree_init(&mp->blocks, nxt_mp_rbtree_compare); + } - nxt_debug_alloc("mp %p create(%uz, %uz, %uz, %uz)", mp, cluster_size, - page_alignment, page_size, min_chunk_size); + nxt_debug_alloc("mp %p create(%uz, %uz, %uz, %uz)", mp, cluster_size, + page_alignment, page_size, min_chunk_size); - return mp; + return mp; } +void nxt_mp_retain(nxt_mp_t *mp) { + mp->retain++; -void -nxt_mp_retain(nxt_mp_t *mp) -{ - mp->retain++; - - nxt_thread_log_debug("mp %p retain: %uD", mp, mp->retain); + nxt_thread_log_debug("mp %p retain: %uD", mp, mp->retain); } +void nxt_mp_release(nxt_mp_t *mp) { + mp->retain--; -void -nxt_mp_release(nxt_mp_t *mp) -{ - mp->retain--; - - nxt_thread_log_debug("mp %p release: %uD", mp, mp->retain); + nxt_thread_log_debug("mp %p release: %uD", mp, mp->retain); - if (mp->retain == 0) { - nxt_mp_destroy(mp); - } + if (mp->retain == 0) { + nxt_mp_destroy(mp); + } } +void nxt_mp_destroy(nxt_mp_t *mp) { + void *p; + nxt_work_t *work, *next_work; + nxt_mp_block_t *block; + nxt_rbtree_node_t *node, *next; -void -nxt_mp_destroy(nxt_mp_t *mp) -{ - void *p; - nxt_work_t *work, *next_work; - nxt_mp_block_t *block; - nxt_rbtree_node_t *node, *next; + nxt_debug_alloc("mp %p destroy", mp); - nxt_debug_alloc("mp %p destroy", mp); + nxt_mp_thread_assert(mp); - nxt_mp_thread_assert(mp); + while (mp->cleanup != NULL) { + work = mp->cleanup; + next_work = work->next; - while (mp->cleanup != NULL) { - work = mp->cleanup; - next_work = work->next; + work->handler(work->task, work->obj, work->data); - work->handler(work->task, work->obj, work->data); + mp->cleanup = next_work; + } - mp->cleanup = next_work; - } + next = nxt_rbtree_root(&mp->blocks); - next = nxt_rbtree_root(&mp->blocks); + while (next != nxt_rbtree_sentinel(&mp->blocks)) { - while (next != nxt_rbtree_sentinel(&mp->blocks)) { + node = nxt_rbtree_destroy_next(&mp->blocks, &next); + block = (nxt_mp_block_t *)node; - node = nxt_rbtree_destroy_next(&mp->blocks, &next); - block = (nxt_mp_block_t *) node; + p = block->start; - p = block->start; - - if (block->type != NXT_MP_EMBEDDED_BLOCK) { - nxt_free(block); - } - - nxt_free(p); + if (block->type != NXT_MP_EMBEDDED_BLOCK) { + nxt_free(block); } - nxt_free(mp); + nxt_free(p); + } + + nxt_free(mp); } +nxt_bool_t nxt_mp_test_sizes(size_t cluster_size, size_t page_alignment, + size_t page_size, size_t min_chunk_size) { + nxt_bool_t valid; -nxt_bool_t -nxt_mp_test_sizes(size_t cluster_size, size_t page_alignment, size_t page_size, - size_t min_chunk_size) -{ - nxt_bool_t valid; + /* Alignment and sizes must be a power of 2. */ - /* Alignment and sizes must be a power of 2. */ + valid = nxt_expect(1, (nxt_is_power_of_two(page_alignment) && + nxt_is_power_of_two(page_size) && + nxt_is_power_of_two(min_chunk_size))); + if (!valid) { + return 0; + } - valid = nxt_expect(1, (nxt_is_power_of_two(page_alignment) - && nxt_is_power_of_two(page_size) - && nxt_is_power_of_two(min_chunk_size))); - if (!valid) { - return 0; - } + page_alignment = nxt_max(page_alignment, NXT_MAX_ALIGNMENT); - page_alignment = nxt_max(page_alignment, NXT_MAX_ALIGNMENT); - - valid = nxt_expect(1, (page_size >= 64 - && page_size >= page_alignment - && page_size >= min_chunk_size - && min_chunk_size * 32 >= page_size - && cluster_size >= page_size - && cluster_size / page_size <= 256 - && cluster_size % page_size == 0)); - if (!valid) { - return 0; - } + valid = nxt_expect( + 1, (page_size >= 64 && page_size >= page_alignment && + page_size >= min_chunk_size && min_chunk_size * 32 >= page_size && + cluster_size >= page_size && cluster_size / page_size <= 256 && + cluster_size % page_size == 0)); + if (!valid) { + return 0; + } - return 1; + return 1; } - -nxt_bool_t -nxt_mp_is_empty(nxt_mp_t *mp) -{ - return (nxt_rbtree_is_empty(&mp->blocks) - && nxt_queue_is_empty(&mp->free_pages)); +nxt_bool_t nxt_mp_is_empty(nxt_mp_t *mp) { + return (nxt_rbtree_is_empty(&mp->blocks) && + nxt_queue_is_empty(&mp->free_pages)); } - -void * -nxt_mp_alloc(nxt_mp_t *mp, size_t size) -{ - void *p; +void *nxt_mp_alloc(nxt_mp_t *mp, size_t size) { + void *p; #if !(NXT_DEBUG_MEMORY) - if (size <= mp->page_size) { - p = nxt_mp_alloc_small(mp, size); + if (size <= mp->page_size) { + p = nxt_mp_alloc_small(mp, size); - } else { - p = nxt_mp_alloc_large(mp, NXT_MAX_ALIGNMENT, size, 1); - } + } else { + p = nxt_mp_alloc_large(mp, NXT_MAX_ALIGNMENT, size, 1); + } #else - p = nxt_mp_alloc_large(mp, NXT_MAX_ALIGNMENT, size, 1); + p = nxt_mp_alloc_large(mp, NXT_MAX_ALIGNMENT, size, 1); #endif - nxt_debug_alloc("mp %p alloc(%uz): %p", mp, size, p); + nxt_debug_alloc("mp %p alloc(%uz): %p", mp, size, p); - return p; + return p; } +void *nxt_mp_zalloc(nxt_mp_t *mp, size_t size) { + void *p; -void * -nxt_mp_zalloc(nxt_mp_t *mp, size_t size) -{ - void *p; + p = nxt_mp_alloc(mp, size); - p = nxt_mp_alloc(mp, size); + if (nxt_fast_path(p != NULL)) { + memset(p, 0, size); + } - if (nxt_fast_path(p != NULL)) { - memset(p, 0, size); - } - - return p; + return p; } +void *nxt_mp_align(nxt_mp_t *mp, size_t alignment, size_t size) { + void *p; -void * -nxt_mp_align(nxt_mp_t *mp, size_t alignment, size_t size) -{ - void *p; - - /* Alignment must be a power of 2. */ + /* Alignment must be a power of 2. */ - if (nxt_fast_path(nxt_is_power_of_two(alignment))) { + if (nxt_fast_path(nxt_is_power_of_two(alignment))) { #if !(NXT_DEBUG_MEMORY) - size_t aligned_size; + size_t aligned_size; - aligned_size = nxt_max(size, alignment); + aligned_size = nxt_max(size, alignment); - if (aligned_size <= mp->page_size && alignment <= mp->page_alignment) { - p = nxt_mp_alloc_small(mp, aligned_size); + if (aligned_size <= mp->page_size && alignment <= mp->page_alignment) { + p = nxt_mp_alloc_small(mp, aligned_size); - } else { - p = nxt_mp_alloc_large(mp, alignment, size, 1); - } + } else { + p = nxt_mp_alloc_large(mp, alignment, size, 1); + } #else - p = nxt_mp_alloc_large(mp, alignment, size, 1); + p = nxt_mp_alloc_large(mp, alignment, size, 1); #endif - } else { - p = NULL; - } + } else { + p = NULL; + } - nxt_debug_alloc("mp %p align(@%uz:%uz): %p", mp, alignment, size, p); + nxt_debug_alloc("mp %p align(@%uz:%uz): %p", mp, alignment, size, p); - return p; + return p; } +void *nxt_mp_zalign(nxt_mp_t *mp, size_t alignment, size_t size) { + void *p; -void * -nxt_mp_zalign(nxt_mp_t *mp, size_t alignment, size_t size) -{ - void *p; + p = nxt_mp_align(mp, alignment, size); - p = nxt_mp_align(mp, alignment, size); + if (nxt_fast_path(p != NULL)) { + memset(p, 0, size); + } - if (nxt_fast_path(p != NULL)) { - memset(p, 0, size); - } - - return p; + return p; } +nxt_inline nxt_uint_t nxt_mp_chunk_pages_index(nxt_mp_t *mp, size_t size) { + nxt_int_t n, index; -nxt_inline nxt_uint_t -nxt_mp_chunk_pages_index(nxt_mp_t *mp, size_t size) -{ - nxt_int_t n, index; - - index = 0; + index = 0; - if (size > 1) { - n = nxt_lg2(size - 1) + 1 - mp->chunk_size_shift; + if (size > 1) { + n = nxt_lg2(size - 1) + 1 - mp->chunk_size_shift; - if (n > 0) { - index = n; - } + if (n > 0) { + index = n; } + } - return index; + return index; } - #if !(NXT_DEBUG_MEMORY) -nxt_inline u_char * -nxt_mp_page_addr(nxt_mp_t *mp, nxt_mp_page_t *page) -{ - size_t page_offset; - nxt_mp_block_t *block; +nxt_inline u_char *nxt_mp_page_addr(nxt_mp_t *mp, nxt_mp_page_t *page) { + size_t page_offset; + nxt_mp_block_t *block; - page_offset = page->number * sizeof(nxt_mp_page_t) - + offsetof(nxt_mp_block_t, pages); + page_offset = + page->number * sizeof(nxt_mp_page_t) + offsetof(nxt_mp_block_t, pages); - block = (nxt_mp_block_t *) ((u_char *) page - page_offset); + block = (nxt_mp_block_t *)((u_char *)page - page_offset); - return block->start + (page->number << mp->page_size_shift); + return block->start + (page->number << mp->page_size_shift); } +static void *nxt_mp_alloc_small(nxt_mp_t *mp, size_t size) { + u_char *p; + nxt_uint_t n, index; + nxt_queue_t *chunk_pages; + nxt_mp_page_t *page; + nxt_queue_link_t *link; -static void * -nxt_mp_alloc_small(nxt_mp_t *mp, size_t size) -{ - u_char *p; - nxt_uint_t n, index; - nxt_queue_t *chunk_pages; - nxt_mp_page_t *page; - nxt_queue_link_t *link; + nxt_mp_thread_assert(mp); - nxt_mp_thread_assert(mp); + p = NULL; - p = NULL; - - if (size <= mp->page_size / 2) { + if (size <= mp->page_size / 2) { - index = nxt_mp_chunk_pages_index(mp, size); - chunk_pages = &mp->chunk_pages[index]; + index = nxt_mp_chunk_pages_index(mp, size); + chunk_pages = &mp->chunk_pages[index]; - if (nxt_fast_path(!nxt_queue_is_empty(chunk_pages))) { + if (nxt_fast_path(!nxt_queue_is_empty(chunk_pages))) { - link = nxt_queue_first(chunk_pages); - page = nxt_queue_link_data(link, nxt_mp_page_t, link); + link = nxt_queue_first(chunk_pages); + page = nxt_queue_link_data(link, nxt_mp_page_t, link); - p = nxt_mp_page_addr(mp, page); + p = nxt_mp_page_addr(mp, page); - n = nxt_mp_chunk_get_free(page->u.map); - nxt_mp_chunk_set_busy(page->u.map, n); + n = nxt_mp_chunk_get_free(page->u.map); + nxt_mp_chunk_set_busy(page->u.map, n); - p += ((n << index) << mp->chunk_size_shift); + p += ((n << index) << mp->chunk_size_shift); - page->chunks--; + page->chunks--; - if (page->chunks == 0) { - /* - * Remove full page from the pool chunk pages list - * of pages with free chunks. - */ - nxt_queue_remove(&page->link); - } + if (page->chunks == 0) { + /* + * Remove full page from the pool chunk pages list + * of pages with free chunks. + */ + nxt_queue_remove(&page->link); + } - } else { - page = nxt_mp_alloc_page(mp); + } else { + page = nxt_mp_alloc_page(mp); - if (nxt_fast_path(page != NULL)) { - page->size = (1 << index); + if (nxt_fast_path(page != NULL)) { + page->size = (1 << index); - n = mp->page_size_shift - (index + mp->chunk_size_shift); - page->chunks = (1 << n) - 1; + n = mp->page_size_shift - (index + mp->chunk_size_shift); + page->chunks = (1 << n) - 1; - nxt_queue_insert_head(chunk_pages, &page->link); + nxt_queue_insert_head(chunk_pages, &page->link); - /* Mark the first chunk as busy. */ - page->u.map = 0xFFFFFFFE; + /* Mark the first chunk as busy. */ + page->u.map = 0xFFFFFFFE; - p = nxt_mp_page_addr(mp, page); - } - } + p = nxt_mp_page_addr(mp, page); + } + } - } else { - page = nxt_mp_alloc_page(mp); + } else { + page = nxt_mp_alloc_page(mp); - if (nxt_fast_path(page != NULL)) { - page->size = mp->page_size >> mp->chunk_size_shift; + if (nxt_fast_path(page != NULL)) { + page->size = mp->page_size >> mp->chunk_size_shift; - p = nxt_mp_page_addr(mp, page); - } + p = nxt_mp_page_addr(mp, page); } + } - nxt_debug_alloc("mp %p chunk:%uz alloc: %p", mp, - page->size << mp->chunk_size_shift, p); + nxt_debug_alloc("mp %p chunk:%uz alloc: %p", mp, + page->size << mp->chunk_size_shift, p); - return p; + return p; } +static void *nxt_mp_get_small(nxt_mp_t *mp, nxt_queue_t *pages, size_t size) { + u_char *p; + uint32_t available; + nxt_mp_page_t *page; + nxt_queue_link_t *link, *next; -static void * -nxt_mp_get_small(nxt_mp_t *mp, nxt_queue_t *pages, size_t size) -{ - u_char *p; - uint32_t available; - nxt_mp_page_t *page; - nxt_queue_link_t *link, *next; + nxt_mp_thread_assert(mp); - nxt_mp_thread_assert(mp); - - for (link = nxt_queue_first(pages); - link != nxt_queue_tail(pages); - link = next) - { - next = nxt_queue_next(link); - page = nxt_queue_link_data(link, nxt_mp_page_t, link); + for (link = nxt_queue_first(pages); link != nxt_queue_tail(pages); + link = next) { + next = nxt_queue_next(link); + page = nxt_queue_link_data(link, nxt_mp_page_t, link); - available = mp->page_size - page->u.taken; + available = mp->page_size - page->u.taken; - if (size <= available) { - goto found; - } + if (size <= available) { + goto found; + } - if (available == 0 || page->fails++ > 100) { - nxt_queue_remove(link); - } + if (available == 0 || page->fails++ > 100) { + nxt_queue_remove(link); } + } - page = nxt_mp_alloc_page(mp); + page = nxt_mp_alloc_page(mp); - if (nxt_slow_path(page == NULL)) { - return page; - } + if (nxt_slow_path(page == NULL)) { + return page; + } - nxt_queue_insert_head(pages, &page->link); + nxt_queue_insert_head(pages, &page->link); - page->size = 0xFF; - page->u.taken = 0; + page->size = 0xFF; + page->u.taken = 0; found: - p = nxt_mp_page_addr(mp, page); + p = nxt_mp_page_addr(mp, page); - p += page->u.taken; - page->u.taken += size; + p += page->u.taken; + page->u.taken += size; - return p; + return p; } +static nxt_mp_page_t *nxt_mp_alloc_page(nxt_mp_t *mp) { + nxt_mp_page_t *page; + nxt_mp_block_t *cluster; + nxt_queue_link_t *link; -static nxt_mp_page_t * -nxt_mp_alloc_page(nxt_mp_t *mp) -{ - nxt_mp_page_t *page; - nxt_mp_block_t *cluster; - nxt_queue_link_t *link; - - if (nxt_queue_is_empty(&mp->free_pages)) { - cluster = nxt_mp_alloc_cluster(mp); - if (nxt_slow_path(cluster == NULL)) { - return NULL; - } + if (nxt_queue_is_empty(&mp->free_pages)) { + cluster = nxt_mp_alloc_cluster(mp); + if (nxt_slow_path(cluster == NULL)) { + return NULL; } + } - link = nxt_queue_first(&mp->free_pages); - nxt_queue_remove(link); + link = nxt_queue_first(&mp->free_pages); + nxt_queue_remove(link); - page = nxt_queue_link_data(link, nxt_mp_page_t, link); + page = nxt_queue_link_data(link, nxt_mp_page_t, link); - return page; + return page; } +static nxt_mp_block_t *nxt_mp_alloc_cluster(nxt_mp_t *mp) { + nxt_uint_t n; + nxt_mp_block_t *cluster; -static nxt_mp_block_t * -nxt_mp_alloc_cluster(nxt_mp_t *mp) -{ - nxt_uint_t n; - nxt_mp_block_t *cluster; + n = mp->cluster_size >> mp->page_size_shift; - n = mp->cluster_size >> mp->page_size_shift; + cluster = nxt_zalloc(sizeof(nxt_mp_block_t) + n * sizeof(nxt_mp_page_t)); - cluster = nxt_zalloc(sizeof(nxt_mp_block_t) + n * sizeof(nxt_mp_page_t)); + if (nxt_slow_path(cluster == NULL)) { + return NULL; + } - if (nxt_slow_path(cluster == NULL)) { - return NULL; - } + /* NXT_MP_CLUSTER_BLOCK type is zero. */ - /* NXT_MP_CLUSTER_BLOCK type is zero. */ + cluster->size = mp->cluster_size; - cluster->size = mp->cluster_size; + cluster->start = nxt_memalign(mp->page_alignment, mp->cluster_size); + if (nxt_slow_path(cluster->start == NULL)) { + nxt_free(cluster); + return NULL; + } - cluster->start = nxt_memalign(mp->page_alignment, mp->cluster_size); - if (nxt_slow_path(cluster->start == NULL)) { - nxt_free(cluster); - return NULL; - } + n--; + cluster->pages[n].number = n; + nxt_queue_insert_head(&mp->free_pages, &cluster->pages[n].link); + while (n != 0) { n--; cluster->pages[n].number = n; - nxt_queue_insert_head(&mp->free_pages, &cluster->pages[n].link); + nxt_queue_insert_before(&cluster->pages[n + 1].link, + &cluster->pages[n].link); + } - while (n != 0) { - n--; - cluster->pages[n].number = n; - nxt_queue_insert_before(&cluster->pages[n + 1].link, - &cluster->pages[n].link); - } - - nxt_rbtree_insert(&mp->blocks, &cluster->node); + nxt_rbtree_insert(&mp->blocks, &cluster->node); - return cluster; + return cluster; } #endif +static void *nxt_mp_alloc_large(nxt_mp_t *mp, size_t alignment, size_t size, + nxt_bool_t freeable) { + u_char *p; + size_t aligned_size; + uint8_t type; + nxt_mp_block_t *block; -static void * -nxt_mp_alloc_large(nxt_mp_t *mp, size_t alignment, size_t size, - nxt_bool_t freeable) -{ - u_char *p; - size_t aligned_size; - uint8_t type; - nxt_mp_block_t *block; + nxt_mp_thread_assert(mp); - nxt_mp_thread_assert(mp); + /* Allocation must be less than 4G. */ + if (nxt_slow_path(size >= 0xFFFFFFFF)) { + return NULL; + } - /* Allocation must be less than 4G. */ - if (nxt_slow_path(size >= 0xFFFFFFFF)) { - return NULL; + if (nxt_is_power_of_two(size)) { + block = nxt_malloc(sizeof(nxt_mp_block_t)); + if (nxt_slow_path(block == NULL)) { + return NULL; } - if (nxt_is_power_of_two(size)) { - block = nxt_malloc(sizeof(nxt_mp_block_t)); - if (nxt_slow_path(block == NULL)) { - return NULL; - } - - p = nxt_memalign(alignment, size); - if (nxt_slow_path(p == NULL)) { - nxt_free(block); - return NULL; - } - - type = NXT_MP_DISCRETE_BLOCK; - - } else { - aligned_size = nxt_align_size(size, sizeof(uintptr_t)); - - p = nxt_memalign(alignment, aligned_size + sizeof(nxt_mp_block_t)); - if (nxt_slow_path(p == NULL)) { - return NULL; - } - - block = (nxt_mp_block_t *) (p + aligned_size); - type = NXT_MP_EMBEDDED_BLOCK; + p = nxt_memalign(alignment, size); + if (nxt_slow_path(p == NULL)) { + nxt_free(block); + return NULL; } - block->type = type; - block->freeable = freeable; - block->size = size; - block->start = p; + type = NXT_MP_DISCRETE_BLOCK; - nxt_rbtree_insert(&mp->blocks, &block->node); + } else { + aligned_size = nxt_align_size(size, sizeof(uintptr_t)); - return p; -} + p = nxt_memalign(alignment, aligned_size + sizeof(nxt_mp_block_t)); + if (nxt_slow_path(p == NULL)) { + return NULL; + } + block = (nxt_mp_block_t *)(p + aligned_size); + type = NXT_MP_EMBEDDED_BLOCK; + } -static intptr_t -nxt_mp_rbtree_compare(nxt_rbtree_node_t *node1, nxt_rbtree_node_t *node2) -{ - nxt_mp_block_t *block1, *block2; + block->type = type; + block->freeable = freeable; + block->size = size; + block->start = p; - block1 = (nxt_mp_block_t *) node1; - block2 = (nxt_mp_block_t *) node2; + nxt_rbtree_insert(&mp->blocks, &block->node); - /* - * Shifting is necessary to prevent overflow of intptr_t when block1->start - * is much greater than block2->start or vice versa. - * - * It is safe to drop one bit since there cannot be adjacent addresses - * because of alignments and allocation sizes. Effectively this reduces - * the absolute values to fit into the magnitude of intptr_t. - */ - return ((uintptr_t) block1->start >> 1) - ((uintptr_t) block2->start >> 1); + return p; } +static intptr_t nxt_mp_rbtree_compare(nxt_rbtree_node_t *node1, + nxt_rbtree_node_t *node2) { + nxt_mp_block_t *block1, *block2; + + block1 = (nxt_mp_block_t *)node1; + block2 = (nxt_mp_block_t *)node2; + + /* + * Shifting is necessary to prevent overflow of intptr_t when block1->start + * is much greater than block2->start or vice versa. + * + * It is safe to drop one bit since there cannot be adjacent addresses + * because of alignments and allocation sizes. Effectively this reduces + * the absolute values to fit into the magnitude of intptr_t. + */ + return ((uintptr_t)block1->start >> 1) - ((uintptr_t)block2->start >> 1); +} -void -nxt_mp_free(nxt_mp_t *mp, void *p) -{ - const char *err; - nxt_mp_block_t *block; - - nxt_mp_thread_assert(mp); +void nxt_mp_free(nxt_mp_t *mp, void *p) { + const char *err; + nxt_mp_block_t *block; - nxt_debug_alloc("mp %p free(%p)", mp, p); + nxt_mp_thread_assert(mp); - block = nxt_mp_find_block(&mp->blocks, p); + nxt_debug_alloc("mp %p free(%p)", mp, p); - if (nxt_fast_path(block != NULL)) { + block = nxt_mp_find_block(&mp->blocks, p); - if (block->type == NXT_MP_CLUSTER_BLOCK) { - err = nxt_mp_chunk_free(mp, block, p); + if (nxt_fast_path(block != NULL)) { - if (nxt_fast_path(err == NULL)) { - return; - } + if (block->type == NXT_MP_CLUSTER_BLOCK) { + err = nxt_mp_chunk_free(mp, block, p); - } else if (nxt_fast_path(p == block->start)) { + if (nxt_fast_path(err == NULL)) { + return; + } - if (block->freeable) { - nxt_rbtree_delete(&mp->blocks, &block->node); + } else if (nxt_fast_path(p == block->start)) { - if (block->type == NXT_MP_DISCRETE_BLOCK) { - nxt_free(block); - } + if (block->freeable) { + nxt_rbtree_delete(&mp->blocks, &block->node); - nxt_free(p); + if (block->type == NXT_MP_DISCRETE_BLOCK) { + nxt_free(block); + } - return; - } + nxt_free(p); - err = "freed pointer points to non-freeable block: %p"; + return; + } - } else { - err = "freed pointer points to middle of block: %p"; - } + err = "freed pointer points to non-freeable block: %p"; } else { - err = "freed pointer is out of pool: %p"; + err = "freed pointer points to middle of block: %p"; } - nxt_thread_log_alert(err, p); -} + } else { + err = "freed pointer is out of pool: %p"; + } + nxt_thread_log_alert(err, p); +} -static nxt_mp_block_t * -nxt_mp_find_block(nxt_rbtree_t *tree, const u_char *p) -{ - nxt_mp_block_t *block; - nxt_rbtree_node_t *node, *sentinel; +static nxt_mp_block_t *nxt_mp_find_block(nxt_rbtree_t *tree, const u_char *p) { + nxt_mp_block_t *block; + nxt_rbtree_node_t *node, *sentinel; - node = nxt_rbtree_root(tree); - sentinel = nxt_rbtree_sentinel(tree); + node = nxt_rbtree_root(tree); + sentinel = nxt_rbtree_sentinel(tree); - while (node != sentinel) { + while (node != sentinel) { - block = (nxt_mp_block_t *) node; + block = (nxt_mp_block_t *)node; - if (p < block->start) { - node = node->left; + if (p < block->start) { + node = node->left; - } else if (p >= block->start + block->size) { - node = node->right; + } else if (p >= block->start + block->size) { + node = node->right; - } else { - return block; - } + } else { + return block; } + } - return NULL; + return NULL; } +static const char *nxt_mp_chunk_free(nxt_mp_t *mp, nxt_mp_block_t *cluster, + u_char *p) { + u_char *start; + uintptr_t offset; + nxt_uint_t n, size, chunk; + nxt_queue_t *chunk_pages; + nxt_mp_page_t *page; -static const char * -nxt_mp_chunk_free(nxt_mp_t *mp, nxt_mp_block_t *cluster, u_char *p) -{ - u_char *start; - uintptr_t offset; - nxt_uint_t n, size, chunk; - nxt_queue_t *chunk_pages; - nxt_mp_page_t *page; - - n = (p - cluster->start) >> mp->page_size_shift; - start = cluster->start + (n << mp->page_size_shift); + n = (p - cluster->start) >> mp->page_size_shift; + start = cluster->start + (n << mp->page_size_shift); - page = &cluster->pages[n]; + page = &cluster->pages[n]; - if (nxt_slow_path(page->size == 0)) { - return "freed pointer points to already free page: %p"; - } - - if (nxt_slow_path(page->size == 0xFF)) { - return "freed pointer points to non-freeable page: %p"; - } + if (nxt_slow_path(page->size == 0)) { + return "freed pointer points to already free page: %p"; + } - size = page->size << mp->chunk_size_shift; + if (nxt_slow_path(page->size == 0xFF)) { + return "freed pointer points to non-freeable page: %p"; + } - if (size != mp->page_size) { + size = page->size << mp->chunk_size_shift; - offset = (uintptr_t) (p - start) & (mp->page_size - 1); - chunk = offset / size; + if (size != mp->page_size) { - if (nxt_slow_path(offset != chunk * size)) { - return "freed pointer points to wrong chunk: %p"; - } + offset = (uintptr_t)(p - start) & (mp->page_size - 1); + chunk = offset / size; - if (nxt_slow_path(nxt_mp_chunk_is_free(page->u.map, chunk))) { - return "freed pointer points to already free chunk: %p"; - } + if (nxt_slow_path(offset != chunk * size)) { + return "freed pointer points to wrong chunk: %p"; + } - nxt_mp_chunk_set_free(page->u.map, chunk); + if (nxt_slow_path(nxt_mp_chunk_is_free(page->u.map, chunk))) { + return "freed pointer points to already free chunk: %p"; + } - if (page->u.map != 0xFFFFFFFF) { - page->chunks++; + nxt_mp_chunk_set_free(page->u.map, chunk); - if (page->chunks == 1) { - /* - * Add the page to the head of pool chunk pages list - * of pages with free chunks. - */ - n = nxt_mp_chunk_pages_index(mp, size); - chunk_pages = &mp->chunk_pages[n]; + if (page->u.map != 0xFFFFFFFF) { + page->chunks++; - nxt_queue_insert_head(chunk_pages, &page->link); - } + if (page->chunks == 1) { + /* + * Add the page to the head of pool chunk pages list + * of pages with free chunks. + */ + n = nxt_mp_chunk_pages_index(mp, size); + chunk_pages = &mp->chunk_pages[n]; - nxt_mp_free_junk(p, size); + nxt_queue_insert_head(chunk_pages, &page->link); + } - return NULL; + nxt_mp_free_junk(p, size); - } else { - /* - * All chunks are free, remove the page from pool - * chunk pages list of pages with free chunks. - */ - nxt_queue_remove(&page->link); - } + return NULL; - } else if (nxt_slow_path(p != start)) { - return "invalid pointer to chunk: %p"; + } else { + /* + * All chunks are free, remove the page from pool + * chunk pages list of pages with free chunks. + */ + nxt_queue_remove(&page->link); } - /* Add the free page to the pool's free pages tree. */ + } else if (nxt_slow_path(p != start)) { + return "invalid pointer to chunk: %p"; + } - page->size = 0; - nxt_queue_insert_head(&mp->free_pages, &page->link); + /* Add the free page to the pool's free pages tree. */ - nxt_mp_free_junk(p, size); + page->size = 0; + nxt_queue_insert_head(&mp->free_pages, &page->link); - /* Test if all pages in the cluster are free. */ + nxt_mp_free_junk(p, size); - n = mp->cluster_size >> mp->page_size_shift; - page = cluster->pages; + /* Test if all pages in the cluster are free. */ - do { - if (page->size != 0) { - return NULL; - } + n = mp->cluster_size >> mp->page_size_shift; + page = cluster->pages; - page++; - n--; - } while (n != 0); + do { + if (page->size != 0) { + return NULL; + } - /* Free cluster. */ + page++; + n--; + } while (n != 0); - n = mp->cluster_size >> mp->page_size_shift; - page = cluster->pages; + /* Free cluster. */ - do { - nxt_queue_remove(&page->link); - page++; - n--; - } while (n != 0); + n = mp->cluster_size >> mp->page_size_shift; + page = cluster->pages; - nxt_rbtree_delete(&mp->blocks, &cluster->node); + do { + nxt_queue_remove(&page->link); + page++; + n--; + } while (n != 0); - p = cluster->start; + nxt_rbtree_delete(&mp->blocks, &cluster->node); - nxt_free(cluster); - nxt_free(p); + p = cluster->start; - return NULL; -} + nxt_free(cluster); + nxt_free(p); + return NULL; +} -void * -nxt_mp_nget(nxt_mp_t *mp, size_t size) -{ - void *p; +void *nxt_mp_nget(nxt_mp_t *mp, size_t size) { + void *p; #if !(NXT_DEBUG_MEMORY) - if (size <= mp->page_size) { - p = nxt_mp_get_small(mp, &mp->nget_pages, size); + if (size <= mp->page_size) { + p = nxt_mp_get_small(mp, &mp->nget_pages, size); - } else { - p = nxt_mp_alloc_large(mp, NXT_MAX_ALIGNMENT, size, 0); - } + } else { + p = nxt_mp_alloc_large(mp, NXT_MAX_ALIGNMENT, size, 0); + } #else - p = nxt_mp_alloc_large(mp, NXT_MAX_ALIGNMENT, size, 0); + p = nxt_mp_alloc_large(mp, NXT_MAX_ALIGNMENT, size, 0); #endif - nxt_debug_alloc("mp %p nget(%uz): %p", mp, size, p); + nxt_debug_alloc("mp %p nget(%uz): %p", mp, size, p); - return p; + return p; } - -void * -nxt_mp_get(nxt_mp_t *mp, size_t size) -{ - void *p; +void *nxt_mp_get(nxt_mp_t *mp, size_t size) { + void *p; #if !(NXT_DEBUG_MEMORY) - if (size <= mp->page_size) { - size = nxt_max(size, NXT_MAX_ALIGNMENT); - p = nxt_mp_get_small(mp, &mp->get_pages, size); + if (size <= mp->page_size) { + size = nxt_max(size, NXT_MAX_ALIGNMENT); + p = nxt_mp_get_small(mp, &mp->get_pages, size); - } else { - p = nxt_mp_alloc_large(mp, NXT_MAX_ALIGNMENT, size, 0); - } + } else { + p = nxt_mp_alloc_large(mp, NXT_MAX_ALIGNMENT, size, 0); + } #else - p = nxt_mp_alloc_large(mp, NXT_MAX_ALIGNMENT, size, 0); + p = nxt_mp_alloc_large(mp, NXT_MAX_ALIGNMENT, size, 0); #endif - nxt_debug_alloc("mp %p get(%uz): %p", mp, size, p); + nxt_debug_alloc("mp %p get(%uz): %p", mp, size, p); - return p; + return p; } +void *nxt_mp_zget(nxt_mp_t *mp, size_t size) { + void *p; -void * -nxt_mp_zget(nxt_mp_t *mp, size_t size) -{ - void *p; + p = nxt_mp_get(mp, size); - p = nxt_mp_get(mp, size); + if (nxt_fast_path(p != NULL)) { + memset(p, 0, size); + } - if (nxt_fast_path(p != NULL)) { - memset(p, 0, size); - } - - return p; + return p; } +nxt_int_t nxt_mp_cleanup(nxt_mp_t *mp, nxt_work_handler_t handler, + nxt_task_t *task, void *obj, void *data) { + nxt_work_t *work; -nxt_int_t -nxt_mp_cleanup(nxt_mp_t *mp, nxt_work_handler_t handler, - nxt_task_t *task, void *obj, void *data) -{ - nxt_work_t *work; + work = nxt_mp_get(mp, sizeof(nxt_work_t)); - work = nxt_mp_get(mp, sizeof(nxt_work_t)); + if (nxt_slow_path(work == NULL)) { + return NXT_ERROR; + } - if (nxt_slow_path(work == NULL)) { - return NXT_ERROR; - } + work->next = mp->cleanup; + work->handler = handler; + work->task = task; + work->obj = obj; + work->data = data; - work->next = mp->cleanup; - work->handler = handler; - work->task = task; - work->obj = obj; - work->data = data; + mp->cleanup = work; - mp->cleanup = work; - - return NXT_OK; + return NXT_OK; } - -void * -nxt_mp_lvlhsh_alloc(void *pool, size_t size) -{ - return nxt_mp_align(pool, size, size); +void *nxt_mp_lvlhsh_alloc(void *pool, size_t size) { + return nxt_mp_align(pool, size, size); } - -void -nxt_mp_lvlhsh_free(void *pool, void *p) -{ - nxt_mp_free(pool, p); -} +void nxt_mp_lvlhsh_free(void *pool, void *p) { nxt_mp_free(pool, p); } diff --git a/src/nxt_mp.h b/src/nxt_mp.h index a5aaabd19..8ea38c20b 100644 --- a/src/nxt_mp.h +++ b/src/nxt_mp.h @@ -7,7 +7,6 @@ #ifndef _NXT_MP_H_INCLUDED_ #define _NXT_MP_H_INCLUDED_ - /* * Memory pool keeps track of all allocations so they can be freed at once * on pool destruction. A memory pool is not thread safe, so only one thread @@ -24,16 +23,15 @@ * may also improve data cache locality. */ -typedef struct nxt_mp_s nxt_mp_t; - +typedef struct nxt_mp_s nxt_mp_t; /* * nxt_mp_create() creates a memory pool and sets the pool's retention * counter to 1. */ NXT_EXPORT nxt_mp_t *nxt_mp_create(size_t cluster_size, size_t page_alignment, - size_t page_size, size_t min_chunk_size) - NXT_MALLOC_LIKE; + size_t page_size, + size_t min_chunk_size) NXT_MALLOC_LIKE; /* * nxt_mp_destroy() destroys memory pool in spite of the pool's retention @@ -54,65 +52,55 @@ NXT_EXPORT void nxt_mp_release(nxt_mp_t *mp); /* nxt_mp_test_sizes() tests validity of memory pool parameters. */ NXT_EXPORT nxt_bool_t nxt_mp_test_sizes(size_t cluster_size, - size_t page_alignment, size_t page_size, size_t min_chunk_size); + size_t page_alignment, size_t page_size, + size_t min_chunk_size); /* nxt_mp_is_empty() tests that pool is empty. */ NXT_EXPORT nxt_bool_t nxt_mp_is_empty(nxt_mp_t *mp); - /* * nxt_mp_alloc() returns aligned freeable memory. * The alignment is sutiable to allocate structures. */ -NXT_EXPORT void *nxt_mp_alloc(nxt_mp_t *mp, size_t size) - NXT_MALLOC_LIKE; - +NXT_EXPORT void *nxt_mp_alloc(nxt_mp_t *mp, size_t size) NXT_MALLOC_LIKE; /* * nxt_mp_zalloc() returns zeroed aligned freeable memory. * The alignment is sutiable to allocate structures. */ -NXT_EXPORT void *nxt_mp_zalloc(nxt_mp_t *mp, size_t size) - NXT_MALLOC_LIKE; +NXT_EXPORT void *nxt_mp_zalloc(nxt_mp_t *mp, size_t size) NXT_MALLOC_LIKE; /* nxt_mp_align() returns aligned freeable memory. */ -NXT_EXPORT void *nxt_mp_align(nxt_mp_t *mp, size_t alignment, size_t size) - NXT_MALLOC_LIKE; +NXT_EXPORT void *nxt_mp_align(nxt_mp_t *mp, size_t alignment, + size_t size) NXT_MALLOC_LIKE; /* nxt_mp_zalign() returns zeroed aligned freeable memory. */ -NXT_EXPORT void *nxt_mp_zalign(nxt_mp_t *mp, size_t alignment, size_t size) - NXT_MALLOC_LIKE; +NXT_EXPORT void *nxt_mp_zalign(nxt_mp_t *mp, size_t alignment, + size_t size) NXT_MALLOC_LIKE; /* nxt_mp_free() frees freeable memory. */ NXT_EXPORT void nxt_mp_free(nxt_mp_t *mp, void *p); - /* nxt_mp_nget() returns non-aligned non-freeable memory. */ -NXT_EXPORT void *nxt_mp_nget(nxt_mp_t *mp, size_t size) - NXT_MALLOC_LIKE; +NXT_EXPORT void *nxt_mp_nget(nxt_mp_t *mp, size_t size) NXT_MALLOC_LIKE; /* * nxt_mp_get() returns aligned non-freeable memory. * The alignment is sutiable to allocate structures. */ -NXT_EXPORT void *nxt_mp_get(nxt_mp_t *mp, size_t size) - NXT_MALLOC_LIKE; +NXT_EXPORT void *nxt_mp_get(nxt_mp_t *mp, size_t size) NXT_MALLOC_LIKE; /* * nxt_mp_zget() returns zeroed aligned non-freeable memory. * The alignment is sutiable to allocate structures. */ -NXT_EXPORT void *nxt_mp_zget(nxt_mp_t *mp, size_t size) - NXT_MALLOC_LIKE; - +NXT_EXPORT void *nxt_mp_zget(nxt_mp_t *mp, size_t size) NXT_MALLOC_LIKE; NXT_EXPORT nxt_int_t nxt_mp_cleanup(nxt_mp_t *mp, nxt_work_handler_t handler, - nxt_task_t *task, void *obj, void *data); - + nxt_task_t *task, void *obj, void *data); NXT_EXPORT void nxt_mp_thread_adopt(nxt_mp_t *mp); - NXT_EXPORT void *nxt_mp_lvlhsh_alloc(void *pool, size_t size); NXT_EXPORT void nxt_mp_lvlhsh_free(void *pool, void *p); diff --git a/src/nxt_murmur_hash.c b/src/nxt_murmur_hash.c index 56bf2d4b6..fbe21c341 100644 --- a/src/nxt_murmur_hash.c +++ b/src/nxt_murmur_hash.c @@ -6,66 +6,16 @@ #include +uint32_t nxt_murmur_hash2(const void *data, size_t len) { + uint32_t h, k; + const u_char *p; + const uint32_t m = 0x5BD1E995; -uint32_t -nxt_murmur_hash2(const void *data, size_t len) -{ - uint32_t h, k; - const u_char *p; - const uint32_t m = 0x5BD1E995; - - p = data; - h = 0 ^ (uint32_t) len; - - while (len >= 4) { - k = p[0]; - k |= p[1] << 8; - k |= p[2] << 16; - k |= p[3] << 24; - - k *= m; - k ^= k >> 24; - k *= m; - - h *= m; - h ^= k; - - p += 4; - len -= 4; - } - - switch (len) { - case 3: - h ^= p[2] << 16; - /* Fall through. */ - case 2: - h ^= p[1] << 8; - /* Fall through. */ - case 1: - h ^= p[0]; - h *= m; - } - - h ^= h >> 13; - h *= m; - h ^= h >> 15; - - return h; -} - - -/* The MurmurHash2 for fixed 4 byte length. */ - -uint32_t -nxt_murmur_hash2_uint32(const void *data) -{ - uint32_t h, k; - const u_char *p; - const uint32_t m = 0x5BD1E995; - - p = data; + p = data; + h = 0 ^ (uint32_t)len; - k = p[0]; + while (len >= 4) { + k = p[0]; k |= p[1] << 8; k |= p[2] << 16; k |= p[3] << 24; @@ -74,13 +24,57 @@ nxt_murmur_hash2_uint32(const void *data) k ^= k >> 24; k *= m; - h = 0 ^ 4; h *= m; h ^= k; - h ^= h >> 13; + p += 4; + len -= 4; + } + + switch (len) { + case 3: + h ^= p[2] << 16; + /* Fall through. */ + case 2: + h ^= p[1] << 8; + /* Fall through. */ + case 1: + h ^= p[0]; h *= m; - h ^= h >> 15; + } + + h ^= h >> 13; + h *= m; + h ^= h >> 15; + + return h; +} + +/* The MurmurHash2 for fixed 4 byte length. */ + +uint32_t nxt_murmur_hash2_uint32(const void *data) { + uint32_t h, k; + const u_char *p; + const uint32_t m = 0x5BD1E995; + + p = data; + + k = p[0]; + k |= p[1] << 8; + k |= p[2] << 16; + k |= p[3] << 24; + + k *= m; + k ^= k >> 24; + k *= m; + + h = 0 ^ 4; + h *= m; + h ^= k; + + h ^= h >> 13; + h *= m; + h ^= h >> 15; - return h; + return h; } diff --git a/src/nxt_murmur_hash.h b/src/nxt_murmur_hash.h index 289dc5b01..8a5d8d576 100644 --- a/src/nxt_murmur_hash.h +++ b/src/nxt_murmur_hash.h @@ -7,9 +7,7 @@ #ifndef _NXT_MURMUR_HASH_H_INCLUDED_ #define _NXT_MURMUR_HASH_H_INCLUDED_ - NXT_EXPORT uint32_t nxt_murmur_hash2(const void *data, size_t len); NXT_EXPORT uint32_t nxt_murmur_hash2_uint32(const void *data); - #endif /* _NXT_MURMUR_HASH_H_INCLUDED_ */ diff --git a/src/nxt_nncq.h b/src/nxt_nncq.h index 6c9ab3262..cb20706e3 100644 --- a/src/nxt_nncq.h +++ b/src/nxt_nncq.h @@ -6,157 +6,126 @@ #ifndef _NXT_NNCQ_H_INCLUDED_ #define _NXT_NNCQ_H_INCLUDED_ - /* Numeric Naive Circular Queue */ -#define NXT_NNCQ_SIZE 16384 +#define NXT_NNCQ_SIZE 16384 typedef uint32_t nxt_nncq_atomic_t; typedef uint16_t nxt_nncq_cycle_t; typedef struct { - nxt_nncq_atomic_t head; - nxt_nncq_atomic_t entries[NXT_NNCQ_SIZE]; - nxt_nncq_atomic_t tail; + nxt_nncq_atomic_t head; + nxt_nncq_atomic_t entries[NXT_NNCQ_SIZE]; + nxt_nncq_atomic_t tail; } nxt_nncq_t; - -static inline nxt_nncq_atomic_t -nxt_nncq_head(nxt_nncq_t const volatile *q) -{ - return q->head; +static inline nxt_nncq_atomic_t nxt_nncq_head(nxt_nncq_t const volatile *q) { + return q->head; } - -static inline nxt_nncq_atomic_t -nxt_nncq_tail(nxt_nncq_t const volatile *q) -{ - return q->tail; +static inline nxt_nncq_atomic_t nxt_nncq_tail(nxt_nncq_t const volatile *q) { + return q->tail; } - -static inline void -nxt_nncq_tail_cmp_inc(nxt_nncq_t volatile *q, nxt_nncq_atomic_t t) -{ - nxt_atomic_cmp_set(&q->tail, t, t + 1); +static inline void nxt_nncq_tail_cmp_inc(nxt_nncq_t volatile *q, + nxt_nncq_atomic_t t) { + nxt_atomic_cmp_set(&q->tail, t, t + 1); } - -static inline nxt_nncq_atomic_t -nxt_nncq_index(nxt_nncq_t const volatile *q, nxt_nncq_atomic_t i) -{ - return i % NXT_NNCQ_SIZE; +static inline nxt_nncq_atomic_t nxt_nncq_index(nxt_nncq_t const volatile *q, + nxt_nncq_atomic_t i) { + return i % NXT_NNCQ_SIZE; } - -static inline nxt_nncq_atomic_t -nxt_nncq_map(nxt_nncq_t const volatile *q, nxt_nncq_atomic_t i) -{ - return i % NXT_NNCQ_SIZE; +static inline nxt_nncq_atomic_t nxt_nncq_map(nxt_nncq_t const volatile *q, + nxt_nncq_atomic_t i) { + return i % NXT_NNCQ_SIZE; } - -static inline nxt_nncq_cycle_t -nxt_nncq_cycle(nxt_nncq_t const volatile *q, nxt_nncq_atomic_t i) -{ - return i / NXT_NNCQ_SIZE; +static inline nxt_nncq_cycle_t nxt_nncq_cycle(nxt_nncq_t const volatile *q, + nxt_nncq_atomic_t i) { + return i / NXT_NNCQ_SIZE; } - -static inline nxt_nncq_cycle_t -nxt_nncq_next_cycle(nxt_nncq_t const volatile *q, nxt_nncq_cycle_t i) -{ - return i + 1; +static inline nxt_nncq_cycle_t nxt_nncq_next_cycle(nxt_nncq_t const volatile *q, + nxt_nncq_cycle_t i) { + return i + 1; } - -static inline nxt_nncq_atomic_t -nxt_nncq_new_entry(nxt_nncq_t const volatile *q, nxt_nncq_cycle_t cycle, - nxt_nncq_atomic_t i) -{ - return cycle * NXT_NNCQ_SIZE + (i % NXT_NNCQ_SIZE); +static inline nxt_nncq_atomic_t nxt_nncq_new_entry(nxt_nncq_t const volatile *q, + nxt_nncq_cycle_t cycle, + nxt_nncq_atomic_t i) { + return cycle * NXT_NNCQ_SIZE + (i % NXT_NNCQ_SIZE); } - -static inline nxt_nncq_atomic_t -nxt_nncq_empty(nxt_nncq_t const volatile *q) -{ - return NXT_NNCQ_SIZE; +static inline nxt_nncq_atomic_t nxt_nncq_empty(nxt_nncq_t const volatile *q) { + return NXT_NNCQ_SIZE; } - -static inline void -nxt_nncq_init(nxt_nncq_t volatile *q) -{ - q->head = NXT_NNCQ_SIZE; - nxt_memzero((void *) q->entries, NXT_NNCQ_SIZE * sizeof(nxt_nncq_atomic_t)); - q->tail = NXT_NNCQ_SIZE; +static inline void nxt_nncq_init(nxt_nncq_t volatile *q) { + q->head = NXT_NNCQ_SIZE; + nxt_memzero((void *)q->entries, NXT_NNCQ_SIZE * sizeof(nxt_nncq_atomic_t)); + q->tail = NXT_NNCQ_SIZE; } +static inline void nxt_nncq_enqueue(nxt_nncq_t volatile *q, + nxt_nncq_atomic_t val) { + nxt_nncq_cycle_t e_cycle, t_cycle; + nxt_nncq_atomic_t n, t, e, j; -static inline void -nxt_nncq_enqueue(nxt_nncq_t volatile *q, nxt_nncq_atomic_t val) -{ - nxt_nncq_cycle_t e_cycle, t_cycle; - nxt_nncq_atomic_t n, t, e, j; + for (;;) { + t = nxt_nncq_tail(q); + j = nxt_nncq_map(q, t); + e = q->entries[j]; - for ( ;; ) { - t = nxt_nncq_tail(q); - j = nxt_nncq_map(q, t); - e = q->entries[j]; + e_cycle = nxt_nncq_cycle(q, e); + t_cycle = nxt_nncq_cycle(q, t); - e_cycle = nxt_nncq_cycle(q, e); - t_cycle = nxt_nncq_cycle(q, t); - - if (e_cycle == t_cycle) { - nxt_nncq_tail_cmp_inc(q, t); - continue; - } + if (e_cycle == t_cycle) { + nxt_nncq_tail_cmp_inc(q, t); + continue; + } - if (nxt_nncq_next_cycle(q, e_cycle) != t_cycle) { - continue; - } + if (nxt_nncq_next_cycle(q, e_cycle) != t_cycle) { + continue; + } - n = nxt_nncq_new_entry(q, t_cycle, val); + n = nxt_nncq_new_entry(q, t_cycle, val); - if (nxt_atomic_cmp_set(&q->entries[j], e, n)) { - break; - } + if (nxt_atomic_cmp_set(&q->entries[j], e, n)) { + break; } + } - nxt_nncq_tail_cmp_inc(q, t); + nxt_nncq_tail_cmp_inc(q, t); } +static inline nxt_nncq_atomic_t nxt_nncq_dequeue(nxt_nncq_t volatile *q) { + nxt_nncq_cycle_t e_cycle, h_cycle; + nxt_nncq_atomic_t h, j, e; -static inline nxt_nncq_atomic_t -nxt_nncq_dequeue(nxt_nncq_t volatile *q) -{ - nxt_nncq_cycle_t e_cycle, h_cycle; - nxt_nncq_atomic_t h, j, e; - - for ( ;; ) { - h = nxt_nncq_head(q); - j = nxt_nncq_map(q, h); - e = q->entries[j]; + for (;;) { + h = nxt_nncq_head(q); + j = nxt_nncq_map(q, h); + e = q->entries[j]; - e_cycle = nxt_nncq_cycle(q, e); - h_cycle = nxt_nncq_cycle(q, h); + e_cycle = nxt_nncq_cycle(q, e); + h_cycle = nxt_nncq_cycle(q, h); - if (e_cycle != h_cycle) { - if (nxt_nncq_next_cycle(q, e_cycle) == h_cycle) { - return nxt_nncq_empty(q); - } + if (e_cycle != h_cycle) { + if (nxt_nncq_next_cycle(q, e_cycle) == h_cycle) { + return nxt_nncq_empty(q); + } - continue; - } + continue; + } - if (nxt_atomic_cmp_set(&q->head, h, h + 1)) { - break; - } + if (nxt_atomic_cmp_set(&q->head, h, h + 1)) { + break; } + } - return nxt_nncq_index(q, e); + return nxt_nncq_index(q, e); } - #endif /* _NXT_NNCQ_H_INCLUDED_ */ diff --git a/src/nxt_nvbcq.h b/src/nxt_nvbcq.h index e164615b6..15aed059a 100644 --- a/src/nxt_nvbcq.h +++ b/src/nxt_nvbcq.h @@ -6,141 +6,115 @@ #ifndef _NXT_NVBCQ_H_INCLUDED_ #define _NXT_NVBCQ_H_INCLUDED_ - /* Numeric VBart Circular Queue */ -#define NXT_NVBCQ_SIZE 16384 +#define NXT_NVBCQ_SIZE 16384 typedef uint32_t nxt_nvbcq_atomic_t; struct nxt_nvbcq_s { - nxt_nvbcq_atomic_t head; - nxt_nvbcq_atomic_t entries[NXT_NVBCQ_SIZE]; - nxt_nvbcq_atomic_t tail; + nxt_nvbcq_atomic_t head; + nxt_nvbcq_atomic_t entries[NXT_NVBCQ_SIZE]; + nxt_nvbcq_atomic_t tail; }; typedef struct nxt_nvbcq_s nxt_nvbcq_t; - -static inline nxt_nvbcq_atomic_t -nxt_nvbcq_head(nxt_nvbcq_t const volatile *q) -{ - return q->head; +static inline nxt_nvbcq_atomic_t nxt_nvbcq_head(nxt_nvbcq_t const volatile *q) { + return q->head; } - -static inline nxt_nvbcq_atomic_t -nxt_nvbcq_tail(nxt_nvbcq_t const volatile *q) -{ - return q->tail; +static inline nxt_nvbcq_atomic_t nxt_nvbcq_tail(nxt_nvbcq_t const volatile *q) { + return q->tail; } - -static inline void -nxt_nvbcq_tail_cmp_inc(nxt_nvbcq_t volatile *q, nxt_nvbcq_atomic_t t) -{ - nxt_atomic_cmp_set(&q->tail, t, t + 1); +static inline void nxt_nvbcq_tail_cmp_inc(nxt_nvbcq_t volatile *q, + nxt_nvbcq_atomic_t t) { + nxt_atomic_cmp_set(&q->tail, t, t + 1); } - -static inline nxt_nvbcq_atomic_t -nxt_nvbcq_index(nxt_nvbcq_t const volatile *q, nxt_nvbcq_atomic_t i) -{ - return i % NXT_NVBCQ_SIZE; +static inline nxt_nvbcq_atomic_t nxt_nvbcq_index(nxt_nvbcq_t const volatile *q, + nxt_nvbcq_atomic_t i) { + return i % NXT_NVBCQ_SIZE; } - -static inline nxt_nvbcq_atomic_t -nxt_nvbcq_map(nxt_nvbcq_t const volatile *q, nxt_nvbcq_atomic_t i) -{ - return i % NXT_NVBCQ_SIZE; +static inline nxt_nvbcq_atomic_t nxt_nvbcq_map(nxt_nvbcq_t const volatile *q, + nxt_nvbcq_atomic_t i) { + return i % NXT_NVBCQ_SIZE; } - static inline nxt_nvbcq_atomic_t -nxt_nvbcq_empty(nxt_nvbcq_t const volatile *q) -{ - return NXT_NVBCQ_SIZE; +nxt_nvbcq_empty(nxt_nvbcq_t const volatile *q) { + return NXT_NVBCQ_SIZE; } +static inline void nxt_nvbcq_init(nxt_nvbcq_t volatile *q) { + nxt_nvbcq_atomic_t i; -static inline void -nxt_nvbcq_init(nxt_nvbcq_t volatile *q) -{ - nxt_nvbcq_atomic_t i; + q->head = 0; - q->head = 0; + for (i = 0; i < NXT_NVBCQ_SIZE; i++) { + q->entries[i] = NXT_NVBCQ_SIZE; + } - for (i = 0; i < NXT_NVBCQ_SIZE; i++) { - q->entries[i] = NXT_NVBCQ_SIZE; - } - - q->tail = NXT_NVBCQ_SIZE; + q->tail = NXT_NVBCQ_SIZE; } +static inline void nxt_nvbcq_enqueue(nxt_nvbcq_t volatile *q, + nxt_nvbcq_atomic_t val) { + nxt_nvbcq_atomic_t t, h, i; -static inline void -nxt_nvbcq_enqueue(nxt_nvbcq_t volatile *q, nxt_nvbcq_atomic_t val) -{ - nxt_nvbcq_atomic_t t, h, i; - - t = nxt_nvbcq_tail(q); - h = t - NXT_NVBCQ_SIZE; - - for ( ;; ) { - i = nxt_nvbcq_map(q, t); + t = nxt_nvbcq_tail(q); + h = t - NXT_NVBCQ_SIZE; - if (q->entries[i] == NXT_NVBCQ_SIZE - && nxt_atomic_cmp_set(&q->entries[i], NXT_NVBCQ_SIZE, val)) - { - nxt_nvbcq_tail_cmp_inc(q, t); - return; - } + for (;;) { + i = nxt_nvbcq_map(q, t); - if ((t - h) == NXT_NVBCQ_SIZE) { - h = nxt_nvbcq_head(q); + if (q->entries[i] == NXT_NVBCQ_SIZE && + nxt_atomic_cmp_set(&q->entries[i], NXT_NVBCQ_SIZE, val)) { + nxt_nvbcq_tail_cmp_inc(q, t); + return; + } - if ((t - h) == NXT_NVBCQ_SIZE) { - return; - } - } + if ((t - h) == NXT_NVBCQ_SIZE) { + h = nxt_nvbcq_head(q); - t++; + if ((t - h) == NXT_NVBCQ_SIZE) { + return; + } } -} - -static inline nxt_nvbcq_atomic_t -nxt_nvbcq_dequeue(nxt_nvbcq_t volatile *q) -{ - nxt_nvbcq_atomic_t h, t, i, e; + t++; + } +} - h = nxt_nvbcq_head(q); - t = h + NXT_NVBCQ_SIZE; +static inline nxt_nvbcq_atomic_t nxt_nvbcq_dequeue(nxt_nvbcq_t volatile *q) { + nxt_nvbcq_atomic_t h, t, i, e; - for ( ;; ) { - i = nxt_nvbcq_map(q, h); - e = q->entries[i]; + h = nxt_nvbcq_head(q); + t = h + NXT_NVBCQ_SIZE; - if (e < NXT_NVBCQ_SIZE - && nxt_atomic_cmp_set(&q->entries[i], e, NXT_NVBCQ_SIZE)) - { - nxt_atomic_cmp_set(&q->head, h, h + 1); + for (;;) { + i = nxt_nvbcq_map(q, h); + e = q->entries[i]; - return e; - } + if (e < NXT_NVBCQ_SIZE && + nxt_atomic_cmp_set(&q->entries[i], e, NXT_NVBCQ_SIZE)) { + nxt_atomic_cmp_set(&q->head, h, h + 1); - if ((t - h) == NXT_NVBCQ_SIZE) { - t = nxt_nvbcq_tail(q); + return e; + } - if ((t - h) == NXT_NVBCQ_SIZE) { - return NXT_NVBCQ_SIZE; - } - } + if ((t - h) == NXT_NVBCQ_SIZE) { + t = nxt_nvbcq_tail(q); - h++; + if ((t - h) == NXT_NVBCQ_SIZE) { + return NXT_NVBCQ_SIZE; + } } -} + h++; + } +} #endif /* _NXT_NVBCQ_H_INCLUDED_ */ diff --git a/src/nxt_openssl.c b/src/nxt_openssl.c index 8f66f45b3..5d37a1db3 100644 --- a/src/nxt_openssl.c +++ b/src/nxt_openssl.c @@ -17,42 +17,37 @@ #include #include - typedef struct { - SSL *session; - nxt_conn_t *conn; + SSL *session; + nxt_conn_t *conn; - int ssl_error; - uint8_t times; /* 2 bits */ - uint8_t handshake; /* 1 bit */ + int ssl_error; + uint8_t times; /* 2 bits */ + uint8_t handshake; /* 1 bit */ - nxt_tls_conf_t *conf; - nxt_buf_mem_t buffer; + nxt_tls_conf_t *conf; + nxt_buf_mem_t buffer; } nxt_openssl_conn_t; - struct nxt_tls_ticket_s { - u_char name[16]; - u_char hmac_key[32]; - u_char aes_key[32]; - uint8_t size; + u_char name[16]; + u_char hmac_key[32]; + u_char aes_key[32]; + uint8_t size; }; - struct nxt_tls_tickets_s { - nxt_uint_t count; - nxt_tls_ticket_t tickets[]; + nxt_uint_t count; + nxt_tls_ticket_t tickets[]; }; - typedef enum { - NXT_OPENSSL_HANDSHAKE = 0, - NXT_OPENSSL_READ, - NXT_OPENSSL_WRITE, - NXT_OPENSSL_SHUTDOWN, + NXT_OPENSSL_HANDSHAKE = 0, + NXT_OPENSSL_READ, + NXT_OPENSSL_WRITE, + NXT_OPENSSL_SHUTDOWN, } nxt_openssl_io_t; - static nxt_int_t nxt_openssl_library_init(nxt_task_t *task); static void nxt_openssl_library_free(nxt_task_t *task); #if OPENSSL_VERSION_NUMBER < 0x10100004L @@ -62,50 +57,55 @@ static unsigned long nxt_openssl_thread_id(void); static void nxt_openssl_locks_free(void); #endif static nxt_int_t nxt_openssl_server_init(nxt_task_t *task, nxt_mp_t *mp, - nxt_tls_init_t *tls_init, nxt_bool_t last); + nxt_tls_init_t *tls_init, + nxt_bool_t last); static nxt_int_t nxt_openssl_chain_file(nxt_task_t *task, SSL_CTX *ctx, - nxt_tls_conf_t *conf, nxt_mp_t *mp, nxt_bool_t single); + nxt_tls_conf_t *conf, nxt_mp_t *mp, + nxt_bool_t single); #if (NXT_HAVE_OPENSSL_CONF_CMD) static nxt_int_t nxt_ssl_conf_commands(nxt_task_t *task, SSL_CTX *ctx, - nxt_conf_value_t *value, nxt_mp_t *mp); + nxt_conf_value_t *value, nxt_mp_t *mp); #endif #if (NXT_HAVE_OPENSSL_TLSEXT) static nxt_int_t nxt_tls_ticket_keys(nxt_task_t *task, SSL_CTX *ctx, - nxt_tls_init_t *tls_init, nxt_mp_t *mp); + nxt_tls_init_t *tls_init, nxt_mp_t *mp); static int nxt_tls_ticket_key_callback(SSL *s, unsigned char *name, - unsigned char *iv, EVP_CIPHER_CTX *ectx, HMAC_CTX *hctx, int enc); + unsigned char *iv, EVP_CIPHER_CTX *ectx, + HMAC_CTX *hctx, int enc); #endif static void nxt_ssl_session_cache(SSL_CTX *ctx, size_t cache_size, - time_t timeout); + time_t timeout); static nxt_uint_t nxt_openssl_cert_get_names(nxt_task_t *task, X509 *cert, - nxt_tls_conf_t *conf, nxt_mp_t *mp); + nxt_tls_conf_t *conf, + nxt_mp_t *mp); static nxt_int_t nxt_openssl_bundle_hash_test(nxt_lvlhsh_query_t *lhq, - void *data); -static nxt_int_t nxt_openssl_bundle_hash_insert(nxt_task_t *task, - nxt_lvlhsh_t *lvlhsh, nxt_tls_bundle_hash_item_t *item, nxt_mp_t * mp); + void *data); +static nxt_int_t +nxt_openssl_bundle_hash_insert(nxt_task_t *task, nxt_lvlhsh_t *lvlhsh, + nxt_tls_bundle_hash_item_t *item, nxt_mp_t *mp); static nxt_int_t nxt_openssl_servername(SSL *s, int *ad, void *arg); static nxt_tls_bundle_conf_t *nxt_openssl_find_ctx(nxt_tls_conf_t *conf, - nxt_str_t *sn); + nxt_str_t *sn); static void nxt_openssl_server_free(nxt_task_t *task, nxt_tls_conf_t *conf); static void nxt_openssl_conn_init(nxt_task_t *task, nxt_tls_conf_t *conf, - nxt_conn_t *c); + nxt_conn_t *c); static void nxt_openssl_conn_handshake(nxt_task_t *task, void *obj, void *data); static ssize_t nxt_openssl_conn_io_recvbuf(nxt_conn_t *c, nxt_buf_t *b); static ssize_t nxt_openssl_conn_io_sendbuf(nxt_task_t *task, nxt_sendbuf_t *sb); static ssize_t nxt_openssl_conn_io_send(nxt_task_t *task, nxt_sendbuf_t *sb, - void *buf, size_t size); + void *buf, size_t size); static void nxt_openssl_conn_io_shutdown(nxt_task_t *task, void *obj, - void *data); + void *data); static nxt_int_t nxt_openssl_conn_test_error(nxt_task_t *task, nxt_conn_t *c, - int ret, nxt_err_t sys_err, nxt_openssl_io_t io); + int ret, nxt_err_t sys_err, + nxt_openssl_io_t io); static void nxt_openssl_conn_io_shutdown_timeout(nxt_task_t *task, void *obj, - void *data); -static void nxt_cdecl nxt_openssl_conn_error(nxt_task_t *task, - nxt_err_t err, const char *fmt, ...); + void *data); +static void nxt_cdecl nxt_openssl_conn_error(nxt_task_t *task, nxt_err_t err, + const char *fmt, ...); static nxt_uint_t nxt_openssl_log_error_level(nxt_err_t err); - -const nxt_tls_lib_t nxt_openssl_lib = { +const nxt_tls_lib_t nxt_openssl_lib = { .library_init = nxt_openssl_library_init, .library_free = nxt_openssl_library_free, @@ -113,8 +113,7 @@ const nxt_tls_lib_t nxt_openssl_lib = { .server_free = nxt_openssl_server_free, }; - -static nxt_conn_io_t nxt_openssl_conn_io = { +static nxt_conn_io_t nxt_openssl_conn_io = { .read = nxt_conn_io_read, .recvbuf = nxt_openssl_conn_io_recvbuf, @@ -124,1694 +123,1601 @@ static nxt_conn_io_t nxt_openssl_conn_io = { .shutdown = nxt_openssl_conn_io_shutdown, }; +static long nxt_openssl_version; +static int nxt_openssl_connection_index; -static long nxt_openssl_version; -static int nxt_openssl_connection_index; - +static nxt_int_t nxt_openssl_library_init(nxt_task_t *task) { + int index; -static nxt_int_t -nxt_openssl_library_init(nxt_task_t *task) -{ - int index; - - if (nxt_fast_path(nxt_openssl_version != 0)) { - return NXT_OK; - } + if (nxt_fast_path(nxt_openssl_version != 0)) { + return NXT_OK; + } #if OPENSSL_VERSION_NUMBER >= 0x10100003L - OPENSSL_init_ssl(OPENSSL_INIT_LOAD_CONFIG, NULL); + OPENSSL_init_ssl(OPENSSL_INIT_LOAD_CONFIG, NULL); #else - { - nxt_int_t ret; + { + nxt_int_t ret; - SSL_load_error_strings(); + SSL_load_error_strings(); - OPENSSL_config(NULL); + OPENSSL_config(NULL); - /* - * SSL_library_init(3): - * - * SSL_library_init() always returns "1", - * so it is safe to discard the return value. - */ - (void) SSL_library_init(); + /* + * SSL_library_init(3): + * + * SSL_library_init() always returns "1", + * so it is safe to discard the return value. + */ + (void)SSL_library_init(); - ret = nxt_openssl_locks_init(); - if (nxt_slow_path(ret != NXT_OK)) { - return ret; - } + ret = nxt_openssl_locks_init(); + if (nxt_slow_path(ret != NXT_OK)) { + return ret; } + } #endif - nxt_openssl_version = SSLeay(); + nxt_openssl_version = SSLeay(); - nxt_log(task, NXT_LOG_INFO, "%s, %xl", - SSLeay_version(SSLEAY_VERSION), nxt_openssl_version); + nxt_log(task, NXT_LOG_INFO, "%s, %xl", SSLeay_version(SSLEAY_VERSION), + nxt_openssl_version); #ifndef SSL_OP_NO_COMPRESSION - { - /* - * Disable gzip compression in OpenSSL prior to 1.0.0 - * version, this saves about 522K per connection. - */ - int n; - STACK_OF(SSL_COMP) *ssl_comp_methods; - - ssl_comp_methods = SSL_COMP_get_compression_methods(); - - for (n = sk_SSL_COMP_num(ssl_comp_methods); n != 0; n--) { - (void) sk_SSL_COMP_pop(ssl_comp_methods); - } + { + /* + * Disable gzip compression in OpenSSL prior to 1.0.0 + * version, this saves about 522K per connection. + */ + int n; + STACK_OF(SSL_COMP) * ssl_comp_methods; + + ssl_comp_methods = SSL_COMP_get_compression_methods(); + + for (n = sk_SSL_COMP_num(ssl_comp_methods); n != 0; n--) { + (void)sk_SSL_COMP_pop(ssl_comp_methods); } + } #endif - index = SSL_get_ex_new_index(0, NULL, NULL, NULL, NULL); + index = SSL_get_ex_new_index(0, NULL, NULL, NULL, NULL); - if (index == -1) { - nxt_openssl_log_error(task, NXT_LOG_ALERT, - "SSL_get_ex_new_index() failed"); - return NXT_ERROR; - } + if (index == -1) { + nxt_openssl_log_error(task, NXT_LOG_ALERT, "SSL_get_ex_new_index() failed"); + return NXT_ERROR; + } - nxt_openssl_connection_index = index; + nxt_openssl_connection_index = index; - return NXT_OK; + return NXT_OK; } - #if OPENSSL_VERSION_NUMBER >= 0x10100003L -static void -nxt_openssl_library_free(nxt_task_t *task) -{ -} +static void nxt_openssl_library_free(nxt_task_t *task) {} #else -static nxt_thread_mutex_t *nxt_openssl_locks; +static nxt_thread_mutex_t *nxt_openssl_locks; -static nxt_int_t -nxt_openssl_locks_init(void) -{ - int i, n; - nxt_int_t ret; +static nxt_int_t nxt_openssl_locks_init(void) { + int i, n; + nxt_int_t ret; - n = CRYPTO_num_locks(); + n = CRYPTO_num_locks(); - nxt_openssl_locks = OPENSSL_malloc(n * sizeof(nxt_thread_mutex_t)); - if (nxt_slow_path(nxt_openssl_locks == NULL)) { - return NXT_ERROR; - } + nxt_openssl_locks = OPENSSL_malloc(n * sizeof(nxt_thread_mutex_t)); + if (nxt_slow_path(nxt_openssl_locks == NULL)) { + return NXT_ERROR; + } - for (i = 0; i < n; i++) { - ret = nxt_thread_mutex_create(&nxt_openssl_locks[i]); - if (nxt_slow_path(ret != NXT_OK)) { - return ret; - } + for (i = 0; i < n; i++) { + ret = nxt_thread_mutex_create(&nxt_openssl_locks[i]); + if (nxt_slow_path(ret != NXT_OK)) { + return ret; } + } - CRYPTO_set_locking_callback(nxt_openssl_lock); + CRYPTO_set_locking_callback(nxt_openssl_lock); - CRYPTO_set_id_callback(nxt_openssl_thread_id); + CRYPTO_set_id_callback(nxt_openssl_thread_id); - return NXT_OK; + return NXT_OK; } +static void nxt_openssl_lock(int mode, int type, const char *file, int line) { + nxt_thread_mutex_t *lock; -static void -nxt_openssl_lock(int mode, int type, const char *file, int line) -{ - nxt_thread_mutex_t *lock; - - lock = &nxt_openssl_locks[type]; + lock = &nxt_openssl_locks[type]; - if ((mode & CRYPTO_LOCK) != 0) { - (void) nxt_thread_mutex_lock(lock); + if ((mode & CRYPTO_LOCK) != 0) { + (void)nxt_thread_mutex_lock(lock); - } else { - (void) nxt_thread_mutex_unlock(lock); - } + } else { + (void)nxt_thread_mutex_unlock(lock); + } } - -static u_long -nxt_openssl_thread_id(void) -{ - return (u_long) nxt_thread_handle(); +static u_long nxt_openssl_thread_id(void) { + return (u_long)nxt_thread_handle(); } - -static void -nxt_openssl_library_free(nxt_task_t *task) -{ - nxt_openssl_locks_free(); +static void nxt_openssl_library_free(nxt_task_t *task) { + nxt_openssl_locks_free(); } +static void nxt_openssl_locks_free(void) { + int i, n; -static void -nxt_openssl_locks_free(void) -{ - int i, n; + n = CRYPTO_num_locks(); - n = CRYPTO_num_locks(); + CRYPTO_set_locking_callback(NULL); - CRYPTO_set_locking_callback(NULL); + for (i = 0; i < n; i++) { + nxt_thread_mutex_destroy(&nxt_openssl_locks[i]); + } - for (i = 0; i < n; i++) { - nxt_thread_mutex_destroy(&nxt_openssl_locks[i]); - } - - OPENSSL_free(nxt_openssl_locks); + OPENSSL_free(nxt_openssl_locks); } #endif +static nxt_int_t nxt_openssl_server_init(nxt_task_t *task, nxt_mp_t *mp, + nxt_tls_init_t *tls_init, + nxt_bool_t last) { + SSL_CTX *ctx; + const char *ca_certificate; + nxt_tls_conf_t *conf; + STACK_OF(X509_NAME) * list; + nxt_tls_bundle_conf_t *bundle; + + ctx = SSL_CTX_new(SSLv23_server_method()); + if (ctx == NULL) { + nxt_openssl_log_error(task, NXT_LOG_ALERT, "SSL_CTX_new() failed"); + return NXT_ERROR; + } -static nxt_int_t -nxt_openssl_server_init(nxt_task_t *task, nxt_mp_t *mp, - nxt_tls_init_t *tls_init, nxt_bool_t last) -{ - SSL_CTX *ctx; - const char *ca_certificate; - nxt_tls_conf_t *conf; - STACK_OF(X509_NAME) *list; - nxt_tls_bundle_conf_t *bundle; - - ctx = SSL_CTX_new(SSLv23_server_method()); - if (ctx == NULL) { - nxt_openssl_log_error(task, NXT_LOG_ALERT, "SSL_CTX_new() failed"); - return NXT_ERROR; - } - - conf = tls_init->conf; + conf = tls_init->conf; - bundle = conf->bundle; - nxt_assert(bundle != NULL); + bundle = conf->bundle; + nxt_assert(bundle != NULL); - bundle->ctx = ctx; + bundle->ctx = ctx; #ifdef SSL_OP_NO_RENEGOTIATION - /* Renegration is not currently supported. */ - SSL_CTX_set_options(ctx, SSL_OP_NO_RENEGOTIATION); + /* Renegration is not currently supported. */ + SSL_CTX_set_options(ctx, SSL_OP_NO_RENEGOTIATION); #endif #ifdef SSL_OP_NO_COMPRESSION - /* - * Disable gzip compression in OpenSSL 1.0.0, - * this saves about 522K per connection. - */ - SSL_CTX_set_options(ctx, SSL_OP_NO_COMPRESSION); + /* + * Disable gzip compression in OpenSSL 1.0.0, + * this saves about 522K per connection. + */ + SSL_CTX_set_options(ctx, SSL_OP_NO_COMPRESSION); #endif #ifdef SSL_OP_IGNORE_UNEXPECTED_EOF - /* Request SSL_ERROR_ZERO_RETURN on EOF. */ - SSL_CTX_set_options(ctx, SSL_OP_IGNORE_UNEXPECTED_EOF); + /* Request SSL_ERROR_ZERO_RETURN on EOF. */ + SSL_CTX_set_options(ctx, SSL_OP_IGNORE_UNEXPECTED_EOF); #endif #ifdef SSL_MODE_RELEASE_BUFFERS - if (nxt_openssl_version >= 10001078) { - /* - * Allow to release read and write buffers in OpenSSL 1.0.0, - * this saves about 34K per idle connection. It is not safe - * before OpenSSL 1.0.1h (CVE-2010-5298). - */ - SSL_CTX_set_mode(ctx, SSL_MODE_RELEASE_BUFFERS); - } + if (nxt_openssl_version >= 10001078) { + /* + * Allow to release read and write buffers in OpenSSL 1.0.0, + * this saves about 34K per idle connection. It is not safe + * before OpenSSL 1.0.1h (CVE-2010-5298). + */ + SSL_CTX_set_mode(ctx, SSL_MODE_RELEASE_BUFFERS); + } #endif - if (nxt_openssl_chain_file(task, ctx, conf, mp, - last && bundle->next == NULL) - != NXT_OK) - { - goto fail; - } -/* - key = conf->certificate_key; - - if (SSL_CTX_use_PrivateKey_file(ctx, key, SSL_FILETYPE_PEM) == 0) { - nxt_openssl_log_error(task, NXT_LOG_ALERT, - "SSL_CTX_use_PrivateKey_file(\"%s\") failed", - key); - goto fail; - } -*/ - - if (conf->ciphers) { /* else use system crypto policy */ - if (SSL_CTX_set_cipher_list(ctx, conf->ciphers) == 0) { - nxt_openssl_log_error(task, NXT_LOG_ALERT, - "SSL_CTX_set_cipher_list(\"%s\") failed", - conf->ciphers); - goto fail; - } - } + if (nxt_openssl_chain_file(task, ctx, conf, mp, + last && bundle->next == NULL) != NXT_OK) { + goto fail; + } + /* + key = conf->certificate_key; + + if (SSL_CTX_use_PrivateKey_file(ctx, key, SSL_FILETYPE_PEM) == 0) { + nxt_openssl_log_error(task, NXT_LOG_ALERT, + "SSL_CTX_use_PrivateKey_file(\"%s\") failed", + key); + goto fail; + } + */ + + if (conf->ciphers) { /* else use system crypto policy */ + if (SSL_CTX_set_cipher_list(ctx, conf->ciphers) == 0) { + nxt_openssl_log_error(task, NXT_LOG_ALERT, + "SSL_CTX_set_cipher_list(\"%s\") failed", + conf->ciphers); + goto fail; + } + } #if (NXT_HAVE_OPENSSL_CONF_CMD) - if (tls_init->conf_cmds != NULL - && nxt_ssl_conf_commands(task, ctx, tls_init->conf_cmds, mp) != NXT_OK) - { - goto fail; - } + if (tls_init->conf_cmds != NULL && + nxt_ssl_conf_commands(task, ctx, tls_init->conf_cmds, mp) != NXT_OK) { + goto fail; + } #endif - nxt_ssl_session_cache(ctx, tls_init->cache_size, tls_init->timeout); + nxt_ssl_session_cache(ctx, tls_init->cache_size, tls_init->timeout); #if (NXT_HAVE_OPENSSL_TLSEXT) - if (nxt_tls_ticket_keys(task, ctx, tls_init, mp) != NXT_OK) { - goto fail; - } + if (nxt_tls_ticket_keys(task, ctx, tls_init, mp) != NXT_OK) { + goto fail; + } #endif - SSL_CTX_set_options(ctx, SSL_OP_CIPHER_SERVER_PREFERENCE); + SSL_CTX_set_options(ctx, SSL_OP_CIPHER_SERVER_PREFERENCE); - if (conf->ca_certificate != NULL) { + if (conf->ca_certificate != NULL) { - /* TODO: verify callback */ - SSL_CTX_set_verify(ctx, SSL_VERIFY_PEER, NULL); + /* TODO: verify callback */ + SSL_CTX_set_verify(ctx, SSL_VERIFY_PEER, NULL); - /* TODO: verify depth */ - SSL_CTX_set_verify_depth(ctx, 1); + /* TODO: verify depth */ + SSL_CTX_set_verify_depth(ctx, 1); - ca_certificate = conf->ca_certificate; + ca_certificate = conf->ca_certificate; - if (SSL_CTX_load_verify_locations(ctx, ca_certificate, NULL) == 0) { - nxt_openssl_log_error(task, NXT_LOG_ALERT, - "SSL_CTX_load_verify_locations(\"%s\") failed", - ca_certificate); - goto fail; - } + if (SSL_CTX_load_verify_locations(ctx, ca_certificate, NULL) == 0) { + nxt_openssl_log_error(task, NXT_LOG_ALERT, + "SSL_CTX_load_verify_locations(\"%s\") failed", + ca_certificate); + goto fail; + } - list = SSL_load_client_CA_file(ca_certificate); + list = SSL_load_client_CA_file(ca_certificate); - if (list == NULL) { - nxt_openssl_log_error(task, NXT_LOG_ALERT, - "SSL_load_client_CA_file(\"%s\") failed", - ca_certificate); - goto fail; - } + if (list == NULL) { + nxt_openssl_log_error(task, NXT_LOG_ALERT, + "SSL_load_client_CA_file(\"%s\") failed", + ca_certificate); + goto fail; + } - /* - * SSL_load_client_CA_file() in OpenSSL prior to 0.9.7h and - * 0.9.8 versions always leaves an error in the error queue. - */ - ERR_clear_error(); + /* + * SSL_load_client_CA_file() in OpenSSL prior to 0.9.7h and + * 0.9.8 versions always leaves an error in the error queue. + */ + ERR_clear_error(); - SSL_CTX_set_client_CA_list(ctx, list); - } + SSL_CTX_set_client_CA_list(ctx, list); + } - if (last) { - conf->conn_init = nxt_openssl_conn_init; + if (last) { + conf->conn_init = nxt_openssl_conn_init; - if (bundle->next != NULL) { - SSL_CTX_set_tlsext_servername_callback(ctx, nxt_openssl_servername); - } + if (bundle->next != NULL) { + SSL_CTX_set_tlsext_servername_callback(ctx, nxt_openssl_servername); } + } - return NXT_OK; + return NXT_OK; fail: - SSL_CTX_free(ctx); + SSL_CTX_free(ctx); -#if (OPENSSL_VERSION_NUMBER >= 0x1010100fL \ - && OPENSSL_VERSION_NUMBER < 0x1010101fL) - RAND_keep_random_devices_open(0); +#if (OPENSSL_VERSION_NUMBER >= 0x1010100fL && \ + OPENSSL_VERSION_NUMBER < 0x1010101fL) + RAND_keep_random_devices_open(0); #endif - return NXT_ERROR; + return NXT_ERROR; } - -static nxt_int_t -nxt_openssl_chain_file(nxt_task_t *task, SSL_CTX *ctx, nxt_tls_conf_t *conf, - nxt_mp_t *mp, nxt_bool_t single) -{ - BIO *bio; - X509 *cert, *ca; - long reason; - EVP_PKEY *key; - nxt_int_t ret; - nxt_tls_bundle_conf_t *bundle; - - ret = NXT_ERROR; - cert = NULL; - - bio = BIO_new(BIO_s_fd()); - if (bio == NULL) { - goto end; - } - - bundle = conf->bundle; - - BIO_set_fd(bio, bundle->chain_file, BIO_CLOSE); - - cert = PEM_read_bio_X509_AUX(bio, NULL, NULL, NULL); - if (cert == NULL) { - goto end; - } - - if (SSL_CTX_use_certificate(ctx, cert) != 1) { +static nxt_int_t nxt_openssl_chain_file(nxt_task_t *task, SSL_CTX *ctx, + nxt_tls_conf_t *conf, nxt_mp_t *mp, + nxt_bool_t single) { + BIO *bio; + X509 *cert, *ca; + long reason; + EVP_PKEY *key; + nxt_int_t ret; + nxt_tls_bundle_conf_t *bundle; + + ret = NXT_ERROR; + cert = NULL; + + bio = BIO_new(BIO_s_fd()); + if (bio == NULL) { + goto end; + } + + bundle = conf->bundle; + + BIO_set_fd(bio, bundle->chain_file, BIO_CLOSE); + + cert = PEM_read_bio_X509_AUX(bio, NULL, NULL, NULL); + if (cert == NULL) { + goto end; + } + + if (SSL_CTX_use_certificate(ctx, cert) != 1) { + goto end; + } + + if (!single && nxt_openssl_cert_get_names(task, cert, conf, mp) != NXT_OK) { + goto clean; + } + + for (;;) { + ca = PEM_read_bio_X509(bio, NULL, NULL, NULL); + + if (ca == NULL) { + reason = ERR_GET_REASON(ERR_peek_last_error()); + if (reason != PEM_R_NO_START_LINE) { goto end; - } + } - if (!single && nxt_openssl_cert_get_names(task, cert, conf, mp) != NXT_OK) { - goto clean; + ERR_clear_error(); + break; } - for ( ;; ) { - ca = PEM_read_bio_X509(bio, NULL, NULL, NULL); - - if (ca == NULL) { - reason = ERR_GET_REASON(ERR_peek_last_error()); - if (reason != PEM_R_NO_START_LINE) { - goto end; - } - - ERR_clear_error(); - break; - } - - /* - * Note that ca isn't freed if it was successfully added to the chain, - * while the main certificate needs a X509_free() call, since - * its reference count is increased by SSL_CTX_use_certificate(). - */ + /* + * Note that ca isn't freed if it was successfully added to the chain, + * while the main certificate needs a X509_free() call, since + * its reference count is increased by SSL_CTX_use_certificate(). + */ #ifdef SSL_CTX_add0_chain_cert - if (SSL_CTX_add0_chain_cert(ctx, ca) != 1) { + if (SSL_CTX_add0_chain_cert(ctx, ca) != 1) { #else - if (SSL_CTX_add_extra_chain_cert(ctx, ca) != 1) { + if (SSL_CTX_add_extra_chain_cert(ctx, ca) != 1) { #endif - X509_free(ca); - goto end; - } + X509_free(ca); + goto end; } + } - if (BIO_reset(bio) != 0) { - goto end; - } + if (BIO_reset(bio) != 0) { + goto end; + } - key = PEM_read_bio_PrivateKey(bio, NULL, NULL, NULL); - if (key == NULL) { - goto end; - } + key = PEM_read_bio_PrivateKey(bio, NULL, NULL, NULL); + if (key == NULL) { + goto end; + } - if (SSL_CTX_use_PrivateKey(ctx, key) == 1) { - ret = NXT_OK; - } + if (SSL_CTX_use_PrivateKey(ctx, key) == 1) { + ret = NXT_OK; + } - EVP_PKEY_free(key); + EVP_PKEY_free(key); end: - if (ret != NXT_OK) { - nxt_openssl_log_error(task, NXT_LOG_ALERT, - "nxt_openssl_chain_file() failed"); - } + if (ret != NXT_OK) { + nxt_openssl_log_error(task, NXT_LOG_ALERT, + "nxt_openssl_chain_file() failed"); + } clean: - BIO_free(bio); - X509_free(cert); + BIO_free(bio); + X509_free(cert); - return ret; + return ret; } - #if (NXT_HAVE_OPENSSL_CONF_CMD) -static nxt_int_t -nxt_ssl_conf_commands(nxt_task_t *task, SSL_CTX *ctx, nxt_conf_value_t *conf, - nxt_mp_t *mp) -{ - int ret; - char *zcmd, *zvalue; - uint32_t index; - nxt_str_t cmd, value; - SSL_CONF_CTX *cctx; - nxt_conf_value_t *member; - - cctx = SSL_CONF_CTX_new(); - if (nxt_slow_path(cctx == NULL)) { - nxt_openssl_log_error(task, NXT_LOG_ALERT, - "SSL_CONF_CTX_new() failed"); - return NXT_ERROR; - } - - SSL_CONF_CTX_set_flags(cctx, SSL_CONF_FLAG_FILE - | SSL_CONF_FLAG_SERVER - | SSL_CONF_FLAG_CERTIFICATE - | SSL_CONF_FLAG_SHOW_ERRORS); - - SSL_CONF_CTX_set_ssl_ctx(cctx, ctx); +static nxt_int_t nxt_ssl_conf_commands(nxt_task_t *task, SSL_CTX *ctx, + nxt_conf_value_t *conf, nxt_mp_t *mp) { + int ret; + char *zcmd, *zvalue; + uint32_t index; + nxt_str_t cmd, value; + SSL_CONF_CTX *cctx; + nxt_conf_value_t *member; + + cctx = SSL_CONF_CTX_new(); + if (nxt_slow_path(cctx == NULL)) { + nxt_openssl_log_error(task, NXT_LOG_ALERT, "SSL_CONF_CTX_new() failed"); + return NXT_ERROR; + } - index = 0; + SSL_CONF_CTX_set_flags(cctx, SSL_CONF_FLAG_FILE | SSL_CONF_FLAG_SERVER | + SSL_CONF_FLAG_CERTIFICATE | + SSL_CONF_FLAG_SHOW_ERRORS); - for ( ;; ) { - member = nxt_conf_next_object_member(conf, &cmd, &index); - if (nxt_slow_path(member == NULL)) { - break; - } + SSL_CONF_CTX_set_ssl_ctx(cctx, ctx); - nxt_conf_get_string(member, &value); + index = 0; - zcmd = nxt_str_cstrz(mp, &cmd); - zvalue = nxt_str_cstrz(mp, &value); + for (;;) { + member = nxt_conf_next_object_member(conf, &cmd, &index); + if (nxt_slow_path(member == NULL)) { + break; + } - if (nxt_slow_path(zcmd == NULL || zvalue == NULL)) { - goto fail; - } + nxt_conf_get_string(member, &value); - ret = SSL_CONF_cmd(cctx, zcmd, zvalue); - if (ret == -2) { - nxt_openssl_log_error(task, NXT_LOG_ERR, - "unknown command \"%s\" in " - "\"conf_commands\" option", zcmd); - goto fail; - } + zcmd = nxt_str_cstrz(mp, &cmd); + zvalue = nxt_str_cstrz(mp, &value); - if (ret <= 0) { - nxt_openssl_log_error(task, NXT_LOG_ERR, - "invalid value \"%s\" for command \"%s\" " - "in \"conf_commands\" option", - zvalue, zcmd); - goto fail; - } + if (nxt_slow_path(zcmd == NULL || zvalue == NULL)) { + goto fail; + } - nxt_debug(task, "SSL_CONF_cmd(\"%s\", \"%s\")", zcmd, zvalue); + ret = SSL_CONF_cmd(cctx, zcmd, zvalue); + if (ret == -2) { + nxt_openssl_log_error(task, NXT_LOG_ERR, + "unknown command \"%s\" in " + "\"conf_commands\" option", + zcmd); + goto fail; } - if (SSL_CONF_CTX_finish(cctx) != 1) { - nxt_openssl_log_error(task, NXT_LOG_ALERT, - "SSL_CONF_finish() failed"); - goto fail; + if (ret <= 0) { + nxt_openssl_log_error(task, NXT_LOG_ERR, + "invalid value \"%s\" for command \"%s\" " + "in \"conf_commands\" option", + zvalue, zcmd); + goto fail; } - SSL_CONF_CTX_free(cctx); + nxt_debug(task, "SSL_CONF_cmd(\"%s\", \"%s\")", zcmd, zvalue); + } - return NXT_OK; + if (SSL_CONF_CTX_finish(cctx) != 1) { + nxt_openssl_log_error(task, NXT_LOG_ALERT, "SSL_CONF_finish() failed"); + goto fail; + } + + SSL_CONF_CTX_free(cctx); + + return NXT_OK; fail: - SSL_CONF_CTX_free(cctx); + SSL_CONF_CTX_free(cctx); - return NXT_ERROR; + return NXT_ERROR; } #endif #if (NXT_HAVE_OPENSSL_TLSEXT) -static nxt_int_t -nxt_tls_ticket_keys(nxt_task_t *task, SSL_CTX *ctx, nxt_tls_init_t *tls_init, - nxt_mp_t *mp) -{ - size_t len; - uint32_t i; - nxt_str_t value; - nxt_uint_t count; - nxt_conf_value_t *member, *tickets_conf; - nxt_tls_ticket_t *ticket; - nxt_tls_tickets_t *tickets; - u_char buf[80]; - - tickets_conf = tls_init->tickets_conf; - - if (tickets_conf == NULL) { - goto no_ticket; - } +static nxt_int_t nxt_tls_ticket_keys(nxt_task_t *task, SSL_CTX *ctx, + nxt_tls_init_t *tls_init, nxt_mp_t *mp) { + size_t len; + uint32_t i; + nxt_str_t value; + nxt_uint_t count; + nxt_conf_value_t *member, *tickets_conf; + nxt_tls_ticket_t *ticket; + nxt_tls_tickets_t *tickets; + u_char buf[80]; - if (nxt_conf_type(tickets_conf) == NXT_CONF_BOOLEAN) { - if (nxt_conf_get_boolean(tickets_conf) == 0) { - goto no_ticket; - } + tickets_conf = tls_init->tickets_conf; - return NXT_OK; + if (tickets_conf == NULL) { + goto no_ticket; + } + + if (nxt_conf_type(tickets_conf) == NXT_CONF_BOOLEAN) { + if (nxt_conf_get_boolean(tickets_conf) == 0) { + goto no_ticket; } - count = nxt_conf_array_elements_count_or_1(tickets_conf); + return NXT_OK; + } - if (count == 0) { - goto no_ticket; - } + count = nxt_conf_array_elements_count_or_1(tickets_conf); + + if (count == 0) { + goto no_ticket; + } #ifdef SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB - tickets = nxt_mp_get(mp, sizeof(nxt_tls_tickets_t) - + count * sizeof(nxt_tls_ticket_t)); - if (nxt_slow_path(tickets == NULL)) { - return NXT_ERROR; - } + tickets = nxt_mp_get(mp, sizeof(nxt_tls_tickets_t) + + count * sizeof(nxt_tls_ticket_t)); + if (nxt_slow_path(tickets == NULL)) { + return NXT_ERROR; + } - tickets->count = count; - tls_init->conf->tickets = tickets; - i = 0; + tickets->count = count; + tls_init->conf->tickets = tickets; + i = 0; - do { - ticket = &tickets->tickets[i]; + do { + ticket = &tickets->tickets[i]; - i++; + i++; - member = nxt_conf_get_array_element_or_itself(tickets_conf, count - i); - if (member == NULL) { - break; - } + member = nxt_conf_get_array_element_or_itself(tickets_conf, count - i); + if (member == NULL) { + break; + } - nxt_conf_get_string(member, &value); + nxt_conf_get_string(member, &value); - len = nxt_base64_decode(buf, value.start, value.length); + len = nxt_base64_decode(buf, value.start, value.length); - nxt_memcpy(ticket->name, buf, 16); + nxt_memcpy(ticket->name, buf, 16); - if (len == 48) { - nxt_memcpy(ticket->aes_key, buf + 16, 16); - nxt_memcpy(ticket->hmac_key, buf + 32, 16); - ticket->size = 16; + if (len == 48) { + nxt_memcpy(ticket->aes_key, buf + 16, 16); + nxt_memcpy(ticket->hmac_key, buf + 32, 16); + ticket->size = 16; - } else { - nxt_memcpy(ticket->hmac_key, buf + 16, 32); - nxt_memcpy(ticket->aes_key, buf + 48, 32); - ticket->size = 32; - } + } else { + nxt_memcpy(ticket->hmac_key, buf + 16, 32); + nxt_memcpy(ticket->aes_key, buf + 48, 32); + ticket->size = 32; + } - } while (i < count); + } while (i < count); - if (SSL_CTX_set_tlsext_ticket_key_cb(ctx, nxt_tls_ticket_key_callback) - == 0) - { - nxt_openssl_log_error(task, NXT_LOG_ALERT, - "Unit was built with Session Tickets support, however, " - "now it is linked dynamically to an OpenSSL library " - "which has no tlsext support, therefore Session Tickets " - "are not available"); + if (SSL_CTX_set_tlsext_ticket_key_cb(ctx, nxt_tls_ticket_key_callback) == 0) { + nxt_openssl_log_error( + task, NXT_LOG_ALERT, + "Unit was built with Session Tickets support, however, " + "now it is linked dynamically to an OpenSSL library " + "which has no tlsext support, therefore Session Tickets " + "are not available"); - return NXT_ERROR; - } + return NXT_ERROR; + } - return NXT_OK; + return NXT_OK; #else - nxt_alert(task, "Setting custom session ticket keys is not supported with " - "this version of OpenSSL library"); + nxt_alert(task, "Setting custom session ticket keys is not supported with " + "this version of OpenSSL library"); - return NXT_ERROR; + return NXT_ERROR; #endif no_ticket: - SSL_CTX_set_options(ctx, SSL_OP_NO_TICKET); + SSL_CTX_set_options(ctx, SSL_OP_NO_TICKET); - return NXT_OK; + return NXT_OK; } - #ifdef SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB -static int -nxt_tls_ticket_key_callback(SSL *s, unsigned char *name, unsigned char *iv, - EVP_CIPHER_CTX *ectx, HMAC_CTX *hctx, int enc) -{ - nxt_uint_t i; - nxt_conn_t *c; - const EVP_MD *digest; - const EVP_CIPHER *cipher; - nxt_tls_ticket_t *ticket; - nxt_openssl_conn_t *tls; - - c = SSL_get_ex_data(s, nxt_openssl_connection_index); - - if (nxt_slow_path(c == NULL)) { - nxt_thread_log_alert("SSL_get_ex_data() failed"); - return -1; - } +static int nxt_tls_ticket_key_callback(SSL *s, unsigned char *name, + unsigned char *iv, EVP_CIPHER_CTX *ectx, + HMAC_CTX *hctx, int enc) { + nxt_uint_t i; + nxt_conn_t *c; + const EVP_MD *digest; + const EVP_CIPHER *cipher; + nxt_tls_ticket_t *ticket; + nxt_openssl_conn_t *tls; - tls = c->u.tls; - ticket = tls->conf->tickets->tickets; + c = SSL_get_ex_data(s, nxt_openssl_connection_index); - i = 0; + if (nxt_slow_path(c == NULL)) { + nxt_thread_log_alert("SSL_get_ex_data() failed"); + return -1; + } - if (enc == 1) { - /* encrypt session ticket */ + tls = c->u.tls; + ticket = tls->conf->tickets->tickets; - nxt_debug(c->socket.task, "TLS session ticket encrypt"); + i = 0; - cipher = (ticket[0].size == 16) ? EVP_aes_128_cbc() : EVP_aes_256_cbc(); + if (enc == 1) { + /* encrypt session ticket */ - if (RAND_bytes(iv, EVP_CIPHER_iv_length(cipher)) != 1) { - nxt_openssl_log_error(c->socket.task, NXT_LOG_ALERT, - "RAND_bytes() failed"); - return -1; - } + nxt_debug(c->socket.task, "TLS session ticket encrypt"); - nxt_memcpy(name, ticket[0].name, 16); + cipher = (ticket[0].size == 16) ? EVP_aes_128_cbc() : EVP_aes_256_cbc(); - if (EVP_EncryptInit_ex(ectx, cipher, NULL, ticket[0].aes_key, iv) != 1) - { - nxt_openssl_log_error(c->socket.task, NXT_LOG_ALERT, - "EVP_EncryptInit_ex() failed"); - return -1; - } + if (RAND_bytes(iv, EVP_CIPHER_iv_length(cipher)) != 1) { + nxt_openssl_log_error(c->socket.task, NXT_LOG_ALERT, + "RAND_bytes() failed"); + return -1; + } - } else { - /* decrypt session ticket */ + nxt_memcpy(name, ticket[0].name, 16); - do { - if (memcmp(name, ticket[i].name, 16) == 0) { - goto found; - } + if (EVP_EncryptInit_ex(ectx, cipher, NULL, ticket[0].aes_key, iv) != 1) { + nxt_openssl_log_error(c->socket.task, NXT_LOG_ALERT, + "EVP_EncryptInit_ex() failed"); + return -1; + } - } while (++i < tls->conf->tickets->count); + } else { + /* decrypt session ticket */ - nxt_debug(c->socket.task, "TLS session ticket decrypt, key not found"); + do { + if (memcmp(name, ticket[i].name, 16) == 0) { + goto found; + } + + } while (++i < tls->conf->tickets->count); + + nxt_debug(c->socket.task, "TLS session ticket decrypt, key not found"); - return 0; + return 0; - found: + found: - nxt_debug(c->socket.task, - "TLS session ticket decrypt, key number: \"%d\"", i); + nxt_debug(c->socket.task, "TLS session ticket decrypt, key number: \"%d\"", + i); - enc = (i == 0) ? 1 : 2 /* renew */; + enc = (i == 0) ? 1 : 2 /* renew */; - cipher = (ticket[i].size == 16) ? EVP_aes_128_cbc() : EVP_aes_256_cbc(); + cipher = (ticket[i].size == 16) ? EVP_aes_128_cbc() : EVP_aes_256_cbc(); - if (EVP_DecryptInit_ex(ectx, cipher, NULL, ticket[i].aes_key, iv) != 1) - { - nxt_openssl_log_error(c->socket.task, NXT_LOG_ALERT, - "EVP_DecryptInit_ex() failed"); - return -1; - } + if (EVP_DecryptInit_ex(ectx, cipher, NULL, ticket[i].aes_key, iv) != 1) { + nxt_openssl_log_error(c->socket.task, NXT_LOG_ALERT, + "EVP_DecryptInit_ex() failed"); + return -1; } + } #ifdef OPENSSL_NO_SHA256 - digest = EVP_sha1(); + digest = EVP_sha1(); #else - digest = EVP_sha256(); + digest = EVP_sha256(); #endif - if (HMAC_Init_ex(hctx, ticket[i].hmac_key, ticket[i].size, digest, NULL) - != 1) - { - nxt_openssl_log_error(c->socket.task, NXT_LOG_ALERT, - "HMAC_Init_ex() failed"); - return -1; - } + if (HMAC_Init_ex(hctx, ticket[i].hmac_key, ticket[i].size, digest, NULL) != + 1) { + nxt_openssl_log_error(c->socket.task, NXT_LOG_ALERT, + "HMAC_Init_ex() failed"); + return -1; + } - return enc; + return enc; } #endif /* SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB */ #endif /* NXT_HAVE_OPENSSL_TLSEXT */ +static void nxt_ssl_session_cache(SSL_CTX *ctx, size_t cache_size, + time_t timeout) { + if (cache_size == 0) { + SSL_CTX_set_session_cache_mode(ctx, SSL_SESS_CACHE_OFF); + return; + } -static void -nxt_ssl_session_cache(SSL_CTX *ctx, size_t cache_size, time_t timeout) -{ - if (cache_size == 0) { - SSL_CTX_set_session_cache_mode(ctx, SSL_SESS_CACHE_OFF); - return; - } - - SSL_CTX_set_session_cache_mode(ctx, SSL_SESS_CACHE_SERVER); + SSL_CTX_set_session_cache_mode(ctx, SSL_SESS_CACHE_SERVER); - SSL_CTX_sess_set_cache_size(ctx, cache_size); + SSL_CTX_sess_set_cache_size(ctx, cache_size); - SSL_CTX_set_timeout(ctx, (long) timeout); + SSL_CTX_set_timeout(ctx, (long)timeout); } +static nxt_uint_t nxt_openssl_cert_get_names(nxt_task_t *task, X509 *cert, + nxt_tls_conf_t *conf, + nxt_mp_t *mp) { + int len; + nxt_str_t domain, str; + X509_NAME *x509_name; + nxt_uint_t i, n; + GENERAL_NAME *name; + nxt_tls_bundle_conf_t *bundle; + STACK_OF(GENERAL_NAME) * alt_names; + nxt_tls_bundle_hash_item_t *item; -static nxt_uint_t -nxt_openssl_cert_get_names(nxt_task_t *task, X509 *cert, nxt_tls_conf_t *conf, - nxt_mp_t *mp) -{ - int len; - nxt_str_t domain, str; - X509_NAME *x509_name; - nxt_uint_t i, n; - GENERAL_NAME *name; - nxt_tls_bundle_conf_t *bundle; - STACK_OF(GENERAL_NAME) *alt_names; - nxt_tls_bundle_hash_item_t *item; - - bundle = conf->bundle; + bundle = conf->bundle; - alt_names = X509_get_ext_d2i(cert, NID_subject_alt_name, NULL, NULL); + alt_names = X509_get_ext_d2i(cert, NID_subject_alt_name, NULL, NULL); - if (alt_names != NULL) { - n = sk_GENERAL_NAME_num(alt_names); + if (alt_names != NULL) { + n = sk_GENERAL_NAME_num(alt_names); - for (i = 0; i != n; i++) { - name = sk_GENERAL_NAME_value(alt_names, i); + for (i = 0; i != n; i++) { + name = sk_GENERAL_NAME_value(alt_names, i); - if (name->type != GEN_DNS) { - continue; - } + if (name->type != GEN_DNS) { + continue; + } - str.length = ASN1_STRING_length(name->d.dNSName); + str.length = ASN1_STRING_length(name->d.dNSName); #if OPENSSL_VERSION_NUMBER > 0x10100000L - str.start = (u_char *) ASN1_STRING_get0_data(name->d.dNSName); + str.start = (u_char *)ASN1_STRING_get0_data(name->d.dNSName); #else - str.start = ASN1_STRING_data(name->d.dNSName); + str.start = ASN1_STRING_data(name->d.dNSName); #endif - domain.start = nxt_mp_nget(mp, str.length); - if (nxt_slow_path(domain.start == NULL)) { - goto fail; - } + domain.start = nxt_mp_nget(mp, str.length); + if (nxt_slow_path(domain.start == NULL)) { + goto fail; + } - domain.length = str.length; - nxt_memcpy_lowcase(domain.start, str.start, str.length); + domain.length = str.length; + nxt_memcpy_lowcase(domain.start, str.start, str.length); - item = nxt_mp_get(mp, sizeof(nxt_tls_bundle_hash_item_t)); - if (nxt_slow_path(item == NULL)) { - goto fail; - } + item = nxt_mp_get(mp, sizeof(nxt_tls_bundle_hash_item_t)); + if (nxt_slow_path(item == NULL)) { + goto fail; + } - item->name = domain; - item->bundle = bundle; + item->name = domain; + item->bundle = bundle; - if (nxt_openssl_bundle_hash_insert(task, &conf->bundle_hash, - item, mp) - == NXT_ERROR) - { - goto fail; - } - } + if (nxt_openssl_bundle_hash_insert(task, &conf->bundle_hash, item, mp) == + NXT_ERROR) { + goto fail; + } + } - sk_GENERAL_NAME_pop_free(alt_names, GENERAL_NAME_free); + sk_GENERAL_NAME_pop_free(alt_names, GENERAL_NAME_free); - } else { - x509_name = X509_get_subject_name(cert); - len = X509_NAME_get_text_by_NID(x509_name, NID_commonName, - NULL, 0); - if (len <= 0) { - nxt_log(task, NXT_LOG_WARN, "certificate \"%V\" has neither " - "Subject Alternative Name nor Common Name", &bundle->name); - return NXT_OK; - } - - domain.start = nxt_mp_nget(mp, len + 1); - if (nxt_slow_path(domain.start == NULL)) { - return NXT_ERROR; - } - - domain.length = X509_NAME_get_text_by_NID(x509_name, NID_commonName, - (char *) domain.start, - len + 1); - nxt_memcpy_lowcase(domain.start, domain.start, domain.length); - - item = nxt_mp_get(mp, sizeof(nxt_tls_bundle_hash_item_t)); - if (nxt_slow_path(item == NULL)) { - return NXT_ERROR; - } - - item->name = domain; - item->bundle = bundle; - - if (nxt_openssl_bundle_hash_insert(task, &conf->bundle_hash, item, - mp) - == NXT_ERROR) - { - return NXT_ERROR; - } + } else { + x509_name = X509_get_subject_name(cert); + len = X509_NAME_get_text_by_NID(x509_name, NID_commonName, NULL, 0); + if (len <= 0) { + nxt_log(task, NXT_LOG_WARN, + "certificate \"%V\" has neither " + "Subject Alternative Name nor Common Name", + &bundle->name); + return NXT_OK; } - return NXT_OK; + domain.start = nxt_mp_nget(mp, len + 1); + if (nxt_slow_path(domain.start == NULL)) { + return NXT_ERROR; + } -fail: + domain.length = X509_NAME_get_text_by_NID(x509_name, NID_commonName, + (char *)domain.start, len + 1); + nxt_memcpy_lowcase(domain.start, domain.start, domain.length); - sk_GENERAL_NAME_pop_free(alt_names, GENERAL_NAME_free); - - return NXT_ERROR; -} + item = nxt_mp_get(mp, sizeof(nxt_tls_bundle_hash_item_t)); + if (nxt_slow_path(item == NULL)) { + return NXT_ERROR; + } + item->name = domain; + item->bundle = bundle; -static const nxt_lvlhsh_proto_t nxt_openssl_bundle_hash_proto - nxt_aligned(64) = -{ - NXT_LVLHSH_DEFAULT, - nxt_openssl_bundle_hash_test, - nxt_mp_lvlhsh_alloc, - nxt_mp_lvlhsh_free, -}; + if (nxt_openssl_bundle_hash_insert(task, &conf->bundle_hash, item, mp) == + NXT_ERROR) { + return NXT_ERROR; + } + } + return NXT_OK; -static nxt_int_t -nxt_openssl_bundle_hash_test(nxt_lvlhsh_query_t *lhq, void *data) -{ - nxt_tls_bundle_hash_item_t *item; +fail: - item = data; + sk_GENERAL_NAME_pop_free(alt_names, GENERAL_NAME_free); - return nxt_strstr_eq(&lhq->key, &item->name) ? NXT_OK : NXT_DECLINED; + return NXT_ERROR; } +static const nxt_lvlhsh_proto_t + nxt_openssl_bundle_hash_proto nxt_aligned(64) = { + NXT_LVLHSH_DEFAULT, + nxt_openssl_bundle_hash_test, + nxt_mp_lvlhsh_alloc, + nxt_mp_lvlhsh_free, + }; -static nxt_int_t -nxt_openssl_bundle_hash_insert(nxt_task_t *task, nxt_lvlhsh_t *lvlhsh, - nxt_tls_bundle_hash_item_t *item, nxt_mp_t *mp) -{ - nxt_str_t str; - nxt_int_t ret; - nxt_lvlhsh_query_t lhq; - nxt_tls_bundle_hash_item_t *old; - - str = item->name; - - if (item->name.start[0] == '*') { - item->name.start++; - item->name.length--; - - if (item->name.length == 0 || item->name.start[0] != '.') { - nxt_log(task, NXT_LOG_WARN, "ignored invalid name \"%V\" " - "in certificate \"%V\": missing \".\" " - "after wildcard symbol", &str, &item->bundle->name); - return NXT_OK; - } - } +static nxt_int_t nxt_openssl_bundle_hash_test(nxt_lvlhsh_query_t *lhq, + void *data) { + nxt_tls_bundle_hash_item_t *item; - lhq.pool = mp; - lhq.key = item->name; - lhq.value = item; - lhq.proto = &nxt_openssl_bundle_hash_proto; - lhq.replace = 0; - lhq.key_hash = nxt_murmur_hash2(item->name.start, item->name.length); - - ret = nxt_lvlhsh_insert(lvlhsh, &lhq); - if (nxt_fast_path(ret == NXT_OK)) { - nxt_debug(task, "name \"%V\" for certificate \"%V\" is inserted", - &str, &item->bundle->name); - return NXT_OK; - } + item = data; - if (nxt_fast_path(ret == NXT_DECLINED)) { - old = lhq.value; - if (old->bundle != item->bundle) { - nxt_log(task, NXT_LOG_WARN, "ignored duplicate name \"%V\" " - "in certificate \"%V\", identical name appears in \"%V\"", - &str, &old->bundle->name, &item->bundle->name); + return nxt_strstr_eq(&lhq->key, &item->name) ? NXT_OK : NXT_DECLINED; +} + +static nxt_int_t +nxt_openssl_bundle_hash_insert(nxt_task_t *task, nxt_lvlhsh_t *lvlhsh, + nxt_tls_bundle_hash_item_t *item, nxt_mp_t *mp) { + nxt_str_t str; + nxt_int_t ret; + nxt_lvlhsh_query_t lhq; + nxt_tls_bundle_hash_item_t *old; + + str = item->name; + + if (item->name.start[0] == '*') { + item->name.start++; + item->name.length--; + + if (item->name.length == 0 || item->name.start[0] != '.') { + nxt_log(task, NXT_LOG_WARN, + "ignored invalid name \"%V\" " + "in certificate \"%V\": missing \".\" " + "after wildcard symbol", + &str, &item->bundle->name); + return NXT_OK; + } + } + + lhq.pool = mp; + lhq.key = item->name; + lhq.value = item; + lhq.proto = &nxt_openssl_bundle_hash_proto; + lhq.replace = 0; + lhq.key_hash = nxt_murmur_hash2(item->name.start, item->name.length); + + ret = nxt_lvlhsh_insert(lvlhsh, &lhq); + if (nxt_fast_path(ret == NXT_OK)) { + nxt_debug(task, "name \"%V\" for certificate \"%V\" is inserted", &str, + &item->bundle->name); + return NXT_OK; + } - old->bundle = item->bundle; - } + if (nxt_fast_path(ret == NXT_DECLINED)) { + old = lhq.value; + if (old->bundle != item->bundle) { + nxt_log(task, NXT_LOG_WARN, + "ignored duplicate name \"%V\" " + "in certificate \"%V\", identical name appears in \"%V\"", + &str, &old->bundle->name, &item->bundle->name); - return NXT_OK; + old->bundle = item->bundle; } - return NXT_ERROR; + return NXT_OK; + } + + return NXT_ERROR; } +static nxt_int_t nxt_openssl_servername(SSL *s, int *ad, void *arg) { + nxt_str_t str; + nxt_uint_t i; + nxt_conn_t *c; + const char *servername; + nxt_tls_conf_t *conf; + nxt_openssl_conn_t *tls; + nxt_tls_bundle_conf_t *bundle; -static nxt_int_t -nxt_openssl_servername(SSL *s, int *ad, void *arg) -{ - nxt_str_t str; - nxt_uint_t i; - nxt_conn_t *c; - const char *servername; - nxt_tls_conf_t *conf; - nxt_openssl_conn_t *tls; - nxt_tls_bundle_conf_t *bundle; - - c = SSL_get_ex_data(s, nxt_openssl_connection_index); - - if (nxt_slow_path(c == NULL)) { - nxt_thread_log_alert("SSL_get_ex_data() failed"); - return SSL_TLSEXT_ERR_ALERT_FATAL; - } + c = SSL_get_ex_data(s, nxt_openssl_connection_index); - servername = SSL_get_servername(s, TLSEXT_NAMETYPE_host_name); + if (nxt_slow_path(c == NULL)) { + nxt_thread_log_alert("SSL_get_ex_data() failed"); + return SSL_TLSEXT_ERR_ALERT_FATAL; + } - if (servername == NULL) { - nxt_debug(c->socket.task, "SSL_get_servername(): NULL"); - goto done; - } + servername = SSL_get_servername(s, TLSEXT_NAMETYPE_host_name); - str.length = nxt_strlen(servername); - if (str.length == 0) { - nxt_debug(c->socket.task, "SSL_get_servername(): \"\" is empty"); - goto done; - } + if (servername == NULL) { + nxt_debug(c->socket.task, "SSL_get_servername(): NULL"); + goto done; + } - if (servername[0] == '.') { - nxt_debug(c->socket.task, "ignored the server name \"%s\": " - "leading \".\"", servername); - goto done; - } + str.length = nxt_strlen(servername); + if (str.length == 0) { + nxt_debug(c->socket.task, "SSL_get_servername(): \"\" is empty"); + goto done; + } - nxt_debug(c->socket.task, "tls with servername \"%s\"", servername); + if (servername[0] == '.') { + nxt_debug(c->socket.task, + "ignored the server name \"%s\": " + "leading \".\"", + servername); + goto done; + } - str.start = nxt_mp_nget(c->mem_pool, str.length); - if (nxt_slow_path(str.start == NULL)) { - return SSL_TLSEXT_ERR_ALERT_FATAL; - } + nxt_debug(c->socket.task, "tls with servername \"%s\"", servername); - nxt_memcpy_lowcase(str.start, (const u_char *) servername, str.length); + str.start = nxt_mp_nget(c->mem_pool, str.length); + if (nxt_slow_path(str.start == NULL)) { + return SSL_TLSEXT_ERR_ALERT_FATAL; + } - tls = c->u.tls; - conf = tls->conf; + nxt_memcpy_lowcase(str.start, (const u_char *)servername, str.length); - bundle = nxt_openssl_find_ctx(conf, &str); + tls = c->u.tls; + conf = tls->conf; - if (bundle == NULL) { - for (i = 1; i < str.length; i++) { - if (str.start[i] == '.') { - str.start += i; - str.length -= i; + bundle = nxt_openssl_find_ctx(conf, &str); - bundle = nxt_openssl_find_ctx(conf, &str); - break; - } - } + if (bundle == NULL) { + for (i = 1; i < str.length; i++) { + if (str.start[i] == '.') { + str.start += i; + str.length -= i; + + bundle = nxt_openssl_find_ctx(conf, &str); + break; + } } + } - if (bundle != NULL) { - nxt_debug(c->socket.task, "new tls context found for \"%V\": \"%V\" " - "(old: \"%V\")", &str, &bundle->name, - &conf->bundle->name); + if (bundle != NULL) { + nxt_debug(c->socket.task, + "new tls context found for \"%V\": \"%V\" " + "(old: \"%V\")", + &str, &bundle->name, &conf->bundle->name); - if (bundle != conf->bundle) { - if (SSL_set_SSL_CTX(s, bundle->ctx) == NULL) { - nxt_openssl_log_error(c->socket.task, NXT_LOG_ALERT, - "SSL_set_SSL_CTX() failed"); + if (bundle != conf->bundle) { + if (SSL_set_SSL_CTX(s, bundle->ctx) == NULL) { + nxt_openssl_log_error(c->socket.task, NXT_LOG_ALERT, + "SSL_set_SSL_CTX() failed"); - return SSL_TLSEXT_ERR_ALERT_FATAL; - } - } + return SSL_TLSEXT_ERR_ALERT_FATAL; + } } + } done: - return SSL_TLSEXT_ERR_OK; + return SSL_TLSEXT_ERR_OK; } +static nxt_tls_bundle_conf_t *nxt_openssl_find_ctx(nxt_tls_conf_t *conf, + nxt_str_t *sn) { + nxt_int_t ret; + nxt_lvlhsh_query_t lhq; + nxt_tls_bundle_hash_item_t *item; -static nxt_tls_bundle_conf_t * -nxt_openssl_find_ctx(nxt_tls_conf_t *conf, nxt_str_t *sn) -{ - nxt_int_t ret; - nxt_lvlhsh_query_t lhq; - nxt_tls_bundle_hash_item_t *item; - - lhq.key_hash = nxt_murmur_hash2(sn->start, sn->length); - lhq.key = *sn; - lhq.proto = &nxt_openssl_bundle_hash_proto; + lhq.key_hash = nxt_murmur_hash2(sn->start, sn->length); + lhq.key = *sn; + lhq.proto = &nxt_openssl_bundle_hash_proto; - ret = nxt_lvlhsh_find(&conf->bundle_hash, &lhq); - if (ret != NXT_OK) { - return NULL; - } + ret = nxt_lvlhsh_find(&conf->bundle_hash, &lhq); + if (ret != NXT_OK) { + return NULL; + } - item = lhq.value; + item = lhq.value; - return item->bundle; + return item->bundle; } +static void nxt_openssl_server_free(nxt_task_t *task, nxt_tls_conf_t *conf) { + nxt_tls_bundle_conf_t *bundle; -static void -nxt_openssl_server_free(nxt_task_t *task, nxt_tls_conf_t *conf) -{ - nxt_tls_bundle_conf_t *bundle; + bundle = conf->bundle; + nxt_assert(bundle != NULL); - bundle = conf->bundle; - nxt_assert(bundle != NULL); + do { + SSL_CTX_free(bundle->ctx); + bundle = bundle->next; + } while (bundle != NULL); - do { - SSL_CTX_free(bundle->ctx); - bundle = bundle->next; - } while (bundle != NULL); - - if (conf->tickets) { - nxt_memzero(conf->tickets->tickets, - conf->tickets->count * sizeof(nxt_tls_ticket_t)); - } + if (conf->tickets) { + nxt_memzero(conf->tickets->tickets, + conf->tickets->count * sizeof(nxt_tls_ticket_t)); + } -#if (OPENSSL_VERSION_NUMBER >= 0x1010100fL \ - && OPENSSL_VERSION_NUMBER < 0x1010101fL) - RAND_keep_random_devices_open(0); +#if (OPENSSL_VERSION_NUMBER >= 0x1010100fL && \ + OPENSSL_VERSION_NUMBER < 0x1010101fL) + RAND_keep_random_devices_open(0); #endif } +static void nxt_openssl_conn_init(nxt_task_t *task, nxt_tls_conf_t *conf, + nxt_conn_t *c) { + int ret; + SSL *s; + SSL_CTX *ctx; + nxt_openssl_conn_t *tls; -static void -nxt_openssl_conn_init(nxt_task_t *task, nxt_tls_conf_t *conf, nxt_conn_t *c) -{ - int ret; - SSL *s; - SSL_CTX *ctx; - nxt_openssl_conn_t *tls; + nxt_log_debug(c->socket.log, "openssl conn init"); - nxt_log_debug(c->socket.log, "openssl conn init"); + tls = nxt_mp_zget(c->mem_pool, sizeof(nxt_openssl_conn_t)); + if (tls == NULL) { + goto fail; + } - tls = nxt_mp_zget(c->mem_pool, sizeof(nxt_openssl_conn_t)); - if (tls == NULL) { - goto fail; - } + c->u.tls = tls; + nxt_buf_mem_set_size(&tls->buffer, conf->buffer_size); - c->u.tls = tls; - nxt_buf_mem_set_size(&tls->buffer, conf->buffer_size); + ctx = conf->bundle->ctx; - ctx = conf->bundle->ctx; + s = SSL_new(ctx); + if (s == NULL) { + nxt_openssl_log_error(task, NXT_LOG_ALERT, "SSL_new() failed"); + goto fail; + } - s = SSL_new(ctx); - if (s == NULL) { - nxt_openssl_log_error(task, NXT_LOG_ALERT, "SSL_new() failed"); - goto fail; - } + tls->session = s; + /* To pass TLS config to the nxt_openssl_servername() callback. */ + tls->conf = conf; + tls->conn = c; - tls->session = s; - /* To pass TLS config to the nxt_openssl_servername() callback. */ - tls->conf = conf; - tls->conn = c; + ret = SSL_set_fd(s, c->socket.fd); - ret = SSL_set_fd(s, c->socket.fd); + if (ret == 0) { + nxt_openssl_log_error(task, NXT_LOG_ALERT, "SSL_set_fd(%d) failed", + c->socket.fd); + goto fail; + } - if (ret == 0) { - nxt_openssl_log_error(task, NXT_LOG_ALERT, "SSL_set_fd(%d) failed", - c->socket.fd); - goto fail; - } - - SSL_set_accept_state(s); + SSL_set_accept_state(s); - if (SSL_set_ex_data(s, nxt_openssl_connection_index, c) == 0) { - nxt_openssl_log_error(task, NXT_LOG_ALERT, "SSL_set_ex_data() failed"); - goto fail; - } + if (SSL_set_ex_data(s, nxt_openssl_connection_index, c) == 0) { + nxt_openssl_log_error(task, NXT_LOG_ALERT, "SSL_set_ex_data() failed"); + goto fail; + } - c->io = &nxt_openssl_conn_io; - c->sendfile = NXT_CONN_SENDFILE_OFF; + c->io = &nxt_openssl_conn_io; + c->sendfile = NXT_CONN_SENDFILE_OFF; - nxt_openssl_conn_handshake(task, c, c->socket.data); + nxt_openssl_conn_handshake(task, c, c->socket.data); - return; + return; fail: - nxt_work_queue_add(c->read_work_queue, c->read_state->error_handler, - task, c, c->socket.data); + nxt_work_queue_add(c->read_work_queue, c->read_state->error_handler, task, c, + c->socket.data); } +nxt_inline void nxt_openssl_conn_free(nxt_task_t *task, nxt_conn_t *c) { + nxt_openssl_conn_t *tls; -nxt_inline void -nxt_openssl_conn_free(nxt_task_t *task, nxt_conn_t *c) -{ - nxt_openssl_conn_t *tls; - - nxt_debug(task, "openssl conn free"); + nxt_debug(task, "openssl conn free"); - tls = c->u.tls; + tls = c->u.tls; - if (tls != NULL) { - c->u.tls = NULL; - nxt_free(tls->buffer.start); - SSL_free(tls->session); - } + if (tls != NULL) { + c->u.tls = NULL; + nxt_free(tls->buffer.start); + SSL_free(tls->session); + } } +static void nxt_openssl_conn_handshake(nxt_task_t *task, void *obj, + void *data) { + int ret; + nxt_int_t n; + nxt_err_t err; + nxt_conn_t *c; + nxt_work_queue_t *wq; + nxt_work_handler_t handler; + nxt_openssl_conn_t *tls; + const nxt_conn_state_t *state; -static void -nxt_openssl_conn_handshake(nxt_task_t *task, void *obj, void *data) -{ - int ret; - nxt_int_t n; - nxt_err_t err; - nxt_conn_t *c; - nxt_work_queue_t *wq; - nxt_work_handler_t handler; - nxt_openssl_conn_t *tls; - const nxt_conn_state_t *state; + c = obj; - c = obj; + nxt_debug(task, "openssl conn handshake fd:%d", c->socket.fd); - nxt_debug(task, "openssl conn handshake fd:%d", c->socket.fd); - - if (c->socket.error != 0) { - return; - } + if (c->socket.error != 0) { + return; + } - tls = c->u.tls; + tls = c->u.tls; - if (tls == NULL) { - return; - } + if (tls == NULL) { + return; + } - nxt_debug(task, "openssl conn handshake: %d times", tls->times); + nxt_debug(task, "openssl conn handshake: %d times", tls->times); - /* "tls->times == 1" is suitable to run SSL_do_handshake() in job. */ + /* "tls->times == 1" is suitable to run SSL_do_handshake() in job. */ - ret = SSL_do_handshake(tls->session); + ret = SSL_do_handshake(tls->session); - err = (ret <= 0) ? nxt_socket_errno : 0; + err = (ret <= 0) ? nxt_socket_errno : 0; - nxt_thread_time_debug_update(task->thread); + nxt_thread_time_debug_update(task->thread); - nxt_debug(task, "SSL_do_handshake(%d): %d err:%d", c->socket.fd, ret, err); + nxt_debug(task, "SSL_do_handshake(%d): %d err:%d", c->socket.fd, ret, err); - state = (c->read_state != NULL) ? c->read_state : c->write_state; + state = (c->read_state != NULL) ? c->read_state : c->write_state; - if (ret > 0) { - /* ret == 1, the handshake was successfully completed. */ - tls->handshake = 1; + if (ret > 0) { + /* ret == 1, the handshake was successfully completed. */ + tls->handshake = 1; - if (c->read_state != NULL) { - if (state->io_read_handler != NULL || c->read != NULL) { - nxt_conn_read(task->thread->engine, c); - return; - } + if (c->read_state != NULL) { + if (state->io_read_handler != NULL || c->read != NULL) { + nxt_conn_read(task->thread->engine, c); + return; + } - } else { - if (c->write != NULL) { - nxt_conn_write(task->thread->engine, c); - return; - } - } + } else { + if (c->write != NULL) { + nxt_conn_write(task->thread->engine, c); + return; + } + } - handler = state->ready_handler; + handler = state->ready_handler; - } else { - c->socket.read_handler = nxt_openssl_conn_handshake; - c->socket.write_handler = nxt_openssl_conn_handshake; + } else { + c->socket.read_handler = nxt_openssl_conn_handshake; + c->socket.write_handler = nxt_openssl_conn_handshake; - n = nxt_openssl_conn_test_error(task, c, ret, err, - NXT_OPENSSL_HANDSHAKE); - switch (n) { + n = nxt_openssl_conn_test_error(task, c, ret, err, NXT_OPENSSL_HANDSHAKE); + switch (n) { - case NXT_AGAIN: - if (tls->ssl_error == SSL_ERROR_WANT_READ && tls->times < 2) { - tls->times++; - } + case NXT_AGAIN: + if (tls->ssl_error == SSL_ERROR_WANT_READ && tls->times < 2) { + tls->times++; + } - return; + return; - case 0: - handler = state->close_handler; - break; + case 0: + handler = state->close_handler; + break; - default: - case NXT_ERROR: - nxt_openssl_conn_error(task, err, "SSL_do_handshake(%d) failed", - c->socket.fd); + default: + case NXT_ERROR: + nxt_openssl_conn_error(task, err, "SSL_do_handshake(%d) failed", + c->socket.fd); - handler = state->error_handler; - break; - } + handler = state->error_handler; + break; } + } - wq = (c->read_state != NULL) ? c->read_work_queue : c->write_work_queue; + wq = (c->read_state != NULL) ? c->read_work_queue : c->write_work_queue; - nxt_work_queue_add(wq, handler, task, c, data); + nxt_work_queue_add(wq, handler, task, c, data); } +static ssize_t nxt_openssl_conn_io_recvbuf(nxt_conn_t *c, nxt_buf_t *b) { + int ret; + size_t size; + nxt_int_t n; + nxt_err_t err; + nxt_openssl_conn_t *tls; -static ssize_t -nxt_openssl_conn_io_recvbuf(nxt_conn_t *c, nxt_buf_t *b) -{ - int ret; - size_t size; - nxt_int_t n; - nxt_err_t err; - nxt_openssl_conn_t *tls; + tls = c->u.tls; + size = b->mem.end - b->mem.free; - tls = c->u.tls; - size = b->mem.end - b->mem.free; + ret = SSL_read(tls->session, b->mem.free, size); - ret = SSL_read(tls->session, b->mem.free, size); - - err = (ret <= 0) ? nxt_socket_errno : 0; + err = (ret <= 0) ? nxt_socket_errno : 0; - nxt_debug(c->socket.task, "SSL_read(%d, %p, %uz): %d err:%d", - c->socket.fd, b->mem.free, size, ret, err); + nxt_debug(c->socket.task, "SSL_read(%d, %p, %uz): %d err:%d", c->socket.fd, + b->mem.free, size, ret, err); - if (ret > 0) { - return ret; - } + if (ret > 0) { + return ret; + } - n = nxt_openssl_conn_test_error(c->socket.task, c, ret, err, - NXT_OPENSSL_READ); - if (n == NXT_ERROR) { - nxt_openssl_conn_error(c->socket.task, err, - "SSL_read(%d, %p, %uz) failed", - c->socket.fd, b->mem.free, size); - } + n = nxt_openssl_conn_test_error(c->socket.task, c, ret, err, + NXT_OPENSSL_READ); + if (n == NXT_ERROR) { + nxt_openssl_conn_error(c->socket.task, err, "SSL_read(%d, %p, %uz) failed", + c->socket.fd, b->mem.free, size); + } - return n; + return n; } +static ssize_t nxt_openssl_conn_io_sendbuf(nxt_task_t *task, + nxt_sendbuf_t *sb) { + nxt_uint_t niov; + struct iovec iov; -static ssize_t -nxt_openssl_conn_io_sendbuf(nxt_task_t *task, nxt_sendbuf_t *sb) -{ - nxt_uint_t niov; - struct iovec iov; + niov = nxt_sendbuf_mem_coalesce0(task, sb, &iov, 1); - niov = nxt_sendbuf_mem_coalesce0(task, sb, &iov, 1); + if (niov == 0 && sb->sync) { + return 0; + } - if (niov == 0 && sb->sync) { - return 0; - } - - return nxt_openssl_conn_io_send(task, sb, iov.iov_base, iov.iov_len); + return nxt_openssl_conn_io_send(task, sb, iov.iov_base, iov.iov_len); } +static ssize_t nxt_openssl_conn_io_send(nxt_task_t *task, nxt_sendbuf_t *sb, + void *buf, size_t size) { + int ret; + nxt_err_t err; + nxt_int_t n; + nxt_conn_t *c; + nxt_openssl_conn_t *tls; -static ssize_t -nxt_openssl_conn_io_send(nxt_task_t *task, nxt_sendbuf_t *sb, void *buf, - size_t size) -{ - int ret; - nxt_err_t err; - nxt_int_t n; - nxt_conn_t *c; - nxt_openssl_conn_t *tls; - - tls = sb->tls; + tls = sb->tls; - ret = SSL_write(tls->session, buf, size); + ret = SSL_write(tls->session, buf, size); - err = (ret <= 0) ? nxt_socket_errno : 0; + err = (ret <= 0) ? nxt_socket_errno : 0; - nxt_debug(task, "SSL_write(%d, %p, %uz): %d err:%d", - sb->socket, buf, size, ret, err); + nxt_debug(task, "SSL_write(%d, %p, %uz): %d err:%d", sb->socket, buf, size, + ret, err); - if (ret > 0) { - return ret; - } + if (ret > 0) { + return ret; + } - c = tls->conn; - c->socket.write_ready = sb->ready; + c = tls->conn; + c->socket.write_ready = sb->ready; - n = nxt_openssl_conn_test_error(task, c, ret, err, NXT_OPENSSL_WRITE); + n = nxt_openssl_conn_test_error(task, c, ret, err, NXT_OPENSSL_WRITE); - sb->ready = c->socket.write_ready; + sb->ready = c->socket.write_ready; - if (n == NXT_ERROR) { - sb->error = c->socket.error; - nxt_openssl_conn_error(task, err, "SSL_write(%d, %p, %uz) failed", - sb->socket, buf, size); - } + if (n == NXT_ERROR) { + sb->error = c->socket.error; + nxt_openssl_conn_error(task, err, "SSL_write(%d, %p, %uz) failed", + sb->socket, buf, size); + } - return n; + return n; } +static void nxt_openssl_conn_io_shutdown(nxt_task_t *task, void *obj, + void *data) { + int ret, mode; + SSL *s; + nxt_err_t err; + nxt_int_t n; + nxt_bool_t quiet, once; + nxt_conn_t *c; + nxt_openssl_conn_t *tls; + nxt_work_handler_t handler; -static void -nxt_openssl_conn_io_shutdown(nxt_task_t *task, void *obj, void *data) -{ - int ret, mode; - SSL *s; - nxt_err_t err; - nxt_int_t n; - nxt_bool_t quiet, once; - nxt_conn_t *c; - nxt_openssl_conn_t *tls; - nxt_work_handler_t handler; + c = obj; - c = obj; + nxt_debug(task, "openssl conn shutdown fd:%d", c->socket.fd); - nxt_debug(task, "openssl conn shutdown fd:%d", c->socket.fd); + c->read_state = NULL; + tls = c->u.tls; - c->read_state = NULL; - tls = c->u.tls; + if (tls == NULL) { + return; + } - if (tls == NULL) { - return; - } + s = tls->session; - s = tls->session; + if (s == NULL || !tls->handshake) { + handler = c->write_state->ready_handler; + goto done; + } - if (s == NULL || !tls->handshake) { - handler = c->write_state->ready_handler; - goto done; - } + mode = SSL_get_shutdown(s); - mode = SSL_get_shutdown(s); + if (c->socket.timedout || c->socket.error != 0) { + quiet = 1; - if (c->socket.timedout || c->socket.error != 0) { - quiet = 1; + } else if (c->socket.closed && !(mode & SSL_RECEIVED_SHUTDOWN)) { + quiet = 1; - } else if (c->socket.closed && !(mode & SSL_RECEIVED_SHUTDOWN)) { - quiet = 1; + } else { + quiet = 0; + } - } else { - quiet = 0; - } + SSL_set_quiet_shutdown(s, quiet); - SSL_set_quiet_shutdown(s, quiet); + if (tls->conf->no_wait_shutdown) { + mode |= SSL_RECEIVED_SHUTDOWN; + } - if (tls->conf->no_wait_shutdown) { - mode |= SSL_RECEIVED_SHUTDOWN; - } + once = 1; - once = 1; + for (;;) { + SSL_set_shutdown(s, mode); - for ( ;; ) { - SSL_set_shutdown(s, mode); + ret = SSL_shutdown(s); - ret = SSL_shutdown(s); + err = (ret <= 0) ? nxt_socket_errno : 0; - err = (ret <= 0) ? nxt_socket_errno : 0; + nxt_debug(task, "SSL_shutdown(%d, %d, %b): %d err:%d", c->socket.fd, mode, + quiet, ret, err); - nxt_debug(task, "SSL_shutdown(%d, %d, %b): %d err:%d", - c->socket.fd, mode, quiet, ret, err); + if (ret > 0) { + /* ret == 1, the shutdown was successfully completed. */ + handler = c->write_state->ready_handler; + goto done; + } - if (ret > 0) { - /* ret == 1, the shutdown was successfully completed. */ - handler = c->write_state->ready_handler; - goto done; - } + if (ret == 0) { + /* + * If SSL_shutdown() returns 0 then it should be called + * again. The second SSL_shutdown() call should return + * -1/SSL_ERROR_WANT_READ or -1/SSL_ERROR_WANT_WRITE. + * OpenSSL prior to 0.9.8m version however never returns + * -1 at all. Fortunately, OpenSSL preserves internally + * correct status available via SSL_get_error(-1). + */ + if (once) { + once = 0; + mode = SSL_get_shutdown(s); + continue; + } - if (ret == 0) { - /* - * If SSL_shutdown() returns 0 then it should be called - * again. The second SSL_shutdown() call should return - * -1/SSL_ERROR_WANT_READ or -1/SSL_ERROR_WANT_WRITE. - * OpenSSL prior to 0.9.8m version however never returns - * -1 at all. Fortunately, OpenSSL preserves internally - * correct status available via SSL_get_error(-1). - */ - if (once) { - once = 0; - mode = SSL_get_shutdown(s); - continue; - } + ret = -1; + } - ret = -1; - } + /* ret == -1 */ - /* ret == -1 */ + break; + } - break; - } + c->socket.read_handler = nxt_openssl_conn_io_shutdown; + c->socket.write_handler = nxt_openssl_conn_io_shutdown; + c->socket.error_handler = c->write_state->error_handler; - c->socket.read_handler = nxt_openssl_conn_io_shutdown; - c->socket.write_handler = nxt_openssl_conn_io_shutdown; - c->socket.error_handler = c->write_state->error_handler; + n = nxt_openssl_conn_test_error(task, c, ret, err, NXT_OPENSSL_SHUTDOWN); - n = nxt_openssl_conn_test_error(task, c, ret, err, NXT_OPENSSL_SHUTDOWN); + switch (n) { - switch (n) { + case 0: + handler = c->write_state->close_handler; + break; - case 0: - handler = c->write_state->close_handler; - break; - - case NXT_AGAIN: - c->write_timer.handler = nxt_openssl_conn_io_shutdown_timeout; - nxt_timer_add(task->thread->engine, &c->write_timer, 5000); - return; + case NXT_AGAIN: + c->write_timer.handler = nxt_openssl_conn_io_shutdown_timeout; + nxt_timer_add(task->thread->engine, &c->write_timer, 5000); + return; - default: - case NXT_ERROR: - nxt_openssl_conn_error(task, err, "SSL_shutdown(%d) failed", - c->socket.fd); - handler = c->write_state->error_handler; - } + default: + case NXT_ERROR: + nxt_openssl_conn_error(task, err, "SSL_shutdown(%d) failed", c->socket.fd); + handler = c->write_state->error_handler; + } done: - nxt_openssl_conn_free(task, c); + nxt_openssl_conn_free(task, c); - nxt_work_queue_add(c->write_work_queue, handler, task, c, data); + nxt_work_queue_add(c->write_work_queue, handler, task, c, data); } +static nxt_int_t nxt_openssl_conn_test_error(nxt_task_t *task, nxt_conn_t *c, + int ret, nxt_err_t sys_err, + nxt_openssl_io_t io) { + u_long lib_err; + nxt_openssl_conn_t *tls; -static nxt_int_t -nxt_openssl_conn_test_error(nxt_task_t *task, nxt_conn_t *c, int ret, - nxt_err_t sys_err, nxt_openssl_io_t io) -{ - u_long lib_err; - nxt_openssl_conn_t *tls; - - tls = c->u.tls; + tls = c->u.tls; - tls->ssl_error = SSL_get_error(tls->session, ret); + tls->ssl_error = SSL_get_error(tls->session, ret); - nxt_debug(task, "SSL_get_error(): %d", tls->ssl_error); + nxt_debug(task, "SSL_get_error(): %d", tls->ssl_error); - switch (tls->ssl_error) { + switch (tls->ssl_error) { - case SSL_ERROR_WANT_READ: - c->socket.read_ready = 0; + case SSL_ERROR_WANT_READ: + c->socket.read_ready = 0; - if (io != NXT_OPENSSL_READ) { - nxt_fd_event_block_write(task->thread->engine, &c->socket); + if (io != NXT_OPENSSL_READ) { + nxt_fd_event_block_write(task->thread->engine, &c->socket); - if (nxt_fd_event_is_disabled(c->socket.read)) { - nxt_fd_event_enable_read(task->thread->engine, &c->socket); - } - } + if (nxt_fd_event_is_disabled(c->socket.read)) { + nxt_fd_event_enable_read(task->thread->engine, &c->socket); + } + } - return NXT_AGAIN; + return NXT_AGAIN; - case SSL_ERROR_WANT_WRITE: - c->socket.write_ready = 0; + case SSL_ERROR_WANT_WRITE: + c->socket.write_ready = 0; - if (io != NXT_OPENSSL_WRITE) { - nxt_fd_event_block_read(task->thread->engine, &c->socket); + if (io != NXT_OPENSSL_WRITE) { + nxt_fd_event_block_read(task->thread->engine, &c->socket); - if (nxt_fd_event_is_disabled(c->socket.write)) { - nxt_fd_event_enable_write(task->thread->engine, &c->socket); - } - } + if (nxt_fd_event_is_disabled(c->socket.write)) { + nxt_fd_event_enable_write(task->thread->engine, &c->socket); + } + } - return NXT_AGAIN; + return NXT_AGAIN; - case SSL_ERROR_SYSCALL: - lib_err = ERR_peek_error(); + case SSL_ERROR_SYSCALL: + lib_err = ERR_peek_error(); - nxt_debug(task, "ERR_peek_error(): %l", lib_err); + nxt_debug(task, "ERR_peek_error(): %l", lib_err); - if (sys_err != 0 || lib_err != 0) { - c->socket.error = sys_err; - return NXT_ERROR; - } + if (sys_err != 0 || lib_err != 0) { + c->socket.error = sys_err; + return NXT_ERROR; + } - /* A connection was just closed. */ - c->socket.closed = 1; - return 0; + /* A connection was just closed. */ + c->socket.closed = 1; + return 0; - case SSL_ERROR_ZERO_RETURN: - /* A "close notify" alert. */ - return 0; + case SSL_ERROR_ZERO_RETURN: + /* A "close notify" alert. */ + return 0; - default: /* SSL_ERROR_SSL, etc. */ - c->socket.error = 1000; /* Nonexistent errno code. */ - return NXT_ERROR; - } + default: /* SSL_ERROR_SSL, etc. */ + c->socket.error = 1000; /* Nonexistent errno code. */ + return NXT_ERROR; + } } +static void nxt_openssl_conn_io_shutdown_timeout(nxt_task_t *task, void *obj, + void *data) { + nxt_conn_t *c; + nxt_timer_t *timer; -static void -nxt_openssl_conn_io_shutdown_timeout(nxt_task_t *task, void *obj, void *data) -{ - nxt_conn_t *c; - nxt_timer_t *timer; - - timer = obj; + timer = obj; - nxt_debug(task, "openssl conn shutdown timeout"); + nxt_debug(task, "openssl conn shutdown timeout"); - c = nxt_write_timer_conn(timer); + c = nxt_write_timer_conn(timer); - c->socket.timedout = 1; - nxt_openssl_conn_io_shutdown(task, c, NULL); + c->socket.timedout = 1; + nxt_openssl_conn_io_shutdown(task, c, NULL); } +static void nxt_cdecl nxt_openssl_conn_error(nxt_task_t *task, nxt_err_t err, + const char *fmt, ...) { + u_char *p, *end; + va_list args; + nxt_uint_t level; + u_char msg[NXT_MAX_ERROR_STR]; -static void nxt_cdecl -nxt_openssl_conn_error(nxt_task_t *task, nxt_err_t err, const char *fmt, ...) -{ - u_char *p, *end; - va_list args; - nxt_uint_t level; - u_char msg[NXT_MAX_ERROR_STR]; + level = nxt_openssl_log_error_level(err); - level = nxt_openssl_log_error_level(err); + if (nxt_log_level_enough(task->log, level)) { - if (nxt_log_level_enough(task->log, level)) { - - end = msg + sizeof(msg); + end = msg + sizeof(msg); - va_start(args, fmt); - p = nxt_vsprintf(msg, end, fmt, args); - va_end(args); + va_start(args, fmt); + p = nxt_vsprintf(msg, end, fmt, args); + va_end(args); - if (err != 0) { - p = nxt_sprintf(p, end, " %E", err); - } + if (err != 0) { + p = nxt_sprintf(p, end, " %E", err); + } - p = nxt_openssl_copy_error(p, end); + p = nxt_openssl_copy_error(p, end); - nxt_log(task, level, "%*s", p - msg, msg); + nxt_log(task, level, "%*s", p - msg, msg); - } else { - ERR_clear_error(); - } + } else { + ERR_clear_error(); + } } +static nxt_uint_t nxt_openssl_log_error_level(nxt_err_t err) { + switch (ERR_GET_REASON(ERR_peek_error())) { -static nxt_uint_t -nxt_openssl_log_error_level(nxt_err_t err) -{ - switch (ERR_GET_REASON(ERR_peek_error())) { + case 0: + return nxt_socket_error_level(err); - case 0: - return nxt_socket_error_level(err); - - case SSL_R_BAD_CHANGE_CIPHER_SPEC: /* 103 */ - case SSL_R_BLOCK_CIPHER_PAD_IS_WRONG: /* 129 */ - case SSL_R_DIGEST_CHECK_FAILED: /* 149 */ - case SSL_R_ERROR_IN_RECEIVED_CIPHER_LIST: /* 151 */ - case SSL_R_EXCESSIVE_MESSAGE_SIZE: /* 152 */ - case SSL_R_LENGTH_MISMATCH: /* 159 */ + case SSL_R_BAD_CHANGE_CIPHER_SPEC: /* 103 */ + case SSL_R_BLOCK_CIPHER_PAD_IS_WRONG: /* 129 */ + case SSL_R_DIGEST_CHECK_FAILED: /* 149 */ + case SSL_R_ERROR_IN_RECEIVED_CIPHER_LIST: /* 151 */ + case SSL_R_EXCESSIVE_MESSAGE_SIZE: /* 152 */ + case SSL_R_LENGTH_MISMATCH: /* 159 */ #ifdef SSL_R_NO_CIPHERS_PASSED - case SSL_R_NO_CIPHERS_PASSED: /* 182 */ + case SSL_R_NO_CIPHERS_PASSED: /* 182 */ #endif - case SSL_R_NO_CIPHERS_SPECIFIED: /* 183 */ - case SSL_R_NO_COMPRESSION_SPECIFIED: /* 187 */ - case SSL_R_NO_SHARED_CIPHER: /* 193 */ - case SSL_R_RECORD_LENGTH_MISMATCH: /* 213 */ + case SSL_R_NO_CIPHERS_SPECIFIED: /* 183 */ + case SSL_R_NO_COMPRESSION_SPECIFIED: /* 187 */ + case SSL_R_NO_SHARED_CIPHER: /* 193 */ + case SSL_R_RECORD_LENGTH_MISMATCH: /* 213 */ #ifdef SSL_R_PARSE_TLSEXT - case SSL_R_PARSE_TLSEXT: /* 227 */ + case SSL_R_PARSE_TLSEXT: /* 227 */ #endif - case SSL_R_UNEXPECTED_MESSAGE: /* 244 */ - case SSL_R_UNEXPECTED_RECORD: /* 245 */ - case SSL_R_UNKNOWN_ALERT_TYPE: /* 246 */ - case SSL_R_UNKNOWN_PROTOCOL: /* 252 */ - case SSL_R_WRONG_VERSION_NUMBER: /* 267 */ - case SSL_R_DECRYPTION_FAILED_OR_BAD_RECORD_MAC: /* 281 */ + case SSL_R_UNEXPECTED_MESSAGE: /* 244 */ + case SSL_R_UNEXPECTED_RECORD: /* 245 */ + case SSL_R_UNKNOWN_ALERT_TYPE: /* 246 */ + case SSL_R_UNKNOWN_PROTOCOL: /* 252 */ + case SSL_R_WRONG_VERSION_NUMBER: /* 267 */ + case SSL_R_DECRYPTION_FAILED_OR_BAD_RECORD_MAC: /* 281 */ #ifdef SSL_R_RENEGOTIATE_EXT_TOO_LONG - case SSL_R_RENEGOTIATE_EXT_TOO_LONG: /* 335 */ - case SSL_R_RENEGOTIATION_ENCODING_ERR: /* 336 */ - case SSL_R_RENEGOTIATION_MISMATCH: /* 337 */ + case SSL_R_RENEGOTIATE_EXT_TOO_LONG: /* 335 */ + case SSL_R_RENEGOTIATION_ENCODING_ERR: /* 336 */ + case SSL_R_RENEGOTIATION_MISMATCH: /* 337 */ #endif #ifdef SSL_R_UNSAFE_LEGACY_RENEGOTIATION_DISABLED - case SSL_R_UNSAFE_LEGACY_RENEGOTIATION_DISABLED: /* 338 */ + case SSL_R_UNSAFE_LEGACY_RENEGOTIATION_DISABLED: /* 338 */ #endif #ifdef SSL_R_SCSV_RECEIVED_WHEN_RENEGOTIATING - case SSL_R_SCSV_RECEIVED_WHEN_RENEGOTIATING: /* 345 */ + case SSL_R_SCSV_RECEIVED_WHEN_RENEGOTIATING: /* 345 */ #endif - case 1000:/* SSL_R_SSLV3_ALERT_CLOSE_NOTIFY */ - case SSL_R_SSLV3_ALERT_UNEXPECTED_MESSAGE: /* 1010 */ - case SSL_R_SSLV3_ALERT_BAD_RECORD_MAC: /* 1020 */ - case SSL_R_TLSV1_ALERT_DECRYPTION_FAILED: /* 1021 */ - case SSL_R_TLSV1_ALERT_RECORD_OVERFLOW: /* 1022 */ - case SSL_R_SSLV3_ALERT_DECOMPRESSION_FAILURE: /* 1030 */ - case SSL_R_SSLV3_ALERT_HANDSHAKE_FAILURE: /* 1040 */ - case SSL_R_SSLV3_ALERT_ILLEGAL_PARAMETER: /* 1047 */ - break; - - case SSL_R_SSLV3_ALERT_NO_CERTIFICATE: /* 1041 */ - case SSL_R_SSLV3_ALERT_BAD_CERTIFICATE: /* 1042 */ - case SSL_R_SSLV3_ALERT_UNSUPPORTED_CERTIFICATE: /* 1043 */ - case SSL_R_SSLV3_ALERT_CERTIFICATE_REVOKED: /* 1044 */ - case SSL_R_SSLV3_ALERT_CERTIFICATE_EXPIRED: /* 1045 */ - case SSL_R_SSLV3_ALERT_CERTIFICATE_UNKNOWN: /* 1046 */ - case SSL_R_TLSV1_ALERT_UNKNOWN_CA: /* 1048 */ - case SSL_R_TLSV1_ALERT_ACCESS_DENIED: /* 1049 */ - case SSL_R_TLSV1_ALERT_DECODE_ERROR: /* 1050 */ - case SSL_R_TLSV1_ALERT_DECRYPT_ERROR: /* 1051 */ - case SSL_R_TLSV1_ALERT_EXPORT_RESTRICTION: /* 1060 */ - case SSL_R_TLSV1_ALERT_PROTOCOL_VERSION: /* 1070 */ - case SSL_R_TLSV1_ALERT_INSUFFICIENT_SECURITY: /* 1071 */ - case SSL_R_TLSV1_ALERT_INTERNAL_ERROR: /* 1080 */ - case SSL_R_TLSV1_ALERT_USER_CANCELLED: /* 1090 */ - case SSL_R_TLSV1_ALERT_NO_RENEGOTIATION: /* 1100 */ - return NXT_LOG_ERR; - - default: - return NXT_LOG_ALERT; - } - - return NXT_LOG_INFO; + case 1000: /* SSL_R_SSLV3_ALERT_CLOSE_NOTIFY */ + case SSL_R_SSLV3_ALERT_UNEXPECTED_MESSAGE: /* 1010 */ + case SSL_R_SSLV3_ALERT_BAD_RECORD_MAC: /* 1020 */ + case SSL_R_TLSV1_ALERT_DECRYPTION_FAILED: /* 1021 */ + case SSL_R_TLSV1_ALERT_RECORD_OVERFLOW: /* 1022 */ + case SSL_R_SSLV3_ALERT_DECOMPRESSION_FAILURE: /* 1030 */ + case SSL_R_SSLV3_ALERT_HANDSHAKE_FAILURE: /* 1040 */ + case SSL_R_SSLV3_ALERT_ILLEGAL_PARAMETER: /* 1047 */ + break; + + case SSL_R_SSLV3_ALERT_NO_CERTIFICATE: /* 1041 */ + case SSL_R_SSLV3_ALERT_BAD_CERTIFICATE: /* 1042 */ + case SSL_R_SSLV3_ALERT_UNSUPPORTED_CERTIFICATE: /* 1043 */ + case SSL_R_SSLV3_ALERT_CERTIFICATE_REVOKED: /* 1044 */ + case SSL_R_SSLV3_ALERT_CERTIFICATE_EXPIRED: /* 1045 */ + case SSL_R_SSLV3_ALERT_CERTIFICATE_UNKNOWN: /* 1046 */ + case SSL_R_TLSV1_ALERT_UNKNOWN_CA: /* 1048 */ + case SSL_R_TLSV1_ALERT_ACCESS_DENIED: /* 1049 */ + case SSL_R_TLSV1_ALERT_DECODE_ERROR: /* 1050 */ + case SSL_R_TLSV1_ALERT_DECRYPT_ERROR: /* 1051 */ + case SSL_R_TLSV1_ALERT_EXPORT_RESTRICTION: /* 1060 */ + case SSL_R_TLSV1_ALERT_PROTOCOL_VERSION: /* 1070 */ + case SSL_R_TLSV1_ALERT_INSUFFICIENT_SECURITY: /* 1071 */ + case SSL_R_TLSV1_ALERT_INTERNAL_ERROR: /* 1080 */ + case SSL_R_TLSV1_ALERT_USER_CANCELLED: /* 1090 */ + case SSL_R_TLSV1_ALERT_NO_RENEGOTIATION: /* 1100 */ + return NXT_LOG_ERR; + + default: + return NXT_LOG_ALERT; + } + + return NXT_LOG_INFO; } +void nxt_cdecl nxt_openssl_log_error(nxt_task_t *task, nxt_uint_t level, + const char *fmt, ...) { + u_char *p, *end; + va_list args; + u_char msg[NXT_MAX_ERROR_STR]; -void nxt_cdecl -nxt_openssl_log_error(nxt_task_t *task, nxt_uint_t level, const char *fmt, ...) -{ - u_char *p, *end; - va_list args; - u_char msg[NXT_MAX_ERROR_STR]; - - end = msg + sizeof(msg); + end = msg + sizeof(msg); - va_start(args, fmt); - p = nxt_vsprintf(msg, end, fmt, args); - va_end(args); + va_start(args, fmt); + p = nxt_vsprintf(msg, end, fmt, args); + va_end(args); - p = nxt_openssl_copy_error(p, end); + p = nxt_openssl_copy_error(p, end); - nxt_log(task, level, "%*s", p - msg, msg); + nxt_log(task, level, "%*s", p - msg, msg); } +u_char *nxt_openssl_copy_error(u_char *p, u_char *end) { + int flags; + u_long err; + nxt_bool_t clear; + const char *data, *delimiter; -u_char * -nxt_openssl_copy_error(u_char *p, u_char *end) -{ - int flags; - u_long err; - nxt_bool_t clear; - const char *data, *delimiter; + err = ERR_peek_error(); + if (err == 0) { + return p; + } - err = ERR_peek_error(); - if (err == 0) { - return p; - } + /* Log the most relevant error message ... */ + data = ERR_reason_error_string(err); - /* Log the most relevant error message ... */ - data = ERR_reason_error_string(err); + p = nxt_sprintf(p, end, " (%d: %s) (OpenSSL: ", ERR_GET_REASON(err), data); - p = nxt_sprintf(p, end, " (%d: %s) (OpenSSL: ", ERR_GET_REASON(err), data); + /* + * ... followed by all queued cumbersome OpenSSL error messages + * and drain the error queue. + */ + delimiter = ""; + clear = 0; - /* - * ... followed by all queued cumbersome OpenSSL error messages - * and drain the error queue. - */ - delimiter = ""; - clear = 0; - - for ( ;; ) { + for (;;) { #if OPENSSL_VERSION_NUMBER >= 0x30000000L - err = ERR_get_error_all(NULL, NULL, NULL, &data, &flags); + err = ERR_get_error_all(NULL, NULL, NULL, &data, &flags); #else - err = ERR_get_error_line_data(NULL, NULL, &data, &flags); + err = ERR_get_error_line_data(NULL, NULL, &data, &flags); #endif - if (err == 0) { - break; - } + if (err == 0) { + break; + } - p = nxt_sprintf(p, end, "%s", delimiter); + p = nxt_sprintf(p, end, "%s", delimiter); - ERR_error_string_n(err, (char *) p, end - p); + ERR_error_string_n(err, (char *)p, end - p); - while (p < end && *p != '\0') { - p++; - } + while (p < end && *p != '\0') { + p++; + } - if ((flags & ERR_TXT_STRING) != 0) { - p = nxt_sprintf(p, end, ":%s", data); - } + if ((flags & ERR_TXT_STRING) != 0) { + p = nxt_sprintf(p, end, ":%s", data); + } - clear |= ((flags & ERR_TXT_MALLOCED) != 0); + clear |= ((flags & ERR_TXT_MALLOCED) != 0); - delimiter = "; "; - } + delimiter = "; "; + } - /* Deallocate additional data. */ + /* Deallocate additional data. */ - if (clear) { - ERR_clear_error(); - } + if (clear) { + ERR_clear_error(); + } - if (p < end) { - *p++ = ')'; - } + if (p < end) { + *p++ = ')'; + } - return p; + return p; } diff --git a/src/nxt_parse.c b/src/nxt_parse.c index e60bab4c4..8b0ed7337 100644 --- a/src/nxt_parse.c +++ b/src/nxt_parse.c @@ -6,343 +6,324 @@ #include - /* * nxt_int_parse() returns size_t value >= 0 on success, * -1 on failure, and -2 on overflow. */ -nxt_int_t -nxt_int_parse(const u_char *p, size_t length) -{ - u_char c; - nxt_uint_t val; +nxt_int_t nxt_int_parse(const u_char *p, size_t length) { + u_char c; + nxt_uint_t val; - static const nxt_uint_t cutoff = NXT_INT_T_MAX / 10; - static const nxt_uint_t cutlim = NXT_INT_T_MAX % 10; + static const nxt_uint_t cutoff = NXT_INT_T_MAX / 10; + static const nxt_uint_t cutlim = NXT_INT_T_MAX % 10; - if (nxt_fast_path(length != 0)) { + if (nxt_fast_path(length != 0)) { - val = 0; + val = 0; - do { - c = *p++; + do { + c = *p++; - /* Values below '0' become >= 208. */ - c = c - '0'; + /* Values below '0' become >= 208. */ + c = c - '0'; - if (nxt_slow_path(c > 9)) { - return -1; - } + if (nxt_slow_path(c > 9)) { + return -1; + } - if (nxt_slow_path(val >= cutoff && (val > cutoff || c > cutlim))) { - /* An overflow. */ - return -2; - } + if (nxt_slow_path(val >= cutoff && (val > cutoff || c > cutlim))) { + /* An overflow. */ + return -2; + } - val = val * 10 + c; + val = val * 10 + c; - length--; + length--; - } while (length != 0); + } while (length != 0); - return val; - } + return val; + } - return -1; + return -1; } - /* * nxt_size_t_parse() returns size_t value >= 0 on success, * -1 on failure, and -2 on overflow. */ -ssize_t -nxt_size_t_parse(const u_char *p, size_t length) -{ - u_char c; - size_t val; +ssize_t nxt_size_t_parse(const u_char *p, size_t length) { + u_char c; + size_t val; - static const size_t cutoff = NXT_SIZE_T_MAX / 10; - static const size_t cutlim = NXT_SIZE_T_MAX % 10; + static const size_t cutoff = NXT_SIZE_T_MAX / 10; + static const size_t cutlim = NXT_SIZE_T_MAX % 10; - if (nxt_fast_path(length != 0)) { + if (nxt_fast_path(length != 0)) { - val = 0; + val = 0; - do { - c = *p++; + do { + c = *p++; - /* Values below '0' become >= 208. */ - c = c - '0'; + /* Values below '0' become >= 208. */ + c = c - '0'; - if (nxt_slow_path(c > 9)) { - return -1; - } + if (nxt_slow_path(c > 9)) { + return -1; + } - if (nxt_slow_path(val >= cutoff && (val > cutoff || c > cutlim))) { - /* An overflow. */ - return -2; - } + if (nxt_slow_path(val >= cutoff && (val > cutoff || c > cutlim))) { + /* An overflow. */ + return -2; + } - val = val * 10 + c; + val = val * 10 + c; - length--; + length--; - } while (length != 0); + } while (length != 0); - return val; - } + return val; + } - return -1; + return -1; } - /* * nxt_size_parse() parses size string with optional K or M units and * returns size_t value >= 0 on success, -1 on failure, and -2 on overflow. */ -ssize_t -nxt_size_parse(const u_char *p, size_t length) -{ - u_char unit; - ssize_t val, max; - nxt_uint_t shift; - - if (nxt_fast_path(length != 0)) { +ssize_t nxt_size_parse(const u_char *p, size_t length) { + u_char unit; + ssize_t val, max; + nxt_uint_t shift; - length--; + if (nxt_fast_path(length != 0)) { - /* Upper case. */ - unit = p[length] & ~0x20; + length--; - switch (unit) { + /* Upper case. */ + unit = p[length] & ~0x20; - case 'G': - max = NXT_SIZE_T_MAX >> 30; - shift = 30; - break; + switch (unit) { - case 'M': - max = NXT_SIZE_T_MAX >> 20; - shift = 20; - break; + case 'G': + max = NXT_SIZE_T_MAX >> 30; + shift = 30; + break; - case 'K': - max = NXT_SIZE_T_MAX >> 10; - shift = 10; - break; + case 'M': + max = NXT_SIZE_T_MAX >> 20; + shift = 20; + break; - default: - return nxt_size_t_parse(p, length + 1); - } + case 'K': + max = NXT_SIZE_T_MAX >> 10; + shift = 10; + break; - val = nxt_size_t_parse(p, length); + default: + return nxt_size_t_parse(p, length + 1); + } - if (nxt_fast_path(val >= 0)) { + val = nxt_size_t_parse(p, length); - if (nxt_slow_path(val > max)) { - /* An overflow. */ - return -2; - } + if (nxt_fast_path(val >= 0)) { - val <<= shift; - } + if (nxt_slow_path(val > max)) { + /* An overflow. */ + return -2; + } - return val; + val <<= shift; } - return -1; -} + return val; + } + return -1; +} /* * nxt_off_t_parse() returns nxt_off_t value >= 0 on success, * -1 on failure, and -2 on overflow. */ -nxt_off_t -nxt_off_t_parse(const u_char *p, size_t length) -{ - u_char c; - nxt_uoff_t val; +nxt_off_t nxt_off_t_parse(const u_char *p, size_t length) { + u_char c; + nxt_uoff_t val; - static const nxt_uoff_t cutoff = NXT_OFF_T_MAX / 10; - static const nxt_uoff_t cutlim = NXT_OFF_T_MAX % 10; + static const nxt_uoff_t cutoff = NXT_OFF_T_MAX / 10; + static const nxt_uoff_t cutlim = NXT_OFF_T_MAX % 10; - if (nxt_fast_path(length != 0)) { + if (nxt_fast_path(length != 0)) { - val = 0; + val = 0; - do { - c = *p++; + do { + c = *p++; - /* Values below '0' become >= 208. */ - c = c - '0'; + /* Values below '0' become >= 208. */ + c = c - '0'; - if (nxt_slow_path(c > 9)) { - return -1; - } + if (nxt_slow_path(c > 9)) { + return -1; + } - if (nxt_slow_path(val >= cutoff && (val > cutoff || c > cutlim))) { - /* An overflow. */ - return -2; - } + if (nxt_slow_path(val >= cutoff && (val > cutoff || c > cutlim))) { + /* An overflow. */ + return -2; + } - val = val * 10 + c; + val = val * 10 + c; - length--; + length--; - } while (length != 0); + } while (length != 0); - return val; - } + return val; + } - return -1; + return -1; } - /* * nxt_str_int_parse() returns nxt_int_t value >= 0 on success, * -1 on failure, and -2 on overflow and also updates the 's' argument. */ -nxt_int_t -nxt_str_int_parse(nxt_str_t *s) -{ - u_char c, *p; - size_t length; - nxt_uint_t val; +nxt_int_t nxt_str_int_parse(nxt_str_t *s) { + u_char c, *p; + size_t length; + nxt_uint_t val; - static const nxt_uint_t cutoff = NXT_INT_T_MAX / 10; - static const nxt_uint_t cutlim = NXT_INT_T_MAX % 10; + static const nxt_uint_t cutoff = NXT_INT_T_MAX / 10; + static const nxt_uint_t cutlim = NXT_INT_T_MAX % 10; - length = s->length; + length = s->length; - if (nxt_slow_path(length == 0)) { - return -1; - } + if (nxt_slow_path(length == 0)) { + return -1; + } - p = s->start; - val = 0; + p = s->start; + val = 0; - do { - c = *p; + do { + c = *p; - /* Values below '0' become >= 208. */ - c = c - '0'; + /* Values below '0' become >= 208. */ + c = c - '0'; - if (c > 9) { - break; - } + if (c > 9) { + break; + } - if (nxt_slow_path(val >= cutoff && (val > cutoff || c > cutlim))) { - /* An overflow. */ - return -2; - } + if (nxt_slow_path(val >= cutoff && (val > cutoff || c > cutlim))) { + /* An overflow. */ + return -2; + } - val = val * 10 + c; + val = val * 10 + c; - p++; - length--; + p++; + length--; - } while (length != 0); + } while (length != 0); - s->length = length; - s->start = p; + s->length = length; + s->start = p; - return val; + return val; } - /* * nxt_number_parse() returns a double value >= 0 and updates the start * argument on success, or returns -1 on failure or -2 on overflow. */ -double -nxt_number_parse(const u_char **start, const u_char *end) -{ - u_char c; - nxt_bool_t overflow; - nxt_uint_t integral, frac, power; - const u_char *p; +double nxt_number_parse(const u_char **start, const u_char *end) { + u_char c; + nxt_bool_t overflow; + nxt_uint_t integral, frac, power; + const u_char *p; - static const nxt_uint_t cutoff = NXT_INT_T_MAX / 10; - static const nxt_uint_t cutlim = NXT_INT_T_MAX % 10; + static const nxt_uint_t cutoff = NXT_INT_T_MAX / 10; + static const nxt_uint_t cutlim = NXT_INT_T_MAX % 10; - p = *start; - integral = 0; + p = *start; + integral = 0; - while (p < end) { - c = *p; + while (p < end) { + c = *p; - if (c == '.') { - goto dot; - } + if (c == '.') { + goto dot; + } - /* Values below '0' become >= 208. */ - c = c - '0'; + /* Values below '0' become >= 208. */ + c = c - '0'; - if (c > 9) { - break; - } + if (c > 9) { + break; + } - overflow = nxt_expect(0, (integral >= cutoff - && (integral > cutoff || c > cutlim))); + overflow = nxt_expect( + 0, (integral >= cutoff && (integral > cutoff || c > cutlim))); - if (overflow) { - return -2; - } + if (overflow) { + return -2; + } - integral = integral * 10 + c; + integral = integral * 10 + c; - p++; - } + p++; + } - if (nxt_fast_path(p != *start)) { - *start = p; - return integral; - } + if (nxt_fast_path(p != *start)) { + *start = p; + return integral; + } - /* No value. */ - return -1; + /* No value. */ + return -1; dot: - if (nxt_slow_path(p == *start)) { - /* No leading digit before dot. */ - return -1; - } - - frac = 0; - power = 1; + if (nxt_slow_path(p == *start)) { + /* No leading digit before dot. */ + return -1; + } - for (p++; p < end; p++) { - c = *p; + frac = 0; + power = 1; - /* Values below '0' become >= 208. */ - c = c - '0'; + for (p++; p < end; p++) { + c = *p; - if (c > 9) { - break; - } + /* Values below '0' become >= 208. */ + c = c - '0'; - overflow = nxt_expect(0, (frac >= cutoff && (frac > cutoff - || c > cutlim)) - || power > cutoff); + if (c > 9) { + break; + } - if (overflow) { - return -2; - } + overflow = nxt_expect( + 0, (frac >= cutoff && (frac > cutoff || c > cutlim)) || power > cutoff); - frac = frac * 10 + c; - power *= 10; + if (overflow) { + return -2; } - *start = p; + frac = frac * 10 + c; + power *= 10; + } + + *start = p; - return integral + (double) frac / power; + return integral + (double)frac / power; } diff --git a/src/nxt_parse.h b/src/nxt_parse.h index 0643af1ed..c9cb95032 100644 --- a/src/nxt_parse.h +++ b/src/nxt_parse.h @@ -7,7 +7,6 @@ #ifndef _NXT_PARSE_H_INCLUDED_ #define _NXT_PARSE_H_INCLUDED_ - NXT_EXPORT nxt_int_t nxt_int_parse(const u_char *p, size_t len); NXT_EXPORT ssize_t nxt_size_t_parse(const u_char *p, size_t len); NXT_EXPORT ssize_t nxt_size_parse(const u_char *p, size_t len); @@ -19,7 +18,6 @@ NXT_EXPORT double nxt_number_parse(const u_char **start, const u_char *end); NXT_EXPORT nxt_time_t nxt_time_parse(const u_char *p, size_t len); NXT_EXPORT nxt_int_t nxt_term_parse(const u_char *p, size_t len, - nxt_bool_t seconds); - + nxt_bool_t seconds); #endif /* _NXT_PARSE_H_INCLUDED_ */ diff --git a/src/nxt_pcre.c b/src/nxt_pcre.c index 737fc7cf7..4fb1f9f68 100644 --- a/src/nxt_pcre.c +++ b/src/nxt_pcre.c @@ -7,129 +7,111 @@ #include #include - struct nxt_regex_s { - pcre *code; - pcre_extra *extra; - nxt_str_t pattern; + pcre *code; + pcre_extra *extra; + nxt_str_t pattern; }; struct nxt_regex_match_s { - int ovecsize; - int ovec[]; + int ovecsize; + int ovec[]; }; - static void *nxt_pcre_malloc(size_t size); static void nxt_pcre_free(void *p); -static nxt_mp_t *nxt_pcre_mp; +static nxt_mp_t *nxt_pcre_mp; +nxt_regex_t *nxt_regex_compile(nxt_mp_t *mp, nxt_str_t *source, + nxt_regex_err_t *err) { + int erroffset; + char *pattern; + void *saved_malloc, *saved_free; + nxt_regex_t *re; -nxt_regex_t * -nxt_regex_compile(nxt_mp_t *mp, nxt_str_t *source, nxt_regex_err_t *err) -{ - int erroffset; - char *pattern; - void *saved_malloc, *saved_free; - nxt_regex_t *re; + err->offset = source->length; - err->offset = source->length; + re = nxt_mp_get(mp, sizeof(nxt_regex_t) + source->length + 1); + if (nxt_slow_path(re == NULL)) { + err->msg = "memory allocation failed"; + return NULL; + } - re = nxt_mp_get(mp, sizeof(nxt_regex_t) + source->length + 1); - if (nxt_slow_path(re == NULL)) { - err->msg = "memory allocation failed"; - return NULL; - } + pattern = nxt_pointer_to(re, sizeof(nxt_regex_t)); - pattern = nxt_pointer_to(re, sizeof(nxt_regex_t)); + nxt_memcpy(pattern, source->start, source->length); + pattern[source->length] = '\0'; - nxt_memcpy(pattern, source->start, source->length); - pattern[source->length] = '\0'; + re->pattern.length = source->length; + re->pattern.start = (u_char *)pattern; - re->pattern.length = source->length; - re->pattern.start = (u_char *) pattern; + saved_malloc = pcre_malloc; + saved_free = pcre_free; - saved_malloc = pcre_malloc; - saved_free = pcre_free; + pcre_malloc = nxt_pcre_malloc; + pcre_free = nxt_pcre_free; + nxt_pcre_mp = mp; - pcre_malloc = nxt_pcre_malloc; - pcre_free = nxt_pcre_free; - nxt_pcre_mp = mp; - - re->code = pcre_compile(pattern, 0, &err->msg, &erroffset, NULL); - if (nxt_fast_path(re->code != NULL)) { + re->code = pcre_compile(pattern, 0, &err->msg, &erroffset, NULL); + if (nxt_fast_path(re->code != NULL)) { #if 0 re->extra = pcre_study(re->code, PCRE_STUDY_JIT_COMPILE, &err->msg); if (nxt_slow_path(re->extra == NULL && err->msg != NULL)) { nxt_log_warn(thr->log, "pcre_study(%V) failed: %s", source, err->msg); } #else - re->extra = NULL; + re->extra = NULL; #endif - } else { - err->offset = erroffset; - re = NULL; - } + } else { + err->offset = erroffset; + re = NULL; + } - pcre_malloc = saved_malloc; - pcre_free = saved_free; + pcre_malloc = saved_malloc; + pcre_free = saved_free; - return re; + return re; } +static void *nxt_pcre_malloc(size_t size) { + if (nxt_slow_path(nxt_pcre_mp == NULL)) { + nxt_thread_log_alert("pcre_malloc(%uz) called without memory pool", size); + return NULL; + } -static void* -nxt_pcre_malloc(size_t size) -{ - if (nxt_slow_path(nxt_pcre_mp == NULL)) { - nxt_thread_log_alert("pcre_malloc(%uz) called without memory pool", - size); - return NULL; - } - - nxt_thread_log_debug("pcre_malloc(%uz), pool %p", size, nxt_pcre_mp); + nxt_thread_log_debug("pcre_malloc(%uz), pool %p", size, nxt_pcre_mp); - return nxt_mp_get(nxt_pcre_mp, size); + return nxt_mp_get(nxt_pcre_mp, size); } +static void nxt_pcre_free(void *p) {} -static void -nxt_pcre_free(void *p) -{ -} - +nxt_regex_match_t *nxt_regex_match_create(nxt_mp_t *mp, size_t size) { + nxt_regex_match_t *match; -nxt_regex_match_t * -nxt_regex_match_create(nxt_mp_t *mp, size_t size) -{ - nxt_regex_match_t *match; + match = nxt_mp_get(mp, sizeof(nxt_regex_match_t) + sizeof(int) * size); + if (nxt_fast_path(match != NULL)) { + match->ovecsize = size; + } - match = nxt_mp_get(mp, sizeof(nxt_regex_match_t) + sizeof(int) * size); - if (nxt_fast_path(match != NULL)) { - match->ovecsize = size; - } - - return match; + return match; } +nxt_int_t nxt_regex_match(nxt_regex_t *re, u_char *subject, size_t length, + nxt_regex_match_t *match) { + int ret; -nxt_int_t -nxt_regex_match(nxt_regex_t *re, u_char *subject, size_t length, - nxt_regex_match_t *match) -{ - int ret; - - ret = pcre_exec(re->code, re->extra, (const char *) subject, length, 0, 0, - match->ovec, match->ovecsize); - if (nxt_slow_path(ret < PCRE_ERROR_NOMATCH)) { - nxt_thread_log_error(NXT_LOG_ERR, - "pcre_exec() failed: %d on \"%*s\" using \"%V\"", - ret, length, subject, &re->pattern); + ret = pcre_exec(re->code, re->extra, (const char *)subject, length, 0, 0, + match->ovec, match->ovecsize); + if (nxt_slow_path(ret < PCRE_ERROR_NOMATCH)) { + nxt_thread_log_error(NXT_LOG_ERR, + "pcre_exec() failed: %d on \"%*s\" using \"%V\"", ret, + length, subject, &re->pattern); - return NXT_ERROR; - } + return NXT_ERROR; + } - return (ret != PCRE_ERROR_NOMATCH); + return (ret != PCRE_ERROR_NOMATCH); } diff --git a/src/nxt_pcre2.c b/src/nxt_pcre2.c index cb51062c0..029c70342 100644 --- a/src/nxt_pcre2.c +++ b/src/nxt_pcre2.c @@ -9,64 +9,61 @@ #define PCRE2_CODE_UNIT_WIDTH 8 #include - static void *nxt_pcre2_malloc(PCRE2_SIZE size, void *memory_data); static void nxt_pcre2_free(void *p, void *memory_data); - struct nxt_regex_s { - pcre2_code *code; - nxt_str_t pattern; + pcre2_code *code; + nxt_str_t pattern; }; - -nxt_regex_t * -nxt_regex_compile(nxt_mp_t *mp, nxt_str_t *source, nxt_regex_err_t *err) -{ - int errcode; - nxt_int_t ret; - PCRE2_SIZE erroffset; - nxt_regex_t *re; - pcre2_general_context *general_ctx; - pcre2_compile_context *compile_ctx; - - static const u_char alloc_error[] = "memory allocation failed"; - - general_ctx = pcre2_general_context_create(nxt_pcre2_malloc, - nxt_pcre2_free, mp); - if (nxt_slow_path(general_ctx == NULL)) { - goto alloc_fail; +nxt_regex_t *nxt_regex_compile(nxt_mp_t *mp, nxt_str_t *source, + nxt_regex_err_t *err) { + int errcode; + nxt_int_t ret; + PCRE2_SIZE erroffset; + nxt_regex_t *re; + pcre2_general_context *general_ctx; + pcre2_compile_context *compile_ctx; + + static const u_char alloc_error[] = "memory allocation failed"; + + general_ctx = + pcre2_general_context_create(nxt_pcre2_malloc, nxt_pcre2_free, mp); + if (nxt_slow_path(general_ctx == NULL)) { + goto alloc_fail; + } + + compile_ctx = pcre2_compile_context_create(general_ctx); + if (nxt_slow_path(compile_ctx == NULL)) { + goto alloc_fail; + } + + re = nxt_mp_get(mp, sizeof(nxt_regex_t)); + if (nxt_slow_path(re == NULL)) { + goto alloc_fail; + } + + if (nxt_slow_path(nxt_str_dup(mp, &re->pattern, source) == NULL)) { + goto alloc_fail; + } + + re->code = pcre2_compile((PCRE2_SPTR)source->start, source->length, 0, + &errcode, &erroffset, compile_ctx); + if (nxt_slow_path(re->code == NULL)) { + err->offset = erroffset; + + ret = + pcre2_get_error_message(errcode, (PCRE2_UCHAR *)err->msg, ERR_BUF_SIZE); + if (ret < 0) { + (void)nxt_sprintf(err->msg, err->msg + ERR_BUF_SIZE, + "compilation failed with unknown " + "error code: %d%Z", + errcode); } - compile_ctx = pcre2_compile_context_create(general_ctx); - if (nxt_slow_path(compile_ctx == NULL)) { - goto alloc_fail; - } - - re = nxt_mp_get(mp, sizeof(nxt_regex_t)); - if (nxt_slow_path(re == NULL)) { - goto alloc_fail; - } - - if (nxt_slow_path(nxt_str_dup(mp, &re->pattern, source) == NULL)) { - goto alloc_fail; - } - - re->code = pcre2_compile((PCRE2_SPTR) source->start, source->length, 0, - &errcode, &erroffset, compile_ctx); - if (nxt_slow_path(re->code == NULL)) { - err->offset = erroffset; - - ret = pcre2_get_error_message(errcode, (PCRE2_UCHAR *) err->msg, - ERR_BUF_SIZE); - if (ret < 0) { - (void) nxt_sprintf(err->msg, err->msg + ERR_BUF_SIZE, - "compilation failed with unknown " - "error code: %d%Z", errcode); - } - - return NULL; - } + return NULL; + } #if 0 errcode = pcre2_jit_compile(re, PCRE2_JIT_COMPLETE); @@ -83,79 +80,65 @@ nxt_regex_compile(nxt_mp_t *mp, nxt_str_t *source, nxt_regex_err_t *err) } #endif - return re; + return re; alloc_fail: - err->offset = source->length; - nxt_memcpy(err->msg, alloc_error, sizeof(alloc_error)); + err->offset = source->length; + nxt_memcpy(err->msg, alloc_error, sizeof(alloc_error)); - return NULL; + return NULL; } - -static void * -nxt_pcre2_malloc(PCRE2_SIZE size, void *mp) -{ - return nxt_mp_get(mp, size); +static void *nxt_pcre2_malloc(PCRE2_SIZE size, void *mp) { + return nxt_mp_get(mp, size); } +static void nxt_pcre2_free(void *p, void *mp) {} -static void -nxt_pcre2_free(void *p, void *mp) -{ -} - +nxt_regex_match_t *nxt_regex_match_create(nxt_mp_t *mp, size_t size) { + nxt_regex_match_t *match; + pcre2_general_context *ctx; -nxt_regex_match_t * -nxt_regex_match_create(nxt_mp_t *mp, size_t size) -{ - nxt_regex_match_t *match; - pcre2_general_context *ctx; - - ctx = pcre2_general_context_create(nxt_pcre2_malloc, nxt_pcre2_free, mp); - if (nxt_slow_path(ctx == NULL)) { - nxt_thread_log_alert("pcre2_general_context_create() failed"); - return NULL; - } + ctx = pcre2_general_context_create(nxt_pcre2_malloc, nxt_pcre2_free, mp); + if (nxt_slow_path(ctx == NULL)) { + nxt_thread_log_alert("pcre2_general_context_create() failed"); + return NULL; + } - match = pcre2_match_data_create(size, ctx); - if (nxt_slow_path(match == NULL)) { - nxt_thread_log_alert("pcre2_match_data_create(%uz) failed", size); - return NULL; - } + match = pcre2_match_data_create(size, ctx); + if (nxt_slow_path(match == NULL)) { + nxt_thread_log_alert("pcre2_match_data_create(%uz) failed", size); + return NULL; + } - return match; + return match; } +nxt_int_t nxt_regex_match(nxt_regex_t *re, u_char *subject, size_t length, + nxt_regex_match_t *match) { + nxt_int_t ret; + PCRE2_UCHAR errptr[ERR_BUF_SIZE]; -nxt_int_t -nxt_regex_match(nxt_regex_t *re, u_char *subject, size_t length, - nxt_regex_match_t *match) -{ - nxt_int_t ret; - PCRE2_UCHAR errptr[ERR_BUF_SIZE]; + ret = pcre2_match(re->code, (PCRE2_SPTR)subject, length, 0, 0, match, NULL); - ret = pcre2_match(re->code, (PCRE2_SPTR) subject, length, 0, 0, match, - NULL); + if (nxt_slow_path(ret < PCRE2_ERROR_NOMATCH)) { - if (nxt_slow_path(ret < PCRE2_ERROR_NOMATCH)) { + if (pcre2_get_error_message(ret, errptr, ERR_BUF_SIZE) < 0) { + nxt_thread_log_error(NXT_LOG_ERR, + "pcre2_match() failed: %d on \"%*s\" " + "using \"%V\"", + ret, length, subject, &re->pattern); - if (pcre2_get_error_message(ret, errptr, ERR_BUF_SIZE) < 0) { - nxt_thread_log_error(NXT_LOG_ERR, - "pcre2_match() failed: %d on \"%*s\" " - "using \"%V\"", ret, length, subject, - &re->pattern); - - } else { - nxt_thread_log_error(NXT_LOG_ERR, - "pcre2_match() failed: %s (%d) on \"%*s\" " - "using \"%V\"", errptr, ret, length, subject, - &re->pattern); - } - - return NXT_ERROR; + } else { + nxt_thread_log_error(NXT_LOG_ERR, + "pcre2_match() failed: %s (%d) on \"%*s\" " + "using \"%V\"", + errptr, ret, length, subject, &re->pattern); } - return (ret != PCRE2_ERROR_NOMATCH); + return NXT_ERROR; + } + + return (ret != PCRE2_ERROR_NOMATCH); } diff --git a/src/nxt_php_sapi.c b/src/nxt_php_sapi.c index da667b660..e513696d8 100644 --- a/src/nxt_php_sapi.c +++ b/src/nxt_php_sapi.c @@ -16,7 +16,6 @@ #include #include - #if (PHP_VERSION_ID >= 50400) #define NXT_HAVE_PHP_IGNORE_CWD 1 #endif @@ -38,34 +37,31 @@ #ifndef TSRMLS_CC #define TSRMLS_CC #define TSRMLS_DC -#define TSRMLS_D void +#define TSRMLS_D void #define TSRMLS_C #endif - typedef struct { - nxt_str_t root; - nxt_str_t index; - nxt_str_t script_name; - nxt_str_t script_dirname; - nxt_str_t script_filename; + nxt_str_t root; + nxt_str_t index; + nxt_str_t script_name; + nxt_str_t script_dirname; + nxt_str_t script_filename; } nxt_php_target_t; - typedef struct { - char *cookie; - nxt_str_t *root; - nxt_str_t *index; - nxt_str_t path_info; - nxt_str_t script_name; - nxt_str_t script_filename; - nxt_str_t script_dirname; - nxt_unit_request_info_t *req; - - uint8_t chdir; /* 1 bit */ + char *cookie; + nxt_str_t *root; + nxt_str_t *index; + nxt_str_t path_info; + nxt_str_t script_name; + nxt_str_t script_filename; + nxt_str_t script_dirname; + nxt_unit_request_info_t *req; + + uint8_t chdir; /* 1 bit */ } nxt_php_run_ctx_t; - #if NXT_PHP8 typedef int (*nxt_php_disable_t)(const char *p, size_t size); #elif NXT_PHP7 @@ -78,23 +74,23 @@ typedef int (*nxt_php_disable_t)(char *p, uint TSRMLS_DC); typedef void (*zif_handler)(INTERNAL_FUNCTION_PARAMETERS); #endif - static nxt_int_t nxt_php_setup(nxt_task_t *task, nxt_process_t *process, - nxt_common_app_conf_t *conf); + nxt_common_app_conf_t *conf); static nxt_int_t nxt_php_start(nxt_task_t *task, nxt_process_data_t *data); static nxt_int_t nxt_php_set_target(nxt_task_t *task, nxt_php_target_t *target, - nxt_conf_value_t *conf); + nxt_conf_value_t *conf); static nxt_int_t nxt_php_set_ini_path(nxt_task_t *task, nxt_str_t *path, - char *workdir); + char *workdir); static void nxt_php_set_options(nxt_task_t *task, nxt_conf_value_t *options, - int type); + int type); static nxt_int_t nxt_php_alter_option(nxt_str_t *name, nxt_str_t *value, - int type); + int type); #ifdef NXT_PHP8 static void nxt_php_disable_functions(nxt_str_t *str); #endif static void nxt_php_disable(nxt_task_t *task, const char *type, - nxt_str_t *value, char **ptr, nxt_php_disable_t disable); + nxt_str_t *value, char **ptr, + nxt_php_disable_t disable); static nxt_int_t nxt_php_dirname(const nxt_str_t *file, nxt_str_t *dir); static void nxt_php_str_trim_trail(nxt_str_t *str, u_char t); @@ -106,10 +102,10 @@ static nxt_int_t nxt_php_handle_fs_err(nxt_unit_request_info_t *req); static void nxt_php_request_handler(nxt_unit_request_info_t *req); static void nxt_php_dynamic_request(nxt_php_run_ctx_t *ctx, - nxt_unit_request_t *r); + nxt_unit_request_t *r); #if (PHP_VERSION_ID < 70400) static void nxt_zend_stream_init_fp(zend_file_handle *handle, FILE *fp, - const char *filename); + const char *filename); #endif static void nxt_php_execute(nxt_php_run_ctx_t *ctx, nxt_unit_request_t *r); nxt_inline void nxt_php_vcwd_chdir(nxt_unit_request_info_t *req, u_char *dir); @@ -117,14 +113,16 @@ nxt_inline void nxt_php_vcwd_chdir(nxt_unit_request_info_t *req, u_char *dir); static int nxt_php_startup(sapi_module_struct *sapi_module); static int nxt_php_send_headers(sapi_headers_struct *sapi_headers TSRMLS_DC); static void *nxt_php_hash_str_find_ptr(const HashTable *ht, - const nxt_str_t *str); + const nxt_str_t *str); static char *nxt_php_read_cookies(TSRMLS_D); static void nxt_php_set_sptr(nxt_unit_request_info_t *req, const char *name, - nxt_unit_sptr_t *v, uint32_t len, zval *track_vars_array TSRMLS_DC); + nxt_unit_sptr_t *v, uint32_t len, + zval *track_vars_array TSRMLS_DC); nxt_inline void nxt_php_set_str(nxt_unit_request_info_t *req, const char *name, - nxt_str_t *s, zval *track_vars_array TSRMLS_DC); + nxt_str_t *s, zval *track_vars_array TSRMLS_DC); static void nxt_php_set_cstr(nxt_unit_request_info_t *req, const char *name, - const char *str, uint32_t len, zval *track_vars_array TSRMLS_DC); + const char *str, uint32_t len, + zval *track_vars_array TSRMLS_DC); static void nxt_php_register_variables(zval *track_vars_array TSRMLS_DC); #if NXT_PHP8 static void nxt_php_log_message(const char *message, int syslog_type_int); @@ -138,14 +136,13 @@ static void nxt_php_log_message(char *message TSRMLS_DC); #ifdef NXT_PHP7 static size_t nxt_php_unbuffered_write(const char *str, - size_t str_length TSRMLS_DC); + size_t str_length TSRMLS_DC); static size_t nxt_php_read_post(char *buffer, size_t count_bytes TSRMLS_DC); #else static int nxt_php_unbuffered_write(const char *str, uint str_length TSRMLS_DC); static int nxt_php_read_post(char *buffer, uint count_bytes TSRMLS_DC); #endif - #ifdef NXT_PHP7 #if (PHP_VERSION_ID < 70200) ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_fastcgi_finish_request, 0, 0, @@ -164,232 +161,207 @@ ZEND_FUNCTION(fastcgi_finish_request); PHP_MINIT_FUNCTION(nxt_php_ext); ZEND_NAMED_FUNCTION(nxt_php_chdir); +static const zend_function_entry nxt_php_ext_functions[] = {ZEND_FE( + fastcgi_finish_request, arginfo_fastcgi_finish_request) ZEND_FE_END}; -static const zend_function_entry nxt_php_ext_functions[] = { - ZEND_FE(fastcgi_finish_request, arginfo_fastcgi_finish_request) - ZEND_FE_END -}; - - -zif_handler nxt_php_chdir_handler; -zend_auto_global *nxt_php_server_ag; - +zif_handler nxt_php_chdir_handler; +zend_auto_global *nxt_php_server_ag; -static zend_module_entry nxt_php_unit_module = { +static zend_module_entry nxt_php_unit_module = { STANDARD_MODULE_HEADER, "unit", - nxt_php_ext_functions, /* function table */ - PHP_MINIT(nxt_php_ext), /* initialization */ - NULL, /* shutdown */ - NULL, /* request initialization */ - NULL, /* request shutdown */ - NULL, /* information */ + nxt_php_ext_functions, /* function table */ + PHP_MINIT(nxt_php_ext), /* initialization */ + NULL, /* shutdown */ + NULL, /* request initialization */ + NULL, /* request shutdown */ + NULL, /* information */ NXT_VERSION, - STANDARD_MODULE_PROPERTIES -}; + STANDARD_MODULE_PROPERTIES}; +PHP_MINIT_FUNCTION(nxt_php_ext) { + zend_function *func; -PHP_MINIT_FUNCTION(nxt_php_ext) -{ - zend_function *func; + static const nxt_str_t chdir = nxt_string("chdir"); - static const nxt_str_t chdir = nxt_string("chdir"); + func = nxt_php_hash_str_find_ptr(CG(function_table), &chdir); + if (nxt_slow_path(func == NULL)) { + return FAILURE; + } - func = nxt_php_hash_str_find_ptr(CG(function_table), &chdir); - if (nxt_slow_path(func == NULL)) { - return FAILURE; - } + nxt_php_chdir_handler = func->internal_function.handler; + func->internal_function.handler = nxt_php_chdir; - nxt_php_chdir_handler = func->internal_function.handler; - func->internal_function.handler = nxt_php_chdir; - - return SUCCESS; + return SUCCESS; } +ZEND_NAMED_FUNCTION(nxt_php_chdir) { + nxt_php_run_ctx_t *ctx; -ZEND_NAMED_FUNCTION(nxt_php_chdir) -{ - nxt_php_run_ctx_t *ctx; + ctx = SG(server_context); - ctx = SG(server_context); - - if (nxt_fast_path(ctx != NULL)) { - ctx->chdir = 1; - } + if (nxt_fast_path(ctx != NULL)) { + ctx->chdir = 1; + } - nxt_php_chdir_handler(INTERNAL_FUNCTION_PARAM_PASSTHRU); + nxt_php_chdir_handler(INTERNAL_FUNCTION_PARAM_PASSTHRU); } +PHP_FUNCTION(fastcgi_finish_request) { + zend_auto_global *ag; + nxt_php_run_ctx_t *ctx; -PHP_FUNCTION(fastcgi_finish_request) -{ - zend_auto_global *ag; - nxt_php_run_ctx_t *ctx; - - if (nxt_slow_path(zend_parse_parameters_none() == FAILURE)) { + if (nxt_slow_path(zend_parse_parameters_none() == FAILURE)) { #ifdef NXT_PHP8 - RETURN_THROWS(); + RETURN_THROWS(); #else - return; + return; #endif - } + } - ctx = SG(server_context); + ctx = SG(server_context); - if (nxt_slow_path(ctx == NULL || ctx->req == NULL)) { - RETURN_FALSE; - } + if (nxt_slow_path(ctx == NULL || ctx->req == NULL)) { + RETURN_FALSE; + } #ifdef NXT_PHP7 - php_output_end_all(); - php_header(); + php_output_end_all(); + php_header(); #else #ifdef PHP_OUTPUT_NEWAPI - php_output_end_all(TSRMLS_C); + php_output_end_all(TSRMLS_C); #else - php_end_ob_buffers(1 TSRMLS_CC); + php_end_ob_buffers(1 TSRMLS_CC); #endif - php_header(TSRMLS_C); + php_header(TSRMLS_C); #endif - ag = nxt_php_server_ag; + ag = nxt_php_server_ag; - if (ag->armed) { + if (ag->armed) { #ifdef NXT_PHP7 - ag->armed = ag->auto_global_callback(ag->name); + ag->armed = ag->auto_global_callback(ag->name); #else - ag->armed = ag->auto_global_callback(ag->name, ag->name_len TSRMLS_CC); + ag->armed = ag->auto_global_callback(ag->name, ag->name_len TSRMLS_CC); #endif - } + } - nxt_unit_request_done(ctx->req, NXT_UNIT_OK); - ctx->req = NULL; + nxt_unit_request_done(ctx->req, NXT_UNIT_OK); + ctx->req = NULL; - PG(connection_status) = PHP_CONNECTION_ABORTED; + PG(connection_status) = PHP_CONNECTION_ABORTED; #ifdef NXT_PHP7 - php_output_set_status(PHP_OUTPUT_DISABLED); + php_output_set_status(PHP_OUTPUT_DISABLED); #else #ifdef PHP_OUTPUT_NEWAPI - php_output_set_status(PHP_OUTPUT_DISABLED TSRMLS_CC); + php_output_set_status(PHP_OUTPUT_DISABLED TSRMLS_CC); #else - php_output_set_status(0 TSRMLS_CC); + php_output_set_status(0 TSRMLS_CC); #endif #endif - RETURN_TRUE; + RETURN_TRUE; } - -static sapi_module_struct nxt_php_sapi_module = -{ - (char *) "cli-server", - (char *) "unit", +static sapi_module_struct nxt_php_sapi_module = { + (char *)"cli-server", + (char *)"unit", nxt_php_startup, /* startup */ php_module_shutdown_wrapper, /* shutdown */ - NULL, /* activate */ - NULL, /* deactivate */ + NULL, /* activate */ + NULL, /* deactivate */ - nxt_php_unbuffered_write, /* unbuffered write */ - NULL, /* flush */ - NULL, /* get uid */ - NULL, /* getenv */ + nxt_php_unbuffered_write, /* unbuffered write */ + NULL, /* flush */ + NULL, /* get uid */ + NULL, /* getenv */ - php_error, /* error handler */ + php_error, /* error handler */ - NULL, /* header handler */ - nxt_php_send_headers, /* send headers handler */ - NULL, /* send header handler */ + NULL, /* header handler */ + nxt_php_send_headers, /* send headers handler */ + NULL, /* send header handler */ - nxt_php_read_post, /* read POST data */ - nxt_php_read_cookies, /* read Cookies */ + nxt_php_read_post, /* read POST data */ + nxt_php_read_cookies, /* read Cookies */ - nxt_php_register_variables, /* register server variables */ - nxt_php_log_message, /* log message */ - NULL, /* get request time */ - NULL, /* terminate process */ + nxt_php_register_variables, /* register server variables */ + nxt_php_log_message, /* log message */ + NULL, /* get request time */ + NULL, /* terminate process */ - NULL, /* php_ini_path_override */ + NULL, /* php_ini_path_override */ #ifdef NXT_HAVE_PHP_INTERRUPTS - NULL, /* block_interruptions */ - NULL, /* unblock_interruptions */ + NULL, /* block_interruptions */ + NULL, /* unblock_interruptions */ #endif - NULL, /* default_post_reader */ - NULL, /* treat_data */ - NULL, /* executable_location */ + NULL, /* default_post_reader */ + NULL, /* treat_data */ + NULL, /* executable_location */ - 0, /* php_ini_ignore */ + 0, /* php_ini_ignore */ #ifdef NXT_HAVE_PHP_IGNORE_CWD - 1, /* php_ini_ignore_cwd */ + 1, /* php_ini_ignore_cwd */ #endif - NULL, /* get_fd */ + NULL, /* get_fd */ - NULL, /* force_http_10 */ + NULL, /* force_http_10 */ - NULL, /* get_target_uid */ - NULL, /* get_target_gid */ + NULL, /* get_target_uid */ + NULL, /* get_target_gid */ - NULL, /* input_filter */ + NULL, /* input_filter */ - NULL, /* ini_defaults */ - 0, /* phpinfo_as_text */ + NULL, /* ini_defaults */ + 0, /* phpinfo_as_text */ - NULL, /* ini_entries */ - NULL, /* additional_functions */ - NULL /* input_filter_init */ + NULL, /* ini_entries */ + NULL, /* additional_functions */ + NULL /* input_filter_init */ }; - -static uint32_t compat[] = { - NXT_VERNUM, NXT_DEBUG, +static uint32_t compat[] = { + NXT_VERNUM, + NXT_DEBUG, }; - -NXT_EXPORT nxt_app_module_t nxt_app_module = { - sizeof(compat), - compat, - nxt_string("php"), - PHP_VERSION, - NULL, - 0, - nxt_php_setup, - nxt_php_start, +NXT_EXPORT nxt_app_module_t nxt_app_module = { + sizeof(compat), compat, nxt_string("php"), PHP_VERSION, + NULL, 0, nxt_php_setup, nxt_php_start, }; +static nxt_php_target_t *nxt_php_targets; +static nxt_int_t nxt_php_last_target = -1; -static nxt_php_target_t *nxt_php_targets; -static nxt_int_t nxt_php_last_target = -1; - -static nxt_unit_ctx_t *nxt_php_unit_ctx; +static nxt_unit_ctx_t *nxt_php_unit_ctx; #if defined(ZTS) && (PHP_VERSION_ID < 70400) -static void ***tsrm_ls; +static void ***tsrm_ls; #endif +static nxt_int_t nxt_php_setup(nxt_task_t *task, nxt_process_t *process, + nxt_common_app_conf_t *conf) { + nxt_str_t ini_path; + nxt_int_t ret; + nxt_conf_value_t *value; + nxt_php_app_conf_t *c; -static nxt_int_t -nxt_php_setup(nxt_task_t *task, nxt_process_t *process, - nxt_common_app_conf_t *conf) -{ - nxt_str_t ini_path; - nxt_int_t ret; - nxt_conf_value_t *value; - nxt_php_app_conf_t *c; - - static const nxt_str_t file_str = nxt_string("file"); - static const nxt_str_t user_str = nxt_string("user"); - static const nxt_str_t admin_str = nxt_string("admin"); + static const nxt_str_t file_str = nxt_string("file"); + static const nxt_str_t user_str = nxt_string("user"); + static const nxt_str_t admin_str = nxt_string("admin"); - c = &conf->u.php; + c = &conf->u.php; #ifdef ZTS #if (PHP_VERSION_ID >= 70400) - php_tsrm_startup(); + php_tsrm_startup(); #else - tsrm_startup(1, 1, 0, NULL); - tsrm_ls = ts_resource(0); + tsrm_startup(1, 1, 0, NULL); + tsrm_ls = ts_resource(0); #endif #endif @@ -397,1245 +369,1137 @@ nxt_php_setup(nxt_task_t *task, nxt_process_t *process, #if defined(NXT_PHP7) && defined(ZEND_SIGNALS) #if (NXT_ZEND_SIGNAL_STARTUP) - zend_signal_startup(); + zend_signal_startup(); #elif defined(ZTS) #error PHP is built with thread safety and broken signals. #endif #endif - sapi_startup(&nxt_php_sapi_module); - - if (c->options != NULL) { - value = nxt_conf_get_object_member(c->options, &file_str, NULL); + sapi_startup(&nxt_php_sapi_module); - if (value != NULL) { - nxt_conf_get_string(value, &ini_path); + if (c->options != NULL) { + value = nxt_conf_get_object_member(c->options, &file_str, NULL); - ret = nxt_php_set_ini_path(task, &ini_path, - conf->working_directory); + if (value != NULL) { + nxt_conf_get_string(value, &ini_path); - if (nxt_slow_path(ret != NXT_OK)) { - return NXT_ERROR; - } - } - } + ret = nxt_php_set_ini_path(task, &ini_path, conf->working_directory); - if (nxt_slow_path(nxt_php_startup(&nxt_php_sapi_module) == FAILURE)) { - nxt_alert(task, "failed to initialize SAPI module and extension"); + if (nxt_slow_path(ret != NXT_OK)) { return NXT_ERROR; + } } + } - if (c->options != NULL) { - value = nxt_conf_get_object_member(c->options, &admin_str, NULL); - nxt_php_set_options(task, value, ZEND_INI_SYSTEM); + if (nxt_slow_path(nxt_php_startup(&nxt_php_sapi_module) == FAILURE)) { + nxt_alert(task, "failed to initialize SAPI module and extension"); + return NXT_ERROR; + } - value = nxt_conf_get_object_member(c->options, &user_str, NULL); - nxt_php_set_options(task, value, ZEND_INI_USER); - } + if (c->options != NULL) { + value = nxt_conf_get_object_member(c->options, &admin_str, NULL); + nxt_php_set_options(task, value, ZEND_INI_SYSTEM); + + value = nxt_conf_get_object_member(c->options, &user_str, NULL); + nxt_php_set_options(task, value, ZEND_INI_USER); + } #ifdef NXT_PHP7 - nxt_php_server_ag = zend_hash_str_find_ptr(CG(auto_globals), "_SERVER", - nxt_length("_SERVER")); + nxt_php_server_ag = zend_hash_str_find_ptr(CG(auto_globals), "_SERVER", + nxt_length("_SERVER")); #else - zend_hash_quick_find(CG(auto_globals), "_SERVER", sizeof("_SERVER"), - zend_hash_func("_SERVER", sizeof("_SERVER")), - (void **) &nxt_php_server_ag); + zend_hash_quick_find(CG(auto_globals), "_SERVER", sizeof("_SERVER"), + zend_hash_func("_SERVER", sizeof("_SERVER")), + (void **)&nxt_php_server_ag); #endif - if (nxt_slow_path(nxt_php_server_ag == NULL)) { - nxt_alert(task, "failed to find $_SERVER auto global"); - return NXT_ERROR; - } + if (nxt_slow_path(nxt_php_server_ag == NULL)) { + nxt_alert(task, "failed to find $_SERVER auto global"); + return NXT_ERROR; + } - return NXT_OK; + return NXT_OK; } - -static nxt_int_t -nxt_php_start(nxt_task_t *task, nxt_process_data_t *data) -{ - uint32_t next; - nxt_int_t ret; - nxt_str_t name; - nxt_uint_t n; - nxt_unit_ctx_t *unit_ctx; - nxt_unit_init_t php_init; - nxt_conf_value_t *value; - nxt_php_app_conf_t *c; - nxt_common_app_conf_t *conf; - - conf = data->app; - c = &conf->u.php; - - n = (c->targets != NULL) ? nxt_conf_object_members_count(c->targets) : 1; - - nxt_php_targets = nxt_zalloc(sizeof(nxt_php_target_t) * n); - if (nxt_slow_path(nxt_php_targets == NULL)) { +static nxt_int_t nxt_php_start(nxt_task_t *task, nxt_process_data_t *data) { + uint32_t next; + nxt_int_t ret; + nxt_str_t name; + nxt_uint_t n; + nxt_unit_ctx_t *unit_ctx; + nxt_unit_init_t php_init; + nxt_conf_value_t *value; + nxt_php_app_conf_t *c; + nxt_common_app_conf_t *conf; + + conf = data->app; + c = &conf->u.php; + + n = (c->targets != NULL) ? nxt_conf_object_members_count(c->targets) : 1; + + nxt_php_targets = nxt_zalloc(sizeof(nxt_php_target_t) * n); + if (nxt_slow_path(nxt_php_targets == NULL)) { + return NXT_ERROR; + } + + if (c->targets != NULL) { + next = 0; + + for (n = 0; /* void */; n++) { + value = nxt_conf_next_object_member(c->targets, &name, &next); + if (value == NULL) { + break; + } + + ret = nxt_php_set_target(task, &nxt_php_targets[n], value); + if (nxt_slow_path(ret != NXT_OK)) { return NXT_ERROR; + } } - if (c->targets != NULL) { - next = 0; + } else { + ret = nxt_php_set_target(task, &nxt_php_targets[0], conf->self); + if (nxt_slow_path(ret != NXT_OK)) { + return NXT_ERROR; + } + } - for (n = 0; /* void */; n++) { - value = nxt_conf_next_object_member(c->targets, &name, &next); - if (value == NULL) { - break; - } + ret = nxt_unit_default_init(task, &php_init, conf); + if (nxt_slow_path(ret != NXT_OK)) { + nxt_alert(task, "nxt_unit_default_init() failed"); + return ret; + } - ret = nxt_php_set_target(task, &nxt_php_targets[n], value); - if (nxt_slow_path(ret != NXT_OK)) { - return NXT_ERROR; - } - } + php_init.callbacks.request_handler = nxt_php_request_handler; - } else { - ret = nxt_php_set_target(task, &nxt_php_targets[0], conf->self); - if (nxt_slow_path(ret != NXT_OK)) { - return NXT_ERROR; - } - } + unit_ctx = nxt_unit_init(&php_init); + if (nxt_slow_path(unit_ctx == NULL)) { + return NXT_ERROR; + } - ret = nxt_unit_default_init(task, &php_init, conf); - if (nxt_slow_path(ret != NXT_OK)) { - nxt_alert(task, "nxt_unit_default_init() failed"); - return ret; - } + nxt_php_unit_ctx = unit_ctx; - php_init.callbacks.request_handler = nxt_php_request_handler; + nxt_unit_run(nxt_php_unit_ctx); + nxt_unit_done(nxt_php_unit_ctx); - unit_ctx = nxt_unit_init(&php_init); - if (nxt_slow_path(unit_ctx == NULL)) { - return NXT_ERROR; - } + exit(0); - nxt_php_unit_ctx = unit_ctx; + return NXT_OK; +} - nxt_unit_run(nxt_php_unit_ctx); - nxt_unit_done(nxt_php_unit_ctx); +static nxt_int_t nxt_php_set_target(nxt_task_t *task, nxt_php_target_t *target, + nxt_conf_value_t *conf) { + u_char *tmp, *p; + nxt_str_t str; + nxt_int_t ret; + nxt_conf_value_t *value; - exit(0); + static const nxt_str_t root_str = nxt_string("root"); + static const nxt_str_t script_str = nxt_string("script"); + static const nxt_str_t index_str = nxt_string("index"); - return NXT_OK; -} + value = nxt_conf_get_object_member(conf, &root_str, NULL); + nxt_conf_get_string(value, &str); -static nxt_int_t -nxt_php_set_target(nxt_task_t *task, nxt_php_target_t *target, - nxt_conf_value_t *conf) -{ - u_char *tmp, *p; - nxt_str_t str; - nxt_int_t ret; - nxt_conf_value_t *value; + tmp = nxt_malloc(str.length + 1); + if (nxt_slow_path(tmp == NULL)) { + return NXT_ERROR; + } + + p = tmp; + + p = nxt_cpymem(p, str.start, str.length); + *p = '\0'; + + p = nxt_realpath(tmp); + if (nxt_slow_path(p == NULL)) { + nxt_alert(task, "root realpath(%s) failed %E", tmp, nxt_errno); + return NXT_ERROR; + } + + nxt_free(tmp); - static const nxt_str_t root_str = nxt_string("root"); - static const nxt_str_t script_str = nxt_string("script"); - static const nxt_str_t index_str = nxt_string("index"); + target->root.length = nxt_strlen(p); + target->root.start = p; - value = nxt_conf_get_object_member(conf, &root_str, NULL); + nxt_php_str_trim_trail(&target->root, '/'); + value = nxt_conf_get_object_member(conf, &script_str, NULL); + + if (value != NULL) { nxt_conf_get_string(value, &str); - tmp = nxt_malloc(str.length + 1); + nxt_php_str_trim_lead(&str, '/'); + + tmp = nxt_malloc(target->root.length + 1 + str.length + 1); if (nxt_slow_path(tmp == NULL)) { - return NXT_ERROR; + return NXT_ERROR; } p = tmp; + p = nxt_cpymem(p, target->root.start, target->root.length); + *p++ = '/'; + p = nxt_cpymem(p, str.start, str.length); *p = '\0'; p = nxt_realpath(tmp); if (nxt_slow_path(p == NULL)) { - nxt_alert(task, "root realpath(%s) failed %E", tmp, nxt_errno); - return NXT_ERROR; + nxt_alert(task, "script realpath(%s) failed %E", tmp, nxt_errno); + return NXT_ERROR; } nxt_free(tmp); - target->root.length = nxt_strlen(p); - target->root.start = p; - - nxt_php_str_trim_trail(&target->root, '/'); - - value = nxt_conf_get_object_member(conf, &script_str, NULL); - - if (value != NULL) { - nxt_conf_get_string(value, &str); - - nxt_php_str_trim_lead(&str, '/'); - - tmp = nxt_malloc(target->root.length + 1 + str.length + 1); - if (nxt_slow_path(tmp == NULL)) { - return NXT_ERROR; - } + target->script_filename.length = nxt_strlen(p); + target->script_filename.start = p; - p = tmp; + if (!nxt_str_start(&target->script_filename, target->root.start, + target->root.length)) { + nxt_alert(task, "script is not under php root"); + return NXT_ERROR; + } - p = nxt_cpymem(p, target->root.start, target->root.length); - *p++ = '/'; + ret = nxt_php_dirname(&target->script_filename, &target->script_dirname); + if (nxt_slow_path(ret != NXT_OK)) { + return NXT_ERROR; + } - p = nxt_cpymem(p, str.start, str.length); - *p = '\0'; + target->script_name.length = + target->script_filename.length - target->root.length; + target->script_name.start = + target->script_filename.start + target->root.length; - p = nxt_realpath(tmp); - if (nxt_slow_path(p == NULL)) { - nxt_alert(task, "script realpath(%s) failed %E", tmp, nxt_errno); - return NXT_ERROR; - } + } else { + value = nxt_conf_get_object_member(conf, &index_str, NULL); - nxt_free(tmp); - - target->script_filename.length = nxt_strlen(p); - target->script_filename.start = p; + if (value != NULL) { + nxt_conf_get_string(value, &str); - if (!nxt_str_start(&target->script_filename, - target->root.start, target->root.length)) - { - nxt_alert(task, "script is not under php root"); - return NXT_ERROR; - } + tmp = nxt_malloc(str.length); + if (nxt_slow_path(tmp == NULL)) { + return NXT_ERROR; + } - ret = nxt_php_dirname(&target->script_filename, - &target->script_dirname); - if (nxt_slow_path(ret != NXT_OK)) { - return NXT_ERROR; - } + nxt_memcpy(tmp, str.start, str.length); - target->script_name.length = target->script_filename.length - - target->root.length; - target->script_name.start = target->script_filename.start - + target->root.length; + target->index.length = str.length; + target->index.start = tmp; } else { - value = nxt_conf_get_object_member(conf, &index_str, NULL); - - if (value != NULL) { - nxt_conf_get_string(value, &str); - - tmp = nxt_malloc(str.length); - if (nxt_slow_path(tmp == NULL)) { - return NXT_ERROR; - } - - nxt_memcpy(tmp, str.start, str.length); - - target->index.length = str.length; - target->index.start = tmp; - - } else { - nxt_str_set(&target->index, "index.php"); - } + nxt_str_set(&target->index, "index.php"); } + } - return NXT_OK; + return NXT_OK; } +static nxt_int_t nxt_php_set_ini_path(nxt_task_t *task, nxt_str_t *ini_path, + char *workdir) { + size_t wdlen; + u_char *p, *start; -static nxt_int_t -nxt_php_set_ini_path(nxt_task_t *task, nxt_str_t *ini_path, char *workdir) -{ - size_t wdlen; - u_char *p, *start; - - if (ini_path->start[0] == '/' || workdir == NULL) { - p = nxt_malloc(ini_path->length + 1); - if (nxt_slow_path(p == NULL)) { - return NXT_ERROR; - } + if (ini_path->start[0] == '/' || workdir == NULL) { + p = nxt_malloc(ini_path->length + 1); + if (nxt_slow_path(p == NULL)) { + return NXT_ERROR; + } - start = p; + start = p; - } else { - wdlen = nxt_strlen(workdir); + } else { + wdlen = nxt_strlen(workdir); - p = nxt_malloc(wdlen + ini_path->length + 2); - if (nxt_slow_path(p == NULL)) { - return NXT_ERROR; - } + p = nxt_malloc(wdlen + ini_path->length + 2); + if (nxt_slow_path(p == NULL)) { + return NXT_ERROR; + } - start = p; + start = p; - p = nxt_cpymem(p, workdir, wdlen); + p = nxt_cpymem(p, workdir, wdlen); - if (workdir[wdlen - 1] != '/') { - *p++ = '/'; - } + if (workdir[wdlen - 1] != '/') { + *p++ = '/'; } + } - p = nxt_cpymem(p, ini_path->start, ini_path->length); - *p = '\0'; + p = nxt_cpymem(p, ini_path->start, ini_path->length); + *p = '\0'; - nxt_php_sapi_module.php_ini_path_override = (char *) start; + nxt_php_sapi_module.php_ini_path_override = (char *)start; - return NXT_OK; + return NXT_OK; } +static void nxt_php_set_options(nxt_task_t *task, nxt_conf_value_t *options, + int type) { + uint32_t next; + nxt_str_t name, value; + nxt_conf_value_t *value_obj; -static void -nxt_php_set_options(nxt_task_t *task, nxt_conf_value_t *options, int type) -{ - uint32_t next; - nxt_str_t name, value; - nxt_conf_value_t *value_obj; - - if (options != NULL) { - next = 0; + if (options != NULL) { + next = 0; - for ( ;; ) { - value_obj = nxt_conf_next_object_member(options, &name, &next); - if (value_obj == NULL) { - break; - } + for (;;) { + value_obj = nxt_conf_next_object_member(options, &name, &next); + if (value_obj == NULL) { + break; + } - nxt_conf_get_string(value_obj, &value); + nxt_conf_get_string(value_obj, &value); - if (nxt_php_alter_option(&name, &value, type) != NXT_OK) { - nxt_log(task, NXT_LOG_ERR, - "setting PHP option \"%V: %V\" failed", &name, &value); - continue; - } + if (nxt_php_alter_option(&name, &value, type) != NXT_OK) { + nxt_log(task, NXT_LOG_ERR, "setting PHP option \"%V: %V\" failed", + &name, &value); + continue; + } - if (nxt_str_eq(&name, "disable_functions", 17)) { + if (nxt_str_eq(&name, "disable_functions", 17)) { #ifdef NXT_PHP8 - nxt_php_disable_functions(&value); + nxt_php_disable_functions(&value); #else - nxt_php_disable(task, "function", &value, - &PG(disable_functions), - zend_disable_function); + nxt_php_disable(task, "function", &value, &PG(disable_functions), + zend_disable_function); #endif - continue; - } - - if (nxt_str_eq(&name, "disable_classes", 15)) { - nxt_php_disable(task, "class", &value, - &PG(disable_classes), - zend_disable_class); - continue; - } - } + continue; + } + + if (nxt_str_eq(&name, "disable_classes", 15)) { + nxt_php_disable(task, "class", &value, &PG(disable_classes), + zend_disable_class); + continue; + } } + } } - #ifdef NXT_PHP7 -static nxt_int_t -nxt_php_alter_option(nxt_str_t *name, nxt_str_t *value, int type) -{ - zend_string *zs; - zend_ini_entry *ini_entry; - - ini_entry = nxt_php_hash_str_find_ptr(EG(ini_directives), name); - if (nxt_slow_path(ini_entry == NULL)) { - return NXT_ERROR; - } - - /* PHP exits on memory allocation errors. */ - zs = zend_string_init((char *) value->start, value->length, 1); - - if (ini_entry->on_modify - && ini_entry->on_modify(ini_entry, zs, ini_entry->mh_arg1, - ini_entry->mh_arg2, ini_entry->mh_arg3, - ZEND_INI_STAGE_ACTIVATE) - != SUCCESS) - { - zend_string_release(zs); - return NXT_ERROR; - } - - ini_entry->value = zs; - ini_entry->modifiable = type; - - return NXT_OK; +static nxt_int_t nxt_php_alter_option(nxt_str_t *name, nxt_str_t *value, + int type) { + zend_string *zs; + zend_ini_entry *ini_entry; + + ini_entry = nxt_php_hash_str_find_ptr(EG(ini_directives), name); + if (nxt_slow_path(ini_entry == NULL)) { + return NXT_ERROR; + } + + /* PHP exits on memory allocation errors. */ + zs = zend_string_init((char *)value->start, value->length, 1); + + if (ini_entry->on_modify && + ini_entry->on_modify(ini_entry, zs, ini_entry->mh_arg1, + ini_entry->mh_arg2, ini_entry->mh_arg3, + ZEND_INI_STAGE_ACTIVATE) != SUCCESS) { + zend_string_release(zs); + return NXT_ERROR; + } + + ini_entry->value = zs; + ini_entry->modifiable = type; + + return NXT_OK; } -#else /* PHP 5. */ - -static nxt_int_t -nxt_php_alter_option(nxt_str_t *name, nxt_str_t *value, int type) -{ - char *cstr; - zend_ini_entry *ini_entry; - - ini_entry = nxt_php_hash_str_find_ptr(EG(ini_directives), name); - if (nxt_slow_path(ini_entry == NULL)) { - return NXT_ERROR; - } - - cstr = nxt_malloc(value->length + 1); - if (nxt_slow_path(cstr == NULL)) { - return NXT_ERROR; - } - - nxt_memcpy(cstr, value->start, value->length); - cstr[value->length] = '\0'; - - if (ini_entry->on_modify - && ini_entry->on_modify(ini_entry, cstr, value->length, - ini_entry->mh_arg1, ini_entry->mh_arg2, - ini_entry->mh_arg3, ZEND_INI_STAGE_ACTIVATE - TSRMLS_CC) - != SUCCESS) - { - nxt_free(cstr); - return NXT_ERROR; - } - - ini_entry->value = cstr; - ini_entry->value_length = value->length; - ini_entry->modifiable = type; +#else /* PHP 5. */ - return NXT_OK; +static nxt_int_t nxt_php_alter_option(nxt_str_t *name, nxt_str_t *value, + int type) { + char *cstr; + zend_ini_entry *ini_entry; + + ini_entry = nxt_php_hash_str_find_ptr(EG(ini_directives), name); + if (nxt_slow_path(ini_entry == NULL)) { + return NXT_ERROR; + } + + cstr = nxt_malloc(value->length + 1); + if (nxt_slow_path(cstr == NULL)) { + return NXT_ERROR; + } + + nxt_memcpy(cstr, value->start, value->length); + cstr[value->length] = '\0'; + + if (ini_entry->on_modify && + ini_entry->on_modify(ini_entry, cstr, value->length, ini_entry->mh_arg1, + ini_entry->mh_arg2, ini_entry->mh_arg3, + ZEND_INI_STAGE_ACTIVATE TSRMLS_CC) != SUCCESS) { + nxt_free(cstr); + return NXT_ERROR; + } + + ini_entry->value = cstr; + ini_entry->value_length = value->length; + ini_entry->modifiable = type; + + return NXT_OK; } #endif - #ifdef NXT_PHP8 -static void -nxt_php_disable_functions(nxt_str_t *str) -{ - char *p; +static void nxt_php_disable_functions(nxt_str_t *str) { + char *p; - p = nxt_malloc(str->length + 1); - if (nxt_slow_path(p == NULL)) { - return; - } + p = nxt_malloc(str->length + 1); + if (nxt_slow_path(p == NULL)) { + return; + } - nxt_memcpy(p, str->start, str->length); - p[str->length] = '\0'; + nxt_memcpy(p, str->start, str->length); + p[str->length] = '\0'; - zend_disable_functions(p); + zend_disable_functions(p); - nxt_free(p); + nxt_free(p); } #endif +static void nxt_php_disable(nxt_task_t *task, const char *type, + nxt_str_t *value, char **ptr, + nxt_php_disable_t disable) { + char c, *p, *start; -static void -nxt_php_disable(nxt_task_t *task, const char *type, nxt_str_t *value, - char **ptr, nxt_php_disable_t disable) -{ - char c, *p, *start; - - p = nxt_malloc(value->length + 1); - if (nxt_slow_path(p == NULL)) { - return; - } + p = nxt_malloc(value->length + 1); + if (nxt_slow_path(p == NULL)) { + return; + } - /* - * PHP frees this memory on module shutdown. - * See core_globals_dtor() for details. - */ - *ptr = p; + /* + * PHP frees this memory on module shutdown. + * See core_globals_dtor() for details. + */ + *ptr = p; - nxt_memcpy(p, value->start, value->length); - p[value->length] = '\0'; + nxt_memcpy(p, value->start, value->length); + p[value->length] = '\0'; - start = p; + start = p; - do { - c = *p; + do { + c = *p; - if (c == ' ' || c == ',' || c == '\0') { + if (c == ' ' || c == ',' || c == '\0') { - if (p != start) { - *p = '\0'; + if (p != start) { + *p = '\0'; #ifdef NXT_PHP7 - if (disable(start, p - start) + if (disable(start, p - start) #else - if (disable(start, p - start TSRMLS_CC) + if (disable(start, p - start TSRMLS_CC) #endif - != SUCCESS) - { - nxt_log(task, NXT_LOG_ERR, - "PHP: failed to disable \"%s\": no such %s", - start, type); - } - } - - start = p + 1; + != SUCCESS) { + nxt_log(task, NXT_LOG_ERR, + "PHP: failed to disable \"%s\": no such %s", start, type); } + } + + start = p + 1; + } - p++; + p++; - } while (c != '\0'); + } while (c != '\0'); } +static nxt_int_t nxt_php_dirname(const nxt_str_t *file, nxt_str_t *dir) { + size_t length; -static nxt_int_t -nxt_php_dirname(const nxt_str_t *file, nxt_str_t *dir) -{ - size_t length; - - if (file->length == 0 || file->start[0] != '/') { - nxt_unit_alert(NULL, "php_dirname: invalid file name " - "(not starts from '/')"); - return NXT_ERROR; - } + if (file->length == 0 || file->start[0] != '/') { + nxt_unit_alert(NULL, "php_dirname: invalid file name " + "(not starts from '/')"); + return NXT_ERROR; + } - length = file->length; + length = file->length; - while (file->start[length - 1] != '/') { - length--; - } + while (file->start[length - 1] != '/') { + length--; + } - dir->length = length; - dir->start = nxt_malloc(length + 1); - if (nxt_slow_path(dir->start == NULL)) { - return NXT_ERROR; - } + dir->length = length; + dir->start = nxt_malloc(length + 1); + if (nxt_slow_path(dir->start == NULL)) { + return NXT_ERROR; + } - nxt_memcpy(dir->start, file->start, length); + nxt_memcpy(dir->start, file->start, length); - dir->start[length] = '\0'; + dir->start[length] = '\0'; - return NXT_OK; + return NXT_OK; } +static void nxt_php_str_trim_trail(nxt_str_t *str, u_char t) { + while (str->length > 0 && str->start[str->length - 1] == t) { + str->length--; + } -static void -nxt_php_str_trim_trail(nxt_str_t *str, u_char t) -{ - while (str->length > 0 && str->start[str->length - 1] == t) { - str->length--; - } - - str->start[str->length] = '\0'; + str->start[str->length] = '\0'; } - -static void -nxt_php_str_trim_lead(nxt_str_t *str, u_char t) -{ - while (str->length > 0 && str->start[0] == t) { - str->length--; - str->start++; - } +static void nxt_php_str_trim_lead(nxt_str_t *str, u_char t) { + while (str->length > 0 && str->start[0] == t) { + str->length--; + str->start++; + } } - -nxt_inline u_char * -nxt_realpath(const void *c) -{ - return (u_char *) realpath(c, NULL); +nxt_inline u_char *nxt_realpath(const void *c) { + return (u_char *)realpath(c, NULL); } +static nxt_int_t nxt_php_do_301(nxt_unit_request_info_t *req) { + char *p, *url, *port; + uint32_t size; + const char *proto; + nxt_unit_request_t *r; -static nxt_int_t -nxt_php_do_301(nxt_unit_request_info_t *req) -{ - char *p, *url, *port; - uint32_t size; - const char *proto; - nxt_unit_request_t *r; - - r = req->request; - - url = nxt_malloc(sizeof("https://") - 1 - + r->server_name_length - + r->local_port_length + 1 - + r->path_length + 1 - + r->query_length + 1 - + 1); - if (nxt_slow_path(url == NULL)) { - return NXT_UNIT_ERROR; - } - - proto = r->tls ? "https://" : "http://"; - p = nxt_cpymem(url, proto, strlen(proto)); - p = nxt_cpymem(p, nxt_unit_sptr_get(&r->server_name), - r->server_name_length); - - port = nxt_unit_sptr_get(&r->local_port); - if (r->local_port_length > 0 - && !(r->tls && strcmp(port, "443") == 0) - && !(!r->tls && strcmp(port, "80") == 0)) - { - *p++ = ':'; - p = nxt_cpymem(p, port, r->local_port_length); - } + r = req->request; - p = nxt_cpymem(p, nxt_unit_sptr_get(&r->path), r->path_length); - *p++ = '/'; + url = nxt_malloc(sizeof("https://") - 1 + r->server_name_length + + r->local_port_length + 1 + r->path_length + 1 + + r->query_length + 1 + 1); + if (nxt_slow_path(url == NULL)) { + return NXT_UNIT_ERROR; + } - if (r->query_length > 0) { - *p++ = '?'; - p = nxt_cpymem(p, nxt_unit_sptr_get(&r->query), r->query_length); - } + proto = r->tls ? "https://" : "http://"; + p = nxt_cpymem(url, proto, strlen(proto)); + p = nxt_cpymem(p, nxt_unit_sptr_get(&r->server_name), r->server_name_length); - *p = '\0'; + port = nxt_unit_sptr_get(&r->local_port); + if (r->local_port_length > 0 && !(r->tls && strcmp(port, "443") == 0) && + !(!r->tls && strcmp(port, "80") == 0)) { + *p++ = ':'; + p = nxt_cpymem(p, port, r->local_port_length); + } - size = p - url; + p = nxt_cpymem(p, nxt_unit_sptr_get(&r->path), r->path_length); + *p++ = '/'; - nxt_unit_response_init(req, NXT_HTTP_MOVED_PERMANENTLY, 1, - nxt_length("Location") + size); - nxt_unit_response_add_field(req, "Location", nxt_length("Location"), - url, size); + if (r->query_length > 0) { + *p++ = '?'; + p = nxt_cpymem(p, nxt_unit_sptr_get(&r->query), r->query_length); + } - nxt_free(url); + *p = '\0'; - return NXT_UNIT_OK; -} + size = p - url; + nxt_unit_response_init(req, NXT_HTTP_MOVED_PERMANENTLY, 1, + nxt_length("Location") + size); + nxt_unit_response_add_field(req, "Location", nxt_length("Location"), url, + size); -static nxt_int_t -nxt_php_handle_fs_err(nxt_unit_request_info_t *req) -{ - switch (nxt_errno) { - case ELOOP: - case EACCES: - case ENFILE: - return nxt_unit_response_init(req, NXT_HTTP_FORBIDDEN, 0, 0); - case ENOENT: - case ENOTDIR: - case ENAMETOOLONG: - return nxt_unit_response_init(req, NXT_HTTP_NOT_FOUND, 0, 0); - } + nxt_free(url); - return NXT_UNIT_ERROR; + return NXT_UNIT_OK; } +static nxt_int_t nxt_php_handle_fs_err(nxt_unit_request_info_t *req) { + switch (nxt_errno) { + case ELOOP: + case EACCES: + case ENFILE: + return nxt_unit_response_init(req, NXT_HTTP_FORBIDDEN, 0, 0); + case ENOENT: + case ENOTDIR: + case ENAMETOOLONG: + return nxt_unit_response_init(req, NXT_HTTP_NOT_FOUND, 0, 0); + } + + return NXT_UNIT_ERROR; +} -static void -nxt_php_request_handler(nxt_unit_request_info_t *req) -{ - nxt_php_target_t *target; - nxt_php_run_ctx_t ctx; - nxt_unit_request_t *r; +static void nxt_php_request_handler(nxt_unit_request_info_t *req) { + nxt_php_target_t *target; + nxt_php_run_ctx_t ctx; + nxt_unit_request_t *r; - r = req->request; - target = &nxt_php_targets[r->app_target]; + r = req->request; + target = &nxt_php_targets[r->app_target]; - nxt_memzero(&ctx, sizeof(ctx)); + nxt_memzero(&ctx, sizeof(ctx)); - ctx.req = req; - ctx.root = &target->root; - ctx.index = &target->index; + ctx.req = req; + ctx.root = &target->root; + ctx.index = &target->index; - if (target->script_filename.length == 0) { - nxt_php_dynamic_request(&ctx, r); - return; - } + if (target->script_filename.length == 0) { + nxt_php_dynamic_request(&ctx, r); + return; + } - ctx.script_filename = target->script_filename; - ctx.script_dirname = target->script_dirname; - ctx.script_name = target->script_name; + ctx.script_filename = target->script_filename; + ctx.script_dirname = target->script_dirname; + ctx.script_name = target->script_name; - ctx.chdir = (r->app_target != nxt_php_last_target); + ctx.chdir = (r->app_target != nxt_php_last_target); - nxt_php_execute(&ctx, r); + nxt_php_execute(&ctx, r); - nxt_php_last_target = ctx.chdir ? -1 : r->app_target; + nxt_php_last_target = ctx.chdir ? -1 : r->app_target; } +static void nxt_php_dynamic_request(nxt_php_run_ctx_t *ctx, + nxt_unit_request_t *r) { + u_char *p; + nxt_str_t path, script_name; + nxt_int_t ret; -static void -nxt_php_dynamic_request(nxt_php_run_ctx_t *ctx, nxt_unit_request_t *r) -{ - u_char *p; - nxt_str_t path, script_name; - nxt_int_t ret; - - path.length = r->path_length; - path.start = nxt_unit_sptr_get(&r->path); + path.length = r->path_length; + path.start = nxt_unit_sptr_get(&r->path); - nxt_str_null(&script_name); + nxt_str_null(&script_name); - ctx->path_info.start = memmem(path.start, path.length, ".php/", - strlen(".php/")); - if (ctx->path_info.start != NULL) { - ctx->path_info.start += 4; - path.length = ctx->path_info.start - path.start; + ctx->path_info.start = + memmem(path.start, path.length, ".php/", strlen(".php/")); + if (ctx->path_info.start != NULL) { + ctx->path_info.start += 4; + path.length = ctx->path_info.start - path.start; - ctx->path_info.length = r->path_length - path.length; + ctx->path_info.length = r->path_length - path.length; - } else if (path.start[path.length - 1] == '/') { - script_name = *ctx->index; + } else if (path.start[path.length - 1] == '/') { + script_name = *ctx->index; - } else if (path.length < 4 - || memcmp(path.start + (path.length - 4), ".php", 4) != 0) - { - char tpath[PATH_MAX]; - nxt_int_t ec; - struct stat sb; + } else if (path.length < 4 || + memcmp(path.start + (path.length - 4), ".php", 4) != 0) { + char tpath[PATH_MAX]; + nxt_int_t ec; + struct stat sb; - ec = NXT_UNIT_ERROR; + ec = NXT_UNIT_ERROR; - if (ctx->root->length + path.length + 1 > PATH_MAX) { - nxt_unit_request_done(ctx->req, ec); + if (ctx->root->length + path.length + 1 > PATH_MAX) { + nxt_unit_request_done(ctx->req, ec); - return; - } + return; + } - p = nxt_cpymem(tpath, ctx->root->start, ctx->root->length); - p = nxt_cpymem(p, path.start, path.length); - *p = '\0'; + p = nxt_cpymem(tpath, ctx->root->start, ctx->root->length); + p = nxt_cpymem(p, path.start, path.length); + *p = '\0'; - ret = stat(tpath, &sb); - if (ret == 0 && S_ISDIR(sb.st_mode)) { - ec = nxt_php_do_301(ctx->req); - } else if (ret == -1) { - ec = nxt_php_handle_fs_err(ctx->req); - } + ret = stat(tpath, &sb); + if (ret == 0 && S_ISDIR(sb.st_mode)) { + ec = nxt_php_do_301(ctx->req); + } else if (ret == -1) { + ec = nxt_php_handle_fs_err(ctx->req); + } - nxt_unit_request_done(ctx->req, ec); + nxt_unit_request_done(ctx->req, ec); - return; - } + return; + } - ctx->script_filename.length = ctx->root->length - + path.length - + script_name.length; + ctx->script_filename.length = + ctx->root->length + path.length + script_name.length; - p = nxt_malloc(ctx->script_filename.length + 1); - if (nxt_slow_path(p == NULL)) { - nxt_unit_request_done(ctx->req, NXT_UNIT_ERROR); + p = nxt_malloc(ctx->script_filename.length + 1); + if (nxt_slow_path(p == NULL)) { + nxt_unit_request_done(ctx->req, NXT_UNIT_ERROR); - return; - } + return; + } - ctx->script_filename.start = p; + ctx->script_filename.start = p; - ctx->script_name.length = path.length + script_name.length; - ctx->script_name.start = p + ctx->root->length; + ctx->script_name.length = path.length + script_name.length; + ctx->script_name.start = p + ctx->root->length; - p = nxt_cpymem(p, ctx->root->start, ctx->root->length); - p = nxt_cpymem(p, path.start, path.length); + p = nxt_cpymem(p, ctx->root->start, ctx->root->length); + p = nxt_cpymem(p, path.start, path.length); - if (script_name.length > 0) { - p = nxt_cpymem(p, script_name.start, script_name.length); - } + if (script_name.length > 0) { + p = nxt_cpymem(p, script_name.start, script_name.length); + } - *p = '\0'; + *p = '\0'; - ctx->chdir = 1; + ctx->chdir = 1; - ret = nxt_php_dirname(&ctx->script_filename, &ctx->script_dirname); - if (nxt_slow_path(ret != NXT_OK)) { - nxt_unit_request_done(ctx->req, NXT_UNIT_ERROR); - nxt_free(ctx->script_filename.start); + ret = nxt_php_dirname(&ctx->script_filename, &ctx->script_dirname); + if (nxt_slow_path(ret != NXT_OK)) { + nxt_unit_request_done(ctx->req, NXT_UNIT_ERROR); + nxt_free(ctx->script_filename.start); - return; - } + return; + } - nxt_php_execute(ctx, r); + nxt_php_execute(ctx, r); - nxt_free(ctx->script_filename.start); - nxt_free(ctx->script_dirname.start); + nxt_free(ctx->script_filename.start); + nxt_free(ctx->script_dirname.start); - nxt_php_last_target = -1; + nxt_php_last_target = -1; } - #if (PHP_VERSION_ID < 70400) -static void -nxt_zend_stream_init_fp(zend_file_handle *handle, FILE *fp, - const char *filename) -{ - nxt_memzero(handle, sizeof(zend_file_handle)); - handle->type = ZEND_HANDLE_FP; - handle->handle.fp = fp; - handle->filename = filename; +static void nxt_zend_stream_init_fp(zend_file_handle *handle, FILE *fp, + const char *filename) { + nxt_memzero(handle, sizeof(zend_file_handle)); + handle->type = ZEND_HANDLE_FP; + handle->handle.fp = fp; + handle->filename = filename; } #else -#define nxt_zend_stream_init_fp zend_stream_init_fp +#define nxt_zend_stream_init_fp zend_stream_init_fp #endif - -static void -nxt_php_execute(nxt_php_run_ctx_t *ctx, nxt_unit_request_t *r) -{ - FILE *fp; +static void nxt_php_execute(nxt_php_run_ctx_t *ctx, nxt_unit_request_t *r) { + FILE *fp; #if (PHP_VERSION_ID < 50600) - void *read_post; + void *read_post; #endif - const char *filename; - nxt_unit_field_t *f; - zend_file_handle file_handle; + const char *filename; + nxt_unit_field_t *f; + zend_file_handle file_handle; - filename = (const char *) ctx->script_filename.start; + filename = (const char *)ctx->script_filename.start; - nxt_unit_req_debug(ctx->req, "PHP execute script %s", filename); + nxt_unit_req_debug(ctx->req, "PHP execute script %s", filename); - fp = fopen(filename, "re"); - if (fp == NULL) { - nxt_int_t ec; + fp = fopen(filename, "re"); + if (fp == NULL) { + nxt_int_t ec; - nxt_unit_req_debug(ctx->req, "PHP fopen(\"%s\") failed", filename); + nxt_unit_req_debug(ctx->req, "PHP fopen(\"%s\") failed", filename); - ec = nxt_php_handle_fs_err(ctx->req); - nxt_unit_request_done(ctx->req, ec); - return; - } + ec = nxt_php_handle_fs_err(ctx->req); + nxt_unit_request_done(ctx->req, ec); + return; + } - SG(server_context) = ctx; - SG(options) |= SAPI_OPTION_NO_CHDIR; - SG(request_info).request_uri = nxt_unit_sptr_get(&r->target); - SG(request_info).request_method = nxt_unit_sptr_get(&r->method); + SG(server_context) = ctx; + SG(options) |= SAPI_OPTION_NO_CHDIR; + SG(request_info).request_uri = nxt_unit_sptr_get(&r->target); + SG(request_info).request_method = nxt_unit_sptr_get(&r->method); - SG(request_info).proto_num = 1001; + SG(request_info).proto_num = 1001; - SG(request_info).query_string = r->query.offset - ? nxt_unit_sptr_get(&r->query) : NULL; - SG(request_info).content_length = r->content_length; + SG(request_info).query_string = + r->query.offset ? nxt_unit_sptr_get(&r->query) : NULL; + SG(request_info).content_length = r->content_length; - if (r->content_type_field != NXT_UNIT_NONE_FIELD) { - f = r->fields + r->content_type_field; + if (r->content_type_field != NXT_UNIT_NONE_FIELD) { + f = r->fields + r->content_type_field; - SG(request_info).content_type = nxt_unit_sptr_get(&f->value); - } + SG(request_info).content_type = nxt_unit_sptr_get(&f->value); + } - if (r->cookie_field != NXT_UNIT_NONE_FIELD) { - f = r->fields + r->cookie_field; + if (r->cookie_field != NXT_UNIT_NONE_FIELD) { + f = r->fields + r->cookie_field; - ctx->cookie = nxt_unit_sptr_get(&f->value); - } + ctx->cookie = nxt_unit_sptr_get(&f->value); + } - if (r->authorization_field != NXT_UNIT_NONE_FIELD) { - f = r->fields + r->authorization_field; + if (r->authorization_field != NXT_UNIT_NONE_FIELD) { + f = r->fields + r->authorization_field; #ifdef NXT_PHP7 - php_handle_auth_data(nxt_unit_sptr_get(&f->value)); + php_handle_auth_data(nxt_unit_sptr_get(&f->value)); #else - php_handle_auth_data(nxt_unit_sptr_get(&f->value) TSRMLS_CC); + php_handle_auth_data(nxt_unit_sptr_get(&f->value) TSRMLS_CC); #endif - } else { - SG(request_info).auth_digest = NULL; - SG(request_info).auth_user = NULL; - SG(request_info).auth_password = NULL; - } + } else { + SG(request_info).auth_digest = NULL; + SG(request_info).auth_user = NULL; + SG(request_info).auth_password = NULL; + } - SG(sapi_headers).http_response_code = 200; + SG(sapi_headers).http_response_code = 200; - SG(request_info).path_translated = NULL; + SG(request_info).path_translated = NULL; #ifdef NXT_PHP7 - if (nxt_slow_path(php_request_startup() == FAILURE)) { + if (nxt_slow_path(php_request_startup() == FAILURE)) { #else - if (nxt_slow_path(php_request_startup(TSRMLS_C) == FAILURE)) { + if (nxt_slow_path(php_request_startup(TSRMLS_C) == FAILURE)) { #endif - nxt_unit_req_debug(ctx->req, "php_request_startup() failed"); + nxt_unit_req_debug(ctx->req, "php_request_startup() failed"); - nxt_unit_request_done(ctx->req, NXT_UNIT_ERROR); - fclose(fp); + nxt_unit_request_done(ctx->req, NXT_UNIT_ERROR); + fclose(fp); - return; - } + return; + } - if (ctx->chdir) { - ctx->chdir = 0; - nxt_php_vcwd_chdir(ctx->req, ctx->script_dirname.start); - } + if (ctx->chdir) { + ctx->chdir = 0; + nxt_php_vcwd_chdir(ctx->req, ctx->script_dirname.start); + } - nxt_zend_stream_init_fp(&file_handle, fp, filename); + nxt_zend_stream_init_fp(&file_handle, fp, filename); - php_execute_script(&file_handle TSRMLS_CC); + php_execute_script(&file_handle TSRMLS_CC); #if (PHP_VERSION_ID >= 80100) - zend_destroy_file_handle(&file_handle); + zend_destroy_file_handle(&file_handle); #endif - /* Prevention of consuming possible unread request body. */ + /* Prevention of consuming possible unread request body. */ #if (PHP_VERSION_ID < 50600) - read_post = sapi_module.read_post; - sapi_module.read_post = NULL; + read_post = sapi_module.read_post; + sapi_module.read_post = NULL; #else - SG(post_read) = 1; + SG(post_read) = 1; #endif - php_request_shutdown(NULL); + php_request_shutdown(NULL); - if (ctx->req != NULL) { - nxt_unit_request_done(ctx->req, NXT_UNIT_OK); - } + if (ctx->req != NULL) { + nxt_unit_request_done(ctx->req, NXT_UNIT_OK); + } #if (PHP_VERSION_ID < 50600) - sapi_module.read_post = read_post; + sapi_module.read_post = read_post; #endif } - -nxt_inline void -nxt_php_vcwd_chdir(nxt_unit_request_info_t *req, u_char *dir) -{ - if (nxt_slow_path(VCWD_CHDIR((char *) dir) != 0)) { - nxt_unit_req_alert(req, "VCWD_CHDIR(%s) failed (%d: %s)", - dir, errno, strerror(errno)); - } +nxt_inline void nxt_php_vcwd_chdir(nxt_unit_request_info_t *req, u_char *dir) { + if (nxt_slow_path(VCWD_CHDIR((char *)dir) != 0)) { + nxt_unit_req_alert(req, "VCWD_CHDIR(%s) failed (%d: %s)", dir, errno, + strerror(errno)); + } } - -static int -nxt_php_startup(sapi_module_struct *sapi_module) -{ +static int nxt_php_startup(sapi_module_struct *sapi_module) { #if (PHP_VERSION_ID < 80200) - return php_module_startup(sapi_module, &nxt_php_unit_module, 1); + return php_module_startup(sapi_module, &nxt_php_unit_module, 1); #else - return php_module_startup(sapi_module, &nxt_php_unit_module); + return php_module_startup(sapi_module, &nxt_php_unit_module); #endif } - #ifdef NXT_PHP7 -static size_t -nxt_php_unbuffered_write(const char *str, size_t str_length TSRMLS_DC) +static size_t nxt_php_unbuffered_write(const char *str, + size_t str_length TSRMLS_DC) #else -static int -nxt_php_unbuffered_write(const char *str, uint str_length TSRMLS_DC) +static int nxt_php_unbuffered_write(const char *str, uint str_length TSRMLS_DC) #endif { - int rc; - nxt_php_run_ctx_t *ctx; + int rc; + nxt_php_run_ctx_t *ctx; - ctx = SG(server_context); + ctx = SG(server_context); - rc = nxt_unit_response_write(ctx->req, str, str_length); - if (nxt_fast_path(rc == NXT_UNIT_OK)) { - return str_length; - } + rc = nxt_unit_response_write(ctx->req, str, str_length); + if (nxt_fast_path(rc == NXT_UNIT_OK)) { + return str_length; + } - php_handle_aborted_connection(); - return 0; + php_handle_aborted_connection(); + return 0; } +static int nxt_php_send_headers(sapi_headers_struct *sapi_headers TSRMLS_DC) { + int rc, fields_count; + char *colon, *value; + uint16_t status; + uint32_t resp_size; + nxt_php_run_ctx_t *ctx; + sapi_header_struct *h; + zend_llist_position zpos; + nxt_unit_request_info_t *req; -static int -nxt_php_send_headers(sapi_headers_struct *sapi_headers TSRMLS_DC) -{ - int rc, fields_count; - char *colon, *value; - uint16_t status; - uint32_t resp_size; - nxt_php_run_ctx_t *ctx; - sapi_header_struct *h; - zend_llist_position zpos; - nxt_unit_request_info_t *req; - - ctx = SG(server_context); - req = ctx->req; - - nxt_unit_req_debug(req, "nxt_php_send_headers"); - - if (SG(request_info).no_headers == 1) { - rc = nxt_unit_response_init(req, 200, 0, 0); - if (nxt_slow_path(rc != NXT_UNIT_OK)) { - return SAPI_HEADER_SEND_FAILED; - } - - return SAPI_HEADER_SENT_SUCCESSFULLY; - } + ctx = SG(server_context); + req = ctx->req; - resp_size = 0; - fields_count = zend_llist_count(&sapi_headers->headers); - - for (h = zend_llist_get_first_ex(&sapi_headers->headers, &zpos); - h; - h = zend_llist_get_next_ex(&sapi_headers->headers, &zpos)) - { - resp_size += h->header_len; - } + nxt_unit_req_debug(req, "nxt_php_send_headers"); - status = SG(sapi_headers).http_response_code; - - rc = nxt_unit_response_init(req, status, fields_count, resp_size); + if (SG(request_info).no_headers == 1) { + rc = nxt_unit_response_init(req, 200, 0, 0); if (nxt_slow_path(rc != NXT_UNIT_OK)) { - return SAPI_HEADER_SEND_FAILED; + return SAPI_HEADER_SEND_FAILED; } - for (h = zend_llist_get_first_ex(&sapi_headers->headers, &zpos); - h; - h = zend_llist_get_next_ex(&sapi_headers->headers, &zpos)) - { - colon = memchr(h->header, ':', h->header_len); - if (nxt_slow_path(colon == NULL)) { - nxt_unit_req_warn(req, "colon not found in header '%.*s'", - (int) h->header_len, h->header); - continue; - } - - value = colon + 1; - while(isspace(*value)) { - value++; - } + return SAPI_HEADER_SENT_SUCCESSFULLY; + } + + resp_size = 0; + fields_count = zend_llist_count(&sapi_headers->headers); + + for (h = zend_llist_get_first_ex(&sapi_headers->headers, &zpos); h; + h = zend_llist_get_next_ex(&sapi_headers->headers, &zpos)) { + resp_size += h->header_len; + } + + status = SG(sapi_headers).http_response_code; + + rc = nxt_unit_response_init(req, status, fields_count, resp_size); + if (nxt_slow_path(rc != NXT_UNIT_OK)) { + return SAPI_HEADER_SEND_FAILED; + } + + for (h = zend_llist_get_first_ex(&sapi_headers->headers, &zpos); h; + h = zend_llist_get_next_ex(&sapi_headers->headers, &zpos)) { + colon = memchr(h->header, ':', h->header_len); + if (nxt_slow_path(colon == NULL)) { + nxt_unit_req_warn(req, "colon not found in header '%.*s'", + (int)h->header_len, h->header); + continue; + } - nxt_unit_response_add_field(req, h->header, colon - h->header, - value, - h->header_len - (value - h->header)); + value = colon + 1; + while (isspace(*value)) { + value++; } - rc = nxt_unit_response_send(req); - if (nxt_slow_path(rc != NXT_UNIT_OK)) { - nxt_unit_req_debug(req, "failed to send response"); + nxt_unit_response_add_field(req, h->header, colon - h->header, value, + h->header_len - (value - h->header)); + } - return SAPI_HEADER_SEND_FAILED; - } + rc = nxt_unit_response_send(req); + if (nxt_slow_path(rc != NXT_UNIT_OK)) { + nxt_unit_req_debug(req, "failed to send response"); - return SAPI_HEADER_SENT_SUCCESSFULLY; -} + return SAPI_HEADER_SEND_FAILED; + } + return SAPI_HEADER_SENT_SUCCESSFULLY; +} #ifdef NXT_PHP7 -static size_t -nxt_php_read_post(char *buffer, size_t count_bytes TSRMLS_DC) +static size_t nxt_php_read_post(char *buffer, size_t count_bytes TSRMLS_DC) #else -static int -nxt_php_read_post(char *buffer, uint count_bytes TSRMLS_DC) +static int nxt_php_read_post(char *buffer, uint count_bytes TSRMLS_DC) #endif { - nxt_php_run_ctx_t *ctx; + nxt_php_run_ctx_t *ctx; - ctx = SG(server_context); + ctx = SG(server_context); - nxt_unit_req_debug(ctx->req, "nxt_php_read_post %d", (int) count_bytes); + nxt_unit_req_debug(ctx->req, "nxt_php_read_post %d", (int)count_bytes); - return nxt_unit_request_read(ctx->req, buffer, count_bytes); + return nxt_unit_request_read(ctx->req, buffer, count_bytes); } +static char *nxt_php_read_cookies(TSRMLS_D) { + nxt_php_run_ctx_t *ctx; -static char * -nxt_php_read_cookies(TSRMLS_D) -{ - nxt_php_run_ctx_t *ctx; - - ctx = SG(server_context); + ctx = SG(server_context); - nxt_unit_req_debug(ctx->req, "nxt_php_read_cookies"); + nxt_unit_req_debug(ctx->req, "nxt_php_read_cookies"); - return ctx->cookie; + return ctx->cookie; } +static void nxt_php_register_variables(zval *track_vars_array TSRMLS_DC) { + const char *name; + nxt_unit_field_t *f, *f_end; + nxt_php_run_ctx_t *ctx; + nxt_unit_request_t *r; + nxt_unit_request_info_t *req; -static void -nxt_php_register_variables(zval *track_vars_array TSRMLS_DC) -{ - const char *name; - nxt_unit_field_t *f, *f_end; - nxt_php_run_ctx_t *ctx; - nxt_unit_request_t *r; - nxt_unit_request_info_t *req; - - ctx = SG(server_context); - - req = ctx->req; - r = req->request; + ctx = SG(server_context); - nxt_unit_req_debug(req, "nxt_php_register_variables"); + req = ctx->req; + r = req->request; - php_register_variable_safe((char *) "SERVER_SOFTWARE", - (char *) nxt_server.start, - nxt_server.length, track_vars_array TSRMLS_CC); - - nxt_php_set_sptr(req, "SERVER_PROTOCOL", &r->version, r->version_length, - track_vars_array TSRMLS_CC); + nxt_unit_req_debug(req, "nxt_php_register_variables"); - /* - * 'PHP_SELF' - * The filename of the currently executing script, relative to the document - * root. For instance, $_SERVER['PHP_SELF'] in a script at the address - * http://example.com/foo/bar.php would be /foo/bar.php. The __FILE__ - * constant contains the full path and filename of the current (i.e. - * included) file. If PHP is running as a command-line processor this - * variable contains the script name since PHP 4.3.0. Previously it was not - * available. - */ - - if (ctx->path_info.length != 0) { - nxt_php_set_sptr(req, "PHP_SELF", &r->path, r->path_length, - track_vars_array TSRMLS_CC); - - nxt_php_set_str(req, "PATH_INFO", &ctx->path_info, - track_vars_array TSRMLS_CC); - - } else { - nxt_php_set_str(req, "PHP_SELF", &ctx->script_name, - track_vars_array TSRMLS_CC); - } + php_register_variable_safe((char *)"SERVER_SOFTWARE", + (char *)nxt_server.start, nxt_server.length, + track_vars_array TSRMLS_CC); - /* - * 'SCRIPT_NAME' - * Contains the current script's path. This is useful for pages which need - * to point to themselves. The __FILE__ constant contains the full path and - * filename of the current (i.e. included) file. - */ + nxt_php_set_sptr(req, "SERVER_PROTOCOL", &r->version, r->version_length, + track_vars_array TSRMLS_CC); - nxt_php_set_str(req, "SCRIPT_NAME", &ctx->script_name, - track_vars_array TSRMLS_CC); + /* + * 'PHP_SELF' + * The filename of the currently executing script, relative to the document + * root. For instance, $_SERVER['PHP_SELF'] in a script at the address + * http://example.com/foo/bar.php would be /foo/bar.php. The __FILE__ + * constant contains the full path and filename of the current (i.e. + * included) file. If PHP is running as a command-line processor this + * variable contains the script name since PHP 4.3.0. Previously it was not + * available. + */ - /* - * 'SCRIPT_FILENAME' - * The absolute pathname of the currently executing script. - */ + if (ctx->path_info.length != 0) { + nxt_php_set_sptr(req, "PHP_SELF", &r->path, r->path_length, + track_vars_array TSRMLS_CC); - nxt_php_set_str(req, "SCRIPT_FILENAME", &ctx->script_filename, + nxt_php_set_str(req, "PATH_INFO", &ctx->path_info, track_vars_array TSRMLS_CC); - /* - * 'DOCUMENT_ROOT' - * The document root directory under which the current script is executing, - * as defined in the server's configuration file. - */ - - nxt_php_set_str(req, "DOCUMENT_ROOT", ctx->root, + } else { + nxt_php_set_str(req, "PHP_SELF", &ctx->script_name, track_vars_array TSRMLS_CC); - - nxt_php_set_sptr(req, "REQUEST_METHOD", &r->method, r->method_length, - track_vars_array TSRMLS_CC); - nxt_php_set_sptr(req, "REQUEST_URI", &r->target, r->target_length, - track_vars_array TSRMLS_CC); - nxt_php_set_sptr(req, "QUERY_STRING", &r->query, r->query_length, + } + + /* + * 'SCRIPT_NAME' + * Contains the current script's path. This is useful for pages which need + * to point to themselves. The __FILE__ constant contains the full path and + * filename of the current (i.e. included) file. + */ + + nxt_php_set_str(req, "SCRIPT_NAME", &ctx->script_name, + track_vars_array TSRMLS_CC); + + /* + * 'SCRIPT_FILENAME' + * The absolute pathname of the currently executing script. + */ + + nxt_php_set_str(req, "SCRIPT_FILENAME", &ctx->script_filename, + track_vars_array TSRMLS_CC); + + /* + * 'DOCUMENT_ROOT' + * The document root directory under which the current script is executing, + * as defined in the server's configuration file. + */ + + nxt_php_set_str(req, "DOCUMENT_ROOT", ctx->root, track_vars_array TSRMLS_CC); + + nxt_php_set_sptr(req, "REQUEST_METHOD", &r->method, r->method_length, + track_vars_array TSRMLS_CC); + nxt_php_set_sptr(req, "REQUEST_URI", &r->target, r->target_length, + track_vars_array TSRMLS_CC); + nxt_php_set_sptr(req, "QUERY_STRING", &r->query, r->query_length, + track_vars_array TSRMLS_CC); + + nxt_php_set_sptr(req, "REMOTE_ADDR", &r->remote, r->remote_length, + track_vars_array TSRMLS_CC); + nxt_php_set_sptr(req, "SERVER_ADDR", &r->local_addr, r->local_addr_length, + track_vars_array TSRMLS_CC); + + nxt_php_set_sptr(req, "SERVER_NAME", &r->server_name, r->server_name_length, + track_vars_array TSRMLS_CC); + nxt_php_set_cstr(req, "SERVER_PORT", "80", 2, track_vars_array TSRMLS_CC); + + if (r->tls) { + nxt_php_set_cstr(req, "HTTPS", "on", 2, track_vars_array TSRMLS_CC); + } + + f_end = r->fields + r->fields_count; + for (f = r->fields; f < f_end; f++) { + name = nxt_unit_sptr_get(&f->name); + + nxt_php_set_sptr(req, name, &f->value, f->value_length, track_vars_array TSRMLS_CC); + } - nxt_php_set_sptr(req, "REMOTE_ADDR", &r->remote, r->remote_length, - track_vars_array TSRMLS_CC); - nxt_php_set_sptr(req, "SERVER_ADDR", &r->local_addr, r->local_addr_length, - track_vars_array TSRMLS_CC); + if (r->content_length_field != NXT_UNIT_NONE_FIELD) { + f = r->fields + r->content_length_field; - nxt_php_set_sptr(req, "SERVER_NAME", &r->server_name, r->server_name_length, + nxt_php_set_sptr(req, "CONTENT_LENGTH", &f->value, f->value_length, track_vars_array TSRMLS_CC); - nxt_php_set_cstr(req, "SERVER_PORT", "80", 2, track_vars_array TSRMLS_CC); + } - if (r->tls) { - nxt_php_set_cstr(req, "HTTPS", "on", 2, track_vars_array TSRMLS_CC); - } - - f_end = r->fields + r->fields_count; - for (f = r->fields; f < f_end; f++) { - name = nxt_unit_sptr_get(&f->name); - - nxt_php_set_sptr(req, name, &f->value, f->value_length, - track_vars_array TSRMLS_CC); - } - - if (r->content_length_field != NXT_UNIT_NONE_FIELD) { - f = r->fields + r->content_length_field; + if (r->content_type_field != NXT_UNIT_NONE_FIELD) { + f = r->fields + r->content_type_field; - nxt_php_set_sptr(req, "CONTENT_LENGTH", &f->value, f->value_length, - track_vars_array TSRMLS_CC); - } - - if (r->content_type_field != NXT_UNIT_NONE_FIELD) { - f = r->fields + r->content_type_field; - - nxt_php_set_sptr(req, "CONTENT_TYPE", &f->value, f->value_length, - track_vars_array TSRMLS_CC); - } + nxt_php_set_sptr(req, "CONTENT_TYPE", &f->value, f->value_length, + track_vars_array TSRMLS_CC); + } } - -static void -nxt_php_set_sptr(nxt_unit_request_info_t *req, const char *name, - nxt_unit_sptr_t *v, uint32_t len, zval *track_vars_array TSRMLS_DC) -{ - char *str; +static void nxt_php_set_sptr(nxt_unit_request_info_t *req, const char *name, + nxt_unit_sptr_t *v, uint32_t len, + zval *track_vars_array TSRMLS_DC) { + char *str; #if NXT_PHP7 - size_t new_len; + size_t new_len; #else - unsigned int new_len; + unsigned int new_len; #endif - str = nxt_unit_sptr_get(v); + str = nxt_unit_sptr_get(v); - nxt_unit_req_debug(req, "php: register %s='%.*s'", name, (int) len, str); + nxt_unit_req_debug(req, "php: register %s='%.*s'", name, (int)len, str); - if (sapi_module.input_filter(PARSE_SERVER, (char *) name, &str, len, - &new_len TSRMLS_CC)) - { - php_register_variable_safe((char *) name, str, new_len, - track_vars_array TSRMLS_CC); - } + if (sapi_module.input_filter(PARSE_SERVER, (char *)name, &str, len, + &new_len TSRMLS_CC)) { + php_register_variable_safe((char *)name, str, new_len, + track_vars_array TSRMLS_CC); + } } - -nxt_inline void -nxt_php_set_str(nxt_unit_request_info_t *req, const char *name, - nxt_str_t *s, zval *track_vars_array TSRMLS_DC) -{ - nxt_php_set_cstr(req, name, (char *) s->start, s->length, - track_vars_array TSRMLS_CC); +nxt_inline void nxt_php_set_str(nxt_unit_request_info_t *req, const char *name, + nxt_str_t *s, + zval *track_vars_array TSRMLS_DC) { + nxt_php_set_cstr(req, name, (char *)s->start, s->length, + track_vars_array TSRMLS_CC); } - #ifdef NXT_PHP7 -static void * -nxt_php_hash_str_find_ptr(const HashTable *ht, const nxt_str_t *str) -{ - return zend_hash_str_find_ptr(ht, (const char *) str->start, str->length); +static void *nxt_php_hash_str_find_ptr(const HashTable *ht, + const nxt_str_t *str) { + return zend_hash_str_find_ptr(ht, (const char *)str->start, str->length); } #else -static void * -nxt_php_hash_str_find_ptr(const HashTable *ht, const nxt_str_t *str) -{ - int ret; - void *entry; - char buf[256]; +static void *nxt_php_hash_str_find_ptr(const HashTable *ht, + const nxt_str_t *str) { + int ret; + void *entry; + char buf[256]; - if (nxt_slow_path(str->length >= (sizeof(buf) - 1))) { - return NULL; - } + if (nxt_slow_path(str->length >= (sizeof(buf) - 1))) { + return NULL; + } - nxt_memcpy(buf, str->start, str->length); - buf[str->length] = '\0'; + nxt_memcpy(buf, str->start, str->length); + buf[str->length] = '\0'; - ret = zend_hash_find(ht, buf, str->length + 1, &entry); - if (nxt_fast_path(ret == SUCCESS)) { - return entry; - } + ret = zend_hash_find(ht, buf, str->length + 1, &entry); + if (nxt_fast_path(ret == SUCCESS)) { + return entry; + } - return NULL; + return NULL; } #endif +static void nxt_php_set_cstr(nxt_unit_request_info_t *req, const char *name, + const char *cstr, uint32_t len, + zval *track_vars_array TSRMLS_DC) { + if (nxt_slow_path(cstr == NULL)) { + return; + } -static void -nxt_php_set_cstr(nxt_unit_request_info_t *req, const char *name, - const char *cstr, uint32_t len, zval *track_vars_array TSRMLS_DC) -{ - if (nxt_slow_path(cstr == NULL)) { - return; - } - - nxt_unit_req_debug(req, "php: register %s='%.*s'", name, (int) len, cstr); + nxt_unit_req_debug(req, "php: register %s='%.*s'", name, (int)len, cstr); - php_register_variable_safe((char *) name, (char *) cstr, len, - track_vars_array TSRMLS_CC); + php_register_variable_safe((char *)name, (char *)cstr, len, + track_vars_array TSRMLS_CC); } - #if NXT_PHP8 -static void -nxt_php_log_message(const char *message, int syslog_type_int) +static void nxt_php_log_message(const char *message, int syslog_type_int) #else #ifdef NXT_HAVE_PHP_LOG_MESSAGE_WITH_SYSLOG_TYPE -static void -nxt_php_log_message(char *message, int syslog_type_int) +static void nxt_php_log_message(char *message, int syslog_type_int) #else -static void -nxt_php_log_message(char *message TSRMLS_DC) +static void nxt_php_log_message(char *message TSRMLS_DC) #endif #endif { - nxt_php_run_ctx_t *ctx; + nxt_php_run_ctx_t *ctx; - ctx = SG(server_context); + ctx = SG(server_context); - if (ctx != NULL) { - nxt_unit_req_log(ctx->req, NXT_UNIT_LOG_NOTICE, - "php message: %s", message); + if (ctx != NULL) { + nxt_unit_req_log(ctx->req, NXT_UNIT_LOG_NOTICE, "php message: %s", message); - } else { - nxt_unit_log(nxt_php_unit_ctx, NXT_UNIT_LOG_NOTICE, - "php message: %s", message); - } + } else { + nxt_unit_log(nxt_php_unit_ctx, NXT_UNIT_LOG_NOTICE, "php message: %s", + message); + } } diff --git a/src/nxt_polarssl.c b/src/nxt_polarssl.c index 4a8144731..c8e3927c5 100644 --- a/src/nxt_polarssl.c +++ b/src/nxt_polarssl.c @@ -10,109 +10,95 @@ #include #include - typedef struct { - ssl_context ssl; - x509_cert certificate; - rsa_context key; + ssl_context ssl; + x509_cert certificate; + rsa_context key; } nxt_polarssl_ctx_t; - static nxt_int_t nxt_polarssl_server_init(nxt_ssltls_conf_t *conf); static void nxt_polarssl_conn_init(nxt_thread_t *thr, nxt_ssltls_conf_t *conf, - nxt_event_conn_t *c); + nxt_event_conn_t *c); static void nxt_polarssl_log_error(nxt_uint_t level, nxt_log_t *log, int err, - const char *fmt, ...); - + const char *fmt, ...); -nxt_ssltls_lib_t nxt_polarssl_lib = { +nxt_ssltls_lib_t nxt_polarssl_lib = { nxt_polarssl_server_init, NULL, }; +static nxt_int_t nxt_polarssl_server_init(nxt_ssltls_conf_t *conf) { + int n; + nxt_thread_t *thr; + nxt_polarssl_ctx_t *ctx; -static nxt_int_t -nxt_polarssl_server_init(nxt_ssltls_conf_t *conf) -{ - int n; - nxt_thread_t *thr; - nxt_polarssl_ctx_t *ctx; + thr = nxt_thread(); - thr = nxt_thread(); + /* TODO: mem_pool */ - /* TODO: mem_pool */ - - ctx = nxt_zalloc(sizeof(nxt_polarssl_ctx_t)); - if (ctx == NULL) { - return NXT_ERROR; - } + ctx = nxt_zalloc(sizeof(nxt_polarssl_ctx_t)); + if (ctx == NULL) { + return NXT_ERROR; + } - n = ssl_init(&ctx->ssl); - if (n != 0) { - nxt_polarssl_log_error(NXT_LOG_ALERT, thr->log, n, "ssl_init() failed"); - return NXT_ERROR; - } + n = ssl_init(&ctx->ssl); + if (n != 0) { + nxt_polarssl_log_error(NXT_LOG_ALERT, thr->log, n, "ssl_init() failed"); + return NXT_ERROR; + } - ssl_set_endpoint(&ctx->ssl, SSL_IS_SERVER ); + ssl_set_endpoint(&ctx->ssl, SSL_IS_SERVER); - conf->ctx = ctx; - conf->conn_init = nxt_polarssl_conn_init; + conf->ctx = ctx; + conf->conn_init = nxt_polarssl_conn_init; - n = x509parse_crtfile(&ctx->certificate, conf->certificate); - if (n != 0) { - nxt_polarssl_log_error(NXT_LOG_ALERT, thr->log, n, - "x509parse_crt(\"%V\") failed", - &conf->certificate); - goto fail; - } + n = x509parse_crtfile(&ctx->certificate, conf->certificate); + if (n != 0) { + nxt_polarssl_log_error(NXT_LOG_ALERT, thr->log, n, + "x509parse_crt(\"%V\") failed", &conf->certificate); + goto fail; + } - rsa_init(&ctx->key, RSA_PKCS_V15, 0); + rsa_init(&ctx->key, RSA_PKCS_V15, 0); - n = x509parse_keyfile(&ctx->key, conf->certificate_key, NULL); - if (n != 0) { - nxt_polarssl_log_error(NXT_LOG_ALERT, thr->log, n, - "x509parse_key(\"%V\") failed", - &conf->certificate_key); - goto fail; - } + n = x509parse_keyfile(&ctx->key, conf->certificate_key, NULL); + if (n != 0) { + nxt_polarssl_log_error(NXT_LOG_ALERT, thr->log, n, + "x509parse_key(\"%V\") failed", + &conf->certificate_key); + goto fail; + } - ssl_set_own_cert(&ctx->ssl, &ctx->certificate, &ctx->key); + ssl_set_own_cert(&ctx->ssl, &ctx->certificate, &ctx->key); - /* TODO: ciphers */ + /* TODO: ciphers */ - /* TODO: ca_certificate */ + /* TODO: ca_certificate */ - return NXT_OK; + return NXT_OK; fail: - return NXT_ERROR; -} - - -static void -nxt_polarssl_conn_init(nxt_thread_t *thr, nxt_ssltls_conf_t *conf, - nxt_event_conn_t *c) -{ + return NXT_ERROR; } +static void nxt_polarssl_conn_init(nxt_thread_t *thr, nxt_ssltls_conf_t *conf, + nxt_event_conn_t *c) {} -static void -nxt_polarssl_log_error(nxt_uint_t level, nxt_log_t *log, int err, - const char *fmt, ...) -{ - va_list args; - u_char *p, *end, msg[NXT_MAX_ERROR_STR]; +static void nxt_polarssl_log_error(nxt_uint_t level, nxt_log_t *log, int err, + const char *fmt, ...) { + va_list args; + u_char *p, *end, msg[NXT_MAX_ERROR_STR]; - end = msg + NXT_MAX_ERROR_STR; + end = msg + NXT_MAX_ERROR_STR; - va_start(args, fmt); - p = nxt_vsprintf(msg, end, fmt, args); - va_end(args); + va_start(args, fmt); + p = nxt_vsprintf(msg, end, fmt, args); + va_end(args); - p = nxt_sprintf(p, end, " (%d: ", err); + p = nxt_sprintf(p, end, " (%d: ", err); - error_strerror(err, (char *) msg, p - msg); + error_strerror(err, (char *)msg, p - msg); - nxt_log_error(level, log, "%*s)", p - msg, msg); + nxt_log_error(level, log, "%*s)", p - msg, msg); } diff --git a/src/nxt_poll_engine.c b/src/nxt_poll_engine.c index f514e0a9a..052cf0585 100644 --- a/src/nxt_poll_engine.c +++ b/src/nxt_poll_engine.c @@ -6,66 +6,61 @@ #include - -#define NXT_POLL_ADD 0 -#define NXT_POLL_CHANGE 1 -#define NXT_POLL_DELETE 2 - +#define NXT_POLL_ADD 0 +#define NXT_POLL_CHANGE 1 +#define NXT_POLL_DELETE 2 typedef struct { - /* - * A file descriptor is stored in hash entry to allow - * nxt_poll_fd_hash_test() to not dereference a pointer to - * nxt_fd_event_t which may be invalid if the file descriptor has - * been already closed and the nxt_fd_event_t's memory has been freed. - */ - nxt_socket_t fd; - - uint32_t index; - void *event; + /* + * A file descriptor is stored in hash entry to allow + * nxt_poll_fd_hash_test() to not dereference a pointer to + * nxt_fd_event_t which may be invalid if the file descriptor has + * been already closed and the nxt_fd_event_t's memory has been freed. + */ + nxt_socket_t fd; + + uint32_t index; + void *event; } nxt_poll_hash_entry_t; - static nxt_int_t nxt_poll_create(nxt_event_engine_t *engine, - nxt_uint_t mchanges, nxt_uint_t mevents); + nxt_uint_t mchanges, nxt_uint_t mevents); static void nxt_poll_free(nxt_event_engine_t *engine); static void nxt_poll_enable(nxt_event_engine_t *engine, nxt_fd_event_t *ev); -static void nxt_poll_disable(nxt_event_engine_t *engine, - nxt_fd_event_t *ev); +static void nxt_poll_disable(nxt_event_engine_t *engine, nxt_fd_event_t *ev); static nxt_bool_t nxt_poll_close(nxt_event_engine_t *engine, - nxt_fd_event_t *ev); + nxt_fd_event_t *ev); static void nxt_poll_enable_read(nxt_event_engine_t *engine, - nxt_fd_event_t *ev); + nxt_fd_event_t *ev); static void nxt_poll_enable_write(nxt_event_engine_t *engine, - nxt_fd_event_t *ev); + nxt_fd_event_t *ev); static void nxt_poll_disable_read(nxt_event_engine_t *engine, - nxt_fd_event_t *ev); + nxt_fd_event_t *ev); static void nxt_poll_disable_write(nxt_event_engine_t *engine, - nxt_fd_event_t *ev); + nxt_fd_event_t *ev); static void nxt_poll_block_read(nxt_event_engine_t *engine, nxt_fd_event_t *ev); static void nxt_poll_block_write(nxt_event_engine_t *engine, - nxt_fd_event_t *ev); + nxt_fd_event_t *ev); static void nxt_poll_oneshot_read(nxt_event_engine_t *engine, - nxt_fd_event_t *ev); + nxt_fd_event_t *ev); static void nxt_poll_oneshot_write(nxt_event_engine_t *engine, - nxt_fd_event_t *ev); + nxt_fd_event_t *ev); static void nxt_poll_change(nxt_event_engine_t *engine, nxt_fd_event_t *ev, - nxt_uint_t op, nxt_uint_t events); + nxt_uint_t op, nxt_uint_t events); static nxt_int_t nxt_poll_commit_changes(nxt_event_engine_t *engine); static nxt_int_t nxt_poll_set_add(nxt_event_engine_t *engine, - nxt_fd_event_t *ev, int events); -static nxt_int_t nxt_poll_set_change(nxt_event_engine_t *engine, - nxt_fd_t fd, int events); + nxt_fd_event_t *ev, int events); +static nxt_int_t nxt_poll_set_change(nxt_event_engine_t *engine, nxt_fd_t fd, + int events); static nxt_int_t nxt_poll_set_delete(nxt_event_engine_t *engine, nxt_fd_t fd); static void nxt_poll(nxt_event_engine_t *engine, nxt_msec_t timeout); static nxt_poll_hash_entry_t *nxt_poll_fd_hash_get(nxt_event_engine_t *engine, - nxt_fd_t fd); + nxt_fd_t fd); static nxt_int_t nxt_poll_fd_hash_test(nxt_lvlhsh_query_t *lhq, void *data); static void nxt_poll_fd_hash_destroy(nxt_event_engine_t *engine, - nxt_lvlhsh_t *lh); - + nxt_lvlhsh_t *lh); -const nxt_event_interface_t nxt_poll_engine = { +const nxt_event_interface_t nxt_poll_engine = { "poll", nxt_poll_create, nxt_poll_free, @@ -94,601 +89,547 @@ const nxt_event_interface_t nxt_poll_engine = { NXT_NO_SIGNAL_EVENTS, }; - -static const nxt_lvlhsh_proto_t nxt_poll_fd_hash_proto nxt_aligned(64) = -{ +static const nxt_lvlhsh_proto_t nxt_poll_fd_hash_proto nxt_aligned(64) = { NXT_LVLHSH_LARGE_MEMALIGN, nxt_poll_fd_hash_test, nxt_lvlhsh_alloc, nxt_lvlhsh_free, }; +static nxt_int_t nxt_poll_create(nxt_event_engine_t *engine, + nxt_uint_t mchanges, nxt_uint_t mevents) { + engine->u.poll.mchanges = mchanges; -static nxt_int_t -nxt_poll_create(nxt_event_engine_t *engine, nxt_uint_t mchanges, - nxt_uint_t mevents) -{ - engine->u.poll.mchanges = mchanges; - - engine->u.poll.changes = nxt_malloc(sizeof(nxt_poll_change_t) * mchanges); + engine->u.poll.changes = nxt_malloc(sizeof(nxt_poll_change_t) * mchanges); - if (engine->u.poll.changes != NULL) { - return NXT_OK; - } + if (engine->u.poll.changes != NULL) { + return NXT_OK; + } - return NXT_ERROR; + return NXT_ERROR; } +static void nxt_poll_free(nxt_event_engine_t *engine) { + nxt_debug(&engine->task, "poll free"); -static void -nxt_poll_free(nxt_event_engine_t *engine) -{ - nxt_debug(&engine->task, "poll free"); - - nxt_free(engine->u.poll.set); - nxt_free(engine->u.poll.changes); - nxt_poll_fd_hash_destroy(engine, &engine->u.poll.fd_hash); + nxt_free(engine->u.poll.set); + nxt_free(engine->u.poll.changes); + nxt_poll_fd_hash_destroy(engine, &engine->u.poll.fd_hash); - nxt_memzero(&engine->u.poll, sizeof(nxt_poll_engine_t)); + nxt_memzero(&engine->u.poll, sizeof(nxt_poll_engine_t)); } +static void nxt_poll_enable(nxt_event_engine_t *engine, nxt_fd_event_t *ev) { + ev->read = NXT_EVENT_ACTIVE; + ev->write = NXT_EVENT_ACTIVE; -static void -nxt_poll_enable(nxt_event_engine_t *engine, nxt_fd_event_t *ev) -{ - ev->read = NXT_EVENT_ACTIVE; - ev->write = NXT_EVENT_ACTIVE; - - nxt_poll_change(engine, ev, NXT_POLL_ADD, POLLIN | POLLOUT); + nxt_poll_change(engine, ev, NXT_POLL_ADD, POLLIN | POLLOUT); } +static void nxt_poll_disable(nxt_event_engine_t *engine, nxt_fd_event_t *ev) { + if (ev->read != NXT_EVENT_INACTIVE && ev->write != NXT_EVENT_INACTIVE) { + ev->read = NXT_EVENT_INACTIVE; + ev->write = NXT_EVENT_INACTIVE; -static void -nxt_poll_disable(nxt_event_engine_t *engine, nxt_fd_event_t *ev) -{ - if (ev->read != NXT_EVENT_INACTIVE && ev->write != NXT_EVENT_INACTIVE) { - ev->read = NXT_EVENT_INACTIVE; - ev->write = NXT_EVENT_INACTIVE; - - nxt_poll_change(engine, ev, NXT_POLL_DELETE, 0); - } + nxt_poll_change(engine, ev, NXT_POLL_DELETE, 0); + } } +static nxt_bool_t nxt_poll_close(nxt_event_engine_t *engine, + nxt_fd_event_t *ev) { + nxt_poll_disable(engine, ev); -static nxt_bool_t -nxt_poll_close(nxt_event_engine_t *engine, nxt_fd_event_t *ev) -{ - nxt_poll_disable(engine, ev); - - return ev->changing; + return ev->changing; } +static void nxt_poll_enable_read(nxt_event_engine_t *engine, + nxt_fd_event_t *ev) { + nxt_uint_t op, events; -static void -nxt_poll_enable_read(nxt_event_engine_t *engine, nxt_fd_event_t *ev) -{ - nxt_uint_t op, events; - - ev->read = NXT_EVENT_ACTIVE; + ev->read = NXT_EVENT_ACTIVE; - if (ev->write == NXT_EVENT_INACTIVE) { - op = NXT_POLL_ADD; - events = POLLIN; + if (ev->write == NXT_EVENT_INACTIVE) { + op = NXT_POLL_ADD; + events = POLLIN; - } else { - op = NXT_POLL_CHANGE; - events = POLLIN | POLLOUT; - } + } else { + op = NXT_POLL_CHANGE; + events = POLLIN | POLLOUT; + } - nxt_poll_change(engine, ev, op, events); + nxt_poll_change(engine, ev, op, events); } +static void nxt_poll_enable_write(nxt_event_engine_t *engine, + nxt_fd_event_t *ev) { + nxt_uint_t op, events; -static void -nxt_poll_enable_write(nxt_event_engine_t *engine, nxt_fd_event_t *ev) -{ - nxt_uint_t op, events; - - ev->write = NXT_EVENT_ACTIVE; + ev->write = NXT_EVENT_ACTIVE; - if (ev->read == NXT_EVENT_INACTIVE) { - op = NXT_POLL_ADD; - events = POLLOUT; + if (ev->read == NXT_EVENT_INACTIVE) { + op = NXT_POLL_ADD; + events = POLLOUT; - } else { - op = NXT_POLL_CHANGE; - events = POLLIN | POLLOUT; - } + } else { + op = NXT_POLL_CHANGE; + events = POLLIN | POLLOUT; + } - nxt_poll_change(engine, ev, op, events); + nxt_poll_change(engine, ev, op, events); } +static void nxt_poll_disable_read(nxt_event_engine_t *engine, + nxt_fd_event_t *ev) { + nxt_uint_t op, events; -static void -nxt_poll_disable_read(nxt_event_engine_t *engine, nxt_fd_event_t *ev) -{ - nxt_uint_t op, events; + ev->read = NXT_EVENT_INACTIVE; - ev->read = NXT_EVENT_INACTIVE; + if (ev->write == NXT_EVENT_INACTIVE) { + op = NXT_POLL_DELETE; + events = 0; - if (ev->write == NXT_EVENT_INACTIVE) { - op = NXT_POLL_DELETE; - events = 0; + } else { + op = NXT_POLL_CHANGE; + events = POLLOUT; + } - } else { - op = NXT_POLL_CHANGE; - events = POLLOUT; - } - - nxt_poll_change(engine, ev, op, events); + nxt_poll_change(engine, ev, op, events); } +static void nxt_poll_disable_write(nxt_event_engine_t *engine, + nxt_fd_event_t *ev) { + nxt_uint_t op, events; -static void -nxt_poll_disable_write(nxt_event_engine_t *engine, nxt_fd_event_t *ev) -{ - nxt_uint_t op, events; - - ev->write = NXT_EVENT_INACTIVE; + ev->write = NXT_EVENT_INACTIVE; - if (ev->read == NXT_EVENT_INACTIVE) { - op = NXT_POLL_DELETE; - events = 0; + if (ev->read == NXT_EVENT_INACTIVE) { + op = NXT_POLL_DELETE; + events = 0; - } else { - op = NXT_POLL_CHANGE; - events = POLLIN; - } + } else { + op = NXT_POLL_CHANGE; + events = POLLIN; + } - nxt_poll_change(engine, ev, op, events); + nxt_poll_change(engine, ev, op, events); } - -static void -nxt_poll_block_read(nxt_event_engine_t *engine, nxt_fd_event_t *ev) -{ - if (ev->read != NXT_EVENT_INACTIVE) { - nxt_poll_disable_read(engine, ev); - } +static void nxt_poll_block_read(nxt_event_engine_t *engine, + nxt_fd_event_t *ev) { + if (ev->read != NXT_EVENT_INACTIVE) { + nxt_poll_disable_read(engine, ev); + } } - -static void -nxt_poll_block_write(nxt_event_engine_t *engine, nxt_fd_event_t *ev) -{ - if (ev->write != NXT_EVENT_INACTIVE) { - nxt_poll_disable_write(engine, ev); - } +static void nxt_poll_block_write(nxt_event_engine_t *engine, + nxt_fd_event_t *ev) { + if (ev->write != NXT_EVENT_INACTIVE) { + nxt_poll_disable_write(engine, ev); + } } +static void nxt_poll_oneshot_read(nxt_event_engine_t *engine, + nxt_fd_event_t *ev) { + nxt_uint_t op; -static void -nxt_poll_oneshot_read(nxt_event_engine_t *engine, nxt_fd_event_t *ev) -{ - nxt_uint_t op; - - op = (ev->read == NXT_EVENT_INACTIVE && ev->write == NXT_EVENT_INACTIVE) ? - NXT_POLL_ADD : NXT_POLL_CHANGE; + op = (ev->read == NXT_EVENT_INACTIVE && ev->write == NXT_EVENT_INACTIVE) + ? NXT_POLL_ADD + : NXT_POLL_CHANGE; - ev->read = NXT_EVENT_ONESHOT; - ev->write = NXT_EVENT_INACTIVE; + ev->read = NXT_EVENT_ONESHOT; + ev->write = NXT_EVENT_INACTIVE; - nxt_poll_change(engine, ev, op, POLLIN); + nxt_poll_change(engine, ev, op, POLLIN); } +static void nxt_poll_oneshot_write(nxt_event_engine_t *engine, + nxt_fd_event_t *ev) { + nxt_uint_t op; -static void -nxt_poll_oneshot_write(nxt_event_engine_t *engine, nxt_fd_event_t *ev) -{ - nxt_uint_t op; - - op = (ev->read == NXT_EVENT_INACTIVE && ev->write == NXT_EVENT_INACTIVE) ? - NXT_POLL_ADD : NXT_POLL_CHANGE; + op = (ev->read == NXT_EVENT_INACTIVE && ev->write == NXT_EVENT_INACTIVE) + ? NXT_POLL_ADD + : NXT_POLL_CHANGE; - ev->read = NXT_EVENT_INACTIVE; - ev->write = NXT_EVENT_ONESHOT; + ev->read = NXT_EVENT_INACTIVE; + ev->write = NXT_EVENT_ONESHOT; - nxt_poll_change(engine, ev, op, POLLOUT); + nxt_poll_change(engine, ev, op, POLLOUT); } - /* * poll changes are batched to improve instruction and data cache * locality of several lvlhsh operations followed by poll() call. */ -static void -nxt_poll_change(nxt_event_engine_t *engine, nxt_fd_event_t *ev, nxt_uint_t op, - nxt_uint_t events) -{ - nxt_poll_change_t *change; +static void nxt_poll_change(nxt_event_engine_t *engine, nxt_fd_event_t *ev, + nxt_uint_t op, nxt_uint_t events) { + nxt_poll_change_t *change; - nxt_debug(ev->task, "poll change: fd:%d op:%d ev:%XD", ev->fd, op, events); + nxt_debug(ev->task, "poll change: fd:%d op:%d ev:%XD", ev->fd, op, events); - if (engine->u.poll.nchanges >= engine->u.poll.mchanges) { - (void) nxt_poll_commit_changes(engine); - } + if (engine->u.poll.nchanges >= engine->u.poll.mchanges) { + (void)nxt_poll_commit_changes(engine); + } - ev->changing = 1; + ev->changing = 1; - change = &engine->u.poll.changes[engine->u.poll.nchanges++]; - change->op = op; - change->events = events; - change->event = ev; + change = &engine->u.poll.changes[engine->u.poll.nchanges++]; + change->op = op; + change->events = events; + change->event = ev; } +static nxt_int_t nxt_poll_commit_changes(nxt_event_engine_t *engine) { + nxt_int_t ret, retval; + nxt_fd_event_t *ev; + nxt_poll_change_t *change, *end; -static nxt_int_t -nxt_poll_commit_changes(nxt_event_engine_t *engine) -{ - nxt_int_t ret, retval; - nxt_fd_event_t *ev; - nxt_poll_change_t *change, *end; - - nxt_debug(&engine->task, "poll changes:%ui", engine->u.poll.nchanges); + nxt_debug(&engine->task, "poll changes:%ui", engine->u.poll.nchanges); - retval = NXT_OK; - change = engine->u.poll.changes; - end = change + engine->u.poll.nchanges; + retval = NXT_OK; + change = engine->u.poll.changes; + end = change + engine->u.poll.nchanges; - do { - ev = change->event; - ev->changing = 0; + do { + ev = change->event; + ev->changing = 0; - switch (change->op) { + switch (change->op) { - case NXT_POLL_ADD: - ret = nxt_poll_set_add(engine, ev, change->events); + case NXT_POLL_ADD: + ret = nxt_poll_set_add(engine, ev, change->events); - if (nxt_fast_path(ret == NXT_OK)) { - goto next; - } + if (nxt_fast_path(ret == NXT_OK)) { + goto next; + } - break; + break; - case NXT_POLL_CHANGE: - ret = nxt_poll_set_change(engine, ev->fd, change->events); + case NXT_POLL_CHANGE: + ret = nxt_poll_set_change(engine, ev->fd, change->events); - if (nxt_fast_path(ret == NXT_OK)) { - goto next; - } + if (nxt_fast_path(ret == NXT_OK)) { + goto next; + } - break; + break; - case NXT_POLL_DELETE: - ret = nxt_poll_set_delete(engine, ev->fd); + case NXT_POLL_DELETE: + ret = nxt_poll_set_delete(engine, ev->fd); - if (nxt_fast_path(ret == NXT_OK)) { - goto next; - } + if (nxt_fast_path(ret == NXT_OK)) { + goto next; + } - break; - } + break; + } - nxt_work_queue_add(&engine->fast_work_queue, ev->error_handler, - ev->task, ev, ev->data); + nxt_work_queue_add(&engine->fast_work_queue, ev->error_handler, ev->task, + ev, ev->data); - retval = NXT_ERROR; + retval = NXT_ERROR; - next: + next: - change++; + change++; - } while (change < end); + } while (change < end); - engine->u.poll.nchanges = 0; + engine->u.poll.nchanges = 0; - return retval; + return retval; } +static nxt_int_t nxt_poll_set_add(nxt_event_engine_t *engine, + nxt_fd_event_t *ev, int events) { + nxt_int_t ret; + nxt_uint_t max_nfds; + struct pollfd *pfd; + nxt_lvlhsh_query_t lhq; + nxt_poll_hash_entry_t *phe; -static nxt_int_t -nxt_poll_set_add(nxt_event_engine_t *engine, nxt_fd_event_t *ev, int events) -{ - nxt_int_t ret; - nxt_uint_t max_nfds; - struct pollfd *pfd; - nxt_lvlhsh_query_t lhq; - nxt_poll_hash_entry_t *phe; - - nxt_debug(&engine->task, "poll add event: fd:%d ev:%04Xi", ev->fd, events); - - if (engine->u.poll.nfds >= engine->u.poll.max_nfds) { - max_nfds = engine->u.poll.max_nfds + 512; /* 4K */ + nxt_debug(&engine->task, "poll add event: fd:%d ev:%04Xi", ev->fd, events); - pfd = nxt_realloc(engine->u.poll.set, sizeof(struct pollfd) * max_nfds); - if (nxt_slow_path(pfd == NULL)) { - return NXT_ERROR; - } + if (engine->u.poll.nfds >= engine->u.poll.max_nfds) { + max_nfds = engine->u.poll.max_nfds + 512; /* 4K */ - engine->u.poll.set = pfd; - engine->u.poll.max_nfds = max_nfds; + pfd = nxt_realloc(engine->u.poll.set, sizeof(struct pollfd) * max_nfds); + if (nxt_slow_path(pfd == NULL)) { + return NXT_ERROR; } - phe = nxt_malloc(sizeof(nxt_poll_hash_entry_t)); - if (nxt_slow_path(phe == NULL)) { - return NXT_ERROR; - } + engine->u.poll.set = pfd; + engine->u.poll.max_nfds = max_nfds; + } - phe->fd = ev->fd; - phe->index = engine->u.poll.nfds; - phe->event = ev; + phe = nxt_malloc(sizeof(nxt_poll_hash_entry_t)); + if (nxt_slow_path(phe == NULL)) { + return NXT_ERROR; + } - pfd = &engine->u.poll.set[engine->u.poll.nfds++]; - pfd->fd = ev->fd; - pfd->events = events; - pfd->revents = 0; + phe->fd = ev->fd; + phe->index = engine->u.poll.nfds; + phe->event = ev; - lhq.key_hash = nxt_murmur_hash2(&ev->fd, sizeof(nxt_fd_t)); - lhq.replace = 0; - lhq.value = phe; - lhq.proto = &nxt_poll_fd_hash_proto; - lhq.data = engine; + pfd = &engine->u.poll.set[engine->u.poll.nfds++]; + pfd->fd = ev->fd; + pfd->events = events; + pfd->revents = 0; - ret = nxt_lvlhsh_insert(&engine->u.poll.fd_hash, &lhq); + lhq.key_hash = nxt_murmur_hash2(&ev->fd, sizeof(nxt_fd_t)); + lhq.replace = 0; + lhq.value = phe; + lhq.proto = &nxt_poll_fd_hash_proto; + lhq.data = engine; - if (nxt_fast_path(ret == NXT_OK)) { - return NXT_OK; - } + ret = nxt_lvlhsh_insert(&engine->u.poll.fd_hash, &lhq); - nxt_free(phe); + if (nxt_fast_path(ret == NXT_OK)) { + return NXT_OK; + } - return NXT_ERROR; + nxt_free(phe); + + return NXT_ERROR; } +static nxt_int_t nxt_poll_set_change(nxt_event_engine_t *engine, nxt_fd_t fd, + int events) { + nxt_poll_hash_entry_t *phe; -static nxt_int_t -nxt_poll_set_change(nxt_event_engine_t *engine, nxt_fd_t fd, int events) -{ - nxt_poll_hash_entry_t *phe; + nxt_debug(&engine->task, "poll change event: fd:%d ev:%04Xi", fd, events); - nxt_debug(&engine->task, "poll change event: fd:%d ev:%04Xi", - fd, events); + phe = nxt_poll_fd_hash_get(engine, fd); - phe = nxt_poll_fd_hash_get(engine, fd); + if (nxt_fast_path(phe != NULL)) { + engine->u.poll.set[phe->index].events = events; + return NXT_OK; + } - if (nxt_fast_path(phe != NULL)) { - engine->u.poll.set[phe->index].events = events; - return NXT_OK; - } + return NXT_ERROR; +} + +static nxt_int_t nxt_poll_set_delete(nxt_event_engine_t *engine, nxt_fd_t fd) { + nxt_int_t ret; + nxt_uint_t index, nfds; + nxt_lvlhsh_query_t lhq; + nxt_poll_hash_entry_t *phe; + nxt_debug(&engine->task, "poll delete event: fd:%d", fd); + + lhq.key_hash = nxt_murmur_hash2(&fd, sizeof(nxt_fd_t)); + lhq.proto = &nxt_poll_fd_hash_proto; + lhq.data = engine; + + ret = nxt_lvlhsh_delete(&engine->u.poll.fd_hash, &lhq); + + if (nxt_slow_path(ret != NXT_OK)) { return NXT_ERROR; -} + } + phe = lhq.value; -static nxt_int_t -nxt_poll_set_delete(nxt_event_engine_t *engine, nxt_fd_t fd) -{ - nxt_int_t ret; - nxt_uint_t index, nfds; - nxt_lvlhsh_query_t lhq; - nxt_poll_hash_entry_t *phe; + index = phe->index; + engine->u.poll.nfds--; + nfds = engine->u.poll.nfds; - nxt_debug(&engine->task, "poll delete event: fd:%d", fd); + if (index != nfds) { + engine->u.poll.set[index] = engine->u.poll.set[nfds]; - lhq.key_hash = nxt_murmur_hash2(&fd, sizeof(nxt_fd_t)); - lhq.proto = &nxt_poll_fd_hash_proto; - lhq.data = engine; + phe = nxt_poll_fd_hash_get(engine, engine->u.poll.set[nfds].fd); - ret = nxt_lvlhsh_delete(&engine->u.poll.fd_hash, &lhq); + phe->index = index; + } + + nxt_free(lhq.value); + + return NXT_OK; +} - if (nxt_slow_path(ret != NXT_OK)) { - return NXT_ERROR; +static void nxt_poll(nxt_event_engine_t *engine, nxt_msec_t timeout) { + int nevents; + nxt_fd_t fd; + nxt_err_t err; + nxt_bool_t error; + nxt_uint_t i, events, level; + struct pollfd *pfd; + nxt_fd_event_t *ev; + nxt_poll_hash_entry_t *phe; + + if (engine->u.poll.nchanges != 0) { + if (nxt_poll_commit_changes(engine) != NXT_OK) { + /* Error handlers have been enqueued on failure. */ + timeout = 0; } + } - phe = lhq.value; + nxt_debug(&engine->task, "poll() events:%ui timeout:%M", engine->u.poll.nfds, + timeout); - index = phe->index; - engine->u.poll.nfds--; - nfds = engine->u.poll.nfds; + nevents = poll(engine->u.poll.set, engine->u.poll.nfds, timeout); - if (index != nfds) { - engine->u.poll.set[index] = engine->u.poll.set[nfds]; + err = (nevents == -1) ? nxt_errno : 0; - phe = nxt_poll_fd_hash_get(engine, engine->u.poll.set[nfds].fd); + nxt_thread_time_update(engine->task.thread); - phe->index = index; - } + nxt_debug(&engine->task, "poll(): %d", nevents); - nxt_free(lhq.value); + if (nevents == -1) { + level = (err == NXT_EINTR) ? NXT_LOG_INFO : NXT_LOG_ALERT; + nxt_log(&engine->task, level, "poll() failed %E", err); + return; + } - return NXT_OK; -} + for (i = 0; i < engine->u.poll.nfds && nevents != 0; i++) { + pfd = &engine->u.poll.set[i]; + events = pfd->revents; -static void -nxt_poll(nxt_event_engine_t *engine, nxt_msec_t timeout) -{ - int nevents; - nxt_fd_t fd; - nxt_err_t err; - nxt_bool_t error; - nxt_uint_t i, events, level; - struct pollfd *pfd; - nxt_fd_event_t *ev; - nxt_poll_hash_entry_t *phe; - - if (engine->u.poll.nchanges != 0) { - if (nxt_poll_commit_changes(engine) != NXT_OK) { - /* Error handlers have been enqueued on failure. */ - timeout = 0; - } + if (events == 0) { + continue; } - nxt_debug(&engine->task, "poll() events:%ui timeout:%M", - engine->u.poll.nfds, timeout); + fd = pfd->fd; - nevents = poll(engine->u.poll.set, engine->u.poll.nfds, timeout); + phe = nxt_poll_fd_hash_get(engine, fd); - err = (nevents == -1) ? nxt_errno : 0; + if (nxt_slow_path(phe == NULL)) { + nxt_alert(&engine->task, + "poll() returned invalid fd:%d ev:%04Xd rev:%04uXi", fd, + pfd->events, events); - nxt_thread_time_update(engine->task.thread); + /* Mark the poll entry to ignore it by the kernel. */ + pfd->fd = -1; + goto next; + } - nxt_debug(&engine->task, "poll(): %d", nevents); + ev = phe->event; - if (nevents == -1) { - level = (err == NXT_EINTR) ? NXT_LOG_INFO : NXT_LOG_ALERT; - nxt_log(&engine->task, level, "poll() failed %E", err); - return; - } + nxt_debug(ev->task, "poll: fd:%d ev:%04uXi rd:%d wr:%d", fd, events, + ev->read, ev->write); + + if (nxt_slow_path((events & POLLNVAL) != 0)) { + nxt_alert(ev->task, "poll() error fd:%d ev:%04Xd rev:%04uXi", fd, + pfd->events, events); - for (i = 0; i < engine->u.poll.nfds && nevents != 0; i++) { - - pfd = &engine->u.poll.set[i]; - events = pfd->revents; - - if (events == 0) { - continue; - } - - fd = pfd->fd; - - phe = nxt_poll_fd_hash_get(engine, fd); - - if (nxt_slow_path(phe == NULL)) { - nxt_alert(&engine->task, - "poll() returned invalid fd:%d ev:%04Xd rev:%04uXi", - fd, pfd->events, events); - - /* Mark the poll entry to ignore it by the kernel. */ - pfd->fd = -1; - goto next; - } - - ev = phe->event; - - nxt_debug(ev->task, "poll: fd:%d ev:%04uXi rd:%d wr:%d", - fd, events, ev->read, ev->write); - - if (nxt_slow_path((events & POLLNVAL) != 0)) { - nxt_alert(ev->task, "poll() error fd:%d ev:%04Xd rev:%04uXi", - fd, pfd->events, events); - - /* Mark the poll entry to ignore it by the kernel. */ - pfd->fd = -1; - - nxt_work_queue_add(&engine->fast_work_queue, - ev->error_handler, ev->task, ev, ev->data); - goto next; - } - - /* - * On a socket's remote end close: - * - * Linux, FreeBSD, and Solaris set POLLIN; - * MacOSX sets POLLIN and POLLHUP; - * NetBSD sets POLLIN, and poll(2) claims this explicitly: - * - * If the remote end of a socket is closed, poll() - * returns a POLLIN event, rather than a POLLHUP. - * - * On error: - * - * Linux sets POLLHUP and POLLERR only; - * FreeBSD adds POLLHUP to POLLIN or POLLOUT, although poll(2) - * claims the opposite: - * - * Note that POLLHUP and POLLOUT should never be - * present in the revents bitmask at the same time. - * - * Solaris and NetBSD do not add POLLHUP or POLLERR; - * MacOSX sets POLLHUP only. - * - * If an implementation sets POLLERR or POLLHUP only without POLLIN - * or POLLOUT, the "error" variable enqueues only one active handler. - */ - - error = (((events & (POLLERR | POLLHUP)) != 0) - && ((events & (POLLIN | POLLOUT)) == 0)); - - if ((events & POLLIN) || (error && ev->read_handler != NULL)) { - error = 0; - ev->read_ready = 1; - - if (ev->read == NXT_EVENT_ONESHOT) { - ev->read = NXT_EVENT_INACTIVE; - nxt_poll_change(engine, ev, NXT_POLL_DELETE, 0); - } - - nxt_work_queue_add(ev->read_work_queue, ev->read_handler, - ev->task, ev, ev->data); - } - - if ((events & POLLOUT) || (error && ev->write_handler != NULL)) { - ev->write_ready = 1; - - if (ev->write == NXT_EVENT_ONESHOT) { - ev->write = NXT_EVENT_INACTIVE; - nxt_poll_change(engine, ev, NXT_POLL_DELETE, 0); - } - - nxt_work_queue_add(ev->write_work_queue, ev->write_handler, - ev->task, ev, ev->data); - } - - next: - - nevents--; + /* Mark the poll entry to ignore it by the kernel. */ + pfd->fd = -1; + + nxt_work_queue_add(&engine->fast_work_queue, ev->error_handler, ev->task, + ev, ev->data); + goto next; } -} + /* + * On a socket's remote end close: + * + * Linux, FreeBSD, and Solaris set POLLIN; + * MacOSX sets POLLIN and POLLHUP; + * NetBSD sets POLLIN, and poll(2) claims this explicitly: + * + * If the remote end of a socket is closed, poll() + * returns a POLLIN event, rather than a POLLHUP. + * + * On error: + * + * Linux sets POLLHUP and POLLERR only; + * FreeBSD adds POLLHUP to POLLIN or POLLOUT, although poll(2) + * claims the opposite: + * + * Note that POLLHUP and POLLOUT should never be + * present in the revents bitmask at the same time. + * + * Solaris and NetBSD do not add POLLHUP or POLLERR; + * MacOSX sets POLLHUP only. + * + * If an implementation sets POLLERR or POLLHUP only without POLLIN + * or POLLOUT, the "error" variable enqueues only one active handler. + */ + + error = (((events & (POLLERR | POLLHUP)) != 0) && + ((events & (POLLIN | POLLOUT)) == 0)); -static nxt_poll_hash_entry_t * -nxt_poll_fd_hash_get(nxt_event_engine_t *engine, nxt_fd_t fd) -{ - nxt_lvlhsh_query_t lhq; - nxt_poll_hash_entry_t *phe; + if ((events & POLLIN) || (error && ev->read_handler != NULL)) { + error = 0; + ev->read_ready = 1; - lhq.key_hash = nxt_murmur_hash2(&fd, sizeof(nxt_fd_t)); - lhq.proto = &nxt_poll_fd_hash_proto; - lhq.data = engine; + if (ev->read == NXT_EVENT_ONESHOT) { + ev->read = NXT_EVENT_INACTIVE; + nxt_poll_change(engine, ev, NXT_POLL_DELETE, 0); + } - if (nxt_lvlhsh_find(&engine->u.poll.fd_hash, &lhq) == NXT_OK) { - phe = lhq.value; - return phe; + nxt_work_queue_add(ev->read_work_queue, ev->read_handler, ev->task, ev, + ev->data); } - nxt_alert(&engine->task, "fd %d not found in hash", fd); + if ((events & POLLOUT) || (error && ev->write_handler != NULL)) { + ev->write_ready = 1; - return NULL; -} + if (ev->write == NXT_EVENT_ONESHOT) { + ev->write = NXT_EVENT_INACTIVE; + nxt_poll_change(engine, ev, NXT_POLL_DELETE, 0); + } + nxt_work_queue_add(ev->write_work_queue, ev->write_handler, ev->task, ev, + ev->data); + } -static nxt_int_t -nxt_poll_fd_hash_test(nxt_lvlhsh_query_t *lhq, void *data) -{ - nxt_event_engine_t *engine; - nxt_poll_hash_entry_t *phe; + next: - phe = data; + nevents--; + } +} - /* nxt_murmur_hash2() is unique for 4 bytes. */ +static nxt_poll_hash_entry_t *nxt_poll_fd_hash_get(nxt_event_engine_t *engine, + nxt_fd_t fd) { + nxt_lvlhsh_query_t lhq; + nxt_poll_hash_entry_t *phe; - engine = lhq->data; + lhq.key_hash = nxt_murmur_hash2(&fd, sizeof(nxt_fd_t)); + lhq.proto = &nxt_poll_fd_hash_proto; + lhq.data = engine; - if (nxt_fast_path(phe->fd == engine->u.poll.set[phe->index].fd)) { - return NXT_OK; - } + if (nxt_lvlhsh_find(&engine->u.poll.fd_hash, &lhq) == NXT_OK) { + phe = lhq.value; + return phe; + } - nxt_alert(&engine->task, "fd %d in hash mismatches fd %d in poll set", - phe->fd, engine->u.poll.set[phe->index].fd); + nxt_alert(&engine->task, "fd %d not found in hash", fd); - return NXT_DECLINED; + return NULL; } +static nxt_int_t nxt_poll_fd_hash_test(nxt_lvlhsh_query_t *lhq, void *data) { + nxt_event_engine_t *engine; + nxt_poll_hash_entry_t *phe; -static void -nxt_poll_fd_hash_destroy(nxt_event_engine_t *engine, nxt_lvlhsh_t *lh) -{ - nxt_poll_hash_entry_t *phe; + phe = data; - for ( ;; ) { - phe = nxt_lvlhsh_retrieve(lh, &nxt_poll_fd_hash_proto, NULL); + /* nxt_murmur_hash2() is unique for 4 bytes. */ - if (phe == NULL) { - return; - } + engine = lhq->data; - nxt_free(phe); + if (nxt_fast_path(phe->fd == engine->u.poll.set[phe->index].fd)) { + return NXT_OK; + } + + nxt_alert(&engine->task, "fd %d in hash mismatches fd %d in poll set", + phe->fd, engine->u.poll.set[phe->index].fd); + + return NXT_DECLINED; +} + +static void nxt_poll_fd_hash_destroy(nxt_event_engine_t *engine, + nxt_lvlhsh_t *lh) { + nxt_poll_hash_entry_t *phe; + + for (;;) { + phe = nxt_lvlhsh_retrieve(lh, &nxt_poll_fd_hash_proto, NULL); + + if (phe == NULL) { + return; } + + nxt_free(phe); + } } diff --git a/src/nxt_pollset_engine.c b/src/nxt_pollset_engine.c index e2c1a2d01..e207104aa 100644 --- a/src/nxt_pollset_engine.c +++ b/src/nxt_pollset_engine.c @@ -6,7 +6,6 @@ #include - /* * pollset has been introduced in AIX 5L 5.3. * @@ -15,48 +14,45 @@ * The first pollset_create() call returns 0. */ - -#define NXT_POLLSET_ADD 0 -#define NXT_POLLSET_UPDATE 1 -#define NXT_POLLSET_CHANGE 2 -#define NXT_POLLSET_DELETE 3 - +#define NXT_POLLSET_ADD 0 +#define NXT_POLLSET_UPDATE 1 +#define NXT_POLLSET_CHANGE 2 +#define NXT_POLLSET_DELETE 3 static nxt_int_t nxt_pollset_create(nxt_event_engine_t *engine, - nxt_uint_t mchanges, nxt_uint_t mevents); + nxt_uint_t mchanges, nxt_uint_t mevents); static void nxt_pollset_free(nxt_event_engine_t *engine); static void nxt_pollset_enable(nxt_event_engine_t *engine, nxt_fd_event_t *ev); static void nxt_pollset_disable(nxt_event_engine_t *engine, nxt_fd_event_t *ev); static nxt_bool_t nxt_pollset_close(nxt_event_engine_t *engine, - nxt_fd_event_t *ev); + nxt_fd_event_t *ev); static void nxt_pollset_enable_read(nxt_event_engine_t *engine, - nxt_fd_event_t *ev); + nxt_fd_event_t *ev); static void nxt_pollset_enable_write(nxt_event_engine_t *engine, - nxt_fd_event_t *ev); + nxt_fd_event_t *ev); static void nxt_pollset_disable_read(nxt_event_engine_t *engine, - nxt_fd_event_t *ev); + nxt_fd_event_t *ev); static void nxt_pollset_disable_write(nxt_event_engine_t *engine, - nxt_fd_event_t *ev); + nxt_fd_event_t *ev); static void nxt_pollset_block_read(nxt_event_engine_t *engine, - nxt_fd_event_t *ev); + nxt_fd_event_t *ev); static void nxt_pollset_block_write(nxt_event_engine_t *engine, - nxt_fd_event_t *ev); + nxt_fd_event_t *ev); static void nxt_pollset_oneshot_read(nxt_event_engine_t *engine, - nxt_fd_event_t *ev); + nxt_fd_event_t *ev); static void nxt_pollset_oneshot_write(nxt_event_engine_t *engine, - nxt_fd_event_t *ev); + nxt_fd_event_t *ev); static void nxt_pollset_change(nxt_event_engine_t *engine, nxt_fd_event_t *ev, - nxt_uint_t op, nxt_uint_t events); + nxt_uint_t op, nxt_uint_t events); static nxt_int_t nxt_pollset_commit_changes(nxt_event_engine_t *engine); static void nxt_pollset_change_error(nxt_event_engine_t *engine, - nxt_fd_event_t *ev); + nxt_fd_event_t *ev); static void nxt_pollset_remove(nxt_event_engine_t *engine, nxt_fd_t fd); static nxt_int_t nxt_pollset_write(nxt_event_engine_t *engine, - struct poll_ctl *ctl, int n); + struct poll_ctl *ctl, int n); static void nxt_pollset_poll(nxt_event_engine_t *engine, nxt_msec_t timeout); - -const nxt_event_interface_t nxt_pollset_engine = { +const nxt_event_interface_t nxt_pollset_engine = { "pollset", nxt_pollset_create, nxt_pollset_free, @@ -85,105 +81,92 @@ const nxt_event_interface_t nxt_pollset_engine = { NXT_NO_SIGNAL_EVENTS, }; +static nxt_int_t nxt_pollset_create(nxt_event_engine_t *engine, + nxt_uint_t mchanges, nxt_uint_t mevents) { + void *changes; -static nxt_int_t -nxt_pollset_create(nxt_event_engine_t *engine, nxt_uint_t mchanges, - nxt_uint_t mevents) -{ - void *changes; - - engine->u.pollset.ps = -1; - engine->u.pollset.mchanges = mchanges; - engine->u.pollset.mevents = mevents; + engine->u.pollset.ps = -1; + engine->u.pollset.mchanges = mchanges; + engine->u.pollset.mevents = mevents; - changes = nxt_malloc(sizeof(nxt_pollset_change_t) * mchanges); - if (changes == NULL) { - goto fail; - } + changes = nxt_malloc(sizeof(nxt_pollset_change_t) * mchanges); + if (changes == NULL) { + goto fail; + } - engine->u.pollset.changes = changes; + engine->u.pollset.changes = changes; - /* - * NXT_POLLSET_CHANGE requires two struct poll_ctl's - * for PS_DELETE and subsequent PS_ADD. - */ - changes = nxt_malloc(2 * sizeof(struct poll_ctl) * mchanges); - if (changes == NULL) { - goto fail; - } + /* + * NXT_POLLSET_CHANGE requires two struct poll_ctl's + * for PS_DELETE and subsequent PS_ADD. + */ + changes = nxt_malloc(2 * sizeof(struct poll_ctl) * mchanges); + if (changes == NULL) { + goto fail; + } - engine->u.pollset.write_changes = changes; + engine->u.pollset.write_changes = changes; - engine->u.pollset.events = nxt_malloc(sizeof(struct pollfd) * mevents); - if (engine->u.pollset.events == NULL) { - goto fail; - } + engine->u.pollset.events = nxt_malloc(sizeof(struct pollfd) * mevents); + if (engine->u.pollset.events == NULL) { + goto fail; + } - engine->u.pollset.ps = pollset_create(-1); + engine->u.pollset.ps = pollset_create(-1); - if (engine->u.pollset.ps == -1) { - nxt_alert(&engine->task, "pollset_create() failed %E", nxt_errno); - goto fail; - } + if (engine->u.pollset.ps == -1) { + nxt_alert(&engine->task, "pollset_create() failed %E", nxt_errno); + goto fail; + } - nxt_debug(&engine->task, "pollset_create(): %d", engine->u.pollset.ps); + nxt_debug(&engine->task, "pollset_create(): %d", engine->u.pollset.ps); - return NXT_OK; + return NXT_OK; fail: - nxt_pollset_free(engine); + nxt_pollset_free(engine); - return NXT_ERROR; + return NXT_ERROR; } +static void nxt_pollset_free(nxt_event_engine_t *engine) { + pollset_t ps; -static void -nxt_pollset_free(nxt_event_engine_t *engine) -{ - pollset_t ps; + ps = engine->u.pollset.ps; - ps = engine->u.pollset.ps; + nxt_debug(&engine->task, "pollset %d free", ps); - nxt_debug(&engine->task, "pollset %d free", ps); + if (ps != -1 && pollset_destroy(ps) != 0) { + nxt_alert(&engine->task, "pollset_destroy(%d) failed %E", ps, nxt_errno); + } - if (ps != -1 && pollset_destroy(ps) != 0) { - nxt_alert(&engine->task, "pollset_destroy(%d) failed %E", - ps, nxt_errno); - } - - nxt_free(engine->u.pollset.events); - nxt_free(engine->u.pollset.write_changes); - nxt_free(engine->u.pollset.changes); - nxt_fd_event_hash_destroy(&engine->u.pollset.fd_hash); + nxt_free(engine->u.pollset.events); + nxt_free(engine->u.pollset.write_changes); + nxt_free(engine->u.pollset.changes); + nxt_fd_event_hash_destroy(&engine->u.pollset.fd_hash); - nxt_memzero(&engine->u.pollset, sizeof(nxt_pollset_engine_t)); + nxt_memzero(&engine->u.pollset, sizeof(nxt_pollset_engine_t)); } +static void nxt_pollset_enable(nxt_event_engine_t *engine, nxt_fd_event_t *ev) { + ev->read = NXT_EVENT_ACTIVE; + ev->write = NXT_EVENT_ACTIVE; -static void -nxt_pollset_enable(nxt_event_engine_t *engine, nxt_fd_event_t *ev) -{ - ev->read = NXT_EVENT_ACTIVE; - ev->write = NXT_EVENT_ACTIVE; - - nxt_pollset_change(engine, ev, NXT_POLLSET_ADD, POLLIN | POLLOUT); + nxt_pollset_change(engine, ev, NXT_POLLSET_ADD, POLLIN | POLLOUT); } +static void nxt_pollset_disable(nxt_event_engine_t *engine, + nxt_fd_event_t *ev) { + if (ev->read != NXT_EVENT_INACTIVE || ev->write != NXT_EVENT_INACTIVE) { -static void -nxt_pollset_disable(nxt_event_engine_t *engine, nxt_fd_event_t *ev) -{ - if (ev->read != NXT_EVENT_INACTIVE || ev->write != NXT_EVENT_INACTIVE) { - - ev->read = NXT_EVENT_INACTIVE; - ev->write = NXT_EVENT_INACTIVE; + ev->read = NXT_EVENT_INACTIVE; + ev->write = NXT_EVENT_INACTIVE; - nxt_pollset_change(engine, ev, NXT_POLLSET_DELETE, 0); - } + nxt_pollset_change(engine, ev, NXT_POLLSET_DELETE, 0); + } } - /* * A closed descriptor must be deleted from a pollset, otherwise next * pollset_poll() will return POLLNVAL on it. However, pollset_ctl() @@ -199,149 +182,131 @@ nxt_pollset_disable(nxt_event_engine_t *engine, nxt_fd_event_t *ev) * the new object will be polled on future pollset_poll calls. */ -static nxt_bool_t -nxt_pollset_close(nxt_event_engine_t *engine, nxt_fd_event_t *ev) -{ - nxt_pollset_disable(engine, ev); +static nxt_bool_t nxt_pollset_close(nxt_event_engine_t *engine, + nxt_fd_event_t *ev) { + nxt_pollset_disable(engine, ev); - return ev->changing; + return ev->changing; } +static void nxt_pollset_enable_read(nxt_event_engine_t *engine, + nxt_fd_event_t *ev) { + nxt_uint_t op, events; -static void -nxt_pollset_enable_read(nxt_event_engine_t *engine, nxt_fd_event_t *ev) -{ - nxt_uint_t op, events; - - if (ev->read != NXT_EVENT_BLOCKED) { - - events = POLLIN; + if (ev->read != NXT_EVENT_BLOCKED) { - if (ev->write == NXT_EVENT_INACTIVE) { - op = NXT_POLLSET_ADD; + events = POLLIN; - } else if (ev->write == NXT_EVENT_BLOCKED) { - ev->write = NXT_EVENT_INACTIVE; - op = NXT_POLLSET_CHANGE; + if (ev->write == NXT_EVENT_INACTIVE) { + op = NXT_POLLSET_ADD; - } else { - op = NXT_POLLSET_UPDATE; - events = POLLIN | POLLOUT; - } + } else if (ev->write == NXT_EVENT_BLOCKED) { + ev->write = NXT_EVENT_INACTIVE; + op = NXT_POLLSET_CHANGE; - nxt_pollset_change(engine, ev, op, events); + } else { + op = NXT_POLLSET_UPDATE; + events = POLLIN | POLLOUT; } - ev->read = NXT_EVENT_ACTIVE; -} - + nxt_pollset_change(engine, ev, op, events); + } -static void -nxt_pollset_enable_write(nxt_event_engine_t *engine, nxt_fd_event_t *ev) -{ - nxt_uint_t op, events; + ev->read = NXT_EVENT_ACTIVE; +} - if (ev->write != NXT_EVENT_BLOCKED) { +static void nxt_pollset_enable_write(nxt_event_engine_t *engine, + nxt_fd_event_t *ev) { + nxt_uint_t op, events; - events = POLLOUT; + if (ev->write != NXT_EVENT_BLOCKED) { - if (ev->read == NXT_EVENT_INACTIVE) { - op = NXT_POLLSET_ADD; + events = POLLOUT; - } else if (ev->read == NXT_EVENT_BLOCKED) { - ev->read = NXT_EVENT_INACTIVE; - op = NXT_POLLSET_CHANGE; + if (ev->read == NXT_EVENT_INACTIVE) { + op = NXT_POLLSET_ADD; - } else { - op = NXT_POLLSET_UPDATE; - events = POLLIN | POLLOUT; - } + } else if (ev->read == NXT_EVENT_BLOCKED) { + ev->read = NXT_EVENT_INACTIVE; + op = NXT_POLLSET_CHANGE; - nxt_pollset_change(engine, ev, op, events); + } else { + op = NXT_POLLSET_UPDATE; + events = POLLIN | POLLOUT; } - ev->write = NXT_EVENT_ACTIVE; + nxt_pollset_change(engine, ev, op, events); + } + + ev->write = NXT_EVENT_ACTIVE; } +static void nxt_pollset_disable_read(nxt_event_engine_t *engine, + nxt_fd_event_t *ev) { + nxt_uint_t op, events; -static void -nxt_pollset_disable_read(nxt_event_engine_t *engine, nxt_fd_event_t *ev) -{ - nxt_uint_t op, events; + ev->read = NXT_EVENT_INACTIVE; - ev->read = NXT_EVENT_INACTIVE; - - if (ev->write <= NXT_EVENT_BLOCKED) { - ev->write = NXT_EVENT_INACTIVE; - op = NXT_POLLSET_DELETE; - events = POLLREMOVE; + if (ev->write <= NXT_EVENT_BLOCKED) { + ev->write = NXT_EVENT_INACTIVE; + op = NXT_POLLSET_DELETE; + events = POLLREMOVE; - } else { - op = NXT_POLLSET_CHANGE; - events = POLLOUT; - } + } else { + op = NXT_POLLSET_CHANGE; + events = POLLOUT; + } - nxt_pollset_change(engine, ev, op, events); + nxt_pollset_change(engine, ev, op, events); } +static void nxt_pollset_disable_write(nxt_event_engine_t *engine, + nxt_fd_event_t *ev) { + nxt_uint_t op, events; -static void -nxt_pollset_disable_write(nxt_event_engine_t *engine, nxt_fd_event_t *ev) -{ - nxt_uint_t op, events; - - ev->write = NXT_EVENT_INACTIVE; + ev->write = NXT_EVENT_INACTIVE; - if (ev->read <= NXT_EVENT_BLOCKED) { - ev->read = NXT_EVENT_INACTIVE; - op = NXT_POLLSET_DELETE; - events = POLLREMOVE; + if (ev->read <= NXT_EVENT_BLOCKED) { + ev->read = NXT_EVENT_INACTIVE; + op = NXT_POLLSET_DELETE; + events = POLLREMOVE; - } else { - op = NXT_POLLSET_CHANGE; - events = POLLIN; - } + } else { + op = NXT_POLLSET_CHANGE; + events = POLLIN; + } - nxt_pollset_change(engine, ev, op, events); + nxt_pollset_change(engine, ev, op, events); } - -static void -nxt_pollset_block_read(nxt_event_engine_t *engine, nxt_fd_event_t *ev) -{ - if (ev->read != NXT_EVENT_INACTIVE) { - ev->read = NXT_EVENT_BLOCKED; - } +static void nxt_pollset_block_read(nxt_event_engine_t *engine, + nxt_fd_event_t *ev) { + if (ev->read != NXT_EVENT_INACTIVE) { + ev->read = NXT_EVENT_BLOCKED; + } } - -static void -nxt_pollset_block_write(nxt_event_engine_t *engine, nxt_fd_event_t *ev) -{ - if (ev->write != NXT_EVENT_INACTIVE) { - ev->write = NXT_EVENT_BLOCKED; - } +static void nxt_pollset_block_write(nxt_event_engine_t *engine, + nxt_fd_event_t *ev) { + if (ev->write != NXT_EVENT_INACTIVE) { + ev->write = NXT_EVENT_BLOCKED; + } } +static void nxt_pollset_oneshot_read(nxt_event_engine_t *engine, + nxt_fd_event_t *ev) { + nxt_pollset_enable_read(engine, ev); -static void -nxt_pollset_oneshot_read(nxt_event_engine_t *engine, nxt_fd_event_t *ev) -{ - nxt_pollset_enable_read(engine, ev); - - ev->read = NXT_EVENT_ONESHOT; + ev->read = NXT_EVENT_ONESHOT; } +static void nxt_pollset_oneshot_write(nxt_event_engine_t *engine, + nxt_fd_event_t *ev) { + nxt_pollset_enable_write(engine, ev); -static void -nxt_pollset_oneshot_write(nxt_event_engine_t *engine, nxt_fd_event_t *ev) -{ - nxt_pollset_enable_write(engine, ev); - - ev->write = NXT_EVENT_ONESHOT; + ev->write = NXT_EVENT_ONESHOT; } - /* * PS_ADD adds only a new file descriptor to a pollset. * PS_DELETE removes a file descriptor from a pollset. @@ -353,293 +318,271 @@ nxt_pollset_oneshot_write(nxt_event_engine_t *engine, nxt_fd_event_t *ev) * added again without the event. */ -static void -nxt_pollset_change(nxt_event_engine_t *engine, nxt_fd_event_t *ev, - nxt_uint_t op, nxt_uint_t events) -{ - nxt_pollset_change_t *change; +static void nxt_pollset_change(nxt_event_engine_t *engine, nxt_fd_event_t *ev, + nxt_uint_t op, nxt_uint_t events) { + nxt_pollset_change_t *change; - nxt_debug(ev->task, "pollset %d change fd:%d op:%ui ev:%04Xi", - engine->u.pollset.ps, ev->fd, op, events); + nxt_debug(ev->task, "pollset %d change fd:%d op:%ui ev:%04Xi", + engine->u.pollset.ps, ev->fd, op, events); - if (engine->u.pollset.nchanges >= engine->u.pollset.mchanges) { - (void) nxt_pollset_commit_changes(engine); - } + if (engine->u.pollset.nchanges >= engine->u.pollset.mchanges) { + (void)nxt_pollset_commit_changes(engine); + } - ev->changing = 1; + ev->changing = 1; - change = &engine->u.pollset.changes[engine->u.pollset.nchanges++]; - change->op = op; - change->cmd = (op == NXT_POLLSET_DELETE) ? PS_DELETE : PS_MOD; - change->events = events; - change->event = ev; + change = &engine->u.pollset.changes[engine->u.pollset.nchanges++]; + change->op = op; + change->cmd = (op == NXT_POLLSET_DELETE) ? PS_DELETE : PS_MOD; + change->events = events; + change->event = ev; } +static nxt_int_t nxt_pollset_commit_changes(nxt_event_engine_t *engine) { + size_t n; + nxt_int_t ret, retval; + nxt_fd_event_t *ev; + struct poll_ctl *ctl, *write_changes; + nxt_pollset_change_t *change, *end; + + nxt_debug(&engine->task, "pollset %d changes:%ui", engine->u.pollset.ps, + engine->u.pollset.nchanges); + + retval = NXT_OK; + n = 0; + write_changes = engine->u.pollset.write_changes; + change = engine->u.pollset.changes; + end = change + engine->u.pollset.nchanges; + + do { + ev = change->event; + ev->changing = 0; + + nxt_debug(&engine->task, "pollset fd:%d op:%d ev:%04Xd", ev->fd, change->op, + change->events); + + if (change->op == NXT_POLLSET_CHANGE) { + ctl = &write_changes[n++]; + ctl->cmd = PS_DELETE; + ctl->events = 0; + ctl->fd = ev->fd; + } -static nxt_int_t -nxt_pollset_commit_changes(nxt_event_engine_t *engine) -{ - size_t n; - nxt_int_t ret, retval; - nxt_fd_event_t *ev; - struct poll_ctl *ctl, *write_changes; - nxt_pollset_change_t *change, *end; - - nxt_debug(&engine->task, "pollset %d changes:%ui", - engine->u.pollset.ps, engine->u.pollset.nchanges); - - retval = NXT_OK; - n = 0; - write_changes = engine->u.pollset.write_changes; - change = engine->u.pollset.changes; - end = change + engine->u.pollset.nchanges; + ctl = &write_changes[n++]; + ctl->cmd = change->cmd; + ctl->events = change->events; + ctl->fd = ev->fd; - do { - ev = change->event; - ev->changing = 0; + change++; - nxt_debug(&engine->task, "pollset fd:%d op:%d ev:%04Xd", - ev->fd, change->op, change->events); + } while (change < end); - if (change->op == NXT_POLLSET_CHANGE) { - ctl = &write_changes[n++]; - ctl->cmd = PS_DELETE; - ctl->events = 0; - ctl->fd = ev->fd; - } + change = engine->u.pollset.changes; + end = change + engine->u.pollset.nchanges; - ctl = &write_changes[n++]; - ctl->cmd = change->cmd; - ctl->events = change->events; - ctl->fd = ev->fd; + ret = nxt_pollset_write(engine, write_changes, n); - change++; + if (nxt_slow_path(ret != NXT_OK)) { + do { + nxt_pollset_change_error(engine, change->event); + change++; } while (change < end); - change = engine->u.pollset.changes; - end = change + engine->u.pollset.nchanges; + engine->u.pollset.nchanges = 0; - ret = nxt_pollset_write(engine, write_changes, n); + return NXT_ERROR; + } - if (nxt_slow_path(ret != NXT_OK)) { + do { + ev = change->event; - do { - nxt_pollset_change_error(engine, change->event); - change++; - } while (change < end); + if (change->op == NXT_POLLSET_ADD) { + ret = nxt_fd_event_hash_add(&engine->u.pollset.fd_hash, ev->fd, ev); - engine->u.pollset.nchanges = 0; + if (nxt_slow_path(ret != NXT_OK)) { + nxt_pollset_change_error(engine, ev); + retval = NXT_ERROR; + } - return NXT_ERROR; + } else if (change->op == NXT_POLLSET_DELETE) { + nxt_fd_event_hash_delete(&engine->task, &engine->u.pollset.fd_hash, + ev->fd, 0); } - do { - ev = change->event; + /* Nothing to do for NXT_POLLSET_UPDATE and NXT_POLLSET_CHANGE. */ - if (change->op == NXT_POLLSET_ADD) { - ret = nxt_fd_event_hash_add(&engine->u.pollset.fd_hash, ev->fd, ev); + change++; - if (nxt_slow_path(ret != NXT_OK)) { - nxt_pollset_change_error(engine, ev); - retval = NXT_ERROR; - } + } while (change < end); - } else if (change->op == NXT_POLLSET_DELETE) { - nxt_fd_event_hash_delete(&engine->task, &engine->u.pollset.fd_hash, - ev->fd, 0); - } + engine->u.pollset.nchanges = 0; - /* Nothing to do for NXT_POLLSET_UPDATE and NXT_POLLSET_CHANGE. */ + return retval; +} - change++; +static void nxt_pollset_change_error(nxt_event_engine_t *engine, + nxt_fd_event_t *ev) { + ev->read = NXT_EVENT_INACTIVE; + ev->write = NXT_EVENT_INACTIVE; - } while (change < end); + nxt_work_queue_add(&engine->fast_work_queue, ev->error_handler, ev->task, ev, + ev->data); - engine->u.pollset.nchanges = 0; + nxt_fd_event_hash_delete(&engine->task, &engine->u.pollset.fd_hash, ev->fd, + 1); - return retval; + nxt_pollset_remove(engine, ev->fd); } +static void nxt_pollset_remove(nxt_event_engine_t *engine, nxt_fd_t fd) { + int n; + struct pollfd pfd; + struct poll_ctl ctl; -static void -nxt_pollset_change_error(nxt_event_engine_t *engine, nxt_fd_event_t *ev) -{ - ev->read = NXT_EVENT_INACTIVE; - ev->write = NXT_EVENT_INACTIVE; + pfd.fd = fd; + pfd.events = 0; + pfd.revents = 0; - nxt_work_queue_add(&engine->fast_work_queue, ev->error_handler, - ev->task, ev, ev->data); + n = pollset_query(engine->u.pollset.ps, &pfd); - nxt_fd_event_hash_delete(&engine->task, &engine->u.pollset.fd_hash, - ev->fd, 1); + nxt_debug(&engine->task, "pollset_query(%d, %d): %d", engine->u.pollset.ps, + fd, n); - nxt_pollset_remove(engine, ev->fd); -} + if (n == 0) { + /* The file descriptor is not in the pollset. */ + return; + } + if (n == -1) { + nxt_alert(&engine->task, "pollset_query(%d, %d) failed %E", + engine->u.pollset.ps, fd, nxt_errno); + /* Fall through. */ + } -static void -nxt_pollset_remove(nxt_event_engine_t *engine, nxt_fd_t fd) -{ - int n; - struct pollfd pfd; - struct poll_ctl ctl; + /* n == 1: The file descriptor is in the pollset. */ - pfd.fd = fd; - pfd.events = 0; - pfd.revents = 0; + nxt_debug(&engine->task, "pollset %d remove fd:%d", engine->u.pollset.ps, fd); - n = pollset_query(engine->u.pollset.ps, &pfd); + ctl.cmd = PS_DELETE; + ctl.events = 0; + ctl.fd = fd; - nxt_debug(&engine->task, "pollset_query(%d, %d): %d", - engine->u.pollset.ps, fd, n); + nxt_pollset_write(engine, &ctl, 1); +} - if (n == 0) { - /* The file descriptor is not in the pollset. */ - return; - } +static nxt_int_t nxt_pollset_write(nxt_event_engine_t *engine, + struct poll_ctl *ctl, int n) { + pollset_t ps; - if (n == -1) { - nxt_alert(&engine->task, "pollset_query(%d, %d) failed %E", - engine->u.pollset.ps, fd, nxt_errno); - /* Fall through. */ - } + ps = engine->u.pollset.ps; + + nxt_debug(&engine->task, "pollset_ctl(%d) changes:%d", ps, n); - /* n == 1: The file descriptor is in the pollset. */ + nxt_set_errno(0); - nxt_debug(&engine->task, "pollset %d remove fd:%d", - engine->u.pollset.ps, fd); + n = pollset_ctl(ps, ctl, n); - ctl.cmd = PS_DELETE; - ctl.events = 0; - ctl.fd = fd; + if (nxt_fast_path(n == 0)) { + return NXT_OK; + } - nxt_pollset_write(engine, &ctl, 1); + nxt_alert(&engine->task, "pollset_ctl(%d) failed: %d %E", ps, n, nxt_errno); + + return NXT_ERROR; } +static void nxt_pollset_poll(nxt_event_engine_t *engine, nxt_msec_t timeout) { + int nevents; + nxt_fd_t fd; + nxt_int_t i; + nxt_err_t err; + nxt_uint_t events, level; + struct pollfd *pfd; + nxt_fd_event_t *ev; + + if (engine->u.pollset.nchanges != 0) { + if (nxt_pollset_commit_changes(engine) != NXT_OK) { + /* Error handlers have been enqueued on failure. */ + timeout = 0; + } + } -static nxt_int_t -nxt_pollset_write(nxt_event_engine_t *engine, struct poll_ctl *ctl, int n) -{ - pollset_t ps; + nxt_debug(&engine->task, "pollset_poll(%d) timeout:%M", engine->u.pollset.ps, + timeout); - ps = engine->u.pollset.ps; + nevents = pollset_poll(engine->u.pollset.ps, engine->u.pollset.events, + engine->u.pollset.mevents, timeout); - nxt_debug(&engine->task, "pollset_ctl(%d) changes:%d", ps, n); + err = (nevents == -1) ? nxt_errno : 0; - nxt_set_errno(0); + nxt_thread_time_update(engine->task.thread); - n = pollset_ctl(ps, ctl, n); + nxt_debug(&engine->task, "pollset_poll(%d): %d", engine->u.pollset.ps, + nevents); - if (nxt_fast_path(n == 0)) { - return NXT_OK; - } + if (nevents == -1) { + level = (err == NXT_EINTR) ? NXT_LOG_INFO : NXT_LOG_ALERT; - nxt_alert(&engine->task, "pollset_ctl(%d) failed: %d %E", ps, n, nxt_errno); + nxt_log(&engine->task, level, "pollset_poll(%d) failed %E", + engine->u.pollset.ps, err); - return NXT_ERROR; -} + return; + } + for (i = 0; i < nevents; i++) { -static void -nxt_pollset_poll(nxt_event_engine_t *engine, nxt_msec_t timeout) -{ - int nevents; - nxt_fd_t fd; - nxt_int_t i; - nxt_err_t err; - nxt_uint_t events, level; - struct pollfd *pfd; - nxt_fd_event_t *ev; - - if (engine->u.pollset.nchanges != 0) { - if (nxt_pollset_commit_changes(engine) != NXT_OK) { - /* Error handlers have been enqueued on failure. */ - timeout = 0; - } - } + pfd = &engine->u.pollset.events[i]; + fd = pfd->fd; + events = pfd->revents; - nxt_debug(&engine->task, "pollset_poll(%d) timeout:%M", - engine->u.pollset.ps, timeout); + ev = nxt_fd_event_hash_get(&engine->task, &engine->u.pollset.fd_hash, fd); - nevents = pollset_poll(engine->u.pollset.ps, engine->u.pollset.events, - engine->u.pollset.mevents, timeout); + if (nxt_slow_path(ev == NULL)) { + nxt_alert(&engine->task, + "pollset_poll(%d) returned invalid " + "fd:%d ev:%04Xd rev:%04uXi", + engine->u.pollset.ps, fd, pfd->events, events); - err = (nevents == -1) ? nxt_errno : 0; + nxt_pollset_remove(engine, fd); + continue; + } + + nxt_debug(ev->task, "pollset: fd:%d ev:%04uXi", fd, events); - nxt_thread_time_update(engine->task.thread); + if (nxt_slow_path(events & (POLLERR | POLLHUP | POLLNVAL)) != 0) { + nxt_alert(ev->task, "pollset_poll(%d) error fd:%d ev:%04Xd rev:%04uXi", + engine->u.pollset.ps, fd, pfd->events, events); - nxt_debug(&engine->task, "pollset_poll(%d): %d", - engine->u.pollset.ps, nevents); + nxt_work_queue_add(&engine->fast_work_queue, ev->error_handler, ev->task, + ev, ev->data); + continue; + } - if (nevents == -1) { - level = (err == NXT_EINTR) ? NXT_LOG_INFO : NXT_LOG_ALERT; + if (events & POLLIN) { + ev->read_ready = 1; - nxt_log(&engine->task, level, "pollset_poll(%d) failed %E", - engine->u.pollset.ps, err); + if (ev->read != NXT_EVENT_BLOCKED) { + nxt_work_queue_add(ev->read_work_queue, ev->read_handler, ev->task, ev, + ev->data); + } - return; + if (ev->read == NXT_EVENT_BLOCKED || ev->read == NXT_EVENT_ONESHOT) { + nxt_pollset_disable_read(engine, ev); + } } - for (i = 0; i < nevents; i++) { - - pfd = &engine->u.pollset.events[i]; - fd = pfd->fd; - events = pfd->revents; - - ev = nxt_fd_event_hash_get(&engine->task, &engine->u.pollset.fd_hash, - fd); - - if (nxt_slow_path(ev == NULL)) { - nxt_alert(&engine->task, - "pollset_poll(%d) returned invalid " - "fd:%d ev:%04Xd rev:%04uXi", - engine->u.pollset.ps, fd, pfd->events, events); - - nxt_pollset_remove(engine, fd); - continue; - } - - nxt_debug(ev->task, "pollset: fd:%d ev:%04uXi", fd, events); - - if (nxt_slow_path(events & (POLLERR | POLLHUP | POLLNVAL)) != 0) { - nxt_alert(ev->task, - "pollset_poll(%d) error fd:%d ev:%04Xd rev:%04uXi", - engine->u.pollset.ps, fd, pfd->events, events); - - nxt_work_queue_add(&engine->fast_work_queue, ev->error_handler, - ev->task, ev, ev->data); - continue; - } - - if (events & POLLIN) { - ev->read_ready = 1; - - if (ev->read != NXT_EVENT_BLOCKED) { - nxt_work_queue_add(ev->read_work_queue, ev->read_handler, - ev->task, ev, ev->data); - } - - if (ev->read == NXT_EVENT_BLOCKED - || ev->read == NXT_EVENT_ONESHOT) - { - nxt_pollset_disable_read(engine, ev); - } - } - - if (events & POLLOUT) { - ev->write_ready = 1; - - if (ev->write != NXT_EVENT_BLOCKED) { - nxt_work_queue_add(ev->write_work_queue, ev->write_handler, - ev->task, ev, ev->data); - } - - if (ev->write == NXT_EVENT_BLOCKED - || ev->write == NXT_EVENT_ONESHOT) - { - nxt_pollset_disable_write(engine, ev); - } - } + if (events & POLLOUT) { + ev->write_ready = 1; + + if (ev->write != NXT_EVENT_BLOCKED) { + nxt_work_queue_add(ev->write_work_queue, ev->write_handler, ev->task, + ev, ev->data); + } + + if (ev->write == NXT_EVENT_BLOCKED || ev->write == NXT_EVENT_ONESHOT) { + nxt_pollset_disable_write(engine, ev); + } } + } } diff --git a/src/nxt_port.c b/src/nxt_port.c index b9964df46..65df9b409 100644 --- a/src/nxt_port.c +++ b/src/nxt_port.c @@ -11,621 +11,540 @@ #include #include - static void nxt_port_remove_pid(nxt_task_t *task, nxt_port_recv_msg_t *msg, - nxt_pid_t pid); + nxt_pid_t pid); static void nxt_port_handler(nxt_task_t *task, nxt_port_recv_msg_t *msg); static nxt_atomic_uint_t nxt_port_last_id = 1; +static void nxt_port_mp_cleanup(nxt_task_t *task, void *obj, void *data) { + nxt_mp_t *mp; + nxt_port_t *port; -static void -nxt_port_mp_cleanup(nxt_task_t *task, void *obj, void *data) -{ - nxt_mp_t *mp; - nxt_port_t *port; - - port = obj; - mp = data; + port = obj; + mp = data; - nxt_assert(port->pair[0] == -1); - nxt_assert(port->pair[1] == -1); + nxt_assert(port->pair[0] == -1); + nxt_assert(port->pair[1] == -1); - nxt_assert(port->use_count == 0); - nxt_assert(port->app_link.next == NULL); - nxt_assert(port->idle_link.next == NULL); + nxt_assert(port->use_count == 0); + nxt_assert(port->app_link.next == NULL); + nxt_assert(port->idle_link.next == NULL); - nxt_assert(nxt_queue_is_empty(&port->messages)); - nxt_assert(nxt_lvlhsh_is_empty(&port->rpc_streams)); - nxt_assert(nxt_lvlhsh_is_empty(&port->rpc_peers)); + nxt_assert(nxt_queue_is_empty(&port->messages)); + nxt_assert(nxt_lvlhsh_is_empty(&port->rpc_streams)); + nxt_assert(nxt_lvlhsh_is_empty(&port->rpc_peers)); - nxt_thread_mutex_destroy(&port->write_mutex); + nxt_thread_mutex_destroy(&port->write_mutex); - nxt_mp_free(mp, port); + nxt_mp_free(mp, port); } +nxt_port_t *nxt_port_new(nxt_task_t *task, nxt_port_id_t id, nxt_pid_t pid, + nxt_process_type_t type) { + nxt_mp_t *mp; + nxt_port_t *port; -nxt_port_t * -nxt_port_new(nxt_task_t *task, nxt_port_id_t id, nxt_pid_t pid, - nxt_process_type_t type) -{ - nxt_mp_t *mp; - nxt_port_t *port; + mp = nxt_mp_create(1024, 128, 256, 32); - mp = nxt_mp_create(1024, 128, 256, 32); + if (nxt_slow_path(mp == NULL)) { + return NULL; + } - if (nxt_slow_path(mp == NULL)) { - return NULL; - } + port = nxt_mp_zalloc(mp, sizeof(nxt_port_t)); - port = nxt_mp_zalloc(mp, sizeof(nxt_port_t)); + if (nxt_fast_path(port != NULL)) { + port->id = id; + port->pid = pid; + port->type = type; + port->mem_pool = mp; + port->use_count = 1; - if (nxt_fast_path(port != NULL)) { - port->id = id; - port->pid = pid; - port->type = type; - port->mem_pool = mp; - port->use_count = 1; + nxt_mp_cleanup(mp, nxt_port_mp_cleanup, task, port, mp); - nxt_mp_cleanup(mp, nxt_port_mp_cleanup, task, port, mp); + nxt_queue_init(&port->messages); + nxt_thread_mutex_create(&port->write_mutex); - nxt_queue_init(&port->messages); - nxt_thread_mutex_create(&port->write_mutex); + port->queue_fd = -1; - port->queue_fd = -1; - - } else { - nxt_mp_destroy(mp); - } + } else { + nxt_mp_destroy(mp); + } - nxt_thread_log_debug("port %p %d:%d new, type %d", port, pid, id, type); + nxt_thread_log_debug("port %p %d:%d new, type %d", port, pid, id, type); - return port; + return port; } +void nxt_port_close(nxt_task_t *task, nxt_port_t *port) { + size_t size; -void -nxt_port_close(nxt_task_t *task, nxt_port_t *port) -{ - size_t size; + nxt_debug(task, "port %p %d:%d close, type %d", port, port->pid, port->id, + port->type); - nxt_debug(task, "port %p %d:%d close, type %d", port, port->pid, - port->id, port->type); + if (port->pair[0] != -1) { + nxt_port_rpc_close(task, port); - if (port->pair[0] != -1) { - nxt_port_rpc_close(task, port); - - nxt_fd_close(port->pair[0]); - port->pair[0] = -1; - } + nxt_fd_close(port->pair[0]); + port->pair[0] = -1; + } - if (port->pair[1] != -1) { - nxt_fd_close(port->pair[1]); - port->pair[1] = -1; + if (port->pair[1] != -1) { + nxt_fd_close(port->pair[1]); + port->pair[1] = -1; - if (port->app != NULL) { - nxt_router_app_port_close(task, port); - } + if (port->app != NULL) { + nxt_router_app_port_close(task, port); } + } - if (port->queue_fd != -1) { - nxt_fd_close(port->queue_fd); - port->queue_fd = -1; - } + if (port->queue_fd != -1) { + nxt_fd_close(port->queue_fd); + port->queue_fd = -1; + } - if (port->queue != NULL) { - size = (port->id == (nxt_port_id_t) -1) ? sizeof(nxt_app_queue_t) - : sizeof(nxt_port_queue_t); - nxt_mem_munmap(port->queue, size); + if (port->queue != NULL) { + size = (port->id == (nxt_port_id_t)-1) ? sizeof(nxt_app_queue_t) + : sizeof(nxt_port_queue_t); + nxt_mem_munmap(port->queue, size); - port->queue = NULL; - } + port->queue = NULL; + } } +static void nxt_port_release(nxt_task_t *task, nxt_port_t *port) { + nxt_debug(task, "port %p %d:%d release, type %d", port, port->pid, port->id, + port->type); -static void -nxt_port_release(nxt_task_t *task, nxt_port_t *port) -{ - nxt_debug(task, "port %p %d:%d release, type %d", port, port->pid, - port->id, port->type); + port->app = NULL; - port->app = NULL; + if (port->link.next != NULL) { + nxt_assert(port->process != NULL); - if (port->link.next != NULL) { - nxt_assert(port->process != NULL); + nxt_process_port_remove(port); - nxt_process_port_remove(port); + nxt_process_use(task, port->process, -1); + } - nxt_process_use(task, port->process, -1); - } - - nxt_mp_release(port->mem_pool); + nxt_mp_release(port->mem_pool); } - -nxt_port_id_t -nxt_port_get_next_id(void) -{ - return nxt_atomic_fetch_add(&nxt_port_last_id, 1); +nxt_port_id_t nxt_port_get_next_id(void) { + return nxt_atomic_fetch_add(&nxt_port_last_id, 1); } +void nxt_port_reset_next_id(void) { nxt_port_last_id = 1; } -void -nxt_port_reset_next_id(void) -{ - nxt_port_last_id = 1; -} - +void nxt_port_enable(nxt_task_t *task, nxt_port_t *port, + const nxt_port_handlers_t *handlers) { + port->pid = nxt_pid; + port->handler = nxt_port_handler; + port->data = (nxt_port_handler_t *)(handlers); -void -nxt_port_enable(nxt_task_t *task, nxt_port_t *port, - const nxt_port_handlers_t *handlers) -{ - port->pid = nxt_pid; - port->handler = nxt_port_handler; - port->data = (nxt_port_handler_t *) (handlers); - - nxt_port_read_enable(task, port); + nxt_port_read_enable(task, port); } +static void nxt_port_handler(nxt_task_t *task, nxt_port_recv_msg_t *msg) { + nxt_port_handler_t *handlers; -static void -nxt_port_handler(nxt_task_t *task, nxt_port_recv_msg_t *msg) -{ - nxt_port_handler_t *handlers; - - if (nxt_fast_path(msg->port_msg.type < NXT_PORT_MSG_MAX)) { + if (nxt_fast_path(msg->port_msg.type < NXT_PORT_MSG_MAX)) { - nxt_debug(task, "port %d: message type:%uD fds:%d,%d", - msg->port->socket.fd, msg->port_msg.type, - msg->fd[0], msg->fd[1]); + nxt_debug(task, "port %d: message type:%uD fds:%d,%d", msg->port->socket.fd, + msg->port_msg.type, msg->fd[0], msg->fd[1]); - handlers = msg->port->data; - handlers[msg->port_msg.type](task, msg); + handlers = msg->port->data; + handlers[msg->port_msg.type](task, msg); - return; - } + return; + } - nxt_alert(task, "port %d: unknown message type:%uD", - msg->port->socket.fd, msg->port_msg.type); + nxt_alert(task, "port %d: unknown message type:%uD", msg->port->socket.fd, + msg->port_msg.type); } - -void -nxt_port_quit_handler(nxt_task_t *task, nxt_port_recv_msg_t *msg) -{ - nxt_runtime_quit(task, 0); +void nxt_port_quit_handler(nxt_task_t *task, nxt_port_recv_msg_t *msg) { + nxt_runtime_quit(task, 0); } - /* TODO join with process_ready and move to nxt_main_process.c */ -nxt_inline void -nxt_port_send_new_port(nxt_task_t *task, nxt_runtime_t *rt, - nxt_port_t *new_port, uint32_t stream) -{ - nxt_port_t *port; - nxt_process_t *process; - - nxt_debug(task, "new port %d for process %PI", - new_port->pair[1], new_port->pid); +nxt_inline void nxt_port_send_new_port(nxt_task_t *task, nxt_runtime_t *rt, + nxt_port_t *new_port, uint32_t stream) { + nxt_port_t *port; + nxt_process_t *process; - nxt_runtime_process_each(rt, process) { + nxt_debug(task, "new port %d for process %PI", new_port->pair[1], + new_port->pid); - if (process->pid == new_port->pid || process->pid == nxt_pid) { - continue; - } + nxt_runtime_process_each(rt, process) { - port = nxt_process_port_first(process); + if (process->pid == new_port->pid || process->pid == nxt_pid) { + continue; + } - if (nxt_proc_send_matrix[port->type][new_port->type]) { - (void) nxt_port_send_port(task, port, new_port, stream); - } + port = nxt_process_port_first(process); - } nxt_runtime_process_loop; + if (nxt_proc_send_matrix[port->type][new_port->type]) { + (void)nxt_port_send_port(task, port, new_port, stream); + } + } + nxt_runtime_process_loop; } +nxt_int_t nxt_port_send_port(nxt_task_t *task, nxt_port_t *port, + nxt_port_t *new_port, uint32_t stream) { + nxt_buf_t *b; + nxt_port_msg_new_port_t *msg; -nxt_int_t -nxt_port_send_port(nxt_task_t *task, nxt_port_t *port, nxt_port_t *new_port, - uint32_t stream) -{ - nxt_buf_t *b; - nxt_port_msg_new_port_t *msg; + b = nxt_buf_mem_ts_alloc(task, task->thread->engine->mem_pool, + sizeof(nxt_port_data_t)); + if (nxt_slow_path(b == NULL)) { + return NXT_ERROR; + } - b = nxt_buf_mem_ts_alloc(task, task->thread->engine->mem_pool, - sizeof(nxt_port_data_t)); - if (nxt_slow_path(b == NULL)) { - return NXT_ERROR; - } - - nxt_debug(task, "send port %FD to process %PI", - new_port->pair[1], port->pid); + nxt_debug(task, "send port %FD to process %PI", new_port->pair[1], port->pid); - b->mem.free += sizeof(nxt_port_msg_new_port_t); - msg = (nxt_port_msg_new_port_t *) b->mem.pos; + b->mem.free += sizeof(nxt_port_msg_new_port_t); + msg = (nxt_port_msg_new_port_t *)b->mem.pos; - msg->id = new_port->id; - msg->pid = new_port->pid; - msg->max_size = port->max_size; - msg->max_share = port->max_share; - msg->type = new_port->type; + msg->id = new_port->id; + msg->pid = new_port->pid; + msg->max_size = port->max_size; + msg->max_share = port->max_share; + msg->type = new_port->type; - return nxt_port_socket_write2(task, port, NXT_PORT_MSG_NEW_PORT, - new_port->pair[1], new_port->queue_fd, - stream, 0, b); + return nxt_port_socket_write2(task, port, NXT_PORT_MSG_NEW_PORT, + new_port->pair[1], new_port->queue_fd, stream, + 0, b); } +void nxt_port_new_port_handler(nxt_task_t *task, nxt_port_recv_msg_t *msg) { + nxt_port_t *port; + nxt_runtime_t *rt; + nxt_port_msg_new_port_t *new_port_msg; -void -nxt_port_new_port_handler(nxt_task_t *task, nxt_port_recv_msg_t *msg) -{ - nxt_port_t *port; - nxt_runtime_t *rt; - nxt_port_msg_new_port_t *new_port_msg; + rt = task->thread->runtime; - rt = task->thread->runtime; + new_port_msg = (nxt_port_msg_new_port_t *)msg->buf->mem.pos; - new_port_msg = (nxt_port_msg_new_port_t *) msg->buf->mem.pos; + /* TODO check b size and make plain */ - /* TODO check b size and make plain */ + nxt_debug(task, "new port %d received for process %PI:%d", msg->fd[0], + new_port_msg->pid, new_port_msg->id); - nxt_debug(task, "new port %d received for process %PI:%d", - msg->fd[0], new_port_msg->pid, new_port_msg->id); - - port = nxt_runtime_port_find(rt, new_port_msg->pid, new_port_msg->id); - if (port != NULL) { - nxt_debug(task, "port %PI:%d already exists", new_port_msg->pid, + port = nxt_runtime_port_find(rt, new_port_msg->pid, new_port_msg->id); + if (port != NULL) { + nxt_debug(task, "port %PI:%d already exists", new_port_msg->pid, new_port_msg->id); - msg->u.new_port = port; + msg->u.new_port = port; - nxt_fd_close(msg->fd[0]); - msg->fd[0] = -1; - return; - } + nxt_fd_close(msg->fd[0]); + msg->fd[0] = -1; + return; + } - port = nxt_runtime_process_port_create(task, rt, new_port_msg->pid, - new_port_msg->id, - new_port_msg->type); - if (nxt_slow_path(port == NULL)) { - return; - } + port = nxt_runtime_process_port_create(task, rt, new_port_msg->pid, + new_port_msg->id, new_port_msg->type); + if (nxt_slow_path(port == NULL)) { + return; + } - nxt_fd_nonblocking(task, msg->fd[0]); + nxt_fd_nonblocking(task, msg->fd[0]); - port->pair[0] = -1; - port->pair[1] = msg->fd[0]; - port->max_size = new_port_msg->max_size; - port->max_share = new_port_msg->max_share; + port->pair[0] = -1; + port->pair[1] = msg->fd[0]; + port->max_size = new_port_msg->max_size; + port->max_share = new_port_msg->max_share; - port->socket.task = task; + port->socket.task = task; - nxt_port_write_enable(task, port); + nxt_port_write_enable(task, port); - msg->u.new_port = port; + msg->u.new_port = port; } /* TODO move to nxt_main_process.c */ -void -nxt_port_process_ready_handler(nxt_task_t *task, nxt_port_recv_msg_t *msg) -{ - nxt_port_t *port; - nxt_process_t *process; - nxt_runtime_t *rt; - - rt = task->thread->runtime; - - process = nxt_runtime_process_find(rt, msg->port_msg.pid); - if (nxt_slow_path(process == NULL)) { - return; - } +void nxt_port_process_ready_handler(nxt_task_t *task, + nxt_port_recv_msg_t *msg) { + nxt_port_t *port; + nxt_process_t *process; + nxt_runtime_t *rt; - nxt_assert(process->state != NXT_PROCESS_STATE_READY); + rt = task->thread->runtime; - process->state = NXT_PROCESS_STATE_READY; + process = nxt_runtime_process_find(rt, msg->port_msg.pid); + if (nxt_slow_path(process == NULL)) { + return; + } - nxt_assert(!nxt_queue_is_empty(&process->ports)); + nxt_assert(process->state != NXT_PROCESS_STATE_READY); - port = nxt_process_port_first(process); + process->state = NXT_PROCESS_STATE_READY; - nxt_debug(task, "process %PI ready", msg->port_msg.pid); + nxt_assert(!nxt_queue_is_empty(&process->ports)); - if (msg->fd[0] != -1) { - port->queue_fd = msg->fd[0]; - port->queue = nxt_mem_mmap(NULL, sizeof(nxt_port_queue_t), - PROT_READ | PROT_WRITE, MAP_SHARED, - msg->fd[0], 0); - } + port = nxt_process_port_first(process); - nxt_port_send_new_port(task, rt, port, msg->port_msg.stream); -} + nxt_debug(task, "process %PI ready", msg->port_msg.pid); + if (msg->fd[0] != -1) { + port->queue_fd = msg->fd[0]; + port->queue = + nxt_mem_mmap(NULL, sizeof(nxt_port_queue_t), PROT_READ | PROT_WRITE, + MAP_SHARED, msg->fd[0], 0); + } -void -nxt_port_mmap_handler(nxt_task_t *task, nxt_port_recv_msg_t *msg) -{ - nxt_runtime_t *rt; - nxt_process_t *process; + nxt_port_send_new_port(task, rt, port, msg->port_msg.stream); +} - rt = task->thread->runtime; +void nxt_port_mmap_handler(nxt_task_t *task, nxt_port_recv_msg_t *msg) { + nxt_runtime_t *rt; + nxt_process_t *process; - if (nxt_slow_path(msg->fd[0] == -1)) { - nxt_log(task, NXT_LOG_WARN, "invalid fd passed with mmap message"); + rt = task->thread->runtime; - return; - } + if (nxt_slow_path(msg->fd[0] == -1)) { + nxt_log(task, NXT_LOG_WARN, "invalid fd passed with mmap message"); - process = nxt_runtime_process_find(rt, msg->port_msg.pid); - if (nxt_slow_path(process == NULL)) { - nxt_log(task, NXT_LOG_WARN, "failed to get process #%PI", - msg->port_msg.pid); + return; + } - goto fail_close; - } + process = nxt_runtime_process_find(rt, msg->port_msg.pid); + if (nxt_slow_path(process == NULL)) { + nxt_log(task, NXT_LOG_WARN, "failed to get process #%PI", + msg->port_msg.pid); - nxt_port_incoming_port_mmap(task, process, msg->fd[0]); + goto fail_close; + } + + nxt_port_incoming_port_mmap(task, process, msg->fd[0]); fail_close: - nxt_fd_close(msg->fd[0]); + nxt_fd_close(msg->fd[0]); } +void nxt_port_change_log_file(nxt_task_t *task, nxt_runtime_t *rt, + nxt_uint_t slot, nxt_fd_t fd) { + nxt_buf_t *b; + nxt_port_t *port; + nxt_process_t *process; -void -nxt_port_change_log_file(nxt_task_t *task, nxt_runtime_t *rt, nxt_uint_t slot, - nxt_fd_t fd) -{ - nxt_buf_t *b; - nxt_port_t *port; - nxt_process_t *process; + nxt_debug(task, "change log file #%ui fd:%FD", slot, fd); - nxt_debug(task, "change log file #%ui fd:%FD", slot, fd); + nxt_runtime_process_each(rt, process) { - nxt_runtime_process_each(rt, process) { - - if (nxt_pid == process->pid) { - continue; - } - - port = nxt_process_port_first(process); + if (nxt_pid == process->pid) { + continue; + } - b = nxt_buf_mem_alloc(task->thread->engine->mem_pool, - sizeof(nxt_uint_t), 0); - if (nxt_slow_path(b == NULL)) { - continue; - } + port = nxt_process_port_first(process); - b->mem.free = nxt_cpymem(b->mem.free, &slot, sizeof(nxt_uint_t)); + b = nxt_buf_mem_alloc(task->thread->engine->mem_pool, sizeof(nxt_uint_t), + 0); + if (nxt_slow_path(b == NULL)) { + continue; + } - (void) nxt_port_socket_write(task, port, NXT_PORT_MSG_CHANGE_FILE, - fd, 0, 0, b); + b->mem.free = nxt_cpymem(b->mem.free, &slot, sizeof(nxt_uint_t)); - } nxt_runtime_process_loop; + (void)nxt_port_socket_write(task, port, NXT_PORT_MSG_CHANGE_FILE, fd, 0, 0, + b); + } + nxt_runtime_process_loop; } +void nxt_port_change_log_file_handler(nxt_task_t *task, + nxt_port_recv_msg_t *msg) { + nxt_buf_t *b; + nxt_uint_t slot; + nxt_file_t *log_file; + nxt_runtime_t *rt; -void -nxt_port_change_log_file_handler(nxt_task_t *task, nxt_port_recv_msg_t *msg) -{ - nxt_buf_t *b; - nxt_uint_t slot; - nxt_file_t *log_file; - nxt_runtime_t *rt; - - rt = task->thread->runtime; + rt = task->thread->runtime; - b = msg->buf; - slot = *(nxt_uint_t *) b->mem.pos; + b = msg->buf; + slot = *(nxt_uint_t *)b->mem.pos; - log_file = nxt_list_elt(rt->log_files, slot); + log_file = nxt_list_elt(rt->log_files, slot); - nxt_debug(task, "change log file %FD:%FD", msg->fd[0], log_file->fd); + nxt_debug(task, "change log file %FD:%FD", msg->fd[0], log_file->fd); - /* - * The old log file descriptor must be closed at the moment when no - * other threads use it. dup2() allows to use the old file descriptor - * for new log file. This change is performed atomically in the kernel. - */ - if (nxt_file_redirect(log_file, msg->fd[0]) == NXT_OK) { - if (slot == 0) { - (void) nxt_file_stderr(log_file); - } + /* + * The old log file descriptor must be closed at the moment when no + * other threads use it. dup2() allows to use the old file descriptor + * for new log file. This change is performed atomically in the kernel. + */ + if (nxt_file_redirect(log_file, msg->fd[0]) == NXT_OK) { + if (slot == 0) { + (void)nxt_file_stderr(log_file); } + } } +void nxt_port_data_handler(nxt_task_t *task, nxt_port_recv_msg_t *msg) { + size_t dump_size; + nxt_buf_t *b; -void -nxt_port_data_handler(nxt_task_t *task, nxt_port_recv_msg_t *msg) -{ - size_t dump_size; - nxt_buf_t *b; + b = msg->buf; + dump_size = b->mem.free - b->mem.pos; - b = msg->buf; - dump_size = b->mem.free - b->mem.pos; + if (dump_size > 300) { + dump_size = 300; + } - if (dump_size > 300) { - dump_size = 300; - } - - nxt_debug(task, "data: %*s", dump_size, b->mem.pos); + nxt_debug(task, "data: %*s", dump_size, b->mem.pos); } +void nxt_port_remove_notify_others(nxt_task_t *task, nxt_process_t *process) { + nxt_pid_t pid; + nxt_buf_t *buf; + nxt_port_t *port; + nxt_runtime_t *rt; + nxt_process_t *p; + nxt_process_type_t ptype; -void -nxt_port_remove_notify_others(nxt_task_t *task, nxt_process_t *process) -{ - nxt_pid_t pid; - nxt_buf_t *buf; - nxt_port_t *port; - nxt_runtime_t *rt; - nxt_process_t *p; - nxt_process_type_t ptype; - - pid = process->pid; + pid = process->pid; - ptype = nxt_process_type(process); + ptype = nxt_process_type(process); - rt = task->thread->runtime; + rt = task->thread->runtime; - nxt_runtime_process_each(rt, p) { + nxt_runtime_process_each(rt, p) { - if (p->pid == nxt_pid - || p->pid == pid - || nxt_queue_is_empty(&p->ports)) - { - continue; - } - - port = nxt_process_port_first(p); + if (p->pid == nxt_pid || p->pid == pid || nxt_queue_is_empty(&p->ports)) { + continue; + } - if (nxt_proc_remove_notify_matrix[ptype][port->type] == 0) { - continue; - } + port = nxt_process_port_first(p); - buf = nxt_buf_mem_ts_alloc(task, task->thread->engine->mem_pool, - sizeof(pid)); + if (nxt_proc_remove_notify_matrix[ptype][port->type] == 0) { + continue; + } - if (nxt_slow_path(buf == NULL)) { - continue; - } + buf = + nxt_buf_mem_ts_alloc(task, task->thread->engine->mem_pool, sizeof(pid)); - buf->mem.free = nxt_cpymem(buf->mem.free, &pid, sizeof(pid)); + if (nxt_slow_path(buf == NULL)) { + continue; + } - nxt_port_socket_write(task, port, NXT_PORT_MSG_REMOVE_PID, -1, - process->stream, 0, buf); + buf->mem.free = nxt_cpymem(buf->mem.free, &pid, sizeof(pid)); - } nxt_runtime_process_loop; + nxt_port_socket_write(task, port, NXT_PORT_MSG_REMOVE_PID, -1, + process->stream, 0, buf); + } + nxt_runtime_process_loop; } +void nxt_port_remove_pid_handler(nxt_task_t *task, nxt_port_recv_msg_t *msg) { + nxt_pid_t pid; + nxt_buf_t *buf; -void -nxt_port_remove_pid_handler(nxt_task_t *task, nxt_port_recv_msg_t *msg) -{ - nxt_pid_t pid; - nxt_buf_t *buf; + buf = msg->buf; - buf = msg->buf; + nxt_assert(nxt_buf_used_size(buf) == sizeof(pid)); - nxt_assert(nxt_buf_used_size(buf) == sizeof(pid)); + nxt_memcpy(&pid, buf->mem.pos, sizeof(nxt_pid_t)); - nxt_memcpy(&pid, buf->mem.pos, sizeof(nxt_pid_t)); - - nxt_port_remove_pid(task, msg, pid); + nxt_port_remove_pid(task, msg, pid); } +static void nxt_port_remove_pid(nxt_task_t *task, nxt_port_recv_msg_t *msg, + nxt_pid_t pid) { + nxt_runtime_t *rt; + nxt_process_t *process; -static void -nxt_port_remove_pid(nxt_task_t *task, nxt_port_recv_msg_t *msg, - nxt_pid_t pid) -{ - nxt_runtime_t *rt; - nxt_process_t *process; - - msg->u.removed_pid = pid; + msg->u.removed_pid = pid; - nxt_debug(task, "port remove pid %PI handler", pid); + nxt_debug(task, "port remove pid %PI handler", pid); - rt = task->thread->runtime; + rt = task->thread->runtime; - nxt_port_rpc_remove_peer(task, msg->port, pid); + nxt_port_rpc_remove_peer(task, msg->port, pid); - process = nxt_runtime_process_find(rt, pid); + process = nxt_runtime_process_find(rt, pid); - if (process) { - nxt_process_close_ports(task, process); - } + if (process) { + nxt_process_close_ports(task, process); + } } - -void -nxt_port_empty_handler(nxt_task_t *task, nxt_port_recv_msg_t *msg) -{ - nxt_debug(task, "port empty handler"); +void nxt_port_empty_handler(nxt_task_t *task, nxt_port_recv_msg_t *msg) { + nxt_debug(task, "port empty handler"); } - typedef struct { - nxt_work_t work; - nxt_port_t *port; - nxt_port_post_handler_t handler; + nxt_work_t work; + nxt_port_t *port; + nxt_port_post_handler_t handler; } nxt_port_work_t; +static void nxt_port_post_handler(nxt_task_t *task, void *obj, void *data) { + nxt_port_t *port; + nxt_port_work_t *pw; + nxt_port_post_handler_t handler; -static void -nxt_port_post_handler(nxt_task_t *task, void *obj, void *data) -{ - nxt_port_t *port; - nxt_port_work_t *pw; - nxt_port_post_handler_t handler; - - pw = obj; - port = pw->port; - handler = pw->handler; + pw = obj; + port = pw->port; + handler = pw->handler; - nxt_free(pw); + nxt_free(pw); - handler(task, port, data); + handler(task, port, data); - nxt_port_use(task, port, -1); + nxt_port_use(task, port, -1); } +nxt_int_t nxt_port_post(nxt_task_t *task, nxt_port_t *port, + nxt_port_post_handler_t handler, void *data) { + nxt_port_work_t *pw; -nxt_int_t -nxt_port_post(nxt_task_t *task, nxt_port_t *port, - nxt_port_post_handler_t handler, void *data) -{ - nxt_port_work_t *pw; - - if (task->thread->engine == port->engine) { - handler(task, port, data); + if (task->thread->engine == port->engine) { + handler(task, port, data); - return NXT_OK; - } + return NXT_OK; + } - pw = nxt_zalloc(sizeof(nxt_port_work_t)); + pw = nxt_zalloc(sizeof(nxt_port_work_t)); - if (nxt_slow_path(pw == NULL)) { - return NXT_ERROR; - } + if (nxt_slow_path(pw == NULL)) { + return NXT_ERROR; + } - nxt_atomic_fetch_add(&port->use_count, 1); + nxt_atomic_fetch_add(&port->use_count, 1); - pw->work.handler = nxt_port_post_handler; - pw->work.task = &port->engine->task; - pw->work.obj = pw; - pw->work.data = data; + pw->work.handler = nxt_port_post_handler; + pw->work.task = &port->engine->task; + pw->work.obj = pw; + pw->work.data = data; - pw->port = port; - pw->handler = handler; + pw->port = port; + pw->handler = handler; - nxt_event_engine_post(port->engine, &pw->work); + nxt_event_engine_post(port->engine, &pw->work); - return NXT_OK; + return NXT_OK; } - -static void -nxt_port_release_handler(nxt_task_t *task, nxt_port_t *port, void *data) -{ - /* no op */ +static void nxt_port_release_handler(nxt_task_t *task, nxt_port_t *port, + void *data) { + /* no op */ } +void nxt_port_use(nxt_task_t *task, nxt_port_t *port, int i) { + int c; -void -nxt_port_use(nxt_task_t *task, nxt_port_t *port, int i) -{ - int c; - - c = nxt_atomic_fetch_add(&port->use_count, i); + c = nxt_atomic_fetch_add(&port->use_count, i); - if (i < 0 && c == -i) { + if (i < 0 && c == -i) { - if (port->engine == NULL || task->thread->engine == port->engine) { - nxt_port_release(task, port); + if (port->engine == NULL || task->thread->engine == port->engine) { + nxt_port_release(task, port); - return; - } - - nxt_port_post(task, port, nxt_port_release_handler, NULL); + return; } + + nxt_port_post(task, port, nxt_port_release_handler, NULL); + } } diff --git a/src/nxt_port.h b/src/nxt_port.h index 772fb41ae..4c2ee25b1 100644 --- a/src/nxt_port.h +++ b/src/nxt_port.h @@ -7,326 +7,313 @@ #ifndef _NXT_PORT_H_INCLUDED_ #define _NXT_PORT_H_INCLUDED_ - struct nxt_port_handlers_s { - /* RPC responses. */ - nxt_port_handler_t rpc_ready; - nxt_port_handler_t rpc_error; - - /* Main process RPC requests. */ - nxt_port_handler_t start_process; - nxt_port_handler_t socket; - nxt_port_handler_t socket_unlink; - nxt_port_handler_t modules; - nxt_port_handler_t conf_store; - nxt_port_handler_t cert_get; - nxt_port_handler_t cert_delete; - nxt_port_handler_t script_get; - nxt_port_handler_t script_delete; - nxt_port_handler_t access_log; - - /* File descriptor exchange. */ - nxt_port_handler_t change_file; - nxt_port_handler_t new_port; - nxt_port_handler_t get_port; - nxt_port_handler_t port_ack; - nxt_port_handler_t mmap; - nxt_port_handler_t get_mmap; - - /* New process */ - nxt_port_handler_t process_created; - nxt_port_handler_t process_ready; - nxt_port_handler_t whoami; - - /* Process exit/crash notification. */ - nxt_port_handler_t remove_pid; - - /* Stop process command. */ - nxt_port_handler_t quit; - - /* Request headers. */ - nxt_port_handler_t req_headers; - nxt_port_handler_t req_headers_ack; - nxt_port_handler_t req_body; - - /* Websocket frame. */ - nxt_port_handler_t websocket_frame; - - /* Various data. */ - nxt_port_handler_t data; - nxt_port_handler_t app_restart; - - /* Status report. */ - nxt_port_handler_t status; - - nxt_port_handler_t oosm; - nxt_port_handler_t shm_ack; - nxt_port_handler_t read_queue; - nxt_port_handler_t read_socket; + /* RPC responses. */ + nxt_port_handler_t rpc_ready; + nxt_port_handler_t rpc_error; + + /* Main process RPC requests. */ + nxt_port_handler_t start_process; + nxt_port_handler_t socket; + nxt_port_handler_t socket_unlink; + nxt_port_handler_t modules; + nxt_port_handler_t conf_store; + nxt_port_handler_t cert_get; + nxt_port_handler_t cert_delete; + nxt_port_handler_t script_get; + nxt_port_handler_t script_delete; + nxt_port_handler_t access_log; + + /* File descriptor exchange. */ + nxt_port_handler_t change_file; + nxt_port_handler_t new_port; + nxt_port_handler_t get_port; + nxt_port_handler_t port_ack; + nxt_port_handler_t mmap; + nxt_port_handler_t get_mmap; + + /* New process */ + nxt_port_handler_t process_created; + nxt_port_handler_t process_ready; + nxt_port_handler_t whoami; + + /* Process exit/crash notification. */ + nxt_port_handler_t remove_pid; + + /* Stop process command. */ + nxt_port_handler_t quit; + + /* Request headers. */ + nxt_port_handler_t req_headers; + nxt_port_handler_t req_headers_ack; + nxt_port_handler_t req_body; + + /* Websocket frame. */ + nxt_port_handler_t websocket_frame; + + /* Various data. */ + nxt_port_handler_t data; + nxt_port_handler_t app_restart; + + /* Status report. */ + nxt_port_handler_t status; + + nxt_port_handler_t oosm; + nxt_port_handler_t shm_ack; + nxt_port_handler_t read_queue; + nxt_port_handler_t read_socket; }; +#define nxt_port_handler_idx(name) \ + (offsetof(nxt_port_handlers_t, name) / sizeof(nxt_port_handler_t)) -#define nxt_port_handler_idx(name) \ - ( offsetof(nxt_port_handlers_t, name) / sizeof(nxt_port_handler_t) ) - -#define nxt_msg_last(handler) \ - (handler | NXT_PORT_MSG_LAST) +#define nxt_msg_last(handler) (handler | NXT_PORT_MSG_LAST) typedef enum { - NXT_PORT_MSG_LAST = 0x100, - NXT_PORT_MSG_CLOSE_FD = 0x200, - NXT_PORT_MSG_SYNC = 0x400, - - NXT_PORT_MSG_MASK = 0xFF, - - _NXT_PORT_MSG_RPC_READY = nxt_port_handler_idx(rpc_ready), - _NXT_PORT_MSG_RPC_ERROR = nxt_port_handler_idx(rpc_error), - - _NXT_PORT_MSG_START_PROCESS = nxt_port_handler_idx(start_process), - _NXT_PORT_MSG_SOCKET = nxt_port_handler_idx(socket), - _NXT_PORT_MSG_SOCKET_UNLINK = nxt_port_handler_idx(socket_unlink), - _NXT_PORT_MSG_MODULES = nxt_port_handler_idx(modules), - _NXT_PORT_MSG_CONF_STORE = nxt_port_handler_idx(conf_store), - _NXT_PORT_MSG_CERT_GET = nxt_port_handler_idx(cert_get), - _NXT_PORT_MSG_CERT_DELETE = nxt_port_handler_idx(cert_delete), - _NXT_PORT_MSG_SCRIPT_GET = nxt_port_handler_idx(script_get), - _NXT_PORT_MSG_SCRIPT_DELETE = nxt_port_handler_idx(script_delete), - _NXT_PORT_MSG_ACCESS_LOG = nxt_port_handler_idx(access_log), - - _NXT_PORT_MSG_CHANGE_FILE = nxt_port_handler_idx(change_file), - _NXT_PORT_MSG_NEW_PORT = nxt_port_handler_idx(new_port), - _NXT_PORT_MSG_GET_PORT = nxt_port_handler_idx(get_port), - _NXT_PORT_MSG_PORT_ACK = nxt_port_handler_idx(port_ack), - _NXT_PORT_MSG_MMAP = nxt_port_handler_idx(mmap), - _NXT_PORT_MSG_GET_MMAP = nxt_port_handler_idx(get_mmap), - - _NXT_PORT_MSG_PROCESS_CREATED = nxt_port_handler_idx(process_created), - _NXT_PORT_MSG_PROCESS_READY = nxt_port_handler_idx(process_ready), - _NXT_PORT_MSG_WHOAMI = nxt_port_handler_idx(whoami), - _NXT_PORT_MSG_REMOVE_PID = nxt_port_handler_idx(remove_pid), - _NXT_PORT_MSG_QUIT = nxt_port_handler_idx(quit), - - _NXT_PORT_MSG_REQ_HEADERS = nxt_port_handler_idx(req_headers), - _NXT_PORT_MSG_REQ_HEADERS_ACK = nxt_port_handler_idx(req_headers_ack), - _NXT_PORT_MSG_REQ_BODY = nxt_port_handler_idx(req_body), - _NXT_PORT_MSG_WEBSOCKET = nxt_port_handler_idx(websocket_frame), - - _NXT_PORT_MSG_DATA = nxt_port_handler_idx(data), - _NXT_PORT_MSG_APP_RESTART = nxt_port_handler_idx(app_restart), - _NXT_PORT_MSG_STATUS = nxt_port_handler_idx(status), - - _NXT_PORT_MSG_OOSM = nxt_port_handler_idx(oosm), - _NXT_PORT_MSG_SHM_ACK = nxt_port_handler_idx(shm_ack), - _NXT_PORT_MSG_READ_QUEUE = nxt_port_handler_idx(read_queue), - _NXT_PORT_MSG_READ_SOCKET = nxt_port_handler_idx(read_socket), - - NXT_PORT_MSG_MAX = sizeof(nxt_port_handlers_t) - / sizeof(nxt_port_handler_t), - - NXT_PORT_MSG_RPC_READY = _NXT_PORT_MSG_RPC_READY, - NXT_PORT_MSG_RPC_READY_LAST = nxt_msg_last(_NXT_PORT_MSG_RPC_READY), - NXT_PORT_MSG_RPC_ERROR = nxt_msg_last(_NXT_PORT_MSG_RPC_ERROR), - NXT_PORT_MSG_START_PROCESS = nxt_msg_last(_NXT_PORT_MSG_START_PROCESS), - NXT_PORT_MSG_SOCKET = nxt_msg_last(_NXT_PORT_MSG_SOCKET), - NXT_PORT_MSG_SOCKET_UNLINK = nxt_msg_last(_NXT_PORT_MSG_SOCKET_UNLINK), - NXT_PORT_MSG_MODULES = nxt_msg_last(_NXT_PORT_MSG_MODULES), - NXT_PORT_MSG_CONF_STORE = nxt_msg_last(_NXT_PORT_MSG_CONF_STORE), - NXT_PORT_MSG_CERT_GET = nxt_msg_last(_NXT_PORT_MSG_CERT_GET), - NXT_PORT_MSG_CERT_DELETE = nxt_msg_last(_NXT_PORT_MSG_CERT_DELETE), - NXT_PORT_MSG_SCRIPT_GET = nxt_msg_last(_NXT_PORT_MSG_SCRIPT_GET), - NXT_PORT_MSG_SCRIPT_DELETE = nxt_msg_last(_NXT_PORT_MSG_SCRIPT_DELETE), - NXT_PORT_MSG_ACCESS_LOG = nxt_msg_last(_NXT_PORT_MSG_ACCESS_LOG), - NXT_PORT_MSG_CHANGE_FILE = nxt_msg_last(_NXT_PORT_MSG_CHANGE_FILE), - NXT_PORT_MSG_NEW_PORT = nxt_msg_last(_NXT_PORT_MSG_NEW_PORT), - NXT_PORT_MSG_GET_PORT = nxt_msg_last(_NXT_PORT_MSG_GET_PORT), - NXT_PORT_MSG_PORT_ACK = nxt_msg_last(_NXT_PORT_MSG_PORT_ACK), - NXT_PORT_MSG_MMAP = nxt_msg_last(_NXT_PORT_MSG_MMAP) - | NXT_PORT_MSG_SYNC, - NXT_PORT_MSG_GET_MMAP = nxt_msg_last(_NXT_PORT_MSG_GET_MMAP), - - NXT_PORT_MSG_PROCESS_CREATED = nxt_msg_last(_NXT_PORT_MSG_PROCESS_CREATED), - NXT_PORT_MSG_PROCESS_READY = nxt_msg_last(_NXT_PORT_MSG_PROCESS_READY), - NXT_PORT_MSG_WHOAMI = nxt_msg_last(_NXT_PORT_MSG_WHOAMI), - NXT_PORT_MSG_QUIT = nxt_msg_last(_NXT_PORT_MSG_QUIT), - NXT_PORT_MSG_REMOVE_PID = nxt_msg_last(_NXT_PORT_MSG_REMOVE_PID), - - NXT_PORT_MSG_REQ_HEADERS = _NXT_PORT_MSG_REQ_HEADERS, - NXT_PORT_MSG_REQ_BODY = _NXT_PORT_MSG_REQ_BODY, - NXT_PORT_MSG_WEBSOCKET = _NXT_PORT_MSG_WEBSOCKET, - NXT_PORT_MSG_WEBSOCKET_LAST = nxt_msg_last(_NXT_PORT_MSG_WEBSOCKET), - - NXT_PORT_MSG_DATA = _NXT_PORT_MSG_DATA, - NXT_PORT_MSG_DATA_LAST = nxt_msg_last(_NXT_PORT_MSG_DATA), - NXT_PORT_MSG_APP_RESTART = nxt_msg_last(_NXT_PORT_MSG_APP_RESTART), - NXT_PORT_MSG_STATUS = nxt_msg_last(_NXT_PORT_MSG_STATUS), - - NXT_PORT_MSG_OOSM = nxt_msg_last(_NXT_PORT_MSG_OOSM), - NXT_PORT_MSG_SHM_ACK = nxt_msg_last(_NXT_PORT_MSG_SHM_ACK), - NXT_PORT_MSG_READ_QUEUE = _NXT_PORT_MSG_READ_QUEUE, - NXT_PORT_MSG_READ_SOCKET = _NXT_PORT_MSG_READ_SOCKET, + NXT_PORT_MSG_LAST = 0x100, + NXT_PORT_MSG_CLOSE_FD = 0x200, + NXT_PORT_MSG_SYNC = 0x400, + + NXT_PORT_MSG_MASK = 0xFF, + + _NXT_PORT_MSG_RPC_READY = nxt_port_handler_idx(rpc_ready), + _NXT_PORT_MSG_RPC_ERROR = nxt_port_handler_idx(rpc_error), + + _NXT_PORT_MSG_START_PROCESS = nxt_port_handler_idx(start_process), + _NXT_PORT_MSG_SOCKET = nxt_port_handler_idx(socket), + _NXT_PORT_MSG_SOCKET_UNLINK = nxt_port_handler_idx(socket_unlink), + _NXT_PORT_MSG_MODULES = nxt_port_handler_idx(modules), + _NXT_PORT_MSG_CONF_STORE = nxt_port_handler_idx(conf_store), + _NXT_PORT_MSG_CERT_GET = nxt_port_handler_idx(cert_get), + _NXT_PORT_MSG_CERT_DELETE = nxt_port_handler_idx(cert_delete), + _NXT_PORT_MSG_SCRIPT_GET = nxt_port_handler_idx(script_get), + _NXT_PORT_MSG_SCRIPT_DELETE = nxt_port_handler_idx(script_delete), + _NXT_PORT_MSG_ACCESS_LOG = nxt_port_handler_idx(access_log), + + _NXT_PORT_MSG_CHANGE_FILE = nxt_port_handler_idx(change_file), + _NXT_PORT_MSG_NEW_PORT = nxt_port_handler_idx(new_port), + _NXT_PORT_MSG_GET_PORT = nxt_port_handler_idx(get_port), + _NXT_PORT_MSG_PORT_ACK = nxt_port_handler_idx(port_ack), + _NXT_PORT_MSG_MMAP = nxt_port_handler_idx(mmap), + _NXT_PORT_MSG_GET_MMAP = nxt_port_handler_idx(get_mmap), + + _NXT_PORT_MSG_PROCESS_CREATED = nxt_port_handler_idx(process_created), + _NXT_PORT_MSG_PROCESS_READY = nxt_port_handler_idx(process_ready), + _NXT_PORT_MSG_WHOAMI = nxt_port_handler_idx(whoami), + _NXT_PORT_MSG_REMOVE_PID = nxt_port_handler_idx(remove_pid), + _NXT_PORT_MSG_QUIT = nxt_port_handler_idx(quit), + + _NXT_PORT_MSG_REQ_HEADERS = nxt_port_handler_idx(req_headers), + _NXT_PORT_MSG_REQ_HEADERS_ACK = nxt_port_handler_idx(req_headers_ack), + _NXT_PORT_MSG_REQ_BODY = nxt_port_handler_idx(req_body), + _NXT_PORT_MSG_WEBSOCKET = nxt_port_handler_idx(websocket_frame), + + _NXT_PORT_MSG_DATA = nxt_port_handler_idx(data), + _NXT_PORT_MSG_APP_RESTART = nxt_port_handler_idx(app_restart), + _NXT_PORT_MSG_STATUS = nxt_port_handler_idx(status), + + _NXT_PORT_MSG_OOSM = nxt_port_handler_idx(oosm), + _NXT_PORT_MSG_SHM_ACK = nxt_port_handler_idx(shm_ack), + _NXT_PORT_MSG_READ_QUEUE = nxt_port_handler_idx(read_queue), + _NXT_PORT_MSG_READ_SOCKET = nxt_port_handler_idx(read_socket), + + NXT_PORT_MSG_MAX = sizeof(nxt_port_handlers_t) / sizeof(nxt_port_handler_t), + + NXT_PORT_MSG_RPC_READY = _NXT_PORT_MSG_RPC_READY, + NXT_PORT_MSG_RPC_READY_LAST = nxt_msg_last(_NXT_PORT_MSG_RPC_READY), + NXT_PORT_MSG_RPC_ERROR = nxt_msg_last(_NXT_PORT_MSG_RPC_ERROR), + NXT_PORT_MSG_START_PROCESS = nxt_msg_last(_NXT_PORT_MSG_START_PROCESS), + NXT_PORT_MSG_SOCKET = nxt_msg_last(_NXT_PORT_MSG_SOCKET), + NXT_PORT_MSG_SOCKET_UNLINK = nxt_msg_last(_NXT_PORT_MSG_SOCKET_UNLINK), + NXT_PORT_MSG_MODULES = nxt_msg_last(_NXT_PORT_MSG_MODULES), + NXT_PORT_MSG_CONF_STORE = nxt_msg_last(_NXT_PORT_MSG_CONF_STORE), + NXT_PORT_MSG_CERT_GET = nxt_msg_last(_NXT_PORT_MSG_CERT_GET), + NXT_PORT_MSG_CERT_DELETE = nxt_msg_last(_NXT_PORT_MSG_CERT_DELETE), + NXT_PORT_MSG_SCRIPT_GET = nxt_msg_last(_NXT_PORT_MSG_SCRIPT_GET), + NXT_PORT_MSG_SCRIPT_DELETE = nxt_msg_last(_NXT_PORT_MSG_SCRIPT_DELETE), + NXT_PORT_MSG_ACCESS_LOG = nxt_msg_last(_NXT_PORT_MSG_ACCESS_LOG), + NXT_PORT_MSG_CHANGE_FILE = nxt_msg_last(_NXT_PORT_MSG_CHANGE_FILE), + NXT_PORT_MSG_NEW_PORT = nxt_msg_last(_NXT_PORT_MSG_NEW_PORT), + NXT_PORT_MSG_GET_PORT = nxt_msg_last(_NXT_PORT_MSG_GET_PORT), + NXT_PORT_MSG_PORT_ACK = nxt_msg_last(_NXT_PORT_MSG_PORT_ACK), + NXT_PORT_MSG_MMAP = nxt_msg_last(_NXT_PORT_MSG_MMAP) | NXT_PORT_MSG_SYNC, + NXT_PORT_MSG_GET_MMAP = nxt_msg_last(_NXT_PORT_MSG_GET_MMAP), + + NXT_PORT_MSG_PROCESS_CREATED = nxt_msg_last(_NXT_PORT_MSG_PROCESS_CREATED), + NXT_PORT_MSG_PROCESS_READY = nxt_msg_last(_NXT_PORT_MSG_PROCESS_READY), + NXT_PORT_MSG_WHOAMI = nxt_msg_last(_NXT_PORT_MSG_WHOAMI), + NXT_PORT_MSG_QUIT = nxt_msg_last(_NXT_PORT_MSG_QUIT), + NXT_PORT_MSG_REMOVE_PID = nxt_msg_last(_NXT_PORT_MSG_REMOVE_PID), + + NXT_PORT_MSG_REQ_HEADERS = _NXT_PORT_MSG_REQ_HEADERS, + NXT_PORT_MSG_REQ_BODY = _NXT_PORT_MSG_REQ_BODY, + NXT_PORT_MSG_WEBSOCKET = _NXT_PORT_MSG_WEBSOCKET, + NXT_PORT_MSG_WEBSOCKET_LAST = nxt_msg_last(_NXT_PORT_MSG_WEBSOCKET), + + NXT_PORT_MSG_DATA = _NXT_PORT_MSG_DATA, + NXT_PORT_MSG_DATA_LAST = nxt_msg_last(_NXT_PORT_MSG_DATA), + NXT_PORT_MSG_APP_RESTART = nxt_msg_last(_NXT_PORT_MSG_APP_RESTART), + NXT_PORT_MSG_STATUS = nxt_msg_last(_NXT_PORT_MSG_STATUS), + + NXT_PORT_MSG_OOSM = nxt_msg_last(_NXT_PORT_MSG_OOSM), + NXT_PORT_MSG_SHM_ACK = nxt_msg_last(_NXT_PORT_MSG_SHM_ACK), + NXT_PORT_MSG_READ_QUEUE = _NXT_PORT_MSG_READ_QUEUE, + NXT_PORT_MSG_READ_SOCKET = _NXT_PORT_MSG_READ_SOCKET, } nxt_port_msg_type_t; - /* Passed as a first iov chunk. */ typedef struct { - uint32_t stream; + uint32_t stream; - nxt_pid_t pid; /* not used on Linux and FreeBSD */ + nxt_pid_t pid; /* not used on Linux and FreeBSD */ - nxt_port_id_t reply_port; + nxt_port_id_t reply_port; - uint8_t type; + uint8_t type; - /* Last message for this stream. */ - uint8_t last; /* 1 bit */ + /* Last message for this stream. */ + uint8_t last; /* 1 bit */ - /* Message data send using mmap, next chunk is a nxt_port_mmap_msg_t. */ - uint8_t mmap; /* 1 bit */ + /* Message data send using mmap, next chunk is a nxt_port_mmap_msg_t. */ + uint8_t mmap; /* 1 bit */ - /* Non-First fragment in fragmented message sequence. */ - uint8_t nf; /* 1 bit */ + /* Non-First fragment in fragmented message sequence. */ + uint8_t nf; /* 1 bit */ - /* More Fragments followed. */ - uint8_t mf; /* 1 bit */ + /* More Fragments followed. */ + uint8_t mf; /* 1 bit */ } nxt_port_msg_t; - typedef struct { - nxt_queue_link_t link; - nxt_buf_t *buf; - size_t share; - nxt_fd_t fd[2]; - nxt_port_msg_t port_msg; - uint8_t close_fd; /* 1 bit */ - uint8_t allocated; /* 1 bit */ + nxt_queue_link_t link; + nxt_buf_t *buf; + size_t share; + nxt_fd_t fd[2]; + nxt_port_msg_t port_msg; + uint8_t close_fd; /* 1 bit */ + uint8_t allocated; /* 1 bit */ } nxt_port_send_msg_t; #if (NXT_HAVE_UCRED) || (NXT_HAVE_MSGHDR_CMSGCRED) -#define NXT_USE_CMSG_PID 1 +#define NXT_USE_CMSG_PID 1 #endif struct nxt_port_recv_msg_s { - nxt_fd_t fd[2]; - nxt_buf_t *buf; - nxt_port_t *port; - nxt_port_msg_t port_msg; - size_t size; + nxt_fd_t fd[2]; + nxt_buf_t *buf; + nxt_port_t *port; + nxt_port_msg_t port_msg; + size_t size; #if (NXT_USE_CMSG_PID) - nxt_pid_t cmsg_pid; + nxt_pid_t cmsg_pid; #endif - nxt_bool_t cancelled; - union { - nxt_port_t *new_port; - nxt_pid_t removed_pid; - void *data; - } u; + nxt_bool_t cancelled; + union { + nxt_port_t *new_port; + nxt_pid_t removed_pid; + void *data; + } u; }; - #if (NXT_USE_CMSG_PID) -#define nxt_recv_msg_cmsg_pid(msg) ((msg)->cmsg_pid) -#define nxt_recv_msg_cmsg_pid_ref(msg) (&(msg)->cmsg_pid) +#define nxt_recv_msg_cmsg_pid(msg) ((msg)->cmsg_pid) +#define nxt_recv_msg_cmsg_pid_ref(msg) (&(msg)->cmsg_pid) #else -#define nxt_recv_msg_cmsg_pid(msg) ((msg)->port_msg.pid) -#define nxt_recv_msg_cmsg_pid_ref(msg) (NULL) +#define nxt_recv_msg_cmsg_pid(msg) ((msg)->port_msg.pid) +#define nxt_recv_msg_cmsg_pid_ref(msg) (NULL) #endif -typedef struct nxt_app_s nxt_app_t; +typedef struct nxt_app_s nxt_app_t; struct nxt_port_s { - nxt_fd_event_t socket; + nxt_fd_event_t socket; - nxt_queue_link_t link; /* for nxt_process_t.ports */ - nxt_process_t *process; + nxt_queue_link_t link; /* for nxt_process_t.ports */ + nxt_process_t *process; - nxt_queue_link_t app_link; /* for nxt_app_t.ports */ - nxt_app_t *app; - nxt_port_t *main_app_port; + nxt_queue_link_t app_link; /* for nxt_app_t.ports */ + nxt_app_t *app; + nxt_port_t *main_app_port; - nxt_queue_link_t idle_link; /* for nxt_app_t.idle_ports */ - nxt_msec_t idle_start; + nxt_queue_link_t idle_link; /* for nxt_app_t.idle_ports */ + nxt_msec_t idle_start; - nxt_queue_t messages; /* of nxt_port_send_msg_t */ - nxt_thread_mutex_t write_mutex; + nxt_queue_t messages; /* of nxt_port_send_msg_t */ + nxt_thread_mutex_t write_mutex; - /* Maximum size of message part. */ - uint32_t max_size; - /* Maximum interleave of message parts. */ - uint32_t max_share; + /* Maximum size of message part. */ + uint32_t max_size; + /* Maximum interleave of message parts. */ + uint32_t max_share; - uint32_t active_websockets; - uint32_t active_requests; + uint32_t active_websockets; + uint32_t active_requests; - nxt_port_handler_t handler; - nxt_port_handler_t *data; + nxt_port_handler_t handler; + nxt_port_handler_t *data; - nxt_mp_t *mem_pool; - nxt_event_engine_t *engine; + nxt_mp_t *mem_pool; + nxt_event_engine_t *engine; - nxt_buf_t *free_bufs; - nxt_socket_t pair[2]; + nxt_buf_t *free_bufs; + nxt_socket_t pair[2]; - nxt_port_id_t id; - nxt_pid_t pid; + nxt_port_id_t id; + nxt_pid_t pid; - nxt_lvlhsh_t rpc_streams; /* stream to nxt_port_rpc_reg_t */ - nxt_lvlhsh_t rpc_peers; /* peer to queue of nxt_port_rpc_reg_t */ + nxt_lvlhsh_t rpc_streams; /* stream to nxt_port_rpc_reg_t */ + nxt_lvlhsh_t rpc_peers; /* peer to queue of nxt_port_rpc_reg_t */ - nxt_lvlhsh_t frags; + nxt_lvlhsh_t frags; - nxt_atomic_t use_count; + nxt_atomic_t use_count; - nxt_process_type_t type; + nxt_process_type_t type; - nxt_fd_t queue_fd; - void *queue; + nxt_fd_t queue_fd; + void *queue; - void *socket_msg; - int from_socket; + void *socket_msg; + int from_socket; }; - typedef struct { - nxt_port_id_t id; - nxt_pid_t pid; - size_t max_size; - size_t max_share; - nxt_process_type_t type:8; + nxt_port_id_t id; + nxt_pid_t pid; + size_t max_size; + size_t max_share; + nxt_process_type_t type : 8; } nxt_port_msg_new_port_t; - typedef struct { - nxt_port_id_t id; - nxt_pid_t pid; + nxt_port_id_t id; + nxt_pid_t pid; } nxt_port_msg_get_port_t; - typedef struct { - uint32_t id; + uint32_t id; } nxt_port_msg_get_mmap_t; - /* * nxt_port_data_t size is allocation size * which enables effective reuse of memory pool cache. */ typedef union { - nxt_buf_t buf; - nxt_port_msg_new_port_t new_port; + nxt_buf_t buf; + nxt_port_msg_new_port_t new_port; } nxt_port_data_t; - typedef void (*nxt_port_post_handler_t)(nxt_task_t *task, nxt_port_t *port, - void *data); + void *data); nxt_port_t *nxt_port_new(nxt_task_t *task, nxt_port_id_t id, nxt_pid_t pid, - nxt_process_type_t type); + nxt_process_type_t type); nxt_port_id_t nxt_port_get_next_id(void); void nxt_port_reset_next_id(void); nxt_int_t nxt_port_socket_init(nxt_task_t *task, nxt_port_t *port, - size_t max_size); + size_t max_size); void nxt_port_destroy(nxt_port_t *port); void nxt_port_close(nxt_task_t *task, nxt_port_t *port); void nxt_port_write_enable(nxt_task_t *task, nxt_port_t *port); @@ -334,43 +321,43 @@ void nxt_port_write_close(nxt_port_t *port); void nxt_port_read_enable(nxt_task_t *task, nxt_port_t *port); void nxt_port_read_close(nxt_port_t *port); nxt_int_t nxt_port_socket_write2(nxt_task_t *task, nxt_port_t *port, - nxt_uint_t type, nxt_fd_t fd, nxt_fd_t fd2, uint32_t stream, - nxt_port_id_t reply_port, nxt_buf_t *b); - -nxt_inline nxt_int_t -nxt_port_socket_write(nxt_task_t *task, nxt_port_t *port, - nxt_uint_t type, nxt_fd_t fd, uint32_t stream, nxt_port_id_t reply_port, - nxt_buf_t *b) -{ - return nxt_port_socket_write2(task, port, type, fd, -1, stream, reply_port, - b); + nxt_uint_t type, nxt_fd_t fd, nxt_fd_t fd2, + uint32_t stream, nxt_port_id_t reply_port, + nxt_buf_t *b); + +nxt_inline nxt_int_t nxt_port_socket_write(nxt_task_t *task, nxt_port_t *port, + nxt_uint_t type, nxt_fd_t fd, + uint32_t stream, + nxt_port_id_t reply_port, + nxt_buf_t *b) { + return nxt_port_socket_write2(task, port, type, fd, -1, stream, reply_port, + b); } void nxt_port_enable(nxt_task_t *task, nxt_port_t *port, - const nxt_port_handlers_t *handlers); + const nxt_port_handlers_t *handlers); nxt_int_t nxt_port_send_port(nxt_task_t *task, nxt_port_t *port, - nxt_port_t *new_port, uint32_t stream); + nxt_port_t *new_port, uint32_t stream); void nxt_port_change_log_file(nxt_task_t *task, nxt_runtime_t *rt, - nxt_uint_t slot, nxt_fd_t fd); + nxt_uint_t slot, nxt_fd_t fd); void nxt_port_remove_notify_others(nxt_task_t *task, nxt_process_t *process); void nxt_port_quit_handler(nxt_task_t *task, nxt_port_recv_msg_t *msg); void nxt_port_new_port_handler(nxt_task_t *task, nxt_port_recv_msg_t *msg); void nxt_port_process_ready_handler(nxt_task_t *task, nxt_port_recv_msg_t *msg); void nxt_port_change_log_file_handler(nxt_task_t *task, - nxt_port_recv_msg_t *msg); + nxt_port_recv_msg_t *msg); void nxt_port_mmap_handler(nxt_task_t *task, nxt_port_recv_msg_t *msg); void nxt_port_data_handler(nxt_task_t *task, nxt_port_recv_msg_t *msg); void nxt_port_remove_pid_handler(nxt_task_t *task, nxt_port_recv_msg_t *msg); void nxt_port_empty_handler(nxt_task_t *task, nxt_port_recv_msg_t *msg); nxt_int_t nxt_port_post(nxt_task_t *task, nxt_port_t *port, - nxt_port_post_handler_t handler, void *data); + nxt_port_post_handler_t handler, void *data); void nxt_port_use(nxt_task_t *task, nxt_port_t *port, int i); -nxt_inline void nxt_port_inc_use(nxt_port_t *port) -{ - nxt_atomic_fetch_add(&port->use_count, 1); +nxt_inline void nxt_port_inc_use(nxt_port_t *port) { + nxt_atomic_fetch_add(&port->use_count, 1); } #endif /* _NXT_PORT_H_INCLUDED_ */ diff --git a/src/nxt_port_hash.c b/src/nxt_port_hash.c index b23acfb28..d9d90a65d 100644 --- a/src/nxt_port_hash.c +++ b/src/nxt_port_hash.c @@ -6,137 +6,117 @@ #include - // Explicitly using 32 bit types to avoid possible alignment. typedef struct { - int32_t pid; - uint32_t port_id; + int32_t pid; + uint32_t port_id; } nxt_pid_port_id_t; +static nxt_int_t nxt_port_hash_test(nxt_lvlhsh_query_t *lhq, void *data) { + nxt_port_t *port; + nxt_pid_port_id_t *pid_port_id; -static nxt_int_t -nxt_port_hash_test(nxt_lvlhsh_query_t *lhq, void *data) -{ - nxt_port_t *port; - nxt_pid_port_id_t *pid_port_id; - - port = data; - pid_port_id = (nxt_pid_port_id_t *) lhq->key.start; + port = data; + pid_port_id = (nxt_pid_port_id_t *)lhq->key.start; - if (lhq->key.length == sizeof(nxt_pid_port_id_t) - && pid_port_id->pid == port->pid - && pid_port_id->port_id == port->id) - { - return NXT_OK; - } + if (lhq->key.length == sizeof(nxt_pid_port_id_t) && + pid_port_id->pid == port->pid && pid_port_id->port_id == port->id) { + return NXT_OK; + } - return NXT_DECLINED; + return NXT_DECLINED; } -static const nxt_lvlhsh_proto_t lvlhsh_ports_proto nxt_aligned(64) = { +static const nxt_lvlhsh_proto_t lvlhsh_ports_proto nxt_aligned(64) = { NXT_LVLHSH_DEFAULT, nxt_port_hash_test, nxt_lvlhsh_alloc, nxt_lvlhsh_free, }; - -nxt_port_t * -nxt_port_hash_retrieve(nxt_lvlhsh_t *port_hash) -{ - return nxt_lvlhsh_retrieve(port_hash, &lvlhsh_ports_proto, NULL); +nxt_port_t *nxt_port_hash_retrieve(nxt_lvlhsh_t *port_hash) { + return nxt_lvlhsh_retrieve(port_hash, &lvlhsh_ports_proto, NULL); } - -nxt_inline void -nxt_port_hash_lhq(nxt_lvlhsh_query_t *lhq, nxt_pid_port_id_t *pid_port) -{ - lhq->key_hash = nxt_murmur_hash2(pid_port, sizeof(nxt_pid_port_id_t)); - lhq->key.length = sizeof(nxt_pid_port_id_t); - lhq->key.start = (u_char *) pid_port; - lhq->proto = &lvlhsh_ports_proto; - lhq->pool = NULL; +nxt_inline void nxt_port_hash_lhq(nxt_lvlhsh_query_t *lhq, + nxt_pid_port_id_t *pid_port) { + lhq->key_hash = nxt_murmur_hash2(pid_port, sizeof(nxt_pid_port_id_t)); + lhq->key.length = sizeof(nxt_pid_port_id_t); + lhq->key.start = (u_char *)pid_port; + lhq->proto = &lvlhsh_ports_proto; + lhq->pool = NULL; } +nxt_int_t nxt_port_hash_add(nxt_lvlhsh_t *port_hash, nxt_port_t *port) { + nxt_int_t res; + nxt_pid_port_id_t pid_port; + nxt_lvlhsh_query_t lhq; -nxt_int_t -nxt_port_hash_add(nxt_lvlhsh_t *port_hash, nxt_port_t *port) -{ - nxt_int_t res; - nxt_pid_port_id_t pid_port; - nxt_lvlhsh_query_t lhq; + pid_port.pid = port->pid; + pid_port.port_id = port->id; - pid_port.pid = port->pid; - pid_port.port_id = port->id; + nxt_port_hash_lhq(&lhq, &pid_port); + lhq.replace = 0; + lhq.value = port; - nxt_port_hash_lhq(&lhq, &pid_port); - lhq.replace = 0; - lhq.value = port; + res = nxt_lvlhsh_insert(port_hash, &lhq); - res = nxt_lvlhsh_insert(port_hash, &lhq); + switch (res) { - switch (res) { + case NXT_OK: + break; - case NXT_OK: - break; + default: + nxt_thread_log_error(NXT_LOG_WARN, "port #%d for pid %PI add failed", + port->id, port->pid); + break; + } - default: - nxt_thread_log_error(NXT_LOG_WARN, "port #%d for pid %PI add failed", - port->id, port->pid); - break; - } - - return res; + return res; } +nxt_int_t nxt_port_hash_remove(nxt_lvlhsh_t *port_hash, nxt_port_t *port) { + nxt_int_t res; + nxt_pid_port_id_t pid_port; + nxt_lvlhsh_query_t lhq; -nxt_int_t -nxt_port_hash_remove(nxt_lvlhsh_t *port_hash, nxt_port_t *port) -{ - nxt_int_t res; - nxt_pid_port_id_t pid_port; - nxt_lvlhsh_query_t lhq; - - pid_port.pid = port->pid; - pid_port.port_id = port->id; + pid_port.pid = port->pid; + pid_port.port_id = port->id; - nxt_port_hash_lhq(&lhq, &pid_port); + nxt_port_hash_lhq(&lhq, &pid_port); - res = nxt_lvlhsh_delete(port_hash, &lhq); + res = nxt_lvlhsh_delete(port_hash, &lhq); - switch (res) { + switch (res) { - case NXT_OK: - break; + case NXT_OK: + break; - default: - nxt_thread_log_error(NXT_LOG_WARN, "port #%d for pid %PI remove failed", - port->id, port->pid); - break; - } + default: + nxt_thread_log_error(NXT_LOG_WARN, "port #%d for pid %PI remove failed", + port->id, port->pid); + break; + } - return res; + return res; } +nxt_port_t *nxt_port_hash_find(nxt_lvlhsh_t *port_hash, nxt_pid_t pid, + nxt_port_id_t port_id) { + nxt_pid_port_id_t pid_port; + nxt_lvlhsh_query_t lhq; -nxt_port_t * -nxt_port_hash_find(nxt_lvlhsh_t *port_hash, nxt_pid_t pid, - nxt_port_id_t port_id) -{ - nxt_pid_port_id_t pid_port; - nxt_lvlhsh_query_t lhq; - - pid_port.pid = pid; - pid_port.port_id = port_id; + pid_port.pid = pid; + pid_port.port_id = port_id; - nxt_port_hash_lhq(&lhq, &pid_port); + nxt_port_hash_lhq(&lhq, &pid_port); - if (nxt_lvlhsh_find(port_hash, &lhq) == NXT_OK) { - nxt_thread_log_debug("process port (%PI, %d) found", pid, port_id); - return lhq.value; - } + if (nxt_lvlhsh_find(port_hash, &lhq) == NXT_OK) { + nxt_thread_log_debug("process port (%PI, %d) found", pid, port_id); + return lhq.value; + } - nxt_thread_log_debug("process port (%PI, %d) not found", pid, port_id); + nxt_thread_log_debug("process port (%PI, %d) not found", pid, port_id); - return NULL; + return NULL; } diff --git a/src/nxt_port_hash.h b/src/nxt_port_hash.h index c975cab71..3d4a739bc 100644 --- a/src/nxt_port_hash.h +++ b/src/nxt_port_hash.h @@ -7,18 +7,15 @@ #ifndef _NXT_PORT_HASH_H_INCLUDED_ #define _NXT_PORT_HASH_H_INCLUDED_ - #include - nxt_int_t nxt_port_hash_add(nxt_lvlhsh_t *port_hash, nxt_port_t *port); nxt_int_t nxt_port_hash_remove(nxt_lvlhsh_t *port_hash, nxt_port_t *port); nxt_port_t *nxt_port_hash_find(nxt_lvlhsh_t *port_hash, nxt_pid_t pid, - nxt_port_id_t port_id); + nxt_port_id_t port_id); nxt_port_t *nxt_port_hash_retrieve(nxt_lvlhsh_t *port_hash); - #endif /* _NXT_PORT_HASH_H_INCLIDED_ */ diff --git a/src/nxt_port_memory.c b/src/nxt_port_memory.c index ad6e97ade..d48c90c44 100644 --- a/src/nxt_port_memory.c +++ b/src/nxt_port_memory.c @@ -16,410 +16,392 @@ #include - static void nxt_port_broadcast_shm_ack(nxt_task_t *task, nxt_port_t *port, - void *data); - + void *data); -nxt_inline void -nxt_port_mmap_handler_use(nxt_port_mmap_handler_t *mmap_handler, int i) -{ - int c; +nxt_inline void nxt_port_mmap_handler_use(nxt_port_mmap_handler_t *mmap_handler, + int i) { + int c; - c = nxt_atomic_fetch_add(&mmap_handler->use_count, i); - - if (i < 0 && c == -i) { - if (mmap_handler->hdr != NULL) { - nxt_mem_munmap(mmap_handler->hdr, PORT_MMAP_SIZE); - mmap_handler->hdr = NULL; - } + c = nxt_atomic_fetch_add(&mmap_handler->use_count, i); - if (mmap_handler->fd != -1) { - nxt_fd_close(mmap_handler->fd); - } + if (i < 0 && c == -i) { + if (mmap_handler->hdr != NULL) { + nxt_mem_munmap(mmap_handler->hdr, PORT_MMAP_SIZE); + mmap_handler->hdr = NULL; + } - nxt_free(mmap_handler); + if (mmap_handler->fd != -1) { + nxt_fd_close(mmap_handler->fd); } -} + nxt_free(mmap_handler); + } +} -static nxt_port_mmap_t * -nxt_port_mmap_at(nxt_port_mmaps_t *port_mmaps, uint32_t i) -{ - uint32_t cap; +static nxt_port_mmap_t *nxt_port_mmap_at(nxt_port_mmaps_t *port_mmaps, + uint32_t i) { + uint32_t cap; - cap = port_mmaps->cap; + cap = port_mmaps->cap; - if (cap == 0) { - cap = i + 1; - } + if (cap == 0) { + cap = i + 1; + } - while (i + 1 > cap) { + while (i + 1 > cap) { - if (cap < 16) { - cap = cap * 2; + if (cap < 16) { + cap = cap * 2; - } else { - cap = cap + cap / 2; - } + } else { + cap = cap + cap / 2; } + } - if (cap != port_mmaps->cap) { + if (cap != port_mmaps->cap) { - port_mmaps->elts = nxt_realloc(port_mmaps->elts, - cap * sizeof(nxt_port_mmap_t)); - if (nxt_slow_path(port_mmaps->elts == NULL)) { - return NULL; - } + port_mmaps->elts = + nxt_realloc(port_mmaps->elts, cap * sizeof(nxt_port_mmap_t)); + if (nxt_slow_path(port_mmaps->elts == NULL)) { + return NULL; + } - nxt_memzero(port_mmaps->elts + port_mmaps->cap, - sizeof(nxt_port_mmap_t) * (cap - port_mmaps->cap)); + nxt_memzero(port_mmaps->elts + port_mmaps->cap, + sizeof(nxt_port_mmap_t) * (cap - port_mmaps->cap)); - port_mmaps->cap = cap; - } + port_mmaps->cap = cap; + } - if (i + 1 > port_mmaps->size) { - port_mmaps->size = i + 1; - } + if (i + 1 > port_mmaps->size) { + port_mmaps->size = i + 1; + } - return port_mmaps->elts + i; + return port_mmaps->elts + i; } +void nxt_port_mmaps_destroy(nxt_port_mmaps_t *port_mmaps, + nxt_bool_t free_elts) { + uint32_t i; + nxt_port_mmap_t *port_mmap; -void -nxt_port_mmaps_destroy(nxt_port_mmaps_t *port_mmaps, nxt_bool_t free_elts) -{ - uint32_t i; - nxt_port_mmap_t *port_mmap; + if (port_mmaps == NULL) { + return; + } - if (port_mmaps == NULL) { - return; - } - - port_mmap = port_mmaps->elts; + port_mmap = port_mmaps->elts; - for (i = 0; i < port_mmaps->size; i++) { - nxt_port_mmap_handler_use(port_mmap[i].mmap_handler, -1); - } + for (i = 0; i < port_mmaps->size; i++) { + nxt_port_mmap_handler_use(port_mmap[i].mmap_handler, -1); + } - port_mmaps->size = 0; + port_mmaps->size = 0; - if (free_elts != 0) { - nxt_free(port_mmaps->elts); - } + if (free_elts != 0) { + nxt_free(port_mmaps->elts); + } } +#define nxt_port_mmap_free_junk(p, size) memset((p), 0xA5, size) -#define nxt_port_mmap_free_junk(p, size) \ - memset((p), 0xA5, size) +static void nxt_port_mmap_buf_completion(nxt_task_t *task, void *obj, + void *data) { + u_char *p; + nxt_mp_t *mp; + nxt_buf_t *b, *next; + nxt_process_t *process; + nxt_chunk_id_t c; + nxt_port_mmap_header_t *hdr; + nxt_port_mmap_handler_t *mmap_handler; + if (nxt_buf_ts_handle(task, obj, data)) { + return; + } -static void -nxt_port_mmap_buf_completion(nxt_task_t *task, void *obj, void *data) -{ - u_char *p; - nxt_mp_t *mp; - nxt_buf_t *b, *next; - nxt_process_t *process; - nxt_chunk_id_t c; - nxt_port_mmap_header_t *hdr; - nxt_port_mmap_handler_t *mmap_handler; + b = obj; - if (nxt_buf_ts_handle(task, obj, data)) { - return; - } - - b = obj; + nxt_assert(data == b->parent); - nxt_assert(data == b->parent); - - mmap_handler = data; + mmap_handler = data; complete_buf: - hdr = mmap_handler->hdr; + hdr = mmap_handler->hdr; - if (nxt_slow_path(hdr->src_pid != nxt_pid && hdr->dst_pid != nxt_pid)) { - nxt_debug(task, "mmap buf completion: mmap for other process pair " - "%PI->%PI", hdr->src_pid, hdr->dst_pid); + if (nxt_slow_path(hdr->src_pid != nxt_pid && hdr->dst_pid != nxt_pid)) { + nxt_debug(task, + "mmap buf completion: mmap for other process pair " + "%PI->%PI", + hdr->src_pid, hdr->dst_pid); - goto release_buf; - } + goto release_buf; + } - if (b->is_port_mmap_sent && b->mem.pos > b->mem.start) { - /* - * Chunks until b->mem.pos has been sent to other side, - * let's release rest (if any). - */ - p = b->mem.pos - 1; - c = nxt_port_mmap_chunk_id(hdr, p) + 1; - p = nxt_port_mmap_chunk_start(hdr, c); + if (b->is_port_mmap_sent && b->mem.pos > b->mem.start) { + /* + * Chunks until b->mem.pos has been sent to other side, + * let's release rest (if any). + */ + p = b->mem.pos - 1; + c = nxt_port_mmap_chunk_id(hdr, p) + 1; + p = nxt_port_mmap_chunk_start(hdr, c); - } else { - p = b->mem.start; - c = nxt_port_mmap_chunk_id(hdr, p); - } + } else { + p = b->mem.start; + c = nxt_port_mmap_chunk_id(hdr, p); + } - nxt_port_mmap_free_junk(p, b->mem.end - p); + nxt_port_mmap_free_junk(p, b->mem.end - p); - nxt_debug(task, "mmap buf completion: %p [%p,%uz] (sent=%d), " - "%PI->%PI,%d,%d", b, b->mem.start, b->mem.end - b->mem.start, - b->is_port_mmap_sent, hdr->src_pid, hdr->dst_pid, hdr->id, c); + nxt_debug(task, + "mmap buf completion: %p [%p,%uz] (sent=%d), " + "%PI->%PI,%d,%d", + b, b->mem.start, b->mem.end - b->mem.start, b->is_port_mmap_sent, + hdr->src_pid, hdr->dst_pid, hdr->id, c); - while (p < b->mem.end) { - nxt_port_mmap_set_chunk_free(hdr->free_map, c); + while (p < b->mem.end) { + nxt_port_mmap_set_chunk_free(hdr->free_map, c); - p += PORT_MMAP_CHUNK_SIZE; - c++; - } + p += PORT_MMAP_CHUNK_SIZE; + c++; + } - if (hdr->dst_pid == nxt_pid - && nxt_atomic_cmp_set(&hdr->oosm, 1, 0)) - { - process = nxt_runtime_process_find(task->thread->runtime, hdr->src_pid); + if (hdr->dst_pid == nxt_pid && nxt_atomic_cmp_set(&hdr->oosm, 1, 0)) { + process = nxt_runtime_process_find(task->thread->runtime, hdr->src_pid); - nxt_process_broadcast_shm_ack(task, process); - } + nxt_process_broadcast_shm_ack(task, process); + } release_buf: - nxt_port_mmap_handler_use(mmap_handler, -1); + nxt_port_mmap_handler_use(mmap_handler, -1); - next = b->next; - mp = b->data; + next = b->next; + mp = b->data; - nxt_mp_free(mp, b); - nxt_mp_release(mp); + nxt_mp_free(mp, b); + nxt_mp_release(mp); - if (next != NULL) { - b = next; - mmap_handler = b->parent; + if (next != NULL) { + b = next; + mmap_handler = b->parent; - goto complete_buf; - } + goto complete_buf; + } } +nxt_port_mmap_handler_t *nxt_port_incoming_port_mmap(nxt_task_t *task, + nxt_process_t *process, + nxt_fd_t fd) { + void *mem; + struct stat mmap_stat; + nxt_port_mmap_t *port_mmap; + nxt_port_mmap_header_t *hdr; + nxt_port_mmap_handler_t *mmap_handler; -nxt_port_mmap_handler_t * -nxt_port_incoming_port_mmap(nxt_task_t *task, nxt_process_t *process, - nxt_fd_t fd) -{ - void *mem; - struct stat mmap_stat; - nxt_port_mmap_t *port_mmap; - nxt_port_mmap_header_t *hdr; - nxt_port_mmap_handler_t *mmap_handler; - - nxt_debug(task, "got new mmap fd #%FD from process %PI", - fd, process->pid); + nxt_debug(task, "got new mmap fd #%FD from process %PI", fd, process->pid); - port_mmap = NULL; + port_mmap = NULL; - if (fstat(fd, &mmap_stat) == -1) { - nxt_log(task, NXT_LOG_WARN, "fstat(%FD) failed %E", fd, nxt_errno); + if (fstat(fd, &mmap_stat) == -1) { + nxt_log(task, NXT_LOG_WARN, "fstat(%FD) failed %E", fd, nxt_errno); - return NULL; - } + return NULL; + } - mem = nxt_mem_mmap(NULL, mmap_stat.st_size, - PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); + mem = nxt_mem_mmap(NULL, mmap_stat.st_size, PROT_READ | PROT_WRITE, + MAP_SHARED, fd, 0); - if (nxt_slow_path(mem == MAP_FAILED)) { - nxt_log(task, NXT_LOG_WARN, "mmap() failed %E", nxt_errno); + if (nxt_slow_path(mem == MAP_FAILED)) { + nxt_log(task, NXT_LOG_WARN, "mmap() failed %E", nxt_errno); - return NULL; - } + return NULL; + } - hdr = mem; + hdr = mem; - if (nxt_slow_path(hdr->src_pid != process->pid - || hdr->dst_pid != nxt_pid)) - { - nxt_log(task, NXT_LOG_WARN, "unexpected pid in mmap header detected: " - "%PI != %PI or %PI != %PI", hdr->src_pid, process->pid, - hdr->dst_pid, nxt_pid); + if (nxt_slow_path(hdr->src_pid != process->pid || hdr->dst_pid != nxt_pid)) { + nxt_log(task, NXT_LOG_WARN, + "unexpected pid in mmap header detected: " + "%PI != %PI or %PI != %PI", + hdr->src_pid, process->pid, hdr->dst_pid, nxt_pid); - nxt_mem_munmap(mem, PORT_MMAP_SIZE); + nxt_mem_munmap(mem, PORT_MMAP_SIZE); - return NULL; - } + return NULL; + } - mmap_handler = nxt_zalloc(sizeof(nxt_port_mmap_handler_t)); - if (nxt_slow_path(mmap_handler == NULL)) { - nxt_log(task, NXT_LOG_WARN, "failed to allocate mmap_handler"); + mmap_handler = nxt_zalloc(sizeof(nxt_port_mmap_handler_t)); + if (nxt_slow_path(mmap_handler == NULL)) { + nxt_log(task, NXT_LOG_WARN, "failed to allocate mmap_handler"); - nxt_mem_munmap(mem, PORT_MMAP_SIZE); + nxt_mem_munmap(mem, PORT_MMAP_SIZE); - return NULL; - } + return NULL; + } - mmap_handler->hdr = hdr; - mmap_handler->fd = -1; + mmap_handler->hdr = hdr; + mmap_handler->fd = -1; - nxt_thread_mutex_lock(&process->incoming.mutex); + nxt_thread_mutex_lock(&process->incoming.mutex); - port_mmap = nxt_port_mmap_at(&process->incoming, hdr->id); - if (nxt_slow_path(port_mmap == NULL)) { - nxt_log(task, NXT_LOG_WARN, "failed to add mmap to incoming array"); + port_mmap = nxt_port_mmap_at(&process->incoming, hdr->id); + if (nxt_slow_path(port_mmap == NULL)) { + nxt_log(task, NXT_LOG_WARN, "failed to add mmap to incoming array"); - nxt_mem_munmap(mem, PORT_MMAP_SIZE); + nxt_mem_munmap(mem, PORT_MMAP_SIZE); - nxt_free(mmap_handler); - mmap_handler = NULL; + nxt_free(mmap_handler); + mmap_handler = NULL; - goto fail; - } + goto fail; + } - port_mmap->mmap_handler = mmap_handler; - nxt_port_mmap_handler_use(mmap_handler, 1); + port_mmap->mmap_handler = mmap_handler; + nxt_port_mmap_handler_use(mmap_handler, 1); - hdr->sent_over = 0xFFFFu; + hdr->sent_over = 0xFFFFu; fail: - nxt_thread_mutex_unlock(&process->incoming.mutex); + nxt_thread_mutex_unlock(&process->incoming.mutex); - return mmap_handler; + return mmap_handler; } +static nxt_port_mmap_handler_t *nxt_port_new_port_mmap(nxt_task_t *task, + nxt_port_mmaps_t *mmaps, + nxt_bool_t tracking, + nxt_int_t n) { + void *mem; + nxt_fd_t fd; + nxt_int_t i; + nxt_free_map_t *free_map; + nxt_port_mmap_t *port_mmap; + nxt_port_mmap_header_t *hdr; + nxt_port_mmap_handler_t *mmap_handler; + + mmap_handler = nxt_zalloc(sizeof(nxt_port_mmap_handler_t)); + if (nxt_slow_path(mmap_handler == NULL)) { + nxt_alert(task, "failed to allocate mmap_handler"); -static nxt_port_mmap_handler_t * -nxt_port_new_port_mmap(nxt_task_t *task, nxt_port_mmaps_t *mmaps, - nxt_bool_t tracking, nxt_int_t n) -{ - void *mem; - nxt_fd_t fd; - nxt_int_t i; - nxt_free_map_t *free_map; - nxt_port_mmap_t *port_mmap; - nxt_port_mmap_header_t *hdr; - nxt_port_mmap_handler_t *mmap_handler; - - mmap_handler = nxt_zalloc(sizeof(nxt_port_mmap_handler_t)); - if (nxt_slow_path(mmap_handler == NULL)) { - nxt_alert(task, "failed to allocate mmap_handler"); - - return NULL; - } + return NULL; + } - port_mmap = nxt_port_mmap_at(mmaps, mmaps->size); - if (nxt_slow_path(port_mmap == NULL)) { - nxt_alert(task, "failed to add port mmap to mmaps array"); + port_mmap = nxt_port_mmap_at(mmaps, mmaps->size); + if (nxt_slow_path(port_mmap == NULL)) { + nxt_alert(task, "failed to add port mmap to mmaps array"); - nxt_free(mmap_handler); - return NULL; - } + nxt_free(mmap_handler); + return NULL; + } - fd = nxt_shm_open(task, PORT_MMAP_SIZE); - if (nxt_slow_path(fd == -1)) { - goto remove_fail; - } + fd = nxt_shm_open(task, PORT_MMAP_SIZE); + if (nxt_slow_path(fd == -1)) { + goto remove_fail; + } - mem = nxt_mem_mmap(NULL, PORT_MMAP_SIZE, PROT_READ | PROT_WRITE, - MAP_SHARED, fd, 0); + mem = nxt_mem_mmap(NULL, PORT_MMAP_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, + fd, 0); - if (nxt_slow_path(mem == MAP_FAILED)) { - nxt_fd_close(fd); - goto remove_fail; - } + if (nxt_slow_path(mem == MAP_FAILED)) { + nxt_fd_close(fd); + goto remove_fail; + } - mmap_handler->hdr = mem; - mmap_handler->fd = fd; - port_mmap->mmap_handler = mmap_handler; - nxt_port_mmap_handler_use(mmap_handler, 1); + mmap_handler->hdr = mem; + mmap_handler->fd = fd; + port_mmap->mmap_handler = mmap_handler; + nxt_port_mmap_handler_use(mmap_handler, 1); - /* Init segment header. */ - hdr = mmap_handler->hdr; + /* Init segment header. */ + hdr = mmap_handler->hdr; - nxt_memset(hdr->free_map, 0xFFU, sizeof(hdr->free_map)); - nxt_memset(hdr->free_tracking_map, 0xFFU, sizeof(hdr->free_tracking_map)); + nxt_memset(hdr->free_map, 0xFFU, sizeof(hdr->free_map)); + nxt_memset(hdr->free_tracking_map, 0xFFU, sizeof(hdr->free_tracking_map)); - hdr->id = mmaps->size - 1; - hdr->src_pid = nxt_pid; - hdr->sent_over = 0xFFFFu; + hdr->id = mmaps->size - 1; + hdr->src_pid = nxt_pid; + hdr->sent_over = 0xFFFFu; - /* Mark first chunk as busy */ - free_map = tracking ? hdr->free_tracking_map : hdr->free_map; + /* Mark first chunk as busy */ + free_map = tracking ? hdr->free_tracking_map : hdr->free_map; - for (i = 0; i < n; i++) { - nxt_port_mmap_set_chunk_busy(free_map, i); - } + for (i = 0; i < n; i++) { + nxt_port_mmap_set_chunk_busy(free_map, i); + } - /* Mark as busy chunk followed the last available chunk. */ - nxt_port_mmap_set_chunk_busy(hdr->free_map, PORT_MMAP_CHUNK_COUNT); - nxt_port_mmap_set_chunk_busy(hdr->free_tracking_map, PORT_MMAP_CHUNK_COUNT); + /* Mark as busy chunk followed the last available chunk. */ + nxt_port_mmap_set_chunk_busy(hdr->free_map, PORT_MMAP_CHUNK_COUNT); + nxt_port_mmap_set_chunk_busy(hdr->free_tracking_map, PORT_MMAP_CHUNK_COUNT); - nxt_log(task, NXT_LOG_DEBUG, "new mmap #%D created for %PI -> ...", - hdr->id, nxt_pid); + nxt_log(task, NXT_LOG_DEBUG, "new mmap #%D created for %PI -> ...", hdr->id, + nxt_pid); - return mmap_handler; + return mmap_handler; remove_fail: - nxt_free(mmap_handler); + nxt_free(mmap_handler); - mmaps->size--; + mmaps->size--; - return NULL; + return NULL; } - -nxt_int_t -nxt_shm_open(nxt_task_t *task, size_t size) -{ - nxt_fd_t fd; +nxt_int_t nxt_shm_open(nxt_task_t *task, size_t size) { + nxt_fd_t fd; #if (NXT_HAVE_MEMFD_CREATE || NXT_HAVE_SHM_OPEN) - u_char *p, name[64]; + u_char *p, name[64]; - p = nxt_sprintf(name, name + sizeof(name), NXT_SHM_PREFIX "unit.%PI.%uxD", - nxt_pid, nxt_random(&task->thread->random)); - *p = '\0'; + p = nxt_sprintf(name, name + sizeof(name), NXT_SHM_PREFIX "unit.%PI.%uxD", + nxt_pid, nxt_random(&task->thread->random)); + *p = '\0'; #endif #if (NXT_HAVE_MEMFD_CREATE) - fd = syscall(SYS_memfd_create, name, MFD_CLOEXEC); + fd = syscall(SYS_memfd_create, name, MFD_CLOEXEC); - if (nxt_slow_path(fd == -1)) { - nxt_alert(task, "memfd_create(%s) failed %E", name, nxt_errno); + if (nxt_slow_path(fd == -1)) { + nxt_alert(task, "memfd_create(%s) failed %E", name, nxt_errno); - return -1; - } + return -1; + } - nxt_debug(task, "memfd_create(%s): %FD", name, fd); + nxt_debug(task, "memfd_create(%s): %FD", name, fd); #elif (NXT_HAVE_SHM_OPEN_ANON) - fd = shm_open(SHM_ANON, O_RDWR, 0600); - if (nxt_slow_path(fd == -1)) { - nxt_alert(task, "shm_open(SHM_ANON) failed %E", nxt_errno); + fd = shm_open(SHM_ANON, O_RDWR, 0600); + if (nxt_slow_path(fd == -1)) { + nxt_alert(task, "shm_open(SHM_ANON) failed %E", nxt_errno); - return -1; - } + return -1; + } - nxt_debug(task, "shm_open(SHM_ANON): %FD", fd); + nxt_debug(task, "shm_open(SHM_ANON): %FD", fd); #elif (NXT_HAVE_SHM_OPEN) - /* Just in case. */ - shm_unlink((char *) name); + /* Just in case. */ + shm_unlink((char *)name); - fd = shm_open((char *) name, O_CREAT | O_EXCL | O_RDWR, 0600); - if (nxt_slow_path(fd == -1)) { - nxt_alert(task, "shm_open(%s) failed %E", name, nxt_errno); + fd = shm_open((char *)name, O_CREAT | O_EXCL | O_RDWR, 0600); + if (nxt_slow_path(fd == -1)) { + nxt_alert(task, "shm_open(%s) failed %E", name, nxt_errno); - return -1; - } + return -1; + } - nxt_debug(task, "shm_open(%s): %FD", name, fd); + nxt_debug(task, "shm_open(%s): %FD", name, fd); - if (nxt_slow_path(shm_unlink((char *) name) == -1)) { - nxt_log(task, NXT_LOG_WARN, "shm_unlink(%s) failed %E", name, - nxt_errno); - } + if (nxt_slow_path(shm_unlink((char *)name) == -1)) { + nxt_log(task, NXT_LOG_WARN, "shm_unlink(%s) failed %E", name, nxt_errno); + } #else @@ -427,460 +409,430 @@ nxt_shm_open(nxt_task_t *task, size_t size) #endif - if (nxt_slow_path(ftruncate(fd, size) == -1)) { - nxt_alert(task, "ftruncate() failed %E", nxt_errno); + if (nxt_slow_path(ftruncate(fd, size) == -1)) { + nxt_alert(task, "ftruncate() failed %E", nxt_errno); - nxt_fd_close(fd); + nxt_fd_close(fd); - return -1; - } + return -1; + } - return fd; + return fd; } - static nxt_port_mmap_handler_t * nxt_port_mmap_get(nxt_task_t *task, nxt_port_mmaps_t *mmaps, nxt_chunk_id_t *c, - nxt_int_t n, nxt_bool_t tracking) -{ - nxt_int_t i, res, nchunks; - nxt_free_map_t *free_map; - nxt_port_mmap_t *port_mmap; - nxt_port_mmap_t *end_port_mmap; - nxt_port_mmap_header_t *hdr; - nxt_port_mmap_handler_t *mmap_handler; - - nxt_thread_mutex_lock(&mmaps->mutex); - - if (nxt_slow_path(mmaps->elts == NULL)) { - goto end; - } + nxt_int_t n, nxt_bool_t tracking) { + nxt_int_t i, res, nchunks; + nxt_free_map_t *free_map; + nxt_port_mmap_t *port_mmap; + nxt_port_mmap_t *end_port_mmap; + nxt_port_mmap_header_t *hdr; + nxt_port_mmap_handler_t *mmap_handler; - end_port_mmap = mmaps->elts + mmaps->size; + nxt_thread_mutex_lock(&mmaps->mutex); - for (port_mmap = mmaps->elts; - port_mmap < end_port_mmap; - port_mmap++) - { - mmap_handler = port_mmap->mmap_handler; - hdr = mmap_handler->hdr; + if (nxt_slow_path(mmaps->elts == NULL)) { + goto end; + } - if (hdr->sent_over != 0xFFFFu) { - continue; - } + end_port_mmap = mmaps->elts + mmaps->size; - *c = 0; + for (port_mmap = mmaps->elts; port_mmap < end_port_mmap; port_mmap++) { + mmap_handler = port_mmap->mmap_handler; + hdr = mmap_handler->hdr; - free_map = tracking ? hdr->free_tracking_map : hdr->free_map; + if (hdr->sent_over != 0xFFFFu) { + continue; + } - while (nxt_port_mmap_get_free_chunk(free_map, c)) { - nchunks = 1; + *c = 0; - while (nchunks < n) { - res = nxt_port_mmap_chk_set_chunk_busy(free_map, *c + nchunks); + free_map = tracking ? hdr->free_tracking_map : hdr->free_map; - if (res == 0) { - for (i = 0; i < nchunks; i++) { - nxt_port_mmap_set_chunk_free(free_map, *c + i); - } + while (nxt_port_mmap_get_free_chunk(free_map, c)) { + nchunks = 1; - *c += nchunks + 1; - nchunks = 0; - break; - } + while (nchunks < n) { + res = nxt_port_mmap_chk_set_chunk_busy(free_map, *c + nchunks); - nchunks++; - } + if (res == 0) { + for (i = 0; i < nchunks; i++) { + nxt_port_mmap_set_chunk_free(free_map, *c + i); + } - if (nchunks == n) { - goto unlock_return; - } + *c += nchunks + 1; + nchunks = 0; + break; } - hdr->oosm = 1; + nchunks++; + } + + if (nchunks == n) { + goto unlock_return; + } } - /* TODO introduce port_mmap limit and release wait. */ + hdr->oosm = 1; + } + + /* TODO introduce port_mmap limit and release wait. */ end: - *c = 0; - mmap_handler = nxt_port_new_port_mmap(task, mmaps, tracking, n); + *c = 0; + mmap_handler = nxt_port_new_port_mmap(task, mmaps, tracking, n); unlock_return: - nxt_thread_mutex_unlock(&mmaps->mutex); + nxt_thread_mutex_unlock(&mmaps->mutex); - return mmap_handler; + return mmap_handler; } - static nxt_port_mmap_handler_t * -nxt_port_get_port_incoming_mmap(nxt_task_t *task, nxt_pid_t spid, uint32_t id) -{ - nxt_process_t *process; - nxt_port_mmap_handler_t *mmap_handler; - - process = nxt_runtime_process_find(task->thread->runtime, spid); - if (nxt_slow_path(process == NULL)) { - return NULL; - } +nxt_port_get_port_incoming_mmap(nxt_task_t *task, nxt_pid_t spid, uint32_t id) { + nxt_process_t *process; + nxt_port_mmap_handler_t *mmap_handler; - nxt_thread_mutex_lock(&process->incoming.mutex); + process = nxt_runtime_process_find(task->thread->runtime, spid); + if (nxt_slow_path(process == NULL)) { + return NULL; + } - if (nxt_fast_path(process->incoming.size > id)) { - mmap_handler = process->incoming.elts[id].mmap_handler; + nxt_thread_mutex_lock(&process->incoming.mutex); - } else { - mmap_handler = NULL; + if (nxt_fast_path(process->incoming.size > id)) { + mmap_handler = process->incoming.elts[id].mmap_handler; - nxt_debug(task, "invalid incoming mmap id %uD for pid %PI", id, spid); - } + } else { + mmap_handler = NULL; - nxt_thread_mutex_unlock(&process->incoming.mutex); + nxt_debug(task, "invalid incoming mmap id %uD for pid %PI", id, spid); + } - return mmap_handler; -} + nxt_thread_mutex_unlock(&process->incoming.mutex); + return mmap_handler; +} -nxt_buf_t * -nxt_port_mmap_get_buf(nxt_task_t *task, nxt_port_mmaps_t *mmaps, size_t size) -{ - nxt_mp_t *mp; - nxt_buf_t *b; - nxt_int_t nchunks; - nxt_chunk_id_t c; - nxt_port_mmap_header_t *hdr; - nxt_port_mmap_handler_t *mmap_handler; +nxt_buf_t *nxt_port_mmap_get_buf(nxt_task_t *task, nxt_port_mmaps_t *mmaps, + size_t size) { + nxt_mp_t *mp; + nxt_buf_t *b; + nxt_int_t nchunks; + nxt_chunk_id_t c; + nxt_port_mmap_header_t *hdr; + nxt_port_mmap_handler_t *mmap_handler; - nxt_debug(task, "request %z bytes shm buffer", size); + nxt_debug(task, "request %z bytes shm buffer", size); - nchunks = (size + PORT_MMAP_CHUNK_SIZE - 1) / PORT_MMAP_CHUNK_SIZE; + nchunks = (size + PORT_MMAP_CHUNK_SIZE - 1) / PORT_MMAP_CHUNK_SIZE; - if (nxt_slow_path(nchunks > PORT_MMAP_CHUNK_COUNT)) { - nxt_alert(task, "requested buffer (%z) too big", size); + if (nxt_slow_path(nchunks > PORT_MMAP_CHUNK_COUNT)) { + nxt_alert(task, "requested buffer (%z) too big", size); - return NULL; - } + return NULL; + } - b = nxt_buf_mem_ts_alloc(task, task->thread->engine->mem_pool, 0); - if (nxt_slow_path(b == NULL)) { - return NULL; - } + b = nxt_buf_mem_ts_alloc(task, task->thread->engine->mem_pool, 0); + if (nxt_slow_path(b == NULL)) { + return NULL; + } - b->completion_handler = nxt_port_mmap_buf_completion; - nxt_buf_set_port_mmap(b); + b->completion_handler = nxt_port_mmap_buf_completion; + nxt_buf_set_port_mmap(b); - mmap_handler = nxt_port_mmap_get(task, mmaps, &c, nchunks, 0); - if (nxt_slow_path(mmap_handler == NULL)) { - mp = task->thread->engine->mem_pool; - nxt_mp_free(mp, b); - nxt_mp_release(mp); - return NULL; - } + mmap_handler = nxt_port_mmap_get(task, mmaps, &c, nchunks, 0); + if (nxt_slow_path(mmap_handler == NULL)) { + mp = task->thread->engine->mem_pool; + nxt_mp_free(mp, b); + nxt_mp_release(mp); + return NULL; + } - b->parent = mmap_handler; + b->parent = mmap_handler; - nxt_port_mmap_handler_use(mmap_handler, 1); + nxt_port_mmap_handler_use(mmap_handler, 1); - hdr = mmap_handler->hdr; + hdr = mmap_handler->hdr; - b->mem.start = nxt_port_mmap_chunk_start(hdr, c); - b->mem.pos = b->mem.start; - b->mem.free = b->mem.start; - b->mem.end = b->mem.start + nchunks * PORT_MMAP_CHUNK_SIZE; + b->mem.start = nxt_port_mmap_chunk_start(hdr, c); + b->mem.pos = b->mem.start; + b->mem.free = b->mem.start; + b->mem.end = b->mem.start + nchunks * PORT_MMAP_CHUNK_SIZE; - nxt_debug(task, "outgoing mmap buf allocation: %p [%p,%uz] %PI->%PI,%d,%d", - b, b->mem.start, b->mem.end - b->mem.start, - hdr->src_pid, hdr->dst_pid, hdr->id, c); + nxt_debug(task, "outgoing mmap buf allocation: %p [%p,%uz] %PI->%PI,%d,%d", b, + b->mem.start, b->mem.end - b->mem.start, hdr->src_pid, hdr->dst_pid, + hdr->id, c); - return b; + return b; } +nxt_int_t nxt_port_mmap_increase_buf(nxt_task_t *task, nxt_buf_t *b, + size_t size, size_t min_size) { + size_t nchunks, free_size; + nxt_chunk_id_t c, start; + nxt_port_mmap_header_t *hdr; + nxt_port_mmap_handler_t *mmap_handler; -nxt_int_t -nxt_port_mmap_increase_buf(nxt_task_t *task, nxt_buf_t *b, size_t size, - size_t min_size) -{ - size_t nchunks, free_size; - nxt_chunk_id_t c, start; - nxt_port_mmap_header_t *hdr; - nxt_port_mmap_handler_t *mmap_handler; + nxt_debug(task, "request increase %z bytes shm buffer", size); - nxt_debug(task, "request increase %z bytes shm buffer", size); + if (nxt_slow_path(nxt_buf_is_port_mmap(b) == 0)) { + nxt_log(task, NXT_LOG_WARN, "failed to increase, not a mmap buffer"); + return NXT_ERROR; + } - if (nxt_slow_path(nxt_buf_is_port_mmap(b) == 0)) { - nxt_log(task, NXT_LOG_WARN, - "failed to increase, not a mmap buffer"); - return NXT_ERROR; - } + free_size = nxt_buf_mem_free_size(&b->mem); - free_size = nxt_buf_mem_free_size(&b->mem); + if (nxt_slow_path(size <= free_size)) { + return NXT_OK; + } - if (nxt_slow_path(size <= free_size)) { - return NXT_OK; - } + mmap_handler = b->parent; + hdr = mmap_handler->hdr; - mmap_handler = b->parent; - hdr = mmap_handler->hdr; + start = nxt_port_mmap_chunk_id(hdr, b->mem.end); - start = nxt_port_mmap_chunk_id(hdr, b->mem.end); + size -= free_size; - size -= free_size; + nchunks = (size + PORT_MMAP_CHUNK_SIZE - 1) / PORT_MMAP_CHUNK_SIZE; - nchunks = (size + PORT_MMAP_CHUNK_SIZE - 1) / PORT_MMAP_CHUNK_SIZE; + c = start; - c = start; + /* Try to acquire as much chunks as required. */ + while (nchunks > 0) { - /* Try to acquire as much chunks as required. */ - while (nchunks > 0) { + if (nxt_port_mmap_chk_set_chunk_busy(hdr->free_map, c) == 0) { + break; + } - if (nxt_port_mmap_chk_set_chunk_busy(hdr->free_map, c) == 0) { - break; - } + c++; + nchunks--; + } - c++; - nchunks--; + if (nchunks != 0 && + min_size > free_size + PORT_MMAP_CHUNK_SIZE * (c - start)) { + c--; + while (c >= start) { + nxt_port_mmap_set_chunk_free(hdr->free_map, c); + c--; } - if (nchunks != 0 - && min_size > free_size + PORT_MMAP_CHUNK_SIZE * (c - start)) - { - c--; - while (c >= start) { - nxt_port_mmap_set_chunk_free(hdr->free_map, c); - c--; - } - - nxt_debug(task, "failed to increase, %uz chunks busy", nchunks); + nxt_debug(task, "failed to increase, %uz chunks busy", nchunks); - return NXT_ERROR; + return NXT_ERROR; - } else { - b->mem.end += PORT_MMAP_CHUNK_SIZE * (c - start); + } else { + b->mem.end += PORT_MMAP_CHUNK_SIZE * (c - start); - return NXT_OK; - } + return NXT_OK; + } } - static nxt_buf_t * nxt_port_mmap_get_incoming_buf(nxt_task_t *task, nxt_port_t *port, - nxt_pid_t spid, nxt_port_mmap_msg_t *mmap_msg) -{ - size_t nchunks; - nxt_buf_t *b; - nxt_port_mmap_header_t *hdr; - nxt_port_mmap_handler_t *mmap_handler; - - mmap_handler = nxt_port_get_port_incoming_mmap(task, spid, - mmap_msg->mmap_id); - if (nxt_slow_path(mmap_handler == NULL)) { - return NULL; - } + nxt_pid_t spid, nxt_port_mmap_msg_t *mmap_msg) { + size_t nchunks; + nxt_buf_t *b; + nxt_port_mmap_header_t *hdr; + nxt_port_mmap_handler_t *mmap_handler; + + mmap_handler = nxt_port_get_port_incoming_mmap(task, spid, mmap_msg->mmap_id); + if (nxt_slow_path(mmap_handler == NULL)) { + return NULL; + } - b = nxt_buf_mem_ts_alloc(task, port->mem_pool, 0); - if (nxt_slow_path(b == NULL)) { - return NULL; - } + b = nxt_buf_mem_ts_alloc(task, port->mem_pool, 0); + if (nxt_slow_path(b == NULL)) { + return NULL; + } - b->completion_handler = nxt_port_mmap_buf_completion; + b->completion_handler = nxt_port_mmap_buf_completion; - nxt_buf_set_port_mmap(b); + nxt_buf_set_port_mmap(b); - nchunks = mmap_msg->size / PORT_MMAP_CHUNK_SIZE; - if ((mmap_msg->size % PORT_MMAP_CHUNK_SIZE) != 0) { - nchunks++; - } + nchunks = mmap_msg->size / PORT_MMAP_CHUNK_SIZE; + if ((mmap_msg->size % PORT_MMAP_CHUNK_SIZE) != 0) { + nchunks++; + } - hdr = mmap_handler->hdr; + hdr = mmap_handler->hdr; - b->mem.start = nxt_port_mmap_chunk_start(hdr, mmap_msg->chunk_id); - b->mem.pos = b->mem.start; - b->mem.free = b->mem.start + mmap_msg->size; - b->mem.end = b->mem.start + nchunks * PORT_MMAP_CHUNK_SIZE; + b->mem.start = nxt_port_mmap_chunk_start(hdr, mmap_msg->chunk_id); + b->mem.pos = b->mem.start; + b->mem.free = b->mem.start + mmap_msg->size; + b->mem.end = b->mem.start + nchunks * PORT_MMAP_CHUNK_SIZE; - b->parent = mmap_handler; - nxt_port_mmap_handler_use(mmap_handler, 1); + b->parent = mmap_handler; + nxt_port_mmap_handler_use(mmap_handler, 1); - nxt_debug(task, "incoming mmap buf allocation: %p [%p,%uz] %PI->%PI,%d,%d", - b, b->mem.start, b->mem.end - b->mem.start, - hdr->src_pid, hdr->dst_pid, hdr->id, mmap_msg->chunk_id); + nxt_debug(task, "incoming mmap buf allocation: %p [%p,%uz] %PI->%PI,%d,%d", b, + b->mem.start, b->mem.end - b->mem.start, hdr->src_pid, hdr->dst_pid, + hdr->id, mmap_msg->chunk_id); - return b; + return b; } +void nxt_port_mmap_write(nxt_task_t *task, nxt_port_t *port, + nxt_port_send_msg_t *msg, nxt_sendbuf_coalesce_t *sb, + void *mmsg_buf) { + size_t bsize; + nxt_buf_t *bmem; + nxt_uint_t i; + nxt_port_mmap_msg_t *mmap_msg; + nxt_port_mmap_header_t *hdr; + nxt_port_mmap_handler_t *mmap_handler; -void -nxt_port_mmap_write(nxt_task_t *task, nxt_port_t *port, - nxt_port_send_msg_t *msg, nxt_sendbuf_coalesce_t *sb, void *mmsg_buf) -{ - size_t bsize; - nxt_buf_t *bmem; - nxt_uint_t i; - nxt_port_mmap_msg_t *mmap_msg; - nxt_port_mmap_header_t *hdr; - nxt_port_mmap_handler_t *mmap_handler; + nxt_debug(task, + "prepare %z bytes message for transfer to process %PI " + "via shared memory", + sb->size, port->pid); - nxt_debug(task, "prepare %z bytes message for transfer to process %PI " - "via shared memory", sb->size, port->pid); + bsize = sb->niov * sizeof(nxt_port_mmap_msg_t); + mmap_msg = mmsg_buf; - bsize = sb->niov * sizeof(nxt_port_mmap_msg_t); - mmap_msg = mmsg_buf; + bmem = msg->buf; - bmem = msg->buf; + for (i = 0; i < sb->niov; i++, mmap_msg++) { - for (i = 0; i < sb->niov; i++, mmap_msg++) { - - /* Lookup buffer which starts current iov_base. */ - while (bmem && sb->iobuf[i].iov_base != bmem->mem.pos) { - bmem = bmem->next; - } + /* Lookup buffer which starts current iov_base. */ + while (bmem && sb->iobuf[i].iov_base != bmem->mem.pos) { + bmem = bmem->next; + } - if (nxt_slow_path(bmem == NULL)) { - nxt_log_error(NXT_LOG_ERR, task->log, - "failed to find buf for iobuf[%d]", i); - return; - /* TODO clear b and exit */ - } + if (nxt_slow_path(bmem == NULL)) { + nxt_log_error(NXT_LOG_ERR, task->log, "failed to find buf for iobuf[%d]", + i); + return; + /* TODO clear b and exit */ + } - mmap_handler = bmem->parent; - hdr = mmap_handler->hdr; + mmap_handler = bmem->parent; + hdr = mmap_handler->hdr; - mmap_msg->mmap_id = hdr->id; - mmap_msg->chunk_id = nxt_port_mmap_chunk_id(hdr, bmem->mem.pos); - mmap_msg->size = sb->iobuf[i].iov_len; + mmap_msg->mmap_id = hdr->id; + mmap_msg->chunk_id = nxt_port_mmap_chunk_id(hdr, bmem->mem.pos); + mmap_msg->size = sb->iobuf[i].iov_len; - nxt_debug(task, "mmap_msg={%D, %D, %D} to %PI", - mmap_msg->mmap_id, mmap_msg->chunk_id, mmap_msg->size, - port->pid); - } + nxt_debug(task, "mmap_msg={%D, %D, %D} to %PI", mmap_msg->mmap_id, + mmap_msg->chunk_id, mmap_msg->size, port->pid); + } - sb->iobuf[0].iov_base = mmsg_buf; - sb->iobuf[0].iov_len = bsize; - sb->niov = 1; - sb->size = bsize; + sb->iobuf[0].iov_base = mmsg_buf; + sb->iobuf[0].iov_len = bsize; + sb->niov = 1; + sb->size = bsize; - msg->port_msg.mmap = 1; + msg->port_msg.mmap = 1; } +void nxt_port_mmap_read(nxt_task_t *task, nxt_port_recv_msg_t *msg) { + nxt_buf_t *b, **pb; + nxt_port_mmap_msg_t *end, *mmap_msg; -void -nxt_port_mmap_read(nxt_task_t *task, nxt_port_recv_msg_t *msg) -{ - nxt_buf_t *b, **pb; - nxt_port_mmap_msg_t *end, *mmap_msg; - - pb = &msg->buf; - msg->size = 0; + pb = &msg->buf; + msg->size = 0; - for (b = msg->buf; b != NULL; b = b->next) { + for (b = msg->buf; b != NULL; b = b->next) { - mmap_msg = (nxt_port_mmap_msg_t *) b->mem.pos; - end = (nxt_port_mmap_msg_t *) b->mem.free; + mmap_msg = (nxt_port_mmap_msg_t *)b->mem.pos; + end = (nxt_port_mmap_msg_t *)b->mem.free; - while (mmap_msg < end) { - nxt_debug(task, "mmap_msg={%D, %D, %D} from %PI", - mmap_msg->mmap_id, mmap_msg->chunk_id, mmap_msg->size, - msg->port_msg.pid); + while (mmap_msg < end) { + nxt_debug(task, "mmap_msg={%D, %D, %D} from %PI", mmap_msg->mmap_id, + mmap_msg->chunk_id, mmap_msg->size, msg->port_msg.pid); - *pb = nxt_port_mmap_get_incoming_buf(task, msg->port, - msg->port_msg.pid, mmap_msg); - if (nxt_slow_path(*pb == NULL)) { - nxt_log_error(NXT_LOG_ERR, task->log, - "failed to get mmap buffer"); + *pb = nxt_port_mmap_get_incoming_buf(task, msg->port, msg->port_msg.pid, + mmap_msg); + if (nxt_slow_path(*pb == NULL)) { + nxt_log_error(NXT_LOG_ERR, task->log, "failed to get mmap buffer"); - break; - } + break; + } - msg->size += mmap_msg->size; - pb = &(*pb)->next; - mmap_msg++; + msg->size += mmap_msg->size; + pb = &(*pb)->next; + mmap_msg++; - /* Mark original buf as complete. */ - b->mem.pos += sizeof(nxt_port_mmap_msg_t); - } + /* Mark original buf as complete. */ + b->mem.pos += sizeof(nxt_port_mmap_msg_t); } + } } +nxt_port_method_t nxt_port_mmap_get_method(nxt_task_t *task, nxt_port_t *port, + nxt_buf_t *b) { + nxt_port_method_t m; -nxt_port_method_t -nxt_port_mmap_get_method(nxt_task_t *task, nxt_port_t *port, nxt_buf_t *b) -{ - nxt_port_method_t m; - - m = NXT_PORT_METHOD_ANY; + m = NXT_PORT_METHOD_ANY; - for (/* void */; b != NULL; b = b->next) { - if (nxt_buf_used_size(b) == 0) { - /* empty buffers does not affect method */ - continue; - } + for (/* void */; b != NULL; b = b->next) { + if (nxt_buf_used_size(b) == 0) { + /* empty buffers does not affect method */ + continue; + } - if (nxt_buf_is_port_mmap(b)) { - if (m == NXT_PORT_METHOD_PLAIN) { - nxt_log_error(NXT_LOG_ERR, task->log, - "mixing plain and mmap buffers, " - "using plain mode"); + if (nxt_buf_is_port_mmap(b)) { + if (m == NXT_PORT_METHOD_PLAIN) { + nxt_log_error(NXT_LOG_ERR, task->log, + "mixing plain and mmap buffers, " + "using plain mode"); - break; - } + break; + } - if (m == NXT_PORT_METHOD_ANY) { - nxt_debug(task, "using mmap mode"); + if (m == NXT_PORT_METHOD_ANY) { + nxt_debug(task, "using mmap mode"); - m = NXT_PORT_METHOD_MMAP; - } - } else { - if (m == NXT_PORT_METHOD_MMAP) { - nxt_log_error(NXT_LOG_ERR, task->log, - "mixing mmap and plain buffers, " - "switching to plain mode"); + m = NXT_PORT_METHOD_MMAP; + } + } else { + if (m == NXT_PORT_METHOD_MMAP) { + nxt_log_error(NXT_LOG_ERR, task->log, + "mixing mmap and plain buffers, " + "switching to plain mode"); - m = NXT_PORT_METHOD_PLAIN; + m = NXT_PORT_METHOD_PLAIN; - break; - } + break; + } - if (m == NXT_PORT_METHOD_ANY) { - nxt_debug(task, "using plain mode"); + if (m == NXT_PORT_METHOD_ANY) { + nxt_debug(task, "using plain mode"); - m = NXT_PORT_METHOD_PLAIN; - } - } + m = NXT_PORT_METHOD_PLAIN; + } } + } - return m; + return m; } +void nxt_process_broadcast_shm_ack(nxt_task_t *task, nxt_process_t *process) { + nxt_port_t *port; -void -nxt_process_broadcast_shm_ack(nxt_task_t *task, nxt_process_t *process) -{ - nxt_port_t *port; - - if (nxt_slow_path(process == NULL || nxt_queue_is_empty(&process->ports))) - { - return; - } + if (nxt_slow_path(process == NULL || nxt_queue_is_empty(&process->ports))) { + return; + } - port = nxt_process_port_first(process); + port = nxt_process_port_first(process); - if (port->type == NXT_PROCESS_APP) { - nxt_port_post(task, port, nxt_port_broadcast_shm_ack, process); - } + if (port->type == NXT_PROCESS_APP) { + nxt_port_post(task, port, nxt_port_broadcast_shm_ack, process); + } } +static void nxt_port_broadcast_shm_ack(nxt_task_t *task, nxt_port_t *port, + void *data) { + nxt_process_t *process; -static void -nxt_port_broadcast_shm_ack(nxt_task_t *task, nxt_port_t *port, void *data) -{ - nxt_process_t *process; - - process = data; + process = data; - nxt_queue_each(port, &process->ports, nxt_port_t, link) { - (void) nxt_port_socket_write(task, port, NXT_PORT_MSG_SHM_ACK, - -1, 0, 0, NULL); - } nxt_queue_loop; + nxt_queue_each(port, &process->ports, nxt_port_t, link) { + (void)nxt_port_socket_write(task, port, NXT_PORT_MSG_SHM_ACK, -1, 0, 0, + NULL); + } + nxt_queue_loop; } diff --git a/src/nxt_port_memory.h b/src/nxt_port_memory.h index f1e709646..a30a2e6e3 100644 --- a/src/nxt_port_memory.h +++ b/src/nxt_port_memory.h @@ -7,7 +7,6 @@ #ifndef _NXT_PORT_MEMORY_H_INCLUDED_ #define _NXT_PORT_MEMORY_H_INCLUDED_ - #define PORT_MMAP_MIN_SIZE (3 * sizeof(uint32_t)) typedef struct nxt_port_mmap_header_s nxt_port_mmap_header_t; @@ -20,33 +19,32 @@ void nxt_port_mmaps_destroy(nxt_port_mmaps_t *port_mmaps, nxt_bool_t free_elts); * this buf 'mem' pointers to first available shared mem bucket(s). 'size' * used as a hint to acquire several successive buckets if possible. */ -nxt_buf_t * -nxt_port_mmap_get_buf(nxt_task_t *task, nxt_port_mmaps_t *mmaps, size_t size); +nxt_buf_t *nxt_port_mmap_get_buf(nxt_task_t *task, nxt_port_mmaps_t *mmaps, + size_t size); nxt_int_t nxt_port_mmap_increase_buf(nxt_task_t *task, nxt_buf_t *b, - size_t size, size_t min_size); + size_t size, size_t min_size); -nxt_port_mmap_handler_t * -nxt_port_incoming_port_mmap(nxt_task_t *task, nxt_process_t *process, - nxt_fd_t fd); +nxt_port_mmap_handler_t *nxt_port_incoming_port_mmap(nxt_task_t *task, + nxt_process_t *process, + nxt_fd_t fd); -void -nxt_port_mmap_write(nxt_task_t *task, nxt_port_t *port, - nxt_port_send_msg_t *msg, nxt_sendbuf_coalesce_t *sb, void *mmsg_buf); +void nxt_port_mmap_write(nxt_task_t *task, nxt_port_t *port, + nxt_port_send_msg_t *msg, nxt_sendbuf_coalesce_t *sb, + void *mmsg_buf); -void -nxt_port_mmap_read(nxt_task_t *task, nxt_port_recv_msg_t *msg); +void nxt_port_mmap_read(nxt_task_t *task, nxt_port_recv_msg_t *msg); enum nxt_port_method_e { - NXT_PORT_METHOD_ANY = 0, - NXT_PORT_METHOD_PLAIN, - NXT_PORT_METHOD_MMAP + NXT_PORT_METHOD_ANY = 0, + NXT_PORT_METHOD_PLAIN, + NXT_PORT_METHOD_MMAP }; typedef enum nxt_port_method_e nxt_port_method_t; -nxt_port_method_t -nxt_port_mmap_get_method(nxt_task_t *task, nxt_port_t *port, nxt_buf_t *b); +nxt_port_method_t nxt_port_mmap_get_method(nxt_task_t *task, nxt_port_t *port, + nxt_buf_t *b); nxt_int_t nxt_shm_open(nxt_task_t *task, size_t size); diff --git a/src/nxt_port_memory_int.h b/src/nxt_port_memory_int.h index 21a05b104..def9e3217 100644 --- a/src/nxt_port_memory_int.h +++ b/src/nxt_port_memory_int.h @@ -7,63 +7,56 @@ #ifndef _NXT_PORT_MEMORY_INT_H_INCLUDED_ #define _NXT_PORT_MEMORY_INT_H_INCLUDED_ - #include #include - #ifdef NXT_MMAP_TINY_CHUNK -#define PORT_MMAP_CHUNK_SIZE 16 -#define PORT_MMAP_HEADER_SIZE 1024 -#define PORT_MMAP_DATA_SIZE 1024 +#define PORT_MMAP_CHUNK_SIZE 16 +#define PORT_MMAP_HEADER_SIZE 1024 +#define PORT_MMAP_DATA_SIZE 1024 #else -#define PORT_MMAP_CHUNK_SIZE (1024 * 16) -#define PORT_MMAP_HEADER_SIZE (1024 * 4) -#define PORT_MMAP_DATA_SIZE (1024 * 1024 * 10) +#define PORT_MMAP_CHUNK_SIZE (1024 * 16) +#define PORT_MMAP_HEADER_SIZE (1024 * 4) +#define PORT_MMAP_DATA_SIZE (1024 * 1024 * 10) #endif +#define PORT_MMAP_SIZE (PORT_MMAP_HEADER_SIZE + PORT_MMAP_DATA_SIZE) +#define PORT_MMAP_CHUNK_COUNT (PORT_MMAP_DATA_SIZE / PORT_MMAP_CHUNK_SIZE) -#define PORT_MMAP_SIZE (PORT_MMAP_HEADER_SIZE + PORT_MMAP_DATA_SIZE) -#define PORT_MMAP_CHUNK_COUNT (PORT_MMAP_DATA_SIZE / PORT_MMAP_CHUNK_SIZE) - - -typedef uint32_t nxt_chunk_id_t; +typedef uint32_t nxt_chunk_id_t; -typedef nxt_atomic_uint_t nxt_free_map_t; +typedef nxt_atomic_uint_t nxt_free_map_t; #define FREE_BITS (sizeof(nxt_free_map_t) * 8) #define FREE_IDX(nchunk) ((nchunk) / FREE_BITS) -#define FREE_MASK(nchunk) \ - ( 1ULL << ( (nchunk) % FREE_BITS ) ) +#define FREE_MASK(nchunk) (1ULL << ((nchunk) % FREE_BITS)) #define MAX_FREE_IDX FREE_IDX(PORT_MMAP_CHUNK_COUNT) - /* Mapped at the start of shared memory segment. */ struct nxt_port_mmap_header_s { - uint32_t id; - nxt_pid_t src_pid; /* For sanity check. */ - nxt_pid_t dst_pid; /* For sanity check. */ - nxt_port_id_t sent_over; - nxt_atomic_t oosm; - nxt_free_map_t free_map[MAX_FREE_IDX]; - nxt_free_map_t free_map_padding; - nxt_free_map_t free_tracking_map[MAX_FREE_IDX]; - nxt_free_map_t free_tracking_map_padding; - nxt_atomic_t tracking[PORT_MMAP_CHUNK_COUNT]; + uint32_t id; + nxt_pid_t src_pid; /* For sanity check. */ + nxt_pid_t dst_pid; /* For sanity check. */ + nxt_port_id_t sent_over; + nxt_atomic_t oosm; + nxt_free_map_t free_map[MAX_FREE_IDX]; + nxt_free_map_t free_map_padding; + nxt_free_map_t free_tracking_map[MAX_FREE_IDX]; + nxt_free_map_t free_tracking_map_padding; + nxt_atomic_t tracking[PORT_MMAP_CHUNK_COUNT]; }; - struct nxt_port_mmap_handler_s { - nxt_port_mmap_header_t *hdr; - nxt_atomic_t use_count; - nxt_fd_t fd; + nxt_port_mmap_header_t *hdr; + nxt_atomic_t use_count; + nxt_fd_t fd; }; /* @@ -71,126 +64,113 @@ struct nxt_port_mmap_handler_s { * descriptor. */ struct nxt_port_mmap_s { - nxt_port_mmap_handler_t *mmap_handler; + nxt_port_mmap_handler_t *mmap_handler; }; typedef struct nxt_port_mmap_msg_s nxt_port_mmap_msg_t; /* Passed as a second iov chunk when 'mmap' bit in nxt_port_msg_t is 1. */ struct nxt_port_mmap_msg_s { - uint32_t mmap_id; /* Mmap index in nxt_process_t.outgoing. */ - nxt_chunk_id_t chunk_id; /* Mmap chunk index. */ - uint32_t size; /* Payload data size. */ + uint32_t mmap_id; /* Mmap index in nxt_process_t.outgoing. */ + nxt_chunk_id_t chunk_id; /* Mmap chunk index. */ + uint32_t size; /* Payload data size. */ }; +nxt_inline nxt_bool_t nxt_port_mmap_get_free_chunk(nxt_free_map_t *m, + nxt_chunk_id_t *c); -nxt_inline nxt_bool_t -nxt_port_mmap_get_free_chunk(nxt_free_map_t *m, nxt_chunk_id_t *c); - -#define nxt_port_mmap_get_chunk_busy(m, c) \ - ((m[FREE_IDX(c)] & FREE_MASK(c)) == 0) +#define nxt_port_mmap_get_chunk_busy(m, c) \ + ((m[FREE_IDX(c)] & FREE_MASK(c)) == 0) -nxt_inline void -nxt_port_mmap_set_chunk_busy(nxt_free_map_t *m, nxt_chunk_id_t c); +nxt_inline void nxt_port_mmap_set_chunk_busy(nxt_free_map_t *m, + nxt_chunk_id_t c); -nxt_inline nxt_bool_t -nxt_port_mmap_chk_set_chunk_busy(nxt_free_map_t *m, nxt_chunk_id_t c); +nxt_inline nxt_bool_t nxt_port_mmap_chk_set_chunk_busy(nxt_free_map_t *m, + nxt_chunk_id_t c); -nxt_inline void -nxt_port_mmap_set_chunk_free(nxt_free_map_t *m, nxt_chunk_id_t c); +nxt_inline void nxt_port_mmap_set_chunk_free(nxt_free_map_t *m, + nxt_chunk_id_t c); -nxt_inline nxt_chunk_id_t -nxt_port_mmap_chunk_id(nxt_port_mmap_header_t *hdr, const u_char *p) -{ - u_char *mm_start; +nxt_inline nxt_chunk_id_t nxt_port_mmap_chunk_id(nxt_port_mmap_header_t *hdr, + const u_char *p) { + u_char *mm_start; - mm_start = (u_char *) hdr; + mm_start = (u_char *)hdr; - return ((p - mm_start) - PORT_MMAP_HEADER_SIZE) / PORT_MMAP_CHUNK_SIZE; + return ((p - mm_start) - PORT_MMAP_HEADER_SIZE) / PORT_MMAP_CHUNK_SIZE; } +nxt_inline u_char *nxt_port_mmap_chunk_start(nxt_port_mmap_header_t *hdr, + nxt_chunk_id_t c) { + u_char *mm_start; -nxt_inline u_char * -nxt_port_mmap_chunk_start(nxt_port_mmap_header_t *hdr, nxt_chunk_id_t c) -{ - u_char *mm_start; + mm_start = (u_char *)hdr; - mm_start = (u_char *) hdr; - - return mm_start + PORT_MMAP_HEADER_SIZE + c * PORT_MMAP_CHUNK_SIZE; + return mm_start + PORT_MMAP_HEADER_SIZE + c * PORT_MMAP_CHUNK_SIZE; } +nxt_inline nxt_bool_t nxt_port_mmap_get_free_chunk(nxt_free_map_t *m, + nxt_chunk_id_t *c) { + const nxt_free_map_t default_mask = (nxt_free_map_t)-1; -nxt_inline nxt_bool_t -nxt_port_mmap_get_free_chunk(nxt_free_map_t *m, nxt_chunk_id_t *c) -{ - const nxt_free_map_t default_mask = (nxt_free_map_t) -1; - - int ffs; - size_t i, start; - nxt_chunk_id_t chunk; - nxt_free_map_t bits, mask; + int ffs; + size_t i, start; + nxt_chunk_id_t chunk; + nxt_free_map_t bits, mask; - start = FREE_IDX(*c); - mask = default_mask << ((*c) % FREE_BITS); + start = FREE_IDX(*c); + mask = default_mask << ((*c) % FREE_BITS); - for (i = start; i < MAX_FREE_IDX; i++) { - bits = m[i] & mask; - mask = default_mask; + for (i = start; i < MAX_FREE_IDX; i++) { + bits = m[i] & mask; + mask = default_mask; - if (bits == 0) { - continue; - } + if (bits == 0) { + continue; + } - ffs = __builtin_ffsll(bits); - if (ffs != 0) { - chunk = i * FREE_BITS + ffs - 1; + ffs = __builtin_ffsll(bits); + if (ffs != 0) { + chunk = i * FREE_BITS + ffs - 1; - if (nxt_port_mmap_chk_set_chunk_busy(m, chunk)) { - *c = chunk; - return 1; - } - } + if (nxt_port_mmap_chk_set_chunk_busy(m, chunk)) { + *c = chunk; + return 1; + } } + } - return 0; + return 0; } - -nxt_inline void -nxt_port_mmap_set_chunk_busy(nxt_free_map_t *m, nxt_chunk_id_t c) -{ - nxt_atomic_and_fetch(m + FREE_IDX(c), ~FREE_MASK(c)); +nxt_inline void nxt_port_mmap_set_chunk_busy(nxt_free_map_t *m, + nxt_chunk_id_t c) { + nxt_atomic_and_fetch(m + FREE_IDX(c), ~FREE_MASK(c)); } +nxt_inline nxt_bool_t nxt_port_mmap_chk_set_chunk_busy(nxt_free_map_t *m, + nxt_chunk_id_t c) { + nxt_free_map_t *f; + nxt_free_map_t free_val, busy_val; -nxt_inline nxt_bool_t -nxt_port_mmap_chk_set_chunk_busy(nxt_free_map_t *m, nxt_chunk_id_t c) -{ - nxt_free_map_t *f; - nxt_free_map_t free_val, busy_val; + f = m + FREE_IDX(c); - f = m + FREE_IDX(c); + while ((*f & FREE_MASK(c)) != 0) { - while ( (*f & FREE_MASK(c)) != 0 ) { + free_val = *f | FREE_MASK(c); + busy_val = free_val & ~FREE_MASK(c); - free_val = *f | FREE_MASK(c); - busy_val = free_val & ~FREE_MASK(c); - - if (nxt_atomic_cmp_set(f, free_val, busy_val) != 0) { - return 1; - } + if (nxt_atomic_cmp_set(f, free_val, busy_val) != 0) { + return 1; } + } - return 0; + return 0; } - -nxt_inline void -nxt_port_mmap_set_chunk_free(nxt_free_map_t *m, nxt_chunk_id_t c) -{ - nxt_atomic_or_fetch(m + FREE_IDX(c), FREE_MASK(c)); +nxt_inline void nxt_port_mmap_set_chunk_free(nxt_free_map_t *m, + nxt_chunk_id_t c) { + nxt_atomic_or_fetch(m + FREE_IDX(c), FREE_MASK(c)); } - #endif /* _NXT_PORT_MEMORY_INT_H_INCLUDED_ */ diff --git a/src/nxt_port_queue.h b/src/nxt_port_queue.h index d2b2326bf..208366c61 100644 --- a/src/nxt_port_queue.h +++ b/src/nxt_port_queue.h @@ -6,97 +6,84 @@ #ifndef _NXT_PORT_QUEUE_H_INCLUDED_ #define _NXT_PORT_QUEUE_H_INCLUDED_ - #include - /* Using Numeric Naive Circular Queue as a backend. */ -#define NXT_PORT_QUEUE_SIZE NXT_NNCQ_SIZE -#define NXT_PORT_QUEUE_MSG_SIZE 31 - +#define NXT_PORT_QUEUE_SIZE NXT_NNCQ_SIZE +#define NXT_PORT_QUEUE_MSG_SIZE 31 typedef struct { - uint8_t size; - uint8_t data[NXT_PORT_QUEUE_MSG_SIZE]; + uint8_t size; + uint8_t data[NXT_PORT_QUEUE_MSG_SIZE]; } nxt_port_queue_item_t; - typedef struct { - nxt_nncq_atomic_t nitems; - nxt_nncq_t free_items; - nxt_nncq_t queue; - nxt_port_queue_item_t items[NXT_PORT_QUEUE_SIZE]; + nxt_nncq_atomic_t nitems; + nxt_nncq_t free_items; + nxt_nncq_t queue; + nxt_port_queue_item_t items[NXT_PORT_QUEUE_SIZE]; } nxt_port_queue_t; +nxt_inline void nxt_port_queue_init(nxt_port_queue_t volatile *q) { + nxt_nncq_atomic_t i; -nxt_inline void -nxt_port_queue_init(nxt_port_queue_t volatile *q) -{ - nxt_nncq_atomic_t i; - - nxt_nncq_init(&q->free_items); - nxt_nncq_init(&q->queue); + nxt_nncq_init(&q->free_items); + nxt_nncq_init(&q->queue); - for (i = 0; i < NXT_PORT_QUEUE_SIZE; i++) { - nxt_nncq_enqueue(&q->free_items, i); - } + for (i = 0; i < NXT_PORT_QUEUE_SIZE; i++) { + nxt_nncq_enqueue(&q->free_items, i); + } - q->nitems = 0; + q->nitems = 0; } +nxt_inline nxt_int_t nxt_port_queue_send(nxt_port_queue_t volatile *q, + const void *p, uint8_t size, + int *notify) { + nxt_nncq_atomic_t i; + nxt_port_queue_item_t *qi; -nxt_inline nxt_int_t -nxt_port_queue_send(nxt_port_queue_t volatile *q, const void *p, uint8_t size, - int *notify) -{ - nxt_nncq_atomic_t i; - nxt_port_queue_item_t *qi; - - i = nxt_nncq_dequeue(&q->free_items); - if (i == nxt_nncq_empty(&q->free_items)) { - *notify = 0; - return NXT_AGAIN; - } + i = nxt_nncq_dequeue(&q->free_items); + if (i == nxt_nncq_empty(&q->free_items)) { + *notify = 0; + return NXT_AGAIN; + } - qi = (nxt_port_queue_item_t *) &q->items[i]; + qi = (nxt_port_queue_item_t *)&q->items[i]; - qi->size = size; - nxt_memcpy(qi->data, p, size); + qi->size = size; + nxt_memcpy(qi->data, p, size); - nxt_nncq_enqueue(&q->queue, i); + nxt_nncq_enqueue(&q->queue, i); - i = nxt_atomic_fetch_add(&q->nitems, 1); + i = nxt_atomic_fetch_add(&q->nitems, 1); - *notify = (i == 0); + *notify = (i == 0); - return NXT_OK; + return NXT_OK; } +nxt_inline ssize_t nxt_port_queue_recv(nxt_port_queue_t volatile *q, void *p) { + ssize_t res; + nxt_nncq_atomic_t i; + nxt_port_queue_item_t *qi; -nxt_inline ssize_t -nxt_port_queue_recv(nxt_port_queue_t volatile *q, void *p) -{ - ssize_t res; - nxt_nncq_atomic_t i; - nxt_port_queue_item_t *qi; + i = nxt_nncq_dequeue(&q->queue); + if (i == nxt_nncq_empty(&q->queue)) { + return -1; + } - i = nxt_nncq_dequeue(&q->queue); - if (i == nxt_nncq_empty(&q->queue)) { - return -1; - } + qi = (nxt_port_queue_item_t *)&q->items[i]; - qi = (nxt_port_queue_item_t *) &q->items[i]; + res = qi->size; + nxt_memcpy(p, qi->data, qi->size); - res = qi->size; - nxt_memcpy(p, qi->data, qi->size); + nxt_nncq_enqueue(&q->free_items, i); - nxt_nncq_enqueue(&q->free_items, i); + nxt_atomic_fetch_add(&q->nitems, -1); - nxt_atomic_fetch_add(&q->nitems, -1); - - return res; + return res; } - #endif /* _NXT_PORT_QUEUE_H_INCLUDED_ */ diff --git a/src/nxt_port_rpc.c b/src/nxt_port_rpc.c index 285909335..1371a263c 100644 --- a/src/nxt_port_rpc.c +++ b/src/nxt_port_rpc.c @@ -7,515 +7,489 @@ #include #include - -static volatile uint32_t *nxt_stream_ident; +static volatile uint32_t *nxt_stream_ident; typedef struct nxt_port_rpc_reg_s nxt_port_rpc_reg_t; struct nxt_port_rpc_reg_s { - uint32_t stream; + uint32_t stream; - nxt_pid_t peer; - nxt_queue_link_t link; - nxt_bool_t link_first; + nxt_pid_t peer; + nxt_queue_link_t link; + nxt_bool_t link_first; - nxt_port_rpc_handler_t ready_handler; - nxt_port_rpc_handler_t error_handler; - void *data; + nxt_port_rpc_handler_t ready_handler; + nxt_port_rpc_handler_t error_handler; + void *data; }; +static void nxt_port_rpc_remove_from_peers(nxt_task_t *task, nxt_port_t *port, + nxt_port_rpc_reg_t *reg); -static void -nxt_port_rpc_remove_from_peers(nxt_task_t *task, nxt_port_t *port, - nxt_port_rpc_reg_t *reg); - - -nxt_int_t -nxt_port_rpc_init(void) -{ - void *p; +nxt_int_t nxt_port_rpc_init(void) { + void *p; - if (nxt_stream_ident != NULL) { - return NXT_OK; - } + if (nxt_stream_ident != NULL) { + return NXT_OK; + } - p = nxt_mem_mmap(NULL, sizeof(*nxt_stream_ident), PROT_READ | PROT_WRITE, - MAP_ANON | MAP_SHARED, -1, 0); + p = nxt_mem_mmap(NULL, sizeof(*nxt_stream_ident), PROT_READ | PROT_WRITE, + MAP_ANON | MAP_SHARED, -1, 0); - if (nxt_slow_path(p == MAP_FAILED)) { - return NXT_ERROR; - } + if (nxt_slow_path(p == MAP_FAILED)) { + return NXT_ERROR; + } - nxt_stream_ident = p; - *nxt_stream_ident = 1; + nxt_stream_ident = p; + *nxt_stream_ident = 1; - return NXT_OK; + return NXT_OK; } - -static nxt_int_t -nxt_rpc_reg_test(nxt_lvlhsh_query_t *lhq, void *data) -{ - return NXT_OK; +static nxt_int_t nxt_rpc_reg_test(nxt_lvlhsh_query_t *lhq, void *data) { + return NXT_OK; } - -static const nxt_lvlhsh_proto_t lvlhsh_rpc_reg_proto nxt_aligned(64) = { +static const nxt_lvlhsh_proto_t lvlhsh_rpc_reg_proto nxt_aligned(64) = { NXT_LVLHSH_DEFAULT, nxt_rpc_reg_test, nxt_lvlhsh_alloc, nxt_lvlhsh_free, }; - -nxt_inline void -nxt_port_rpc_lhq_stream(nxt_lvlhsh_query_t *lhq, uint32_t *stream) -{ - lhq->key_hash = nxt_murmur_hash2(stream, sizeof(*stream)); - lhq->key.length = sizeof(*stream); - lhq->key.start = (u_char *) stream; - lhq->proto = &lvlhsh_rpc_reg_proto; +nxt_inline void nxt_port_rpc_lhq_stream(nxt_lvlhsh_query_t *lhq, + uint32_t *stream) { + lhq->key_hash = nxt_murmur_hash2(stream, sizeof(*stream)); + lhq->key.length = sizeof(*stream); + lhq->key.start = (u_char *)stream; + lhq->proto = &lvlhsh_rpc_reg_proto; } - -nxt_inline void -nxt_port_rpc_lhq_peer(nxt_lvlhsh_query_t *lhq, nxt_pid_t *peer) -{ - lhq->key_hash = nxt_murmur_hash2(peer, sizeof(*peer)); - lhq->key.length = sizeof(*peer); - lhq->key.start = (u_char *) peer; - lhq->proto = &lvlhsh_rpc_reg_proto; +nxt_inline void nxt_port_rpc_lhq_peer(nxt_lvlhsh_query_t *lhq, + nxt_pid_t *peer) { + lhq->key_hash = nxt_murmur_hash2(peer, sizeof(*peer)); + lhq->key.length = sizeof(*peer); + lhq->key.start = (u_char *)peer; + lhq->proto = &lvlhsh_rpc_reg_proto; } +uint32_t nxt_port_rpc_register_handler(nxt_task_t *task, nxt_port_t *port, + nxt_port_rpc_handler_t ready_handler, + nxt_port_rpc_handler_t error_handler, + nxt_pid_t peer, void *data) { + void *ex; + nxt_port_rpc_reg_t *reg; -uint32_t -nxt_port_rpc_register_handler(nxt_task_t *task, nxt_port_t *port, - nxt_port_rpc_handler_t ready_handler, nxt_port_rpc_handler_t error_handler, - nxt_pid_t peer, void *data) -{ - void *ex; - nxt_port_rpc_reg_t *reg; + ex = nxt_port_rpc_register_handler_ex(task, port, ready_handler, + error_handler, 0); - ex = nxt_port_rpc_register_handler_ex(task, port, ready_handler, - error_handler, 0); + if (ex == NULL) { + return 0; + } - if (ex == NULL) { - return 0; - } - - if (peer != -1) { - nxt_port_rpc_ex_set_peer(task, port, ex, peer); - } + if (peer != -1) { + nxt_port_rpc_ex_set_peer(task, port, ex, peer); + } - reg = nxt_pointer_to(ex, -sizeof(nxt_port_rpc_reg_t)); + reg = nxt_pointer_to(ex, -sizeof(nxt_port_rpc_reg_t)); - nxt_assert(reg->data == ex); + nxt_assert(reg->data == ex); - reg->data = data; + reg->data = data; - return reg->stream; + return reg->stream; } +void *nxt_port_rpc_register_handler_ex(nxt_task_t *task, nxt_port_t *port, + nxt_port_rpc_handler_t ready_handler, + nxt_port_rpc_handler_t error_handler, + size_t ex_size) { + uint32_t stream; + nxt_port_rpc_reg_t *reg; + nxt_lvlhsh_query_t lhq; -void * -nxt_port_rpc_register_handler_ex(nxt_task_t *task, nxt_port_t *port, - nxt_port_rpc_handler_t ready_handler, nxt_port_rpc_handler_t error_handler, - size_t ex_size) -{ - uint32_t stream; - nxt_port_rpc_reg_t *reg; - nxt_lvlhsh_query_t lhq; + nxt_assert(port->pair[0] != -1); - nxt_assert(port->pair[0] != -1); + stream = nxt_atomic_fetch_add(nxt_stream_ident, 1); - stream = nxt_atomic_fetch_add(nxt_stream_ident, 1); + reg = nxt_mp_zalloc(port->mem_pool, sizeof(nxt_port_rpc_reg_t) + ex_size); - reg = nxt_mp_zalloc(port->mem_pool, sizeof(nxt_port_rpc_reg_t) + ex_size); + if (nxt_slow_path(reg == NULL)) { + nxt_debug(task, "rpc: stream #%uD failed to allocate reg", stream); - if (nxt_slow_path(reg == NULL)) { - nxt_debug(task, "rpc: stream #%uD failed to allocate reg", stream); + return NULL; + } - return NULL; - } + reg->stream = stream; + reg->peer = -1; + reg->ready_handler = ready_handler; + reg->error_handler = error_handler; + reg->data = reg + 1; - reg->stream = stream; - reg->peer = -1; - reg->ready_handler = ready_handler; - reg->error_handler = error_handler; - reg->data = reg + 1; + nxt_port_rpc_lhq_stream(&lhq, &stream); + lhq.replace = 0; + lhq.value = reg; + lhq.pool = port->mem_pool; - nxt_port_rpc_lhq_stream(&lhq, &stream); - lhq.replace = 0; - lhq.value = reg; - lhq.pool = port->mem_pool; + switch (nxt_lvlhsh_insert(&port->rpc_streams, &lhq)) { - switch (nxt_lvlhsh_insert(&port->rpc_streams, &lhq)) { + case NXT_OK: + break; - case NXT_OK: - break; + default: + nxt_log_error(NXT_LOG_ERR, task->log, + "rpc: stream #%uD failed to add " + "reg ", + stream); - default: - nxt_log_error(NXT_LOG_ERR, task->log, "rpc: stream #%uD failed to add " - "reg ", stream); + nxt_mp_free(port->mem_pool, reg); - nxt_mp_free(port->mem_pool, reg); + return NULL; + } - return NULL; - } + nxt_debug(task, "rpc: stream #%uD registered", stream); - nxt_debug(task, "rpc: stream #%uD registered", stream); + nxt_port_inc_use(port); - nxt_port_inc_use(port); - - return reg->data; + return reg->data; } +uint32_t nxt_port_rpc_ex_stream(void *ex) { + nxt_port_rpc_reg_t *reg; -uint32_t -nxt_port_rpc_ex_stream(void *ex) -{ - nxt_port_rpc_reg_t *reg; - - reg = nxt_pointer_to(ex, -sizeof(nxt_port_rpc_reg_t)); + reg = nxt_pointer_to(ex, -sizeof(nxt_port_rpc_reg_t)); - nxt_assert(reg->data == ex); + nxt_assert(reg->data == ex); - return reg->stream; + return reg->stream; } +void nxt_port_rpc_ex_set_peer(nxt_task_t *task, nxt_port_t *port, void *ex, + nxt_pid_t peer) { + nxt_int_t ret; + nxt_queue_link_t *peer_link; + nxt_port_rpc_reg_t *reg; + nxt_lvlhsh_query_t lhq; -void -nxt_port_rpc_ex_set_peer(nxt_task_t *task, nxt_port_t *port, - void *ex, nxt_pid_t peer) -{ - nxt_int_t ret; - nxt_queue_link_t *peer_link; - nxt_port_rpc_reg_t *reg; - nxt_lvlhsh_query_t lhq; + reg = nxt_pointer_to(ex, -sizeof(nxt_port_rpc_reg_t)); - reg = nxt_pointer_to(ex, -sizeof(nxt_port_rpc_reg_t)); + nxt_assert(reg->data == ex); - nxt_assert(reg->data == ex); + if (nxt_slow_path(peer == reg->peer)) { + return; + } - if (nxt_slow_path(peer == reg->peer)) { - return; - } - - if (reg->peer != -1) { - nxt_port_rpc_remove_from_peers(task, port, reg); - - reg->peer = -1; - } + if (reg->peer != -1) { + nxt_port_rpc_remove_from_peers(task, port, reg); - if (peer == -1) { - return; - } + reg->peer = -1; + } - reg->peer = peer; + if (peer == -1) { + return; + } - nxt_port_rpc_lhq_peer(&lhq, &peer); - lhq.replace = 0; - lhq.value = ®->link; - lhq.pool = port->mem_pool; + reg->peer = peer; - ret = nxt_lvlhsh_insert(&port->rpc_peers, &lhq); + nxt_port_rpc_lhq_peer(&lhq, &peer); + lhq.replace = 0; + lhq.value = ®->link; + lhq.pool = port->mem_pool; - switch (ret) { + ret = nxt_lvlhsh_insert(&port->rpc_peers, &lhq); - case NXT_OK: - reg->link_first = 1; - nxt_queue_self(®->link); + switch (ret) { - nxt_debug(task, "rpc: stream #%uD assigned uniq pid %PI (%p)", - reg->stream, reg->peer, reg->link.next); - break; + case NXT_OK: + reg->link_first = 1; + nxt_queue_self(®->link); - case NXT_DECLINED: - reg->link_first = 0; - peer_link = lhq.value; - nxt_queue_insert_after(peer_link, ®->link); + nxt_debug(task, "rpc: stream #%uD assigned uniq pid %PI (%p)", reg->stream, + reg->peer, reg->link.next); + break; - nxt_debug(task, "rpc: stream #%uD assigned duplicate pid %PI (%p)", - reg->stream, reg->peer, reg->link.next); - break; + case NXT_DECLINED: + reg->link_first = 0; + peer_link = lhq.value; + nxt_queue_insert_after(peer_link, ®->link); - default: - nxt_log_error(NXT_LOG_ERR, task->log, "rpc: failed to add " - "peer for stream #%uD (%d)", reg->stream, ret); + nxt_debug(task, "rpc: stream #%uD assigned duplicate pid %PI (%p)", + reg->stream, reg->peer, reg->link.next); + break; - reg->peer = -1; - break; - } + default: + nxt_log_error(NXT_LOG_ERR, task->log, + "rpc: failed to add " + "peer for stream #%uD (%d)", + reg->stream, ret); + reg->peer = -1; + break; + } } +static void nxt_port_rpc_remove_from_peers(nxt_task_t *task, nxt_port_t *port, + nxt_port_rpc_reg_t *reg) { + uint32_t stream; + nxt_int_t ret; + nxt_lvlhsh_query_t lhq; + nxt_port_rpc_reg_t *r; -static void -nxt_port_rpc_remove_from_peers(nxt_task_t *task, nxt_port_t *port, - nxt_port_rpc_reg_t *reg) -{ - uint32_t stream; - nxt_int_t ret; - nxt_lvlhsh_query_t lhq; - nxt_port_rpc_reg_t *r; - - stream = reg->stream; + stream = reg->stream; - if (reg->link_first != 0) { - nxt_port_rpc_lhq_peer(&lhq, ®->peer); - lhq.pool = port->mem_pool; - - if (reg->link.next == ®->link) { - nxt_assert(reg->link.prev == ®->link); - - nxt_debug(task, "rpc: stream #%uD remove first and last pid %PI " - "registration (%p)", stream, reg->peer, reg->link.next); + if (reg->link_first != 0) { + nxt_port_rpc_lhq_peer(&lhq, ®->peer); + lhq.pool = port->mem_pool; - ret = nxt_lvlhsh_delete(&port->rpc_peers, &lhq); + if (reg->link.next == ®->link) { + nxt_assert(reg->link.prev == ®->link); - } else { - nxt_debug(task, "rpc: stream #%uD remove first pid %PI " - "registration (%p)", stream, reg->peer, reg->link.next); + nxt_debug(task, + "rpc: stream #%uD remove first and last pid %PI " + "registration (%p)", + stream, reg->peer, reg->link.next); - lhq.replace = 1; - lhq.value = reg->link.next; + ret = nxt_lvlhsh_delete(&port->rpc_peers, &lhq); - r = nxt_queue_link_data(reg->link.next, nxt_port_rpc_reg_t, link); - r->link_first = 1; + } else { + nxt_debug(task, + "rpc: stream #%uD remove first pid %PI " + "registration (%p)", + stream, reg->peer, reg->link.next); - nxt_queue_remove(®->link); + lhq.replace = 1; + lhq.value = reg->link.next; - ret = nxt_lvlhsh_insert(&port->rpc_peers, &lhq); - } + r = nxt_queue_link_data(reg->link.next, nxt_port_rpc_reg_t, link); + r->link_first = 1; - } else { - nxt_debug(task, "rpc: stream #%uD remove pid %PI " - "registration (%p)", stream, reg->peer, reg->link.next); + nxt_queue_remove(®->link); - nxt_queue_remove(®->link); - ret = NXT_OK; + ret = nxt_lvlhsh_insert(&port->rpc_peers, &lhq); } - if (nxt_slow_path(ret != NXT_OK)) { - nxt_log_error(NXT_LOG_ERR, task->log, "rpc: stream #%uD failed" - " to delete peer %PI (%d)", stream, reg->peer, ret); - } + } else { + nxt_debug(task, + "rpc: stream #%uD remove pid %PI " + "registration (%p)", + stream, reg->peer, reg->link.next); + + nxt_queue_remove(®->link); + ret = NXT_OK; + } + + if (nxt_slow_path(ret != NXT_OK)) { + nxt_log_error(NXT_LOG_ERR, task->log, + "rpc: stream #%uD failed" + " to delete peer %PI (%d)", + stream, reg->peer, ret); + } } +void nxt_port_rpc_handler(nxt_task_t *task, nxt_port_recv_msg_t *msg) { + uint8_t last; + uint32_t stream; + nxt_int_t ret; + nxt_port_t *port; + nxt_port_rpc_reg_t *reg; + nxt_lvlhsh_query_t lhq; + nxt_port_msg_type_t type; -void -nxt_port_rpc_handler(nxt_task_t *task, nxt_port_recv_msg_t *msg) -{ - uint8_t last; - uint32_t stream; - nxt_int_t ret; - nxt_port_t *port; - nxt_port_rpc_reg_t *reg; - nxt_lvlhsh_query_t lhq; - nxt_port_msg_type_t type; + stream = msg->port_msg.stream; + port = msg->port; + last = msg->port_msg.last; + type = msg->port_msg.type; - stream = msg->port_msg.stream; - port = msg->port; - last = msg->port_msg.last; - type = msg->port_msg.type; + nxt_port_rpc_lhq_stream(&lhq, &stream); + lhq.pool = port->mem_pool; - nxt_port_rpc_lhq_stream(&lhq, &stream); - lhq.pool = port->mem_pool; - - if (last != 0) { - ret = nxt_lvlhsh_delete(&port->rpc_streams, &lhq); + if (last != 0) { + ret = nxt_lvlhsh_delete(&port->rpc_streams, &lhq); - } else { - ret = nxt_lvlhsh_find(&port->rpc_streams, &lhq); - } + } else { + ret = nxt_lvlhsh_find(&port->rpc_streams, &lhq); + } - if (ret != NXT_OK) { - nxt_debug(task, "rpc: stream #%uD no handler found", stream); + if (ret != NXT_OK) { + nxt_debug(task, "rpc: stream #%uD no handler found", stream); - return; - } + return; + } - nxt_debug(task, "rpc: stream #%uD %shandler, type %d", stream, - (last ? "last " : ""), type); + nxt_debug(task, "rpc: stream #%uD %shandler, type %d", stream, + (last ? "last " : ""), type); - reg = lhq.value; + reg = lhq.value; - if (type == _NXT_PORT_MSG_RPC_ERROR) { - reg->error_handler(task, msg, reg->data); + if (type == _NXT_PORT_MSG_RPC_ERROR) { + reg->error_handler(task, msg, reg->data); - } else { - reg->ready_handler(task, msg, reg->data); - } + } else { + reg->ready_handler(task, msg, reg->data); + } - if (last == 0) { - return; - } + if (last == 0) { + return; + } - if (reg->peer != -1) { - nxt_port_rpc_remove_from_peers(task, port, reg); - } + if (reg->peer != -1) { + nxt_port_rpc_remove_from_peers(task, port, reg); + } - nxt_debug(task, "rpc: stream #%uD free registration", stream); + nxt_debug(task, "rpc: stream #%uD free registration", stream); - nxt_mp_free(port->mem_pool, reg); + nxt_mp_free(port->mem_pool, reg); - nxt_port_use(task, port, -1); + nxt_port_use(task, port, -1); } +void nxt_port_rpc_remove_peer(nxt_task_t *task, nxt_port_t *port, + nxt_pid_t peer) { + uint8_t last; + uint32_t stream; + nxt_int_t ret; + nxt_buf_t buf; + nxt_queue_link_t *peer_link, *next_link; + nxt_port_rpc_reg_t *reg; + nxt_lvlhsh_query_t lhq; + nxt_port_recv_msg_t msg; -void -nxt_port_rpc_remove_peer(nxt_task_t *task, nxt_port_t *port, nxt_pid_t peer) -{ - uint8_t last; - uint32_t stream; - nxt_int_t ret; - nxt_buf_t buf; - nxt_queue_link_t *peer_link, *next_link; - nxt_port_rpc_reg_t *reg; - nxt_lvlhsh_query_t lhq; - nxt_port_recv_msg_t msg; + nxt_port_rpc_lhq_peer(&lhq, &peer); + lhq.pool = port->mem_pool; - nxt_port_rpc_lhq_peer(&lhq, &peer); - lhq.pool = port->mem_pool; + ret = nxt_lvlhsh_delete(&port->rpc_peers, &lhq); - ret = nxt_lvlhsh_delete(&port->rpc_peers, &lhq); + if (nxt_slow_path(ret != NXT_OK)) { + nxt_debug(task, "rpc: no reg found for peer %PI", peer); - if (nxt_slow_path(ret != NXT_OK)) { - nxt_debug(task, "rpc: no reg found for peer %PI", peer); + return; + } - return; - } + nxt_memzero(&msg, sizeof(msg)); + nxt_memzero(&buf, sizeof(buf)); - nxt_memzero(&msg, sizeof(msg)); - nxt_memzero(&buf, sizeof(buf)); + msg.fd[0] = -1; + msg.fd[1] = -1; + msg.buf = &buf; + msg.port = port; + msg.u.removed_pid = peer; + msg.port_msg.pid = nxt_pid; + msg.port_msg.type = _NXT_PORT_MSG_REMOVE_PID; - msg.fd[0] = -1; - msg.fd[1] = -1; - msg.buf = &buf; - msg.port = port; - msg.u.removed_pid = peer; - msg.port_msg.pid = nxt_pid; - msg.port_msg.type = _NXT_PORT_MSG_REMOVE_PID; - - peer_link = lhq.value; - last = 0; + peer_link = lhq.value; + last = 0; - while (last == 0) { + while (last == 0) { - reg = nxt_queue_link_data(peer_link, nxt_port_rpc_reg_t, link); + reg = nxt_queue_link_data(peer_link, nxt_port_rpc_reg_t, link); - nxt_assert(reg->peer == peer); + nxt_assert(reg->peer == peer); - stream = reg->stream; + stream = reg->stream; - nxt_debug(task, "rpc: stream #%uD trigger error", stream); + nxt_debug(task, "rpc: stream #%uD trigger error", stream); - msg.port_msg.stream = stream; - msg.port_msg.last = 1; + msg.port_msg.stream = stream; + msg.port_msg.last = 1; - if (peer_link == peer_link->next) { - nxt_assert(peer_link->prev == peer_link); + if (peer_link == peer_link->next) { + nxt_assert(peer_link->prev == peer_link); - last = 1; + last = 1; - } else { - nxt_assert(peer_link->next->prev == peer_link); - nxt_assert(peer_link->prev->next == peer_link); + } else { + nxt_assert(peer_link->next->prev == peer_link); + nxt_assert(peer_link->prev->next == peer_link); - next_link = peer_link->next; - nxt_queue_remove(peer_link); + next_link = peer_link->next; + nxt_queue_remove(peer_link); - peer_link = next_link; - } + peer_link = next_link; + } - reg->peer = -1; + reg->peer = -1; - reg->error_handler(task, &msg, reg->data); + reg->error_handler(task, &msg, reg->data); - /* Reset 'last' flag to preserve rpc handler. */ - if (msg.port_msg.last == 0) { - continue; - } + /* Reset 'last' flag to preserve rpc handler. */ + if (msg.port_msg.last == 0) { + continue; + } - nxt_port_rpc_lhq_stream(&lhq, &stream); - lhq.pool = port->mem_pool; + nxt_port_rpc_lhq_stream(&lhq, &stream); + lhq.pool = port->mem_pool; - ret = nxt_lvlhsh_delete(&port->rpc_streams, &lhq); + ret = nxt_lvlhsh_delete(&port->rpc_streams, &lhq); - if (nxt_slow_path(ret != NXT_OK)) { - nxt_log_error(NXT_LOG_ERR, task->log, - "rpc: stream #%uD failed to delete handler", stream); + if (nxt_slow_path(ret != NXT_OK)) { + nxt_log_error(NXT_LOG_ERR, task->log, + "rpc: stream #%uD failed to delete handler", stream); - return; - } + return; + } - nxt_mp_free(port->mem_pool, reg); + nxt_mp_free(port->mem_pool, reg); - nxt_port_use(task, port, -1); - } + nxt_port_use(task, port, -1); + } } +void nxt_port_rpc_cancel(nxt_task_t *task, nxt_port_t *port, uint32_t stream) { + nxt_int_t ret; + nxt_port_rpc_reg_t *reg; + nxt_lvlhsh_query_t lhq; -void -nxt_port_rpc_cancel(nxt_task_t *task, nxt_port_t *port, uint32_t stream) -{ - nxt_int_t ret; - nxt_port_rpc_reg_t *reg; - nxt_lvlhsh_query_t lhq; + nxt_port_rpc_lhq_stream(&lhq, &stream); + lhq.pool = port->mem_pool; - nxt_port_rpc_lhq_stream(&lhq, &stream); - lhq.pool = port->mem_pool; + ret = nxt_lvlhsh_delete(&port->rpc_streams, &lhq); - ret = nxt_lvlhsh_delete(&port->rpc_streams, &lhq); + if (ret != NXT_OK) { + nxt_debug(task, "rpc: stream #%uD no handler found", stream); - if (ret != NXT_OK) { - nxt_debug(task, "rpc: stream #%uD no handler found", stream); + return; + } - return; - } + reg = lhq.value; - reg = lhq.value; + if (reg->peer != -1) { + nxt_port_rpc_remove_from_peers(task, port, reg); + } - if (reg->peer != -1) { - nxt_port_rpc_remove_from_peers(task, port, reg); - } - - nxt_debug(task, "rpc: stream #%uD cancel registration", stream); + nxt_debug(task, "rpc: stream #%uD cancel registration", stream); - nxt_mp_free(port->mem_pool, reg); + nxt_mp_free(port->mem_pool, reg); - nxt_port_use(task, port, -1); + nxt_port_use(task, port, -1); } -static nxt_buf_t nxt_port_close_dummy_buf; - -void -nxt_port_rpc_close(nxt_task_t *task, nxt_port_t *port) -{ - nxt_port_rpc_reg_t *reg; - nxt_port_recv_msg_t msg; - - for ( ;; ) { - reg = nxt_lvlhsh_peek(&port->rpc_streams, &lvlhsh_rpc_reg_proto); - if (reg == NULL) { - return; - } - - msg.fd[0] = -1; - msg.fd[1] = -1; - msg.buf = &nxt_port_close_dummy_buf; - msg.port = port; - msg.port_msg.stream = reg->stream; - msg.port_msg.pid = nxt_pid; - msg.port_msg.type = _NXT_PORT_MSG_RPC_ERROR; - msg.port_msg.last = 1; - msg.port_msg.mmap = 0; - msg.port_msg.nf = 0; - msg.port_msg.mf = 0; - msg.size = 0; - msg.cancelled = 0; - msg.u.data = NULL; - - nxt_port_rpc_handler(task, &msg); +static nxt_buf_t nxt_port_close_dummy_buf; + +void nxt_port_rpc_close(nxt_task_t *task, nxt_port_t *port) { + nxt_port_rpc_reg_t *reg; + nxt_port_recv_msg_t msg; + + for (;;) { + reg = nxt_lvlhsh_peek(&port->rpc_streams, &lvlhsh_rpc_reg_proto); + if (reg == NULL) { + return; } + + msg.fd[0] = -1; + msg.fd[1] = -1; + msg.buf = &nxt_port_close_dummy_buf; + msg.port = port; + msg.port_msg.stream = reg->stream; + msg.port_msg.pid = nxt_pid; + msg.port_msg.type = _NXT_PORT_MSG_RPC_ERROR; + msg.port_msg.last = 1; + msg.port_msg.mmap = 0; + msg.port_msg.nf = 0; + msg.port_msg.mf = 0; + msg.size = 0; + msg.cancelled = 0; + msg.u.data = NULL; + + nxt_port_rpc_handler(task, &msg); + } } diff --git a/src/nxt_port_rpc.h b/src/nxt_port_rpc.h index c07683fb0..e1f84c2f9 100644 --- a/src/nxt_port_rpc.h +++ b/src/nxt_port_rpc.h @@ -7,29 +7,28 @@ #ifndef _NXT_PORT_RPC_H_INCLUDED_ #define _NXT_PORT_RPC_H_INCLUDED_ - typedef void (*nxt_port_rpc_handler_t)(nxt_task_t *task, - nxt_port_recv_msg_t *msg, void *data); + nxt_port_recv_msg_t *msg, void *data); nxt_int_t nxt_port_rpc_init(void); uint32_t nxt_port_rpc_register_handler(nxt_task_t *task, nxt_port_t *port, - nxt_port_rpc_handler_t ready_handler, nxt_port_rpc_handler_t error_handler, - nxt_pid_t peer, void *data); + nxt_port_rpc_handler_t ready_handler, + nxt_port_rpc_handler_t error_handler, + nxt_pid_t peer, void *data); void *nxt_port_rpc_register_handler_ex(nxt_task_t *task, nxt_port_t *port, - nxt_port_rpc_handler_t ready_handler, nxt_port_rpc_handler_t error_handler, - size_t ex_size); + nxt_port_rpc_handler_t ready_handler, + nxt_port_rpc_handler_t error_handler, + size_t ex_size); uint32_t nxt_port_rpc_ex_stream(void *ex); -void nxt_port_rpc_ex_set_peer(nxt_task_t *task, nxt_port_t *port, - void *ex, nxt_pid_t peer); +void nxt_port_rpc_ex_set_peer(nxt_task_t *task, nxt_port_t *port, void *ex, + nxt_pid_t peer); void nxt_port_rpc_handler(nxt_task_t *task, nxt_port_recv_msg_t *msg); void nxt_port_rpc_remove_peer(nxt_task_t *task, nxt_port_t *port, - nxt_pid_t peer); + nxt_pid_t peer); void nxt_port_rpc_cancel(nxt_task_t *task, nxt_port_t *port, uint32_t stream); void nxt_port_rpc_close(nxt_task_t *task, nxt_port_t *port); - #endif /* _NXT_PORT_RPC_H_INCLUDED_ */ - diff --git a/src/nxt_port_socket.c b/src/nxt_port_socket.c index 5752d5ab0..59595b951 100644 --- a/src/nxt_port_socket.c +++ b/src/nxt_port_socket.c @@ -9,1378 +9,1275 @@ #include #include - -#define NXT_PORT_MAX_ENQUEUE_BUF_SIZE \ - (int) (NXT_PORT_QUEUE_MSG_SIZE - sizeof(nxt_port_msg_t)) - +#define NXT_PORT_MAX_ENQUEUE_BUF_SIZE \ + (int)(NXT_PORT_QUEUE_MSG_SIZE - sizeof(nxt_port_msg_t)) static nxt_bool_t nxt_port_can_enqueue_buf(nxt_buf_t *b); static uint8_t nxt_port_enqueue_buf(nxt_task_t *task, nxt_port_msg_t *pm, - void *qbuf, nxt_buf_t *b); + void *qbuf, nxt_buf_t *b); static nxt_int_t nxt_port_msg_chk_insert(nxt_task_t *task, nxt_port_t *port, - nxt_port_send_msg_t *msg); + nxt_port_send_msg_t *msg); static nxt_port_send_msg_t *nxt_port_msg_alloc(const nxt_port_send_msg_t *m); static void nxt_port_write_handler(nxt_task_t *task, void *obj, void *data); static nxt_port_send_msg_t *nxt_port_msg_first(nxt_port_t *port); nxt_inline void nxt_port_msg_close_fd(nxt_port_send_msg_t *msg); nxt_inline void nxt_port_close_fds(nxt_fd_t *fd); static nxt_buf_t *nxt_port_buf_completion(nxt_task_t *task, - nxt_work_queue_t *wq, nxt_buf_t *b, size_t sent, nxt_bool_t mmap_mode); + nxt_work_queue_t *wq, nxt_buf_t *b, + size_t sent, nxt_bool_t mmap_mode); static nxt_port_send_msg_t *nxt_port_msg_insert_tail(nxt_port_t *port, - nxt_port_send_msg_t *msg); + nxt_port_send_msg_t *msg); static void nxt_port_read_handler(nxt_task_t *task, void *obj, void *data); static void nxt_port_queue_read_handler(nxt_task_t *task, void *obj, - void *data); + void *data); static void nxt_port_read_msg_process(nxt_task_t *task, nxt_port_t *port, - nxt_port_recv_msg_t *msg); + nxt_port_recv_msg_t *msg); static nxt_buf_t *nxt_port_buf_alloc(nxt_port_t *port); static void nxt_port_buf_free(nxt_port_t *port, nxt_buf_t *b); static void nxt_port_error_handler(nxt_task_t *task, void *obj, void *data); +nxt_int_t nxt_port_socket_init(nxt_task_t *task, nxt_port_t *port, + size_t max_size) { + nxt_int_t sndbuf, rcvbuf, size; + nxt_socket_t snd, rcv; -nxt_int_t -nxt_port_socket_init(nxt_task_t *task, nxt_port_t *port, size_t max_size) -{ - nxt_int_t sndbuf, rcvbuf, size; - nxt_socket_t snd, rcv; + port->socket.task = task; - port->socket.task = task; + port->pair[0] = -1; + port->pair[1] = -1; - port->pair[0] = -1; - port->pair[1] = -1; + if (nxt_slow_path(nxt_socketpair_create(task, port->pair) != NXT_OK)) { + goto socketpair_fail; + } - if (nxt_slow_path(nxt_socketpair_create(task, port->pair) != NXT_OK)) { - goto socketpair_fail; - } + snd = port->pair[1]; - snd = port->pair[1]; + sndbuf = nxt_socket_getsockopt(task, snd, SOL_SOCKET, SO_SNDBUF); + if (nxt_slow_path(sndbuf < 0)) { + goto getsockopt_fail; + } - sndbuf = nxt_socket_getsockopt(task, snd, SOL_SOCKET, SO_SNDBUF); - if (nxt_slow_path(sndbuf < 0)) { - goto getsockopt_fail; - } + rcv = port->pair[0]; - rcv = port->pair[0]; + rcvbuf = nxt_socket_getsockopt(task, rcv, SOL_SOCKET, SO_RCVBUF); + if (nxt_slow_path(rcvbuf < 0)) { + goto getsockopt_fail; + } - rcvbuf = nxt_socket_getsockopt(task, rcv, SOL_SOCKET, SO_RCVBUF); - if (nxt_slow_path(rcvbuf < 0)) { - goto getsockopt_fail; - } + if (max_size == 0) { + max_size = 16 * 1024; + } - if (max_size == 0) { - max_size = 16 * 1024; - } + if ((size_t)sndbuf < max_size) { + /* + * On Unix domain sockets + * Linux uses 224K on both send and receive directions; + * FreeBSD, MacOSX, NetBSD, and OpenBSD use 2K buffer size + * on send direction and 4K buffer size on receive direction; + * Solaris uses 16K on send direction and 5K on receive direction. + */ + (void)nxt_socket_setsockopt(task, snd, SOL_SOCKET, SO_SNDBUF, max_size); - if ((size_t) sndbuf < max_size) { - /* - * On Unix domain sockets - * Linux uses 224K on both send and receive directions; - * FreeBSD, MacOSX, NetBSD, and OpenBSD use 2K buffer size - * on send direction and 4K buffer size on receive direction; - * Solaris uses 16K on send direction and 5K on receive direction. - */ - (void) nxt_socket_setsockopt(task, snd, SOL_SOCKET, SO_SNDBUF, - max_size); - - sndbuf = nxt_socket_getsockopt(task, snd, SOL_SOCKET, SO_SNDBUF); - if (nxt_slow_path(sndbuf < 0)) { - goto getsockopt_fail; - } + sndbuf = nxt_socket_getsockopt(task, snd, SOL_SOCKET, SO_SNDBUF); + if (nxt_slow_path(sndbuf < 0)) { + goto getsockopt_fail; + } - size = sndbuf * 4; + size = sndbuf * 4; - if (rcvbuf < size) { - (void) nxt_socket_setsockopt(task, rcv, SOL_SOCKET, SO_RCVBUF, - size); + if (rcvbuf < size) { + (void)nxt_socket_setsockopt(task, rcv, SOL_SOCKET, SO_RCVBUF, size); - rcvbuf = nxt_socket_getsockopt(task, rcv, SOL_SOCKET, SO_RCVBUF); - if (nxt_slow_path(rcvbuf < 0)) { - goto getsockopt_fail; - } - } + rcvbuf = nxt_socket_getsockopt(task, rcv, SOL_SOCKET, SO_RCVBUF); + if (nxt_slow_path(rcvbuf < 0)) { + goto getsockopt_fail; + } } + } - port->max_size = nxt_min(max_size, (size_t) sndbuf); - port->max_share = (64 * 1024); + port->max_size = nxt_min(max_size, (size_t)sndbuf); + port->max_share = (64 * 1024); - return NXT_OK; + return NXT_OK; getsockopt_fail: - nxt_socket_close(task, port->pair[0]); - nxt_socket_close(task, port->pair[1]); + nxt_socket_close(task, port->pair[0]); + nxt_socket_close(task, port->pair[1]); socketpair_fail: - return NXT_ERROR; + return NXT_ERROR; } - -void -nxt_port_destroy(nxt_port_t *port) -{ - nxt_socket_close(port->socket.task, port->socket.fd); - nxt_mp_destroy(port->mem_pool); +void nxt_port_destroy(nxt_port_t *port) { + nxt_socket_close(port->socket.task, port->socket.fd); + nxt_mp_destroy(port->mem_pool); } +void nxt_port_write_enable(nxt_task_t *task, nxt_port_t *port) { + port->socket.fd = port->pair[1]; + port->socket.log = &nxt_main_log; + port->socket.write_ready = 1; -void -nxt_port_write_enable(nxt_task_t *task, nxt_port_t *port) -{ - port->socket.fd = port->pair[1]; - port->socket.log = &nxt_main_log; - port->socket.write_ready = 1; - - port->engine = task->thread->engine; + port->engine = task->thread->engine; - port->socket.write_work_queue = &port->engine->fast_work_queue; - port->socket.write_handler = nxt_port_write_handler; - port->socket.error_handler = nxt_port_error_handler; + port->socket.write_work_queue = &port->engine->fast_work_queue; + port->socket.write_handler = nxt_port_write_handler; + port->socket.error_handler = nxt_port_error_handler; } - -void -nxt_port_write_close(nxt_port_t *port) -{ - nxt_socket_close(port->socket.task, port->pair[1]); - port->pair[1] = -1; +void nxt_port_write_close(nxt_port_t *port) { + nxt_socket_close(port->socket.task, port->pair[1]); + port->pair[1] = -1; } - -static void -nxt_port_release_send_msg(nxt_port_send_msg_t *msg) -{ - if (msg->allocated) { - nxt_free(msg); - } +static void nxt_port_release_send_msg(nxt_port_send_msg_t *msg) { + if (msg->allocated) { + nxt_free(msg); + } } +nxt_int_t nxt_port_socket_write2(nxt_task_t *task, nxt_port_t *port, + nxt_uint_t type, nxt_fd_t fd, nxt_fd_t fd2, + uint32_t stream, nxt_port_id_t reply_port, + nxt_buf_t *b) { + int notify; + uint8_t qmsg_size; + nxt_int_t res; + nxt_port_send_msg_t msg; + struct { + nxt_port_msg_t pm; + uint8_t buf[NXT_PORT_MAX_ENQUEUE_BUF_SIZE]; + } qmsg; + + msg.link.next = NULL; + msg.link.prev = NULL; + + msg.buf = b; + msg.share = 0; + msg.fd[0] = fd; + msg.fd[1] = fd2; + msg.close_fd = (type & NXT_PORT_MSG_CLOSE_FD) != 0; + msg.allocated = 0; + + msg.port_msg.stream = stream; + msg.port_msg.pid = nxt_pid; + msg.port_msg.reply_port = reply_port; + msg.port_msg.type = type & NXT_PORT_MSG_MASK; + msg.port_msg.last = (type & NXT_PORT_MSG_LAST) != 0; + msg.port_msg.mmap = 0; + msg.port_msg.nf = 0; + msg.port_msg.mf = 0; + + if (port->queue != NULL && type != _NXT_PORT_MSG_READ_QUEUE) { + + if (fd == -1 && nxt_port_can_enqueue_buf(b)) { + qmsg.pm = msg.port_msg; + + qmsg_size = sizeof(qmsg.pm); + + if (b != NULL) { + qmsg_size += nxt_port_enqueue_buf(task, &qmsg.pm, qmsg.buf, b); + } + + res = nxt_port_queue_send(port->queue, &qmsg, qmsg_size, ¬ify); + + nxt_debug(task, "port{%d,%d} %d: enqueue %d notify %d, %d", + (int)port->pid, (int)port->id, port->socket.fd, (int)qmsg_size, + notify, res); + + if (b != NULL && nxt_fast_path(res == NXT_OK)) { + if (qmsg.pm.mmap) { + b->is_port_mmap_sent = 1; + } -nxt_int_t -nxt_port_socket_write2(nxt_task_t *task, nxt_port_t *port, nxt_uint_t type, - nxt_fd_t fd, nxt_fd_t fd2, uint32_t stream, nxt_port_id_t reply_port, - nxt_buf_t *b) -{ - int notify; - uint8_t qmsg_size; - nxt_int_t res; - nxt_port_send_msg_t msg; - struct { - nxt_port_msg_t pm; - uint8_t buf[NXT_PORT_MAX_ENQUEUE_BUF_SIZE]; - } qmsg; - - msg.link.next = NULL; - msg.link.prev = NULL; - - msg.buf = b; - msg.share = 0; - msg.fd[0] = fd; - msg.fd[1] = fd2; - msg.close_fd = (type & NXT_PORT_MSG_CLOSE_FD) != 0; - msg.allocated = 0; - - msg.port_msg.stream = stream; - msg.port_msg.pid = nxt_pid; - msg.port_msg.reply_port = reply_port; - msg.port_msg.type = type & NXT_PORT_MSG_MASK; - msg.port_msg.last = (type & NXT_PORT_MSG_LAST) != 0; - msg.port_msg.mmap = 0; - msg.port_msg.nf = 0; - msg.port_msg.mf = 0; - - if (port->queue != NULL && type != _NXT_PORT_MSG_READ_QUEUE) { - - if (fd == -1 && nxt_port_can_enqueue_buf(b)) { - qmsg.pm = msg.port_msg; - - qmsg_size = sizeof(qmsg.pm); - - if (b != NULL) { - qmsg_size += nxt_port_enqueue_buf(task, &qmsg.pm, qmsg.buf, b); - } - - res = nxt_port_queue_send(port->queue, &qmsg, qmsg_size, ¬ify); - - nxt_debug(task, "port{%d,%d} %d: enqueue %d notify %d, %d", - (int) port->pid, (int) port->id, port->socket.fd, - (int) qmsg_size, notify, res); - - if (b != NULL && nxt_fast_path(res == NXT_OK)) { - if (qmsg.pm.mmap) { - b->is_port_mmap_sent = 1; - } - - b->mem.pos = b->mem.free; + b->mem.pos = b->mem.free; - nxt_work_queue_add(&task->thread->engine->fast_work_queue, - b->completion_handler, task, b, b->parent); - } + nxt_work_queue_add(&task->thread->engine->fast_work_queue, + b->completion_handler, task, b, b->parent); + } - if (notify == 0) { - return res; - } + if (notify == 0) { + return res; + } - msg.port_msg.type = _NXT_PORT_MSG_READ_QUEUE; - msg.buf = NULL; + msg.port_msg.type = _NXT_PORT_MSG_READ_QUEUE; + msg.buf = NULL; - } else { - qmsg.buf[0] = _NXT_PORT_MSG_READ_SOCKET; + } else { + qmsg.buf[0] = _NXT_PORT_MSG_READ_SOCKET; - res = nxt_port_queue_send(port->queue, qmsg.buf, 1, ¬ify); + res = nxt_port_queue_send(port->queue, qmsg.buf, 1, ¬ify); - nxt_debug(task, "port{%d,%d} %d: enqueue 1 notify %d, %d", - (int) port->pid, (int) port->id, port->socket.fd, - notify, res); + nxt_debug(task, "port{%d,%d} %d: enqueue 1 notify %d, %d", (int)port->pid, + (int)port->id, port->socket.fd, notify, res); - if (nxt_slow_path(res == NXT_AGAIN)) { - return NXT_AGAIN; - } - } + if (nxt_slow_path(res == NXT_AGAIN)) { + return NXT_AGAIN; + } } + } - res = nxt_port_msg_chk_insert(task, port, &msg); - if (nxt_fast_path(res == NXT_DECLINED)) { - nxt_port_write_handler(task, &port->socket, &msg); - res = NXT_OK; - } + res = nxt_port_msg_chk_insert(task, port, &msg); + if (nxt_fast_path(res == NXT_DECLINED)) { + nxt_port_write_handler(task, &port->socket, &msg); + res = NXT_OK; + } - return res; + return res; } +static nxt_bool_t nxt_port_can_enqueue_buf(nxt_buf_t *b) { + if (b == NULL) { + return 1; + } -static nxt_bool_t -nxt_port_can_enqueue_buf(nxt_buf_t *b) -{ - if (b == NULL) { - return 1; - } + if (b->next != NULL) { + return 0; + } - if (b->next != NULL) { - return 0; - } - - return (nxt_buf_mem_used_size(&b->mem) <= NXT_PORT_MAX_ENQUEUE_BUF_SIZE - || nxt_buf_is_port_mmap(b)); + return (nxt_buf_mem_used_size(&b->mem) <= NXT_PORT_MAX_ENQUEUE_BUF_SIZE || + nxt_buf_is_port_mmap(b)); } +static uint8_t nxt_port_enqueue_buf(nxt_task_t *task, nxt_port_msg_t *pm, + void *qbuf, nxt_buf_t *b) { + ssize_t size; + nxt_port_mmap_msg_t *mm; + nxt_port_mmap_header_t *hdr; + nxt_port_mmap_handler_t *mmap_handler; -static uint8_t -nxt_port_enqueue_buf(nxt_task_t *task, nxt_port_msg_t *pm, void *qbuf, - nxt_buf_t *b) -{ - ssize_t size; - nxt_port_mmap_msg_t *mm; - nxt_port_mmap_header_t *hdr; - nxt_port_mmap_handler_t *mmap_handler; + size = nxt_buf_mem_used_size(&b->mem); - size = nxt_buf_mem_used_size(&b->mem); + if (size <= NXT_PORT_MAX_ENQUEUE_BUF_SIZE) { + nxt_memcpy(qbuf, b->mem.pos, size); - if (size <= NXT_PORT_MAX_ENQUEUE_BUF_SIZE) { - nxt_memcpy(qbuf, b->mem.pos, size); + return size; + } - return size; - } + mmap_handler = b->parent; + hdr = mmap_handler->hdr; + mm = qbuf; - mmap_handler = b->parent; - hdr = mmap_handler->hdr; - mm = qbuf; + mm->mmap_id = hdr->id; + mm->chunk_id = nxt_port_mmap_chunk_id(hdr, b->mem.pos); + mm->size = nxt_buf_mem_used_size(&b->mem); - mm->mmap_id = hdr->id; - mm->chunk_id = nxt_port_mmap_chunk_id(hdr, b->mem.pos); - mm->size = nxt_buf_mem_used_size(&b->mem); + pm->mmap = 1; - pm->mmap = 1; + nxt_debug(task, "mmap_msg={%D, %D, %D}", mm->mmap_id, mm->chunk_id, mm->size); - nxt_debug(task, "mmap_msg={%D, %D, %D}", mm->mmap_id, mm->chunk_id, - mm->size); - - return sizeof(nxt_port_mmap_msg_t); + return sizeof(nxt_port_mmap_msg_t); } +static nxt_int_t nxt_port_msg_chk_insert(nxt_task_t *task, nxt_port_t *port, + nxt_port_send_msg_t *msg) { + nxt_int_t res; -static nxt_int_t -nxt_port_msg_chk_insert(nxt_task_t *task, nxt_port_t *port, - nxt_port_send_msg_t *msg) -{ - nxt_int_t res; + nxt_thread_mutex_lock(&port->write_mutex); - nxt_thread_mutex_lock(&port->write_mutex); + if (nxt_fast_path(port->socket.write_ready && + nxt_queue_is_empty(&port->messages))) { + res = NXT_DECLINED; - if (nxt_fast_path(port->socket.write_ready - && nxt_queue_is_empty(&port->messages))) - { - res = NXT_DECLINED; + } else { + msg = nxt_port_msg_alloc(msg); - } else { - msg = nxt_port_msg_alloc(msg); + if (nxt_fast_path(msg != NULL)) { + nxt_queue_insert_tail(&port->messages, &msg->link); + nxt_port_use(task, port, 1); + res = NXT_OK; - if (nxt_fast_path(msg != NULL)) { - nxt_queue_insert_tail(&port->messages, &msg->link); - nxt_port_use(task, port, 1); - res = NXT_OK; - - } else { - res = NXT_ERROR; - } + } else { + res = NXT_ERROR; } + } - nxt_thread_mutex_unlock(&port->write_mutex); + nxt_thread_mutex_unlock(&port->write_mutex); - return res; + return res; } +static nxt_port_send_msg_t *nxt_port_msg_alloc(const nxt_port_send_msg_t *m) { + nxt_port_send_msg_t *msg; -static nxt_port_send_msg_t * -nxt_port_msg_alloc(const nxt_port_send_msg_t *m) -{ - nxt_port_send_msg_t *msg; - - msg = nxt_malloc(sizeof(nxt_port_send_msg_t)); - if (nxt_slow_path(msg == NULL)) { - return NULL; - } + msg = nxt_malloc(sizeof(nxt_port_send_msg_t)); + if (nxt_slow_path(msg == NULL)) { + return NULL; + } - *msg = *m; + *msg = *m; - msg->allocated = 1; + msg->allocated = 1; - return msg; + return msg; } - -static void -nxt_port_fd_block_write(nxt_task_t *task, nxt_port_t *port, void *data) -{ - nxt_fd_event_block_write(task->thread->engine, &port->socket); +static void nxt_port_fd_block_write(nxt_task_t *task, nxt_port_t *port, + void *data) { + nxt_fd_event_block_write(task->thread->engine, &port->socket); } - -static void -nxt_port_fd_enable_write(nxt_task_t *task, nxt_port_t *port, void *data) -{ - nxt_fd_event_enable_write(task->thread->engine, &port->socket); +static void nxt_port_fd_enable_write(nxt_task_t *task, nxt_port_t *port, + void *data) { + nxt_fd_event_enable_write(task->thread->engine, &port->socket); } +static void nxt_port_write_handler(nxt_task_t *task, void *obj, void *data) { + int use_delta; + size_t plain_size; + ssize_t n; + uint32_t mmsg_buf[3 * NXT_IOBUF_MAX * 10]; + nxt_bool_t block_write, enable_write; + nxt_port_t *port; + struct iovec iov[NXT_IOBUF_MAX * 10]; + nxt_work_queue_t *wq; + nxt_port_method_t m; + nxt_port_send_msg_t *msg; + nxt_sendbuf_coalesce_t sb; -static void -nxt_port_write_handler(nxt_task_t *task, void *obj, void *data) -{ - int use_delta; - size_t plain_size; - ssize_t n; - uint32_t mmsg_buf[3 * NXT_IOBUF_MAX * 10]; - nxt_bool_t block_write, enable_write; - nxt_port_t *port; - struct iovec iov[NXT_IOBUF_MAX * 10]; - nxt_work_queue_t *wq; - nxt_port_method_t m; - nxt_port_send_msg_t *msg; - nxt_sendbuf_coalesce_t sb; - - port = nxt_container_of(obj, nxt_port_t, socket); + port = nxt_container_of(obj, nxt_port_t, socket); - block_write = 0; - enable_write = 0; - use_delta = 0; + block_write = 0; + enable_write = 0; + use_delta = 0; - wq = &task->thread->engine->fast_work_queue; + wq = &task->thread->engine->fast_work_queue; - do { - if (data) { - msg = data; + do { + if (data) { + msg = data; - } else { - msg = nxt_port_msg_first(port); + } else { + msg = nxt_port_msg_first(port); - if (msg == NULL) { - block_write = 1; - goto cleanup; - } - } + if (msg == NULL) { + block_write = 1; + goto cleanup; + } + } -next_fragment: + next_fragment: - iov[0].iov_base = &msg->port_msg; - iov[0].iov_len = sizeof(nxt_port_msg_t); + iov[0].iov_base = &msg->port_msg; + iov[0].iov_len = sizeof(nxt_port_msg_t); - sb.buf = msg->buf; - sb.iobuf = &iov[1]; - sb.nmax = NXT_IOBUF_MAX - 1; - sb.sync = 0; - sb.last = 0; - sb.size = 0; - sb.limit = port->max_size; + sb.buf = msg->buf; + sb.iobuf = &iov[1]; + sb.nmax = NXT_IOBUF_MAX - 1; + sb.sync = 0; + sb.last = 0; + sb.size = 0; + sb.limit = port->max_size; - sb.limit_reached = 0; - sb.nmax_reached = 0; + sb.limit_reached = 0; + sb.nmax_reached = 0; - m = nxt_port_mmap_get_method(task, port, msg->buf); + m = nxt_port_mmap_get_method(task, port, msg->buf); - if (m == NXT_PORT_METHOD_MMAP) { - sb.limit = (1ULL << 31) - 1; - sb.nmax = nxt_min(NXT_IOBUF_MAX * 10 - 1, - port->max_size / PORT_MMAP_MIN_SIZE); - } + if (m == NXT_PORT_METHOD_MMAP) { + sb.limit = (1ULL << 31) - 1; + sb.nmax = + nxt_min(NXT_IOBUF_MAX * 10 - 1, port->max_size / PORT_MMAP_MIN_SIZE); + } - sb.limit -= iov[0].iov_len; + sb.limit -= iov[0].iov_len; - nxt_sendbuf_mem_coalesce(task, &sb); + nxt_sendbuf_mem_coalesce(task, &sb); - plain_size = sb.size; + plain_size = sb.size; - /* - * Send through mmap enabled only when payload - * is bigger than PORT_MMAP_MIN_SIZE. - */ - if (m == NXT_PORT_METHOD_MMAP && plain_size > PORT_MMAP_MIN_SIZE) { - nxt_port_mmap_write(task, port, msg, &sb, mmsg_buf); - - } else { - m = NXT_PORT_METHOD_PLAIN; - } + /* + * Send through mmap enabled only when payload + * is bigger than PORT_MMAP_MIN_SIZE. + */ + if (m == NXT_PORT_METHOD_MMAP && plain_size > PORT_MMAP_MIN_SIZE) { + nxt_port_mmap_write(task, port, msg, &sb, mmsg_buf); - msg->port_msg.last |= sb.last; - msg->port_msg.mf = sb.limit_reached || sb.nmax_reached; + } else { + m = NXT_PORT_METHOD_PLAIN; + } - n = nxt_socketpair_send(&port->socket, msg->fd, iov, sb.niov + 1); + msg->port_msg.last |= sb.last; + msg->port_msg.mf = sb.limit_reached || sb.nmax_reached; - if (n > 0) { - if (nxt_slow_path((size_t) n != sb.size + iov[0].iov_len)) { - nxt_alert(task, "port %d: short write: %z instead of %uz", - port->socket.fd, n, sb.size + iov[0].iov_len); - goto fail; - } + n = nxt_socketpair_send(&port->socket, msg->fd, iov, sb.niov + 1); - nxt_port_msg_close_fd(msg); + if (n > 0) { + if (nxt_slow_path((size_t)n != sb.size + iov[0].iov_len)) { + nxt_alert(task, "port %d: short write: %z instead of %uz", + port->socket.fd, n, sb.size + iov[0].iov_len); + goto fail; + } - msg->buf = nxt_port_buf_completion(task, wq, msg->buf, plain_size, - m == NXT_PORT_METHOD_MMAP); + nxt_port_msg_close_fd(msg); - if (msg->buf != NULL) { - nxt_debug(task, "port %d: frag stream #%uD", port->socket.fd, - msg->port_msg.stream); + msg->buf = nxt_port_buf_completion(task, wq, msg->buf, plain_size, + m == NXT_PORT_METHOD_MMAP); - /* - * A file descriptor is sent only - * in the first message of a stream. - */ - msg->fd[0] = -1; - msg->fd[1] = -1; - msg->share += n; - msg->port_msg.nf = 1; + if (msg->buf != NULL) { + nxt_debug(task, "port %d: frag stream #%uD", port->socket.fd, + msg->port_msg.stream); - if (msg->share >= port->max_share) { - msg->share = 0; + /* + * A file descriptor is sent only + * in the first message of a stream. + */ + msg->fd[0] = -1; + msg->fd[1] = -1; + msg->share += n; + msg->port_msg.nf = 1; - if (msg->link.next != NULL) { - nxt_thread_mutex_lock(&port->write_mutex); + if (msg->share >= port->max_share) { + msg->share = 0; - nxt_queue_remove(&msg->link); - nxt_queue_insert_tail(&port->messages, &msg->link); + if (msg->link.next != NULL) { + nxt_thread_mutex_lock(&port->write_mutex); - nxt_thread_mutex_unlock(&port->write_mutex); + nxt_queue_remove(&msg->link); + nxt_queue_insert_tail(&port->messages, &msg->link); - } else { - msg = nxt_port_msg_insert_tail(port, msg); - if (nxt_slow_path(msg == NULL)) { - goto fail; - } + nxt_thread_mutex_unlock(&port->write_mutex); - use_delta++; - } + } else { + msg = nxt_port_msg_insert_tail(port, msg); + if (nxt_slow_path(msg == NULL)) { + goto fail; + } - } else { - goto next_fragment; - } + use_delta++; + } - } else { - if (msg->link.next != NULL) { - nxt_thread_mutex_lock(&port->write_mutex); + } else { + goto next_fragment; + } - nxt_queue_remove(&msg->link); - msg->link.next = NULL; + } else { + if (msg->link.next != NULL) { + nxt_thread_mutex_lock(&port->write_mutex); - nxt_thread_mutex_unlock(&port->write_mutex); + nxt_queue_remove(&msg->link); + msg->link.next = NULL; - use_delta--; - } + nxt_thread_mutex_unlock(&port->write_mutex); - nxt_port_release_send_msg(msg); - } + use_delta--; + } - if (data != NULL) { - goto cleanup; - } + nxt_port_release_send_msg(msg); + } - } else { - if (nxt_slow_path(n == NXT_ERROR)) { - if (msg->link.next == NULL) { - nxt_port_msg_close_fd(msg); + if (data != NULL) { + goto cleanup; + } - nxt_port_release_send_msg(msg); - } + } else { + if (nxt_slow_path(n == NXT_ERROR)) { + if (msg->link.next == NULL) { + nxt_port_msg_close_fd(msg); - goto fail; - } + nxt_port_release_send_msg(msg); + } - if (msg->link.next == NULL) { - msg = nxt_port_msg_insert_tail(port, msg); - if (nxt_slow_path(msg == NULL)) { - goto fail; - } + goto fail; + } - use_delta++; - } + if (msg->link.next == NULL) { + msg = nxt_port_msg_insert_tail(port, msg); + if (nxt_slow_path(msg == NULL)) { + goto fail; } - } while (port->socket.write_ready); - - if (nxt_fd_event_is_disabled(port->socket.write)) { - enable_write = 1; + use_delta++; + } } - goto cleanup; + } while (port->socket.write_ready); + + if (nxt_fd_event_is_disabled(port->socket.write)) { + enable_write = 1; + } + + goto cleanup; fail: - use_delta++; + use_delta++; - nxt_work_queue_add(wq, nxt_port_error_handler, task, &port->socket, - &port->socket); + nxt_work_queue_add(wq, nxt_port_error_handler, task, &port->socket, + &port->socket); cleanup: - if (block_write && nxt_fd_event_is_active(port->socket.write)) { - nxt_port_post(task, port, nxt_port_fd_block_write, NULL); - } + if (block_write && nxt_fd_event_is_active(port->socket.write)) { + nxt_port_post(task, port, nxt_port_fd_block_write, NULL); + } - if (enable_write) { - nxt_port_post(task, port, nxt_port_fd_enable_write, NULL); - } + if (enable_write) { + nxt_port_post(task, port, nxt_port_fd_enable_write, NULL); + } - if (use_delta != 0) { - nxt_port_use(task, port, use_delta); - } + if (use_delta != 0) { + nxt_port_use(task, port, use_delta); + } } +static nxt_port_send_msg_t *nxt_port_msg_first(nxt_port_t *port) { + nxt_queue_link_t *lnk; + nxt_port_send_msg_t *msg; -static nxt_port_send_msg_t * -nxt_port_msg_first(nxt_port_t *port) -{ - nxt_queue_link_t *lnk; - nxt_port_send_msg_t *msg; + nxt_thread_mutex_lock(&port->write_mutex); - nxt_thread_mutex_lock(&port->write_mutex); + lnk = nxt_queue_first(&port->messages); - lnk = nxt_queue_first(&port->messages); + if (lnk == nxt_queue_tail(&port->messages)) { + msg = NULL; - if (lnk == nxt_queue_tail(&port->messages)) { - msg = NULL; + } else { + msg = nxt_queue_link_data(lnk, nxt_port_send_msg_t, link); + } - } else { - msg = nxt_queue_link_data(lnk, nxt_port_send_msg_t, link); - } + nxt_thread_mutex_unlock(&port->write_mutex); - nxt_thread_mutex_unlock(&port->write_mutex); - - return msg; + return msg; } +nxt_inline void nxt_port_msg_close_fd(nxt_port_send_msg_t *msg) { + if (!msg->close_fd) { + return; + } -nxt_inline void -nxt_port_msg_close_fd(nxt_port_send_msg_t *msg) -{ - if (!msg->close_fd) { - return; - } - - nxt_port_close_fds(msg->fd); + nxt_port_close_fds(msg->fd); } +nxt_inline void nxt_port_close_fds(nxt_fd_t *fd) { + if (fd[0] != -1) { + nxt_fd_close(fd[0]); + fd[0] = -1; + } -nxt_inline void -nxt_port_close_fds(nxt_fd_t *fd) -{ - if (fd[0] != -1) { - nxt_fd_close(fd[0]); - fd[0] = -1; - } - - if (fd[1] != -1) { - nxt_fd_close(fd[1]); - fd[1] = -1; - } + if (fd[1] != -1) { + nxt_fd_close(fd[1]); + fd[1] = -1; + } } +static nxt_buf_t *nxt_port_buf_completion(nxt_task_t *task, + nxt_work_queue_t *wq, nxt_buf_t *b, + size_t sent, nxt_bool_t mmap_mode) { + size_t size; + nxt_buf_t *next; -static nxt_buf_t * -nxt_port_buf_completion(nxt_task_t *task, nxt_work_queue_t *wq, nxt_buf_t *b, - size_t sent, nxt_bool_t mmap_mode) -{ - size_t size; - nxt_buf_t *next; - - while (b != NULL) { - - nxt_prefetch(b->next); + while (b != NULL) { - if (!nxt_buf_is_sync(b)) { + nxt_prefetch(b->next); - size = nxt_buf_used_size(b); + if (!nxt_buf_is_sync(b)) { - if (size != 0) { + size = nxt_buf_used_size(b); - if (sent == 0) { - break; - } + if (size != 0) { - if (nxt_buf_is_port_mmap(b) && mmap_mode) { - /* - * buffer has been sent to other side which is now - * responsible for shared memory bucket release - */ - b->is_port_mmap_sent = 1; - } + if (sent == 0) { + break; + } - if (sent < size) { + if (nxt_buf_is_port_mmap(b) && mmap_mode) { + /* + * buffer has been sent to other side which is now + * responsible for shared memory bucket release + */ + b->is_port_mmap_sent = 1; + } - if (nxt_buf_is_mem(b)) { - b->mem.pos += sent; - } + if (sent < size) { - if (nxt_buf_is_file(b)) { - b->file_pos += sent; - } + if (nxt_buf_is_mem(b)) { + b->mem.pos += sent; + } - break; - } + if (nxt_buf_is_file(b)) { + b->file_pos += sent; + } - /* b->mem.free is NULL in file-only buffer. */ - b->mem.pos = b->mem.free; + break; + } - if (nxt_buf_is_file(b)) { - b->file_pos = b->file_end; - } + /* b->mem.free is NULL in file-only buffer. */ + b->mem.pos = b->mem.free; - sent -= size; - } + if (nxt_buf_is_file(b)) { + b->file_pos = b->file_end; } - nxt_work_queue_add(wq, b->completion_handler, task, b, b->parent); - - next = b->next; - b->next = NULL; - b = next; + sent -= size; + } } - return b; -} + nxt_work_queue_add(wq, b->completion_handler, task, b, b->parent); + next = b->next; + b->next = NULL; + b = next; + } -static nxt_port_send_msg_t * -nxt_port_msg_insert_tail(nxt_port_t *port, nxt_port_send_msg_t *msg) -{ - if (msg->allocated == 0) { - msg = nxt_port_msg_alloc(msg); + return b; +} - if (nxt_slow_path(msg == NULL)) { - return NULL; - } +static nxt_port_send_msg_t *nxt_port_msg_insert_tail(nxt_port_t *port, + nxt_port_send_msg_t *msg) { + if (msg->allocated == 0) { + msg = nxt_port_msg_alloc(msg); + + if (nxt_slow_path(msg == NULL)) { + return NULL; } + } - nxt_thread_mutex_lock(&port->write_mutex); + nxt_thread_mutex_lock(&port->write_mutex); - nxt_queue_insert_tail(&port->messages, &msg->link); + nxt_queue_insert_tail(&port->messages, &msg->link); - nxt_thread_mutex_unlock(&port->write_mutex); + nxt_thread_mutex_unlock(&port->write_mutex); - return msg; + return msg; } +void nxt_port_read_enable(nxt_task_t *task, nxt_port_t *port) { + port->socket.fd = port->pair[0]; + port->socket.log = &nxt_main_log; -void -nxt_port_read_enable(nxt_task_t *task, nxt_port_t *port) -{ - port->socket.fd = port->pair[0]; - port->socket.log = &nxt_main_log; + port->engine = task->thread->engine; - port->engine = task->thread->engine; + port->socket.read_work_queue = &port->engine->fast_work_queue; + port->socket.read_handler = + port->queue != NULL ? nxt_port_queue_read_handler : nxt_port_read_handler; + port->socket.error_handler = nxt_port_error_handler; - port->socket.read_work_queue = &port->engine->fast_work_queue; - port->socket.read_handler = port->queue != NULL - ? nxt_port_queue_read_handler - : nxt_port_read_handler; - port->socket.error_handler = nxt_port_error_handler; - - nxt_fd_event_enable_read(port->engine, &port->socket); + nxt_fd_event_enable_read(port->engine, &port->socket); } - -void -nxt_port_read_close(nxt_port_t *port) -{ - port->socket.read_ready = 0; - port->socket.read = NXT_EVENT_INACTIVE; - nxt_socket_close(port->socket.task, port->pair[0]); - port->pair[0] = -1; +void nxt_port_read_close(nxt_port_t *port) { + port->socket.read_ready = 0; + port->socket.read = NXT_EVENT_INACTIVE; + nxt_socket_close(port->socket.task, port->pair[0]); + port->pair[0] = -1; } +static void nxt_port_read_handler(nxt_task_t *task, void *obj, void *data) { + ssize_t n; + nxt_buf_t *b; + nxt_int_t ret; + nxt_port_t *port; + nxt_recv_oob_t oob; + nxt_port_recv_msg_t msg; + struct iovec iov[2]; -static void -nxt_port_read_handler(nxt_task_t *task, void *obj, void *data) -{ - ssize_t n; - nxt_buf_t *b; - nxt_int_t ret; - nxt_port_t *port; - nxt_recv_oob_t oob; - nxt_port_recv_msg_t msg; - struct iovec iov[2]; + port = msg.port = nxt_container_of(obj, nxt_port_t, socket); - port = msg.port = nxt_container_of(obj, nxt_port_t, socket); + nxt_assert(port->engine == task->thread->engine); - nxt_assert(port->engine == task->thread->engine); + for (;;) { + b = nxt_port_buf_alloc(port); - for ( ;; ) { - b = nxt_port_buf_alloc(port); - - if (nxt_slow_path(b == NULL)) { - /* TODO: disable event for some time */ - } + if (nxt_slow_path(b == NULL)) { + /* TODO: disable event for some time */ + } - iov[0].iov_base = &msg.port_msg; - iov[0].iov_len = sizeof(nxt_port_msg_t); + iov[0].iov_base = &msg.port_msg; + iov[0].iov_len = sizeof(nxt_port_msg_t); - iov[1].iov_base = b->mem.pos; - iov[1].iov_len = port->max_size; + iov[1].iov_base = b->mem.pos; + iov[1].iov_len = port->max_size; - n = nxt_socketpair_recv(&port->socket, iov, 2, &oob); + n = nxt_socketpair_recv(&port->socket, iov, 2, &oob); - if (n > 0) { - msg.fd[0] = -1; - msg.fd[1] = -1; + if (n > 0) { + msg.fd[0] = -1; + msg.fd[1] = -1; - ret = nxt_socket_msg_oob_get(&oob, msg.fd, - nxt_recv_msg_cmsg_pid_ref(&msg)); - if (nxt_slow_path(ret != NXT_OK)) { - nxt_alert(task, "failed to get oob data from %d", - port->socket.fd); + ret = + nxt_socket_msg_oob_get(&oob, msg.fd, nxt_recv_msg_cmsg_pid_ref(&msg)); + if (nxt_slow_path(ret != NXT_OK)) { + nxt_alert(task, "failed to get oob data from %d", port->socket.fd); - nxt_port_close_fds(msg.fd); + nxt_port_close_fds(msg.fd); - goto fail; - } + goto fail; + } - msg.buf = b; - msg.size = n; + msg.buf = b; + msg.size = n; - nxt_port_read_msg_process(task, port, &msg); + nxt_port_read_msg_process(task, port, &msg); - /* - * To disable instant completion or buffer re-usage, - * handler should reset 'msg.buf'. - */ - if (msg.buf == b) { - nxt_port_buf_free(port, b); - } - - if (port->socket.read_ready) { - continue; - } + /* + * To disable instant completion or buffer re-usage, + * handler should reset 'msg.buf'. + */ + if (msg.buf == b) { + nxt_port_buf_free(port, b); + } - return; - } + if (port->socket.read_ready) { + continue; + } - if (n == NXT_AGAIN) { - nxt_port_buf_free(port, b); + return; + } - nxt_fd_event_enable_read(task->thread->engine, &port->socket); - return; - } + if (n == NXT_AGAIN) { + nxt_port_buf_free(port, b); -fail: - /* n == 0 || error */ - nxt_work_queue_add(&task->thread->engine->fast_work_queue, - nxt_port_error_handler, task, &port->socket, NULL); - return; + nxt_fd_event_enable_read(task->thread->engine, &port->socket); + return; } + + fail: + /* n == 0 || error */ + nxt_work_queue_add(&task->thread->engine->fast_work_queue, + nxt_port_error_handler, task, &port->socket, NULL); + return; + } } +static void nxt_port_queue_read_handler(nxt_task_t *task, void *obj, + void *data) { + ssize_t n; + nxt_buf_t *b; + nxt_int_t ret; + nxt_port_t *port; + struct iovec iov[2]; + nxt_recv_oob_t oob; + nxt_port_queue_t *queue; + nxt_port_recv_msg_t msg, *smsg; + uint8_t qmsg[NXT_PORT_QUEUE_MSG_SIZE]; -static void -nxt_port_queue_read_handler(nxt_task_t *task, void *obj, void *data) -{ - ssize_t n; - nxt_buf_t *b; - nxt_int_t ret; - nxt_port_t *port; - struct iovec iov[2]; - nxt_recv_oob_t oob; - nxt_port_queue_t *queue; - nxt_port_recv_msg_t msg, *smsg; - uint8_t qmsg[NXT_PORT_QUEUE_MSG_SIZE]; + port = nxt_container_of(obj, nxt_port_t, socket); + msg.port = port; - port = nxt_container_of(obj, nxt_port_t, socket); - msg.port = port; + nxt_assert(port->engine == task->thread->engine); - nxt_assert(port->engine == task->thread->engine); + queue = port->queue; + nxt_atomic_fetch_add(&queue->nitems, 1); - queue = port->queue; - nxt_atomic_fetch_add(&queue->nitems, 1); + for (;;) { - for ( ;; ) { + if (port->from_socket == 0) { + n = nxt_port_queue_recv(queue, qmsg); - if (port->from_socket == 0) { - n = nxt_port_queue_recv(queue, qmsg); + if (n < 0 && !port->socket.read_ready) { + nxt_atomic_fetch_add(&queue->nitems, -1); - if (n < 0 && !port->socket.read_ready) { - nxt_atomic_fetch_add(&queue->nitems, -1); - - n = nxt_port_queue_recv(queue, qmsg); - if (n < 0) { - return; - } + n = nxt_port_queue_recv(queue, qmsg); + if (n < 0) { + return; + } - nxt_atomic_fetch_add(&queue->nitems, 1); - } + nxt_atomic_fetch_add(&queue->nitems, 1); + } - if (n == 1 && qmsg[0] == _NXT_PORT_MSG_READ_SOCKET) { - port->from_socket++; + if (n == 1 && qmsg[0] == _NXT_PORT_MSG_READ_SOCKET) { + port->from_socket++; - nxt_debug(task, "port{%d,%d} %d: dequeue 1 read_socket %d", - (int) port->pid, (int) port->id, port->socket.fd, - port->from_socket); + nxt_debug(task, "port{%d,%d} %d: dequeue 1 read_socket %d", + (int)port->pid, (int)port->id, port->socket.fd, + port->from_socket); - continue; - } + continue; + } - nxt_debug(task, "port{%d,%d} %d: dequeue %d", - (int) port->pid, (int) port->id, port->socket.fd, - (int) n); + nxt_debug(task, "port{%d,%d} %d: dequeue %d", (int)port->pid, + (int)port->id, port->socket.fd, (int)n); - } else { - if ((smsg = port->socket_msg) != NULL && smsg->size != 0) { - msg.port_msg = smsg->port_msg; - b = smsg->buf; - n = smsg->size; - msg.fd[0] = smsg->fd[0]; - msg.fd[1] = smsg->fd[1]; + } else { + if ((smsg = port->socket_msg) != NULL && smsg->size != 0) { + msg.port_msg = smsg->port_msg; + b = smsg->buf; + n = smsg->size; + msg.fd[0] = smsg->fd[0]; + msg.fd[1] = smsg->fd[1]; - smsg->size = 0; + smsg->size = 0; - port->from_socket--; + port->from_socket--; - nxt_debug(task, "port{%d,%d} %d: use suspended message %d", - (int) port->pid, (int) port->id, port->socket.fd, - (int) n); + nxt_debug(task, "port{%d,%d} %d: use suspended message %d", + (int)port->pid, (int)port->id, port->socket.fd, (int)n); - goto process; - } + goto process; + } - n = -1; - } + n = -1; + } - if (n < 0 && !port->socket.read_ready) { - nxt_atomic_fetch_add(&queue->nitems, -1); - return; - } + if (n < 0 && !port->socket.read_ready) { + nxt_atomic_fetch_add(&queue->nitems, -1); + return; + } - b = nxt_port_buf_alloc(port); + b = nxt_port_buf_alloc(port); - if (nxt_slow_path(b == NULL)) { - /* TODO: disable event for some time */ - } + if (nxt_slow_path(b == NULL)) { + /* TODO: disable event for some time */ + } - if (n >= (ssize_t) sizeof(nxt_port_msg_t)) { - nxt_memcpy(&msg.port_msg, qmsg, sizeof(nxt_port_msg_t)); + if (n >= (ssize_t)sizeof(nxt_port_msg_t)) { + nxt_memcpy(&msg.port_msg, qmsg, sizeof(nxt_port_msg_t)); - if (n > (ssize_t) sizeof(nxt_port_msg_t)) { - nxt_memcpy(b->mem.pos, qmsg + sizeof(nxt_port_msg_t), - n - sizeof(nxt_port_msg_t)); - } + if (n > (ssize_t)sizeof(nxt_port_msg_t)) { + nxt_memcpy(b->mem.pos, qmsg + sizeof(nxt_port_msg_t), + n - sizeof(nxt_port_msg_t)); + } - } else { - iov[0].iov_base = &msg.port_msg; - iov[0].iov_len = sizeof(nxt_port_msg_t); + } else { + iov[0].iov_base = &msg.port_msg; + iov[0].iov_len = sizeof(nxt_port_msg_t); - iov[1].iov_base = b->mem.pos; - iov[1].iov_len = port->max_size; + iov[1].iov_base = b->mem.pos; + iov[1].iov_len = port->max_size; - n = nxt_socketpair_recv(&port->socket, iov, 2, &oob); + n = nxt_socketpair_recv(&port->socket, iov, 2, &oob); - if (n > 0) { - msg.fd[0] = -1; - msg.fd[1] = -1; + if (n > 0) { + msg.fd[0] = -1; + msg.fd[1] = -1; - ret = nxt_socket_msg_oob_get(&oob, msg.fd, - nxt_recv_msg_cmsg_pid_ref(&msg)); - if (nxt_slow_path(ret != NXT_OK)) { - nxt_alert(task, "failed to get oob data from %d", - port->socket.fd); + ret = nxt_socket_msg_oob_get(&oob, msg.fd, + nxt_recv_msg_cmsg_pid_ref(&msg)); + if (nxt_slow_path(ret != NXT_OK)) { + nxt_alert(task, "failed to get oob data from %d", port->socket.fd); - nxt_port_close_fds(msg.fd); + nxt_port_close_fds(msg.fd); - return; - } - } + return; + } + } - if (n == (ssize_t) sizeof(nxt_port_msg_t) - && msg.port_msg.type == _NXT_PORT_MSG_READ_QUEUE) - { - nxt_port_buf_free(port, b); + if (n == (ssize_t)sizeof(nxt_port_msg_t) && + msg.port_msg.type == _NXT_PORT_MSG_READ_QUEUE) { + nxt_port_buf_free(port, b); - nxt_debug(task, "port{%d,%d} %d: recv %d read_queue", - (int) port->pid, (int) port->id, port->socket.fd, - (int) n); + nxt_debug(task, "port{%d,%d} %d: recv %d read_queue", (int)port->pid, + (int)port->id, port->socket.fd, (int)n); - continue; - } + continue; + } - nxt_debug(task, "port{%d,%d} %d: recvmsg %d", - (int) port->pid, (int) port->id, port->socket.fd, - (int) n); + nxt_debug(task, "port{%d,%d} %d: recvmsg %d", (int)port->pid, + (int)port->id, port->socket.fd, (int)n); - if (n > 0) { - if (port->from_socket == 0) { - nxt_debug(task, "port{%d,%d} %d: suspend message %d", - (int) port->pid, (int) port->id, port->socket.fd, - (int) n); - - smsg = port->socket_msg; + if (n > 0) { + if (port->from_socket == 0) { + nxt_debug(task, "port{%d,%d} %d: suspend message %d", (int)port->pid, + (int)port->id, port->socket.fd, (int)n); - if (nxt_slow_path(smsg == NULL)) { - smsg = nxt_mp_alloc(port->mem_pool, - sizeof(nxt_port_recv_msg_t)); + smsg = port->socket_msg; - if (nxt_slow_path(smsg == NULL)) { - nxt_alert(task, "port{%d,%d} %d: suspend message " - "failed", - (int) port->pid, (int) port->id, - port->socket.fd); + if (nxt_slow_path(smsg == NULL)) { + smsg = nxt_mp_alloc(port->mem_pool, sizeof(nxt_port_recv_msg_t)); - return; - } + if (nxt_slow_path(smsg == NULL)) { + nxt_alert(task, + "port{%d,%d} %d: suspend message " + "failed", + (int)port->pid, (int)port->id, port->socket.fd); - port->socket_msg = smsg; + return; + } - } else { - if (nxt_slow_path(smsg->size != 0)) { - nxt_alert(task, "port{%d,%d} %d: too many suspend " - "messages", - (int) port->pid, (int) port->id, - port->socket.fd); + port->socket_msg = smsg; - return; - } - } + } else { + if (nxt_slow_path(smsg->size != 0)) { + nxt_alert(task, + "port{%d,%d} %d: too many suspend " + "messages", + (int)port->pid, (int)port->id, port->socket.fd); - smsg->port_msg = msg.port_msg; - smsg->buf = b; - smsg->size = n; - smsg->fd[0] = msg.fd[0]; - smsg->fd[1] = msg.fd[1]; + return; + } + } - continue; - } + smsg->port_msg = msg.port_msg; + smsg->buf = b; + smsg->size = n; + smsg->fd[0] = msg.fd[0]; + smsg->fd[1] = msg.fd[1]; - port->from_socket--; - } + continue; } - process: + port->from_socket--; + } + } - if (n > 0) { - msg.buf = b; - msg.size = n; + process: - nxt_port_read_msg_process(task, port, &msg); + if (n > 0) { + msg.buf = b; + msg.size = n; - /* - * To disable instant completion or buffer re-usage, - * handler should reset 'msg.buf'. - */ - if (msg.buf == b) { - nxt_port_buf_free(port, b); - } + nxt_port_read_msg_process(task, port, &msg); - continue; - } - - if (n == NXT_AGAIN) { - nxt_port_buf_free(port, b); + /* + * To disable instant completion or buffer re-usage, + * handler should reset 'msg.buf'. + */ + if (msg.buf == b) { + nxt_port_buf_free(port, b); + } - nxt_fd_event_enable_read(task->thread->engine, &port->socket); + continue; + } - continue; - } + if (n == NXT_AGAIN) { + nxt_port_buf_free(port, b); - /* n == 0 || n == NXT_ERROR */ + nxt_fd_event_enable_read(task->thread->engine, &port->socket); - nxt_work_queue_add(&task->thread->engine->fast_work_queue, - nxt_port_error_handler, task, &port->socket, NULL); - return; + continue; } -} + /* n == 0 || n == NXT_ERROR */ + + nxt_work_queue_add(&task->thread->engine->fast_work_queue, + nxt_port_error_handler, task, &port->socket, NULL); + return; + } +} typedef struct { - uint32_t stream; - uint32_t pid; + uint32_t stream; + uint32_t pid; } nxt_port_frag_key_t; +static nxt_int_t nxt_port_lvlhsh_frag_test(nxt_lvlhsh_query_t *lhq, + void *data) { + nxt_port_recv_msg_t *fmsg; + nxt_port_frag_key_t *frag_key; -static nxt_int_t -nxt_port_lvlhsh_frag_test(nxt_lvlhsh_query_t *lhq, void *data) -{ - nxt_port_recv_msg_t *fmsg; - nxt_port_frag_key_t *frag_key; - - fmsg = data; - frag_key = (nxt_port_frag_key_t *) lhq->key.start; + fmsg = data; + frag_key = (nxt_port_frag_key_t *)lhq->key.start; - if (lhq->key.length == sizeof(nxt_port_frag_key_t) - && frag_key->stream == fmsg->port_msg.stream - && frag_key->pid == (uint32_t) fmsg->port_msg.pid) - { - return NXT_OK; - } + if (lhq->key.length == sizeof(nxt_port_frag_key_t) && + frag_key->stream == fmsg->port_msg.stream && + frag_key->pid == (uint32_t)fmsg->port_msg.pid) { + return NXT_OK; + } - return NXT_DECLINED; + return NXT_DECLINED; } - -static void * -nxt_port_lvlhsh_frag_alloc(void *ctx, size_t size) -{ - return nxt_mp_align(ctx, size, size); +static void *nxt_port_lvlhsh_frag_alloc(void *ctx, size_t size) { + return nxt_mp_align(ctx, size, size); } - -static void -nxt_port_lvlhsh_frag_free(void *ctx, void *p) -{ - nxt_mp_free(ctx, p); +static void nxt_port_lvlhsh_frag_free(void *ctx, void *p) { + nxt_mp_free(ctx, p); } - -static const nxt_lvlhsh_proto_t lvlhsh_frag_proto nxt_aligned(64) = { +static const nxt_lvlhsh_proto_t lvlhsh_frag_proto nxt_aligned(64) = { NXT_LVLHSH_DEFAULT, nxt_port_lvlhsh_frag_test, nxt_port_lvlhsh_frag_alloc, nxt_port_lvlhsh_frag_free, }; +static nxt_port_recv_msg_t *nxt_port_frag_start(nxt_task_t *task, + nxt_port_t *port, + nxt_port_recv_msg_t *msg) { + nxt_int_t res; + nxt_lvlhsh_query_t lhq; + nxt_port_recv_msg_t *fmsg; + nxt_port_frag_key_t frag_key; -static nxt_port_recv_msg_t * -nxt_port_frag_start(nxt_task_t *task, nxt_port_t *port, - nxt_port_recv_msg_t *msg) -{ - nxt_int_t res; - nxt_lvlhsh_query_t lhq; - nxt_port_recv_msg_t *fmsg; - nxt_port_frag_key_t frag_key; + nxt_debug(task, "start frag stream #%uD", msg->port_msg.stream); - nxt_debug(task, "start frag stream #%uD", msg->port_msg.stream); - - fmsg = nxt_mp_alloc(port->mem_pool, sizeof(nxt_port_recv_msg_t)); - - if (nxt_slow_path(fmsg == NULL)) { - return NULL; - } + fmsg = nxt_mp_alloc(port->mem_pool, sizeof(nxt_port_recv_msg_t)); - *fmsg = *msg; + if (nxt_slow_path(fmsg == NULL)) { + return NULL; + } - frag_key.stream = fmsg->port_msg.stream; - frag_key.pid = fmsg->port_msg.pid; + *fmsg = *msg; - lhq.key_hash = nxt_murmur_hash2(&frag_key, sizeof(nxt_port_frag_key_t)); - lhq.key.length = sizeof(nxt_port_frag_key_t); - lhq.key.start = (u_char *) &frag_key; - lhq.proto = &lvlhsh_frag_proto; - lhq.replace = 0; - lhq.value = fmsg; - lhq.pool = port->mem_pool; + frag_key.stream = fmsg->port_msg.stream; + frag_key.pid = fmsg->port_msg.pid; - res = nxt_lvlhsh_insert(&port->frags, &lhq); + lhq.key_hash = nxt_murmur_hash2(&frag_key, sizeof(nxt_port_frag_key_t)); + lhq.key.length = sizeof(nxt_port_frag_key_t); + lhq.key.start = (u_char *)&frag_key; + lhq.proto = &lvlhsh_frag_proto; + lhq.replace = 0; + lhq.value = fmsg; + lhq.pool = port->mem_pool; - switch (res) { + res = nxt_lvlhsh_insert(&port->frags, &lhq); - case NXT_OK: - return fmsg; + switch (res) { - case NXT_DECLINED: - nxt_log(task, NXT_LOG_WARN, "duplicate frag stream #%uD", - fmsg->port_msg.stream); - nxt_mp_free(port->mem_pool, fmsg); + case NXT_OK: + return fmsg; - return NULL; + case NXT_DECLINED: + nxt_log(task, NXT_LOG_WARN, "duplicate frag stream #%uD", + fmsg->port_msg.stream); + nxt_mp_free(port->mem_pool, fmsg); - default: - nxt_log(task, NXT_LOG_WARN, "failed to add frag stream #%uD", - fmsg->port_msg.stream); + return NULL; - nxt_mp_free(port->mem_pool, fmsg); + default: + nxt_log(task, NXT_LOG_WARN, "failed to add frag stream #%uD", + fmsg->port_msg.stream); - return NULL; + nxt_mp_free(port->mem_pool, fmsg); - } + return NULL; + } } +static nxt_port_recv_msg_t *nxt_port_frag_find(nxt_task_t *task, + nxt_port_t *port, + nxt_port_recv_msg_t *msg) { + nxt_int_t res; + nxt_bool_t last; + nxt_lvlhsh_query_t lhq; + nxt_port_frag_key_t frag_key; -static nxt_port_recv_msg_t * -nxt_port_frag_find(nxt_task_t *task, nxt_port_t *port, nxt_port_recv_msg_t *msg) -{ - nxt_int_t res; - nxt_bool_t last; - nxt_lvlhsh_query_t lhq; - nxt_port_frag_key_t frag_key; - - last = msg->port_msg.mf == 0; + last = msg->port_msg.mf == 0; - nxt_debug(task, "%s frag stream #%uD", last ? "last" : "next", - msg->port_msg.stream); + nxt_debug(task, "%s frag stream #%uD", last ? "last" : "next", + msg->port_msg.stream); - frag_key.stream = msg->port_msg.stream; - frag_key.pid = msg->port_msg.pid; + frag_key.stream = msg->port_msg.stream; + frag_key.pid = msg->port_msg.pid; - lhq.key_hash = nxt_murmur_hash2(&frag_key, sizeof(nxt_port_frag_key_t)); - lhq.key.length = sizeof(nxt_port_frag_key_t); - lhq.key.start = (u_char *) &frag_key; - lhq.proto = &lvlhsh_frag_proto; - lhq.pool = port->mem_pool; + lhq.key_hash = nxt_murmur_hash2(&frag_key, sizeof(nxt_port_frag_key_t)); + lhq.key.length = sizeof(nxt_port_frag_key_t); + lhq.key.start = (u_char *)&frag_key; + lhq.proto = &lvlhsh_frag_proto; + lhq.pool = port->mem_pool; - res = last != 0 ? nxt_lvlhsh_delete(&port->frags, &lhq) : - nxt_lvlhsh_find(&port->frags, &lhq); + res = last != 0 ? nxt_lvlhsh_delete(&port->frags, &lhq) + : nxt_lvlhsh_find(&port->frags, &lhq); - switch (res) { + switch (res) { - case NXT_OK: - return lhq.value; + case NXT_OK: + return lhq.value; - default: - nxt_log(task, NXT_LOG_INFO, "frag stream #%uD not found", - frag_key.stream); + default: + nxt_log(task, NXT_LOG_INFO, "frag stream #%uD not found", frag_key.stream); - return NULL; - } + return NULL; + } } +static void nxt_port_read_msg_process(nxt_task_t *task, nxt_port_t *port, + nxt_port_recv_msg_t *msg) { + nxt_buf_t *b, *orig_b, *next; + nxt_port_recv_msg_t *fmsg; -static void -nxt_port_read_msg_process(nxt_task_t *task, nxt_port_t *port, - nxt_port_recv_msg_t *msg) -{ - nxt_buf_t *b, *orig_b, *next; - nxt_port_recv_msg_t *fmsg; - - if (nxt_slow_path(msg->size < sizeof(nxt_port_msg_t))) { - nxt_alert(task, "port %d: too small message:%uz", - port->socket.fd, msg->size); - - nxt_port_close_fds(msg->fd); + if (nxt_slow_path(msg->size < sizeof(nxt_port_msg_t))) { + nxt_alert(task, "port %d: too small message:%uz", port->socket.fd, + msg->size); - return; - } + nxt_port_close_fds(msg->fd); - /* adjust size to actual buffer used size */ - msg->size -= sizeof(nxt_port_msg_t); + return; + } - b = orig_b = msg->buf; - b->mem.free += msg->size; + /* adjust size to actual buffer used size */ + msg->size -= sizeof(nxt_port_msg_t); - msg->cancelled = 0; + b = orig_b = msg->buf; + b->mem.free += msg->size; - if (nxt_slow_path(msg->port_msg.nf != 0)) { + msg->cancelled = 0; - fmsg = nxt_port_frag_find(task, port, msg); + if (nxt_slow_path(msg->port_msg.nf != 0)) { - if (nxt_slow_path(fmsg == NULL)) { - goto fmsg_failed; - } + fmsg = nxt_port_frag_find(task, port, msg); - if (nxt_fast_path(fmsg->cancelled == 0)) { + if (nxt_slow_path(fmsg == NULL)) { + goto fmsg_failed; + } - if (msg->port_msg.mmap) { - nxt_port_mmap_read(task, msg); - } + if (nxt_fast_path(fmsg->cancelled == 0)) { - nxt_buf_chain_add(&fmsg->buf, msg->buf); + if (msg->port_msg.mmap) { + nxt_port_mmap_read(task, msg); + } - fmsg->size += msg->size; - msg->buf = NULL; - b = NULL; + nxt_buf_chain_add(&fmsg->buf, msg->buf); - if (nxt_fast_path(msg->port_msg.mf == 0)) { + fmsg->size += msg->size; + msg->buf = NULL; + b = NULL; - b = fmsg->buf; + if (nxt_fast_path(msg->port_msg.mf == 0)) { - port->handler(task, fmsg); + b = fmsg->buf; - msg->buf = fmsg->buf; - msg->fd[0] = fmsg->fd[0]; - msg->fd[1] = fmsg->fd[1]; + port->handler(task, fmsg); - /* - * To disable instant completion or buffer re-usage, - * handler should reset 'msg.buf'. - */ - if (!msg->port_msg.mmap && msg->buf == b) { - nxt_port_buf_free(port, b); - } - } - } + msg->buf = fmsg->buf; + msg->fd[0] = fmsg->fd[0]; + msg->fd[1] = fmsg->fd[1]; - if (nxt_fast_path(msg->port_msg.mf == 0)) { - nxt_mp_free(port->mem_pool, fmsg); + /* + * To disable instant completion or buffer re-usage, + * handler should reset 'msg.buf'. + */ + if (!msg->port_msg.mmap && msg->buf == b) { + nxt_port_buf_free(port, b); } - } else { - if (nxt_slow_path(msg->port_msg.mf != 0)) { + } + } - if (msg->port_msg.mmap && msg->cancelled == 0) { - nxt_port_mmap_read(task, msg); - b = msg->buf; - } + if (nxt_fast_path(msg->port_msg.mf == 0)) { + nxt_mp_free(port->mem_pool, fmsg); + } + } else { + if (nxt_slow_path(msg->port_msg.mf != 0)) { - fmsg = nxt_port_frag_start(task, port, msg); + if (msg->port_msg.mmap && msg->cancelled == 0) { + nxt_port_mmap_read(task, msg); + b = msg->buf; + } - if (nxt_slow_path(fmsg == NULL)) { - goto fmsg_failed; - } + fmsg = nxt_port_frag_start(task, port, msg); - fmsg->port_msg.nf = 0; - fmsg->port_msg.mf = 0; + if (nxt_slow_path(fmsg == NULL)) { + goto fmsg_failed; + } - if (nxt_fast_path(msg->cancelled == 0)) { - msg->buf = NULL; - msg->fd[0] = -1; - msg->fd[1] = -1; - b = NULL; + fmsg->port_msg.nf = 0; + fmsg->port_msg.mf = 0; - } else { - nxt_port_close_fds(msg->fd); - } - } else { - if (nxt_fast_path(msg->cancelled == 0)) { + if (nxt_fast_path(msg->cancelled == 0)) { + msg->buf = NULL; + msg->fd[0] = -1; + msg->fd[1] = -1; + b = NULL; - if (msg->port_msg.mmap) { - nxt_port_mmap_read(task, msg); - b = msg->buf; - } + } else { + nxt_port_close_fds(msg->fd); + } + } else { + if (nxt_fast_path(msg->cancelled == 0)) { - port->handler(task, msg); - } + if (msg->port_msg.mmap) { + nxt_port_mmap_read(task, msg); + b = msg->buf; } + + port->handler(task, msg); + } } + } fmsg_failed: - if (msg->port_msg.mmap && orig_b != b) { + if (msg->port_msg.mmap && orig_b != b) { - /* - * To disable instant buffer completion, - * handler should reset 'msg->buf'. - */ - if (msg->buf == b) { - /* complete mmap buffers */ - while (b != NULL) { - nxt_debug(task, "complete buffer %p", b); - - nxt_work_queue_add(port->socket.read_work_queue, - b->completion_handler, task, b, b->parent); + /* + * To disable instant buffer completion, + * handler should reset 'msg->buf'. + */ + if (msg->buf == b) { + /* complete mmap buffers */ + while (b != NULL) { + nxt_debug(task, "complete buffer %p", b); - next = b->next; - b->next = NULL; - b = next; - } - } + nxt_work_queue_add(port->socket.read_work_queue, b->completion_handler, + task, b, b->parent); - /* restore original buf */ - msg->buf = orig_b; + next = b->next; + b->next = NULL; + b = next; + } } -} + /* restore original buf */ + msg->buf = orig_b; + } +} -static nxt_buf_t * -nxt_port_buf_alloc(nxt_port_t *port) -{ - nxt_buf_t *b; +static nxt_buf_t *nxt_port_buf_alloc(nxt_port_t *port) { + nxt_buf_t *b; - if (port->free_bufs != NULL) { - b = port->free_bufs; - port->free_bufs = b->next; + if (port->free_bufs != NULL) { + b = port->free_bufs; + port->free_bufs = b->next; - b->mem.pos = b->mem.start; - b->mem.free = b->mem.start; - b->next = NULL; - } else { - b = nxt_buf_mem_alloc(port->mem_pool, port->max_size, 0); - if (nxt_slow_path(b == NULL)) { - return NULL; - } + b->mem.pos = b->mem.start; + b->mem.free = b->mem.start; + b->next = NULL; + } else { + b = nxt_buf_mem_alloc(port->mem_pool, port->max_size, 0); + if (nxt_slow_path(b == NULL)) { + return NULL; } + } - return b; + return b; } - -static void -nxt_port_buf_free(nxt_port_t *port, nxt_buf_t *b) -{ - nxt_buf_chain_add(&b, port->free_bufs); - port->free_bufs = b; +static void nxt_port_buf_free(nxt_port_t *port, nxt_buf_t *b) { + nxt_buf_chain_add(&b, port->free_bufs); + port->free_bufs = b; } +static void nxt_port_error_handler(nxt_task_t *task, void *obj, void *data) { + int use_delta; + nxt_buf_t *b, *next; + nxt_port_t *port; + nxt_work_queue_t *wq; + nxt_port_send_msg_t *msg; -static void -nxt_port_error_handler(nxt_task_t *task, void *obj, void *data) -{ - int use_delta; - nxt_buf_t *b, *next; - nxt_port_t *port; - nxt_work_queue_t *wq; - nxt_port_send_msg_t *msg; - - nxt_debug(task, "port error handler %p", obj); - /* TODO */ + nxt_debug(task, "port error handler %p", obj); + /* TODO */ - port = nxt_container_of(obj, nxt_port_t, socket); + port = nxt_container_of(obj, nxt_port_t, socket); - use_delta = 0; + use_delta = 0; - if (obj == data) { - use_delta--; - } - - wq = &task->thread->engine->fast_work_queue; + if (obj == data) { + use_delta--; + } - nxt_thread_mutex_lock(&port->write_mutex); + wq = &task->thread->engine->fast_work_queue; - nxt_queue_each(msg, &port->messages, nxt_port_send_msg_t, link) { + nxt_thread_mutex_lock(&port->write_mutex); - nxt_port_msg_close_fd(msg); + nxt_queue_each(msg, &port->messages, nxt_port_send_msg_t, link) { - for (b = msg->buf; b != NULL; b = next) { - next = b->next; - b->next = NULL; + nxt_port_msg_close_fd(msg); - if (nxt_buf_is_sync(b)) { - continue; - } + for (b = msg->buf; b != NULL; b = next) { + next = b->next; + b->next = NULL; - nxt_work_queue_add(wq, b->completion_handler, task, b, b->parent); - } + if (nxt_buf_is_sync(b)) { + continue; + } - nxt_queue_remove(&msg->link); - use_delta--; + nxt_work_queue_add(wq, b->completion_handler, task, b, b->parent); + } - nxt_port_release_send_msg(msg); + nxt_queue_remove(&msg->link); + use_delta--; - } nxt_queue_loop; + nxt_port_release_send_msg(msg); + } + nxt_queue_loop; - nxt_thread_mutex_unlock(&port->write_mutex); + nxt_thread_mutex_unlock(&port->write_mutex); - if (use_delta != 0) { - nxt_port_use(task, port, use_delta); - } + if (use_delta != 0) { + nxt_port_use(task, port, use_delta); + } } diff --git a/src/nxt_process.c b/src/nxt_process.c index f445f0f5b..424a78981 100644 --- a/src/nxt_process.c +++ b/src/nxt_process.c @@ -19,27 +19,26 @@ #include #endif - #if (NXT_HAVE_LINUX_NS) && (NXT_HAVE_CLONE_NEWPID) -#define nxt_is_pid_isolated(process) \ - nxt_is_clone_flag_set(process->isolation.clone.flags, NEWPID) +#define nxt_is_pid_isolated(process) \ + nxt_is_clone_flag_set(process->isolation.clone.flags, NEWPID) #else -#define nxt_is_pid_isolated(process) \ - (0) +#define nxt_is_pid_isolated(process) (0) #endif - #if (NXT_HAVE_LINUX_NS) static nxt_int_t nxt_process_pipe_timer(nxt_fd_t fd, short event); static nxt_int_t nxt_process_check_pid_status(const nxt_fd_t *gc_pipe); static nxt_pid_t nxt_process_recv_pid(const nxt_fd_t *pid_pipe, - const nxt_fd_t *gc_pipe); + const nxt_fd_t *gc_pipe); static void nxt_process_send_pid(const nxt_fd_t *pid_pipe, nxt_pid_t pid); static nxt_int_t nxt_process_unshare(nxt_task_t *task, nxt_process_t *process, - nxt_fd_t *pid_pipe, nxt_fd_t *gc_pipe, nxt_bool_t use_pidns); + nxt_fd_t *pid_pipe, nxt_fd_t *gc_pipe, + nxt_bool_t use_pidns); static nxt_int_t nxt_process_init_pidns(nxt_task_t *task, - const nxt_process_t *process, nxt_fd_t *pid_pipe, nxt_fd_t *gc_pipe, - nxt_bool_t *use_pidns); + const nxt_process_t *process, + nxt_fd_t *pid_pipe, nxt_fd_t *gc_pipe, + nxt_bool_t *use_pidns); #endif static nxt_pid_t nxt_process_create(nxt_task_t *task, nxt_process_t *process); @@ -47,1033 +46,948 @@ static nxt_int_t nxt_process_do_start(nxt_task_t *task, nxt_process_t *process); static nxt_int_t nxt_process_whoami(nxt_task_t *task, nxt_process_t *process); static nxt_int_t nxt_process_setup(nxt_task_t *task, nxt_process_t *process); static nxt_int_t nxt_process_child_fixup(nxt_task_t *task, - nxt_process_t *process); + nxt_process_t *process); static void nxt_process_whoami_ok(nxt_task_t *task, nxt_port_recv_msg_t *msg, - void *data); + void *data); static void nxt_process_whoami_error(nxt_task_t *task, nxt_port_recv_msg_t *msg, - void *data); + void *data); static nxt_int_t nxt_process_send_created(nxt_task_t *task, - nxt_process_t *process); + nxt_process_t *process); static nxt_int_t nxt_process_send_ready(nxt_task_t *task, - nxt_process_t *process); + nxt_process_t *process); static void nxt_process_created_ok(nxt_task_t *task, nxt_port_recv_msg_t *msg, - void *data); + void *data); static void nxt_process_created_error(nxt_task_t *task, - nxt_port_recv_msg_t *msg, void *data); - + nxt_port_recv_msg_t *msg, void *data); /* A cached process pid. */ -nxt_pid_t nxt_pid; +nxt_pid_t nxt_pid; /* An original parent process pid. */ -nxt_pid_t nxt_ppid; +nxt_pid_t nxt_ppid; /* A cached process effective uid */ -nxt_uid_t nxt_euid; +nxt_uid_t nxt_euid; /* A cached process effective gid */ -nxt_gid_t nxt_egid; - -uint8_t nxt_proc_keep_matrix[NXT_PROCESS_MAX][NXT_PROCESS_MAX] = { - { 1, 1, 1, 1, 1, 1 }, - { 1, 0, 0, 0, 0, 0 }, - { 1, 0, 0, 1, 0, 0 }, - { 1, 0, 1, 1, 1, 1 }, - { 1, 0, 0, 1, 0, 0 }, - { 1, 0, 0, 1, 0, 0 }, -}; +nxt_gid_t nxt_egid; -uint8_t nxt_proc_send_matrix[NXT_PROCESS_MAX][NXT_PROCESS_MAX] = { - { 1, 1, 1, 1, 1, 1 }, - { 1, 0, 0, 0, 0, 0 }, - { 1, 0, 0, 1, 0, 0 }, - { 1, 0, 1, 1, 1, 1 }, - { 1, 0, 0, 0, 0, 0 }, - { 1, 0, 0, 0, 0, 0 }, +uint8_t nxt_proc_keep_matrix[NXT_PROCESS_MAX][NXT_PROCESS_MAX] = { + {1, 1, 1, 1, 1, 1}, {1, 0, 0, 0, 0, 0}, {1, 0, 0, 1, 0, 0}, + {1, 0, 1, 1, 1, 1}, {1, 0, 0, 1, 0, 0}, {1, 0, 0, 1, 0, 0}, }; -uint8_t nxt_proc_remove_notify_matrix[NXT_PROCESS_MAX][NXT_PROCESS_MAX] = { - { 0, 0, 0, 0, 0, 0 }, - { 0, 0, 0, 0, 0, 0 }, - { 0, 0, 0, 1, 0, 0 }, - { 0, 0, 1, 0, 1, 1 }, - { 0, 0, 0, 1, 0, 0 }, - { 1, 0, 0, 1, 0, 0 }, +uint8_t nxt_proc_send_matrix[NXT_PROCESS_MAX][NXT_PROCESS_MAX] = { + {1, 1, 1, 1, 1, 1}, {1, 0, 0, 0, 0, 0}, {1, 0, 0, 1, 0, 0}, + {1, 0, 1, 1, 1, 1}, {1, 0, 0, 0, 0, 0}, {1, 0, 0, 0, 0, 0}, }; - -static const nxt_port_handlers_t nxt_process_whoami_port_handlers = { - .quit = nxt_signal_quit_handler, - .rpc_ready = nxt_port_rpc_handler, - .rpc_error = nxt_port_rpc_handler, +uint8_t nxt_proc_remove_notify_matrix[NXT_PROCESS_MAX][NXT_PROCESS_MAX] = { + {0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0}, {0, 0, 0, 1, 0, 0}, + {0, 0, 1, 0, 1, 1}, {0, 0, 0, 1, 0, 0}, {1, 0, 0, 1, 0, 0}, }; +static const nxt_port_handlers_t nxt_process_whoami_port_handlers = { + .quit = nxt_signal_quit_handler, + .rpc_ready = nxt_port_rpc_handler, + .rpc_error = nxt_port_rpc_handler, +}; -nxt_process_t * -nxt_process_new(nxt_runtime_t *rt) -{ - nxt_process_t *process; +nxt_process_t *nxt_process_new(nxt_runtime_t *rt) { + nxt_process_t *process; - process = nxt_mp_zalloc(rt->mem_pool, sizeof(nxt_process_t) - + sizeof(nxt_process_init_t)); + process = nxt_mp_zalloc(rt->mem_pool, + sizeof(nxt_process_t) + sizeof(nxt_process_init_t)); - if (nxt_slow_path(process == NULL)) { - return NULL; - } + if (nxt_slow_path(process == NULL)) { + return NULL; + } - nxt_queue_init(&process->ports); + nxt_queue_init(&process->ports); - nxt_thread_mutex_create(&process->incoming.mutex); + nxt_thread_mutex_create(&process->incoming.mutex); - process->use_count = 1; + process->use_count = 1; - nxt_queue_init(&process->children); + nxt_queue_init(&process->children); - return process; + return process; } +void nxt_process_use(nxt_task_t *task, nxt_process_t *process, int i) { + process->use_count += i; -void -nxt_process_use(nxt_task_t *task, nxt_process_t *process, int i) -{ - process->use_count += i; - - if (process->use_count == 0) { - nxt_runtime_process_release(task->thread->runtime, process); - } + if (process->use_count == 0) { + nxt_runtime_process_release(task->thread->runtime, process); + } } +nxt_int_t nxt_process_init_start(nxt_task_t *task, nxt_process_init_t init) { + nxt_int_t ret; + nxt_runtime_t *rt; + nxt_process_t *process; + nxt_process_init_t *pinit; -nxt_int_t -nxt_process_init_start(nxt_task_t *task, nxt_process_init_t init) -{ - nxt_int_t ret; - nxt_runtime_t *rt; - nxt_process_t *process; - nxt_process_init_t *pinit; - - rt = task->thread->runtime; + rt = task->thread->runtime; - process = nxt_process_new(rt); - if (nxt_slow_path(process == NULL)) { - return NXT_ERROR; - } + process = nxt_process_new(rt); + if (nxt_slow_path(process == NULL)) { + return NXT_ERROR; + } - process->parent_port = rt->port_by_type[rt->type]; + process->parent_port = rt->port_by_type[rt->type]; - process->name = init.name; - process->user_cred = &rt->user_cred; + process->name = init.name; + process->user_cred = &rt->user_cred; - pinit = nxt_process_init(process); - *pinit = init; + pinit = nxt_process_init(process); + *pinit = init; - ret = nxt_process_start(task, process); - if (nxt_slow_path(ret == NXT_ERROR)) { - nxt_process_use(task, process, -1); - } + ret = nxt_process_start(task, process); + if (nxt_slow_path(ret == NXT_ERROR)) { + nxt_process_use(task, process, -1); + } - return ret; + return ret; } +nxt_int_t nxt_process_start(nxt_task_t *task, nxt_process_t *process) { + nxt_mp_t *tmp_mp; + nxt_int_t ret; + nxt_pid_t pid; + nxt_port_t *port; + nxt_process_init_t *init; -nxt_int_t -nxt_process_start(nxt_task_t *task, nxt_process_t *process) -{ - nxt_mp_t *tmp_mp; - nxt_int_t ret; - nxt_pid_t pid; - nxt_port_t *port; - nxt_process_init_t *init; - - init = nxt_process_init(process); + init = nxt_process_init(process); - port = nxt_port_new(task, 0, 0, init->type); - if (nxt_slow_path(port == NULL)) { - return NXT_ERROR; - } + port = nxt_port_new(task, 0, 0, init->type); + if (nxt_slow_path(port == NULL)) { + return NXT_ERROR; + } - nxt_process_port_add(task, process, port); + nxt_process_port_add(task, process, port); - ret = nxt_port_socket_init(task, port, 0); - if (nxt_slow_path(ret != NXT_OK)) { - goto free_port; - } + ret = nxt_port_socket_init(task, port, 0); + if (nxt_slow_path(ret != NXT_OK)) { + goto free_port; + } - tmp_mp = nxt_mp_create(1024, 128, 256, 32); - if (nxt_slow_path(tmp_mp == NULL)) { - ret = NXT_ERROR; + tmp_mp = nxt_mp_create(1024, 128, 256, 32); + if (nxt_slow_path(tmp_mp == NULL)) { + ret = NXT_ERROR; - goto close_port; - } + goto close_port; + } - if (init->prefork) { - ret = init->prefork(task, process, tmp_mp); - if (nxt_slow_path(ret != NXT_OK)) { - goto free_mempool; - } + if (init->prefork) { + ret = init->prefork(task, process, tmp_mp); + if (nxt_slow_path(ret != NXT_OK)) { + goto free_mempool; } + } - pid = nxt_process_create(task, process); + pid = nxt_process_create(task, process); - switch (pid) { + switch (pid) { - case -1: - ret = NXT_ERROR; - break; + case -1: + ret = NXT_ERROR; + break; - case 0: - /* The child process: return to the event engine work queue loop. */ + case 0: + /* The child process: return to the event engine work queue loop. */ - nxt_process_use(task, process, -1); + nxt_process_use(task, process, -1); - ret = NXT_AGAIN; - break; + ret = NXT_AGAIN; + break; - default: - /* The parent process created a new process. */ + default: + /* The parent process created a new process. */ - nxt_process_use(task, process, -1); + nxt_process_use(task, process, -1); - nxt_port_read_close(port); - nxt_port_write_enable(task, port); + nxt_port_read_close(port); + nxt_port_write_enable(task, port); - ret = NXT_OK; - break; - } + ret = NXT_OK; + break; + } free_mempool: - nxt_mp_destroy(tmp_mp); + nxt_mp_destroy(tmp_mp); close_port: - if (nxt_slow_path(ret == NXT_ERROR)) { - nxt_port_close(task, port); - } + if (nxt_slow_path(ret == NXT_ERROR)) { + nxt_port_close(task, port); + } free_port: - nxt_port_use(task, port, -1); + nxt_port_use(task, port, -1); - return ret; + return ret; } +static nxt_int_t nxt_process_child_fixup(nxt_task_t *task, + nxt_process_t *process) { + nxt_process_t *p; + nxt_runtime_t *rt; + nxt_process_init_t *init; + nxt_process_type_t ptype; -static nxt_int_t -nxt_process_child_fixup(nxt_task_t *task, nxt_process_t *process) -{ - nxt_process_t *p; - nxt_runtime_t *rt; - nxt_process_init_t *init; - nxt_process_type_t ptype; - - init = nxt_process_init(process); - - nxt_ppid = nxt_pid; - - nxt_pid = getpid(); + init = nxt_process_init(process); - process->pid = nxt_pid; - process->isolated_pid = nxt_pid; + nxt_ppid = nxt_pid; - /* Clean inherited cached thread tid. */ - task->thread->tid = 0; + nxt_pid = getpid(); - ptype = init->type; + process->pid = nxt_pid; + process->isolated_pid = nxt_pid; - nxt_port_reset_next_id(); + /* Clean inherited cached thread tid. */ + task->thread->tid = 0; - nxt_event_engine_thread_adopt(task->thread->engine); + ptype = init->type; - rt = task->thread->runtime; + nxt_port_reset_next_id(); - /* Remove not ready processes. */ - nxt_runtime_process_each(rt, p) { + nxt_event_engine_thread_adopt(task->thread->engine); - if (nxt_proc_keep_matrix[ptype][nxt_process_type(p)] == 0 - && p->pid != nxt_ppid) /* Always keep parent's port. */ - { - nxt_debug(task, "remove not required process %PI", p->pid); + rt = task->thread->runtime; - nxt_process_close_ports(task, p); + /* Remove not ready processes. */ + nxt_runtime_process_each(rt, p) { - continue; - } + if (nxt_proc_keep_matrix[ptype][nxt_process_type(p)] == 0 && + p->pid != nxt_ppid) /* Always keep parent's port. */ + { + nxt_debug(task, "remove not required process %PI", p->pid); - if (p->state != NXT_PROCESS_STATE_READY) { - nxt_debug(task, "remove not ready process %PI", p->pid); + nxt_process_close_ports(task, p); - nxt_process_close_ports(task, p); + continue; + } - continue; - } + if (p->state != NXT_PROCESS_STATE_READY) { + nxt_debug(task, "remove not ready process %PI", p->pid); - nxt_port_mmaps_destroy(&p->incoming, 0); + nxt_process_close_ports(task, p); - } nxt_runtime_process_loop; + continue; + } - if (init->siblings != NULL) { - nxt_queue_each(p, init->siblings, nxt_process_t, link) { + nxt_port_mmaps_destroy(&p->incoming, 0); + } + nxt_runtime_process_loop; - nxt_debug(task, "remove sibling process %PI", p->pid); + if (init->siblings != NULL) { + nxt_queue_each(p, init->siblings, nxt_process_t, link) { - nxt_process_close_ports(task, p); + nxt_debug(task, "remove sibling process %PI", p->pid); - } nxt_queue_loop; + nxt_process_close_ports(task, p); } + nxt_queue_loop; + } - return NXT_OK; + return NXT_OK; } - #if (NXT_HAVE_LINUX_NS) -static nxt_int_t -nxt_process_pipe_timer(nxt_fd_t fd, short event) -{ - int ret; - sigset_t mask; - struct pollfd pfd; - - static const struct timespec ts = { .tv_sec = 5 }; - - /* - * Temporarily block the signals we are handling, (except - * for SIGINT & SIGTERM) so that ppoll(2) doesn't get - * interrupted. After ppoll(2) returns, our old sigmask - * will be back in effect and any pending signals will be - * delivered. - * - * This is because while the kernel ppoll syscall updates - * the struct timespec with the time remaining if it got - * interrupted with EINTR, the glibc wrapper hides this - * from us so we have no way of knowing how long to retry - * the ppoll(2) for and if we just retry with the same - * timeout we could find ourselves in an infinite loop. - */ - pthread_sigmask(SIG_SETMASK, NULL, &mask); - sigdelset(&mask, SIGINT); - sigdelset(&mask, SIGTERM); - - pfd.fd = fd; - pfd.events = event; - - ret = ppoll(&pfd, 1, &ts, &mask); - if (ret <= 0 || (ret == 1 && pfd.revents & POLLERR)) { - return NXT_ERROR; - } +static nxt_int_t nxt_process_pipe_timer(nxt_fd_t fd, short event) { + int ret; + sigset_t mask; + struct pollfd pfd; + + static const struct timespec ts = {.tv_sec = 5}; + + /* + * Temporarily block the signals we are handling, (except + * for SIGINT & SIGTERM) so that ppoll(2) doesn't get + * interrupted. After ppoll(2) returns, our old sigmask + * will be back in effect and any pending signals will be + * delivered. + * + * This is because while the kernel ppoll syscall updates + * the struct timespec with the time remaining if it got + * interrupted with EINTR, the glibc wrapper hides this + * from us so we have no way of knowing how long to retry + * the ppoll(2) for and if we just retry with the same + * timeout we could find ourselves in an infinite loop. + */ + pthread_sigmask(SIG_SETMASK, NULL, &mask); + sigdelset(&mask, SIGINT); + sigdelset(&mask, SIGTERM); + + pfd.fd = fd; + pfd.events = event; + + ret = ppoll(&pfd, 1, &ts, &mask); + if (ret <= 0 || (ret == 1 && pfd.revents & POLLERR)) { + return NXT_ERROR; + } - return NXT_OK; + return NXT_OK; } +static nxt_int_t nxt_process_check_pid_status(const nxt_fd_t *gc_pipe) { + int8_t status = -1; + ssize_t ret; -static nxt_int_t -nxt_process_check_pid_status(const nxt_fd_t *gc_pipe) -{ - int8_t status = -1; - ssize_t ret; + close(gc_pipe[1]); - close(gc_pipe[1]); + ret = nxt_process_pipe_timer(gc_pipe[0], POLLIN); + if (ret == NXT_OK) { + read(gc_pipe[0], &status, sizeof(int8_t)); + } - ret = nxt_process_pipe_timer(gc_pipe[0], POLLIN); - if (ret == NXT_OK) { - read(gc_pipe[0], &status, sizeof(int8_t)); - } + close(gc_pipe[0]); - close(gc_pipe[0]); - - return status; + return status; } +static nxt_pid_t nxt_process_recv_pid(const nxt_fd_t *pid_pipe, + const nxt_fd_t *gc_pipe) { + int8_t status; + ssize_t ret; + nxt_pid_t pid; -static nxt_pid_t -nxt_process_recv_pid(const nxt_fd_t *pid_pipe, const nxt_fd_t *gc_pipe) -{ - int8_t status; - ssize_t ret; - nxt_pid_t pid; + close(pid_pipe[1]); + close(gc_pipe[0]); - close(pid_pipe[1]); - close(gc_pipe[0]); + status = 0; - status = 0; + ret = nxt_process_pipe_timer(pid_pipe[0], POLLIN); + if (ret == NXT_OK) { + ret = read(pid_pipe[0], &pid, sizeof(nxt_pid_t)); + } - ret = nxt_process_pipe_timer(pid_pipe[0], POLLIN); - if (ret == NXT_OK) { - ret = read(pid_pipe[0], &pid, sizeof(nxt_pid_t)); - } + if (ret <= 0) { + status = -1; + pid = -1; + } - if (ret <= 0) { - status = -1; - pid = -1; - } + write(gc_pipe[1], &status, sizeof(int8_t)); - write(gc_pipe[1], &status, sizeof(int8_t)); + close(pid_pipe[0]); + close(gc_pipe[1]); - close(pid_pipe[0]); - close(gc_pipe[1]); - - return pid; + return pid; } +static void nxt_process_send_pid(const nxt_fd_t *pid_pipe, nxt_pid_t pid) { + nxt_int_t ret; -static void -nxt_process_send_pid(const nxt_fd_t *pid_pipe, nxt_pid_t pid) -{ - nxt_int_t ret; - - close(pid_pipe[0]); + close(pid_pipe[0]); - ret = nxt_process_pipe_timer(pid_pipe[1], POLLOUT); - if (ret == NXT_OK) { - write(pid_pipe[1], &pid, sizeof(nxt_pid_t)); - } + ret = nxt_process_pipe_timer(pid_pipe[1], POLLOUT); + if (ret == NXT_OK) { + write(pid_pipe[1], &pid, sizeof(nxt_pid_t)); + } - close(pid_pipe[1]); + close(pid_pipe[1]); } +static nxt_int_t nxt_process_unshare(nxt_task_t *task, nxt_process_t *process, + nxt_fd_t *pid_pipe, nxt_fd_t *gc_pipe, + nxt_bool_t use_pidns) { + int ret; + nxt_pid_t pid; -static nxt_int_t -nxt_process_unshare(nxt_task_t *task, nxt_process_t *process, - nxt_fd_t *pid_pipe, nxt_fd_t *gc_pipe, - nxt_bool_t use_pidns) -{ - int ret; - nxt_pid_t pid; - - if (process->isolation.clone.flags == 0) { - return NXT_OK; - } - - ret = unshare(process->isolation.clone.flags); - if (nxt_slow_path(ret == -1)) { - nxt_alert(task, "unshare() failed for %s %E", process->name, - nxt_errno); + if (process->isolation.clone.flags == 0) { + return NXT_OK; + } - if (use_pidns) { - nxt_pipe_close(task, gc_pipe); - nxt_pipe_close(task, pid_pipe); - } + ret = unshare(process->isolation.clone.flags); + if (nxt_slow_path(ret == -1)) { + nxt_alert(task, "unshare() failed for %s %E", process->name, nxt_errno); - return NXT_ERROR; + if (use_pidns) { + nxt_pipe_close(task, gc_pipe); + nxt_pipe_close(task, pid_pipe); } - if (!use_pidns) { - return NXT_OK; - } + return NXT_ERROR; + } - /* - * PID namespace requested. Employ a double fork(2) technique - * so that the prototype process will be placed into the new - * namespace and end up with PID 1 (as before with clone). - */ - pid = fork(); - if (nxt_slow_path(pid < 0)) { - nxt_alert(task, "fork() failed for %s %E", process->name, nxt_errno); - nxt_pipe_close(task, gc_pipe); - nxt_pipe_close(task, pid_pipe); + if (!use_pidns) { + return NXT_OK; + } + + /* + * PID namespace requested. Employ a double fork(2) technique + * so that the prototype process will be placed into the new + * namespace and end up with PID 1 (as before with clone). + */ + pid = fork(); + if (nxt_slow_path(pid < 0)) { + nxt_alert(task, "fork() failed for %s %E", process->name, nxt_errno); + nxt_pipe_close(task, gc_pipe); + nxt_pipe_close(task, pid_pipe); - return NXT_ERROR; + return NXT_ERROR; - } else if (pid > 0) { - nxt_pipe_close(task, gc_pipe); - nxt_process_send_pid(pid_pipe, pid); + } else if (pid > 0) { + nxt_pipe_close(task, gc_pipe); + nxt_process_send_pid(pid_pipe, pid); - _exit(EXIT_SUCCESS); - } + _exit(EXIT_SUCCESS); + } - nxt_pipe_close(task, pid_pipe); - ret = nxt_process_check_pid_status(gc_pipe); - if (ret == -1) { - return NXT_ERROR; - } + nxt_pipe_close(task, pid_pipe); + ret = nxt_process_check_pid_status(gc_pipe); + if (ret == -1) { + return NXT_ERROR; + } - return NXT_OK; + return NXT_OK; } +static nxt_int_t nxt_process_init_pidns(nxt_task_t *task, + const nxt_process_t *process, + nxt_fd_t *pid_pipe, nxt_fd_t *gc_pipe, + nxt_bool_t *use_pidns) { + int ret; -static nxt_int_t -nxt_process_init_pidns(nxt_task_t *task, const nxt_process_t *process, - nxt_fd_t *pid_pipe, nxt_fd_t *gc_pipe, - nxt_bool_t *use_pidns) -{ - int ret; - - *use_pidns = 0; + *use_pidns = 0; #if (NXT_HAVE_CLONE_NEWPID) - *use_pidns = nxt_is_pid_isolated(process); + *use_pidns = nxt_is_pid_isolated(process); #endif - if (!*use_pidns) { - return NXT_OK; - } + if (!*use_pidns) { + return NXT_OK; + } - ret = nxt_pipe_create(task, pid_pipe, 0, 0); - if (nxt_slow_path(ret == NXT_ERROR)) { - return NXT_ERROR; - } + ret = nxt_pipe_create(task, pid_pipe, 0, 0); + if (nxt_slow_path(ret == NXT_ERROR)) { + return NXT_ERROR; + } - ret = nxt_pipe_create(task, gc_pipe, 0, 0); - if (nxt_slow_path(ret == NXT_ERROR)) { - return NXT_ERROR; - } + ret = nxt_pipe_create(task, gc_pipe, 0, 0); + if (nxt_slow_path(ret == NXT_ERROR)) { + return NXT_ERROR; + } #if (NXT_HAVE_PR_SET_CHILD_SUBREAPER) - ret = prctl(PR_SET_CHILD_SUBREAPER, 1, 0, 0, 0); - if (nxt_slow_path(ret == -1)) { - nxt_alert(task, "prctl(PR_SET_CHILD_SUBREAPER) failed for %s %E", - process->name, nxt_errno); - } + ret = prctl(PR_SET_CHILD_SUBREAPER, 1, 0, 0, 0); + if (nxt_slow_path(ret == -1)) { + nxt_alert(task, "prctl(PR_SET_CHILD_SUBREAPER) failed for %s %E", + process->name, nxt_errno); + } #endif - return NXT_OK; + return NXT_OK; } #endif /* NXT_HAVE_LINUX_NS */ - -static nxt_pid_t -nxt_process_create(nxt_task_t *task, nxt_process_t *process) -{ - nxt_int_t ret; - nxt_pid_t pid; - nxt_runtime_t *rt; +static nxt_pid_t nxt_process_create(nxt_task_t *task, nxt_process_t *process) { + nxt_int_t ret; + nxt_pid_t pid; + nxt_runtime_t *rt; #if (NXT_HAVE_LINUX_NS) - nxt_fd_t pid_pipe[2], gc_pipe[2]; - nxt_bool_t use_pidns; + nxt_fd_t pid_pipe[2], gc_pipe[2]; + nxt_bool_t use_pidns; - ret = nxt_process_init_pidns(task, process, pid_pipe, gc_pipe, &use_pidns); - if (ret == NXT_ERROR) { - return -1; - } + ret = nxt_process_init_pidns(task, process, pid_pipe, gc_pipe, &use_pidns); + if (ret == NXT_ERROR) { + return -1; + } #endif - pid = fork(); - if (nxt_slow_path(pid < 0)) { - nxt_alert(task, "fork() failed for %s %E", process->name, nxt_errno); - return pid; - } + pid = fork(); + if (nxt_slow_path(pid < 0)) { + nxt_alert(task, "fork() failed for %s %E", process->name, nxt_errno); + return pid; + } - if (pid == 0) { - /* Child. */ + if (pid == 0) { + /* Child. */ #if (NXT_HAVE_LINUX_NS) - ret = nxt_process_unshare(task, process, pid_pipe, gc_pipe, use_pidns); - if (ret == NXT_ERROR) { - _exit(EXIT_FAILURE); - } + ret = nxt_process_unshare(task, process, pid_pipe, gc_pipe, use_pidns); + if (ret == NXT_ERROR) { + _exit(EXIT_FAILURE); + } #endif - ret = nxt_process_child_fixup(task, process); - if (nxt_slow_path(ret != NXT_OK)) { - nxt_process_quit(task, 1); - return -1; - } - - ret = nxt_process_setup(task, process); - if (nxt_slow_path(ret != NXT_OK)) { - nxt_process_quit(task, 1); - } - - /* - * Explicitly return 0 to notice the caller function this is the child. - * The caller must return to the event engine work queue loop. - */ - return 0; + ret = nxt_process_child_fixup(task, process); + if (nxt_slow_path(ret != NXT_OK)) { + nxt_process_quit(task, 1); + return -1; + } + + ret = nxt_process_setup(task, process); + if (nxt_slow_path(ret != NXT_OK)) { + nxt_process_quit(task, 1); } - /* Parent. */ + /* + * Explicitly return 0 to notice the caller function this is the child. + * The caller must return to the event engine work queue loop. + */ + return 0; + } + + /* Parent. */ - nxt_debug(task, "fork(%s): %PI", process->name, pid); + nxt_debug(task, "fork(%s): %PI", process->name, pid); #if (NXT_HAVE_LINUX_NS) - if (use_pidns) { - pid = nxt_process_recv_pid(pid_pipe, gc_pipe); - if (pid == -1) { - return pid; - } + if (use_pidns) { + pid = nxt_process_recv_pid(pid_pipe, gc_pipe); + if (pid == -1) { + return pid; } + } #endif - process->pid = pid; - process->isolated_pid = pid; + process->pid = pid; + process->isolated_pid = pid; - rt = task->thread->runtime; + rt = task->thread->runtime; - if (rt->is_pid_isolated) { - /* - * Do not register process in runtime with isolated pid. - * Only global pid can be the key to avoid clash. - */ - nxt_assert(!nxt_queue_is_empty(&process->ports)); + if (rt->is_pid_isolated) { + /* + * Do not register process in runtime with isolated pid. + * Only global pid can be the key to avoid clash. + */ + nxt_assert(!nxt_queue_is_empty(&process->ports)); - nxt_port_use(task, nxt_process_port_first(process), 1); + nxt_port_use(task, nxt_process_port_first(process), 1); - } else { - nxt_runtime_process_add(task, process); - } + } else { + nxt_runtime_process_add(task, process); + } #if (NXT_HAVE_CGROUP) - ret = nxt_cgroup_proc_add(task, process); - if (nxt_slow_path(ret != NXT_OK)) { - nxt_alert(task, "cgroup: failed to add process %s to %s %E", - process->name, process->isolation.cgroup.path, nxt_errno); - nxt_cgroup_cleanup(task, process); - kill(pid, SIGTERM); - return -1; - } + ret = nxt_cgroup_proc_add(task, process); + if (nxt_slow_path(ret != NXT_OK)) { + nxt_alert(task, "cgroup: failed to add process %s to %s %E", process->name, + process->isolation.cgroup.path, nxt_errno); + nxt_cgroup_cleanup(task, process); + kill(pid, SIGTERM); + return -1; + } #endif - return pid; + return pid; } +static nxt_int_t nxt_process_setup(nxt_task_t *task, nxt_process_t *process) { + nxt_int_t ret; + nxt_thread_t *thread; + nxt_runtime_t *rt; + nxt_process_init_t *init; + nxt_event_engine_t *engine; + const nxt_event_interface_t *interface; -static nxt_int_t -nxt_process_setup(nxt_task_t *task, nxt_process_t *process) -{ - nxt_int_t ret; - nxt_thread_t *thread; - nxt_runtime_t *rt; - nxt_process_init_t *init; - nxt_event_engine_t *engine; - const nxt_event_interface_t *interface; + init = nxt_process_init(process); - init = nxt_process_init(process); + nxt_debug(task, "%s setup", process->name); - nxt_debug(task, "%s setup", process->name); + nxt_process_title(task, "unit: %s", process->name); - nxt_process_title(task, "unit: %s", process->name); + thread = task->thread; + rt = thread->runtime; - thread = task->thread; - rt = thread->runtime; + if (process->parent_port == rt->port_by_type[NXT_PROCESS_PROTOTYPE]) { + nxt_app_set_logs(); + } - if (process->parent_port == rt->port_by_type[NXT_PROCESS_PROTOTYPE]) { - nxt_app_set_logs(); - } + nxt_random_init(&thread->random); - nxt_random_init(&thread->random); + rt->type = init->type; - rt->type = init->type; + engine = thread->engine; - engine = thread->engine; + /* Update inherited main process event engine and signals processing. */ + engine->signals->sigev = init->signals; - /* Update inherited main process event engine and signals processing. */ - engine->signals->sigev = init->signals; + interface = nxt_service_get(rt->services, "engine", rt->engine); + if (nxt_slow_path(interface == NULL)) { + return NXT_ERROR; + } - interface = nxt_service_get(rt->services, "engine", rt->engine); - if (nxt_slow_path(interface == NULL)) { - return NXT_ERROR; - } + if (nxt_event_engine_change(engine, interface, rt->batch) != NXT_OK) { + return NXT_ERROR; + } - if (nxt_event_engine_change(engine, interface, rt->batch) != NXT_OK) { - return NXT_ERROR; - } + ret = nxt_runtime_thread_pool_create(thread, rt, rt->auxiliary_threads, + 60000 * 1000000LL); + if (nxt_slow_path(ret != NXT_OK)) { + return NXT_ERROR; + } - ret = nxt_runtime_thread_pool_create(thread, rt, rt->auxiliary_threads, - 60000 * 1000000LL); - if (nxt_slow_path(ret != NXT_OK)) { - return NXT_ERROR; - } + nxt_port_read_close(process->parent_port); + nxt_port_write_enable(task, process->parent_port); - nxt_port_read_close(process->parent_port); - nxt_port_write_enable(task, process->parent_port); + /* + * If the parent process is already isolated, rt->pid_isolation is already + * set to 1 at this point. + */ + if (nxt_is_pid_isolated(process)) { + rt->is_pid_isolated = 1; + } - /* - * If the parent process is already isolated, rt->pid_isolation is already - * set to 1 at this point. - */ - if (nxt_is_pid_isolated(process)) { - rt->is_pid_isolated = 1; - } + if (rt->is_pid_isolated || + process->parent_port != rt->port_by_type[NXT_PROCESS_MAIN]) { + ret = nxt_process_whoami(task, process); - if (rt->is_pid_isolated - || process->parent_port != rt->port_by_type[NXT_PROCESS_MAIN]) - { - ret = nxt_process_whoami(task, process); + } else { + ret = nxt_process_do_start(task, process); + } - } else { - ret = nxt_process_do_start(task, process); - } - - return ret; + return ret; } +static nxt_int_t nxt_process_do_start(nxt_task_t *task, + nxt_process_t *process) { + nxt_int_t ret; + nxt_port_t *port; + nxt_process_init_t *init; -static nxt_int_t -nxt_process_do_start(nxt_task_t *task, nxt_process_t *process) -{ - nxt_int_t ret; - nxt_port_t *port; - nxt_process_init_t *init; - - nxt_runtime_process_add(task, process); + nxt_runtime_process_add(task, process); - init = nxt_process_init(process); - port = nxt_process_port_first(process); + init = nxt_process_init(process); + port = nxt_process_port_first(process); - nxt_port_enable(task, port, init->port_handlers); + nxt_port_enable(task, port, init->port_handlers); - ret = init->setup(task, process); - if (nxt_slow_path(ret != NXT_OK)) { - return NXT_ERROR; - } + ret = init->setup(task, process); + if (nxt_slow_path(ret != NXT_OK)) { + return NXT_ERROR; + } - switch (process->state) { + switch (process->state) { - case NXT_PROCESS_STATE_CREATED: - ret = nxt_process_send_created(task, process); - break; + case NXT_PROCESS_STATE_CREATED: + ret = nxt_process_send_created(task, process); + break; - case NXT_PROCESS_STATE_READY: - ret = nxt_process_send_ready(task, process); + case NXT_PROCESS_STATE_READY: + ret = nxt_process_send_ready(task, process); - if (nxt_slow_path(ret != NXT_OK)) { - break; - } + if (nxt_slow_path(ret != NXT_OK)) { + break; + } - ret = init->start(task, &process->data); + ret = init->start(task, &process->data); - nxt_port_write_close(port); + nxt_port_write_close(port); - break; + break; - default: - nxt_assert(0); - } + default: + nxt_assert(0); + } - if (nxt_slow_path(ret != NXT_OK)) { - nxt_alert(task, "%s failed to start", process->name); - } + if (nxt_slow_path(ret != NXT_OK)) { + nxt_alert(task, "%s failed to start", process->name); + } - return ret; + return ret; } +static nxt_int_t nxt_process_whoami(nxt_task_t *task, nxt_process_t *process) { + uint32_t stream; + nxt_fd_t fd; + nxt_buf_t *buf; + nxt_int_t ret; + nxt_port_t *my_port, *main_port; + nxt_runtime_t *rt; -static nxt_int_t -nxt_process_whoami(nxt_task_t *task, nxt_process_t *process) -{ - uint32_t stream; - nxt_fd_t fd; - nxt_buf_t *buf; - nxt_int_t ret; - nxt_port_t *my_port, *main_port; - nxt_runtime_t *rt; - - rt = task->thread->runtime; + rt = task->thread->runtime; - my_port = nxt_process_port_first(process); - main_port = rt->port_by_type[NXT_PROCESS_MAIN]; + my_port = nxt_process_port_first(process); + main_port = rt->port_by_type[NXT_PROCESS_MAIN]; - nxt_assert(my_port != NULL && main_port != NULL); + nxt_assert(my_port != NULL && main_port != NULL); - nxt_port_enable(task, my_port, &nxt_process_whoami_port_handlers); + nxt_port_enable(task, my_port, &nxt_process_whoami_port_handlers); - buf = nxt_buf_mem_alloc(main_port->mem_pool, sizeof(nxt_pid_t), 0); - if (nxt_slow_path(buf == NULL)) { - return NXT_ERROR; - } + buf = nxt_buf_mem_alloc(main_port->mem_pool, sizeof(nxt_pid_t), 0); + if (nxt_slow_path(buf == NULL)) { + return NXT_ERROR; + } - buf->mem.free = nxt_cpymem(buf->mem.free, &nxt_ppid, sizeof(nxt_pid_t)); + buf->mem.free = nxt_cpymem(buf->mem.free, &nxt_ppid, sizeof(nxt_pid_t)); - stream = nxt_port_rpc_register_handler(task, my_port, - nxt_process_whoami_ok, - nxt_process_whoami_error, - main_port->pid, process); - if (nxt_slow_path(stream == 0)) { - nxt_mp_free(main_port->mem_pool, buf); + stream = nxt_port_rpc_register_handler(task, my_port, nxt_process_whoami_ok, + nxt_process_whoami_error, + main_port->pid, process); + if (nxt_slow_path(stream == 0)) { + nxt_mp_free(main_port->mem_pool, buf); - return NXT_ERROR; - } + return NXT_ERROR; + } - fd = (process->parent_port != main_port) ? my_port->pair[1] : -1; + fd = (process->parent_port != main_port) ? my_port->pair[1] : -1; - ret = nxt_port_socket_write(task, main_port, NXT_PORT_MSG_WHOAMI, - fd, stream, my_port->id, buf); + ret = nxt_port_socket_write(task, main_port, NXT_PORT_MSG_WHOAMI, fd, stream, + my_port->id, buf); - if (nxt_slow_path(ret != NXT_OK)) { - nxt_alert(task, "%s failed to send WHOAMI message", process->name); - nxt_port_rpc_cancel(task, my_port, stream); - nxt_mp_free(main_port->mem_pool, buf); + if (nxt_slow_path(ret != NXT_OK)) { + nxt_alert(task, "%s failed to send WHOAMI message", process->name); + nxt_port_rpc_cancel(task, my_port, stream); + nxt_mp_free(main_port->mem_pool, buf); - return NXT_ERROR; - } + return NXT_ERROR; + } - return NXT_OK; + return NXT_OK; } +static void nxt_process_whoami_ok(nxt_task_t *task, nxt_port_recv_msg_t *msg, + void *data) { + nxt_pid_t pid, isolated_pid; + nxt_buf_t *buf; + nxt_port_t *port; + nxt_process_t *process; + nxt_runtime_t *rt; -static void -nxt_process_whoami_ok(nxt_task_t *task, nxt_port_recv_msg_t *msg, void *data) -{ - nxt_pid_t pid, isolated_pid; - nxt_buf_t *buf; - nxt_port_t *port; - nxt_process_t *process; - nxt_runtime_t *rt; + process = data; - process = data; + buf = msg->buf; - buf = msg->buf; + nxt_assert(nxt_buf_used_size(buf) == sizeof(nxt_pid_t)); - nxt_assert(nxt_buf_used_size(buf) == sizeof(nxt_pid_t)); + nxt_memcpy(&pid, buf->mem.pos, sizeof(nxt_pid_t)); - nxt_memcpy(&pid, buf->mem.pos, sizeof(nxt_pid_t)); + isolated_pid = nxt_pid; - isolated_pid = nxt_pid; + if (isolated_pid != pid) { + nxt_pid = pid; + process->pid = pid; - if (isolated_pid != pid) { - nxt_pid = pid; - process->pid = pid; + nxt_process_port_each(process, port) { port->pid = pid; } + nxt_process_port_loop; + } - nxt_process_port_each(process, port) { - port->pid = pid; - } nxt_process_port_loop; - } + rt = task->thread->runtime; - rt = task->thread->runtime; + if (process->parent_port != rt->port_by_type[NXT_PROCESS_MAIN]) { + port = process->parent_port; - if (process->parent_port != rt->port_by_type[NXT_PROCESS_MAIN]) { - port = process->parent_port; + (void)nxt_port_socket_write(task, port, NXT_PORT_MSG_PROCESS_CREATED, -1, 0, + 0, NULL); - (void) nxt_port_socket_write(task, port, NXT_PORT_MSG_PROCESS_CREATED, - -1, 0, 0, NULL); - - nxt_log(task, NXT_LOG_INFO, "%s started", process->name); - } + nxt_log(task, NXT_LOG_INFO, "%s started", process->name); + } - if (nxt_slow_path(nxt_process_do_start(task, process) != NXT_OK)) { - nxt_process_quit(task, 1); - } + if (nxt_slow_path(nxt_process_do_start(task, process) != NXT_OK)) { + nxt_process_quit(task, 1); + } } +static void nxt_process_whoami_error(nxt_task_t *task, nxt_port_recv_msg_t *msg, + void *data) { + nxt_alert(task, "WHOAMI error"); -static void -nxt_process_whoami_error(nxt_task_t *task, nxt_port_recv_msg_t *msg, void *data) -{ - nxt_alert(task, "WHOAMI error"); - - nxt_process_quit(task, 1); + nxt_process_quit(task, 1); } +static nxt_int_t nxt_process_send_created(nxt_task_t *task, + nxt_process_t *process) { + uint32_t stream; + nxt_int_t ret; + nxt_port_t *my_port, *main_port; + nxt_runtime_t *rt; -static nxt_int_t -nxt_process_send_created(nxt_task_t *task, nxt_process_t *process) -{ - uint32_t stream; - nxt_int_t ret; - nxt_port_t *my_port, *main_port; - nxt_runtime_t *rt; - - nxt_assert(process->state == NXT_PROCESS_STATE_CREATED); + nxt_assert(process->state == NXT_PROCESS_STATE_CREATED); - rt = task->thread->runtime; + rt = task->thread->runtime; - my_port = nxt_process_port_first(process); - main_port = rt->port_by_type[NXT_PROCESS_MAIN]; + my_port = nxt_process_port_first(process); + main_port = rt->port_by_type[NXT_PROCESS_MAIN]; - nxt_assert(my_port != NULL && main_port != NULL); + nxt_assert(my_port != NULL && main_port != NULL); - stream = nxt_port_rpc_register_handler(task, my_port, - nxt_process_created_ok, - nxt_process_created_error, - main_port->pid, process); + stream = nxt_port_rpc_register_handler(task, my_port, nxt_process_created_ok, + nxt_process_created_error, + main_port->pid, process); - if (nxt_slow_path(stream == 0)) { - return NXT_ERROR; - } + if (nxt_slow_path(stream == 0)) { + return NXT_ERROR; + } - ret = nxt_port_socket_write(task, main_port, NXT_PORT_MSG_PROCESS_CREATED, - -1, stream, my_port->id, NULL); + ret = nxt_port_socket_write(task, main_port, NXT_PORT_MSG_PROCESS_CREATED, -1, + stream, my_port->id, NULL); - if (nxt_slow_path(ret != NXT_OK)) { - nxt_alert(task, "%s failed to send CREATED message", process->name); - nxt_port_rpc_cancel(task, my_port, stream); - return NXT_ERROR; - } + if (nxt_slow_path(ret != NXT_OK)) { + nxt_alert(task, "%s failed to send CREATED message", process->name); + nxt_port_rpc_cancel(task, my_port, stream); + return NXT_ERROR; + } - nxt_debug(task, "%s created", process->name); + nxt_debug(task, "%s created", process->name); - return NXT_OK; + return NXT_OK; } +static void nxt_process_created_ok(nxt_task_t *task, nxt_port_recv_msg_t *msg, + void *data) { + nxt_int_t ret; + nxt_process_t *process; + nxt_process_init_t *init; -static void -nxt_process_created_ok(nxt_task_t *task, nxt_port_recv_msg_t *msg, void *data) -{ - nxt_int_t ret; - nxt_process_t *process; - nxt_process_init_t *init; - - process = data; + process = data; - process->state = NXT_PROCESS_STATE_READY; + process->state = NXT_PROCESS_STATE_READY; - init = nxt_process_init(process); + init = nxt_process_init(process); - ret = nxt_process_apply_creds(task, process); - if (nxt_slow_path(ret != NXT_OK)) { - goto fail; - } + ret = nxt_process_apply_creds(task, process); + if (nxt_slow_path(ret != NXT_OK)) { + goto fail; + } - nxt_log(task, NXT_LOG_INFO, "%s started", process->name); + nxt_log(task, NXT_LOG_INFO, "%s started", process->name); - ret = nxt_process_send_ready(task, process); - if (nxt_slow_path(ret != NXT_OK)) { - goto fail; - } + ret = nxt_process_send_ready(task, process); + if (nxt_slow_path(ret != NXT_OK)) { + goto fail; + } - ret = init->start(task, &process->data); + ret = init->start(task, &process->data); - if (nxt_process_type(process) != NXT_PROCESS_PROTOTYPE) { - nxt_port_write_close(nxt_process_port_first(process)); - } + if (nxt_process_type(process) != NXT_PROCESS_PROTOTYPE) { + nxt_port_write_close(nxt_process_port_first(process)); + } - if (nxt_fast_path(ret == NXT_OK)) { - return; - } + if (nxt_fast_path(ret == NXT_OK)) { + return; + } fail: - nxt_process_quit(task, 1); + nxt_process_quit(task, 1); } +static void nxt_process_created_error(nxt_task_t *task, + nxt_port_recv_msg_t *msg, void *data) { + nxt_process_t *process; + nxt_process_init_t *init; -static void -nxt_process_created_error(nxt_task_t *task, nxt_port_recv_msg_t *msg, - void *data) -{ - nxt_process_t *process; - nxt_process_init_t *init; - - process = data; - init = nxt_process_init(process); + process = data; + init = nxt_process_init(process); - nxt_alert(task, "%s failed to start", init->name); + nxt_alert(task, "%s failed to start", init->name); - nxt_process_quit(task, 1); + nxt_process_quit(task, 1); } +nxt_int_t nxt_process_core_setup(nxt_task_t *task, nxt_process_t *process) { + nxt_int_t ret; -nxt_int_t -nxt_process_core_setup(nxt_task_t *task, nxt_process_t *process) -{ - nxt_int_t ret; - - ret = nxt_process_apply_creds(task, process); - if (nxt_slow_path(ret != NXT_OK)) { - return NXT_ERROR; - } + ret = nxt_process_apply_creds(task, process); + if (nxt_slow_path(ret != NXT_OK)) { + return NXT_ERROR; + } - process->state = NXT_PROCESS_STATE_READY; + process->state = NXT_PROCESS_STATE_READY; - return NXT_OK; + return NXT_OK; } +nxt_int_t nxt_process_creds_set(nxt_task_t *task, nxt_process_t *process, + nxt_str_t *user, nxt_str_t *group) { + char *str; -nxt_int_t -nxt_process_creds_set(nxt_task_t *task, nxt_process_t *process, nxt_str_t *user, - nxt_str_t *group) -{ - char *str; - - process->user_cred = nxt_mp_zalloc(process->mem_pool, - sizeof(nxt_credential_t)); + process->user_cred = + nxt_mp_zalloc(process->mem_pool, sizeof(nxt_credential_t)); - if (nxt_slow_path(process->user_cred == NULL)) { - return NXT_ERROR; - } + if (nxt_slow_path(process->user_cred == NULL)) { + return NXT_ERROR; + } - str = nxt_mp_zalloc(process->mem_pool, user->length + 1); - if (nxt_slow_path(str == NULL)) { - return NXT_ERROR; - } + str = nxt_mp_zalloc(process->mem_pool, user->length + 1); + if (nxt_slow_path(str == NULL)) { + return NXT_ERROR; + } - nxt_memcpy(str, user->start, user->length); - str[user->length] = '\0'; + nxt_memcpy(str, user->start, user->length); + str[user->length] = '\0'; - process->user_cred->user = str; + process->user_cred->user = str; - if (group->start != NULL) { - str = nxt_mp_zalloc(process->mem_pool, group->length + 1); - if (nxt_slow_path(str == NULL)) { - return NXT_ERROR; - } + if (group->start != NULL) { + str = nxt_mp_zalloc(process->mem_pool, group->length + 1); + if (nxt_slow_path(str == NULL)) { + return NXT_ERROR; + } - nxt_memcpy(str, group->start, group->length); - str[group->length] = '\0'; + nxt_memcpy(str, group->start, group->length); + str[group->length] = '\0'; - } else { - str = NULL; - } + } else { + str = NULL; + } - return nxt_credential_get(task, process->mem_pool, process->user_cred, str); + return nxt_credential_get(task, process->mem_pool, process->user_cred, str); } +nxt_int_t nxt_process_apply_creds(nxt_task_t *task, nxt_process_t *process) { + nxt_int_t ret, cap_setid; + nxt_runtime_t *rt; -nxt_int_t -nxt_process_apply_creds(nxt_task_t *task, nxt_process_t *process) -{ - nxt_int_t ret, cap_setid; - nxt_runtime_t *rt; - - rt = task->thread->runtime; + rt = task->thread->runtime; - cap_setid = rt->capabilities.setid; + cap_setid = rt->capabilities.setid; #if (NXT_HAVE_LINUX_NS && NXT_HAVE_CLONE_NEWUSER) - if (!cap_setid - && nxt_is_clone_flag_set(process->isolation.clone.flags, NEWUSER)) - { - cap_setid = 1; - } + if (!cap_setid && + nxt_is_clone_flag_set(process->isolation.clone.flags, NEWUSER)) { + cap_setid = 1; + } #endif - if (cap_setid) { - ret = nxt_credential_setgids(task, process->user_cred); - if (nxt_slow_path(ret != NXT_OK)) { - return NXT_ERROR; - } + if (cap_setid) { + ret = nxt_credential_setgids(task, process->user_cred); + if (nxt_slow_path(ret != NXT_OK)) { + return NXT_ERROR; + } - ret = nxt_credential_setuid(task, process->user_cred); - if (nxt_slow_path(ret != NXT_OK)) { - return NXT_ERROR; - } + ret = nxt_credential_setuid(task, process->user_cred); + if (nxt_slow_path(ret != NXT_OK)) { + return NXT_ERROR; } + } #if (NXT_HAVE_PR_SET_NO_NEW_PRIVS) - if (nxt_slow_path(process->isolation.new_privs == 0 - && prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0) != 0)) - { - nxt_alert(task, "failed to set no_new_privs %E", nxt_errno); - return NXT_ERROR; - } + if (nxt_slow_path(process->isolation.new_privs == 0 && + prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0) != 0)) { + nxt_alert(task, "failed to set no_new_privs %E", nxt_errno); + return NXT_ERROR; + } #endif - return NXT_OK; + return NXT_OK; } +static nxt_int_t nxt_process_send_ready(nxt_task_t *task, + nxt_process_t *process) { + nxt_int_t ret; -static nxt_int_t -nxt_process_send_ready(nxt_task_t *task, nxt_process_t *process) -{ - nxt_int_t ret; - - ret = nxt_port_socket_write(task, process->parent_port, - NXT_PORT_MSG_PROCESS_READY, - -1, process->stream, 0, NULL); + ret = nxt_port_socket_write(task, process->parent_port, + NXT_PORT_MSG_PROCESS_READY, -1, process->stream, + 0, NULL); - if (nxt_slow_path(ret != NXT_OK)) { - nxt_alert(task, "%s failed to send READY message", process->name); - return NXT_ERROR; - } + if (nxt_slow_path(ret != NXT_OK)) { + nxt_alert(task, "%s failed to send READY message", process->name); + return NXT_ERROR; + } - nxt_debug(task, "%s sent ready", process->name); + nxt_debug(task, "%s sent ready", process->name); - return NXT_OK; + return NXT_OK; } - /* * Linux glibc 2.2 posix_spawn() is implemented via fork()/execve(). * Linux glibc 2.4 posix_spawn() without file actions and spawn @@ -1093,184 +1007,165 @@ nxt_process_send_ready(nxt_task_t *task, nxt_process_t *process) * as syscall. */ -nxt_pid_t -nxt_process_execute(nxt_task_t *task, char *name, char **argv, char **envp) -{ - nxt_pid_t pid; +nxt_pid_t nxt_process_execute(nxt_task_t *task, char *name, char **argv, + char **envp) { + nxt_pid_t pid; - nxt_debug(task, "posix_spawn(\"%s\")", name); + nxt_debug(task, "posix_spawn(\"%s\")", name); - if (posix_spawn(&pid, name, NULL, NULL, argv, envp) != 0) { - nxt_alert(task, "posix_spawn(\"%s\") failed %E", name, nxt_errno); - return -1; - } + if (posix_spawn(&pid, name, NULL, NULL, argv, envp) != 0) { + nxt_alert(task, "posix_spawn(\"%s\") failed %E", name, nxt_errno); + return -1; + } - return pid; + return pid; } +nxt_int_t nxt_process_daemon(nxt_task_t *task) { + nxt_fd_t fd; + nxt_pid_t pid; + const char *msg; -nxt_int_t -nxt_process_daemon(nxt_task_t *task) -{ - nxt_fd_t fd; - nxt_pid_t pid; - const char *msg; + fd = -1; - fd = -1; - - /* - * fork() followed by a parent process's exit() detaches a child process - * from an init script or terminal shell process which has started the - * parent process and allows the child process to run in background. - */ + /* + * fork() followed by a parent process's exit() detaches a child process + * from an init script or terminal shell process which has started the + * parent process and allows the child process to run in background. + */ - pid = fork(); + pid = fork(); - switch (pid) { + switch (pid) { - case -1: - msg = "fork() failed %E"; - goto fail; + case -1: + msg = "fork() failed %E"; + goto fail; - case 0: - /* A child. */ - break; + case 0: + /* A child. */ + break; - default: - /* A parent. */ - nxt_debug(task, "fork(): %PI", pid); - exit(0); - nxt_unreachable(); - } + default: + /* A parent. */ + nxt_debug(task, "fork(): %PI", pid); + exit(0); + nxt_unreachable(); + } - nxt_pid = getpid(); + nxt_pid = getpid(); - /* Clean inherited cached thread tid. */ - task->thread->tid = 0; + /* Clean inherited cached thread tid. */ + task->thread->tid = 0; - nxt_debug(task, "daemon"); + nxt_debug(task, "daemon"); - /* Detach from controlling terminal. */ + /* Detach from controlling terminal. */ - if (setsid() == -1) { - nxt_alert(task, "setsid() failed %E", nxt_errno); - return NXT_ERROR; - } + if (setsid() == -1) { + nxt_alert(task, "setsid() failed %E", nxt_errno); + return NXT_ERROR; + } - /* - * Set a sefe umask to give at most 755/644 permissions on - * directories/files. - */ - umask(0022); + /* + * Set a sefe umask to give at most 755/644 permissions on + * directories/files. + */ + umask(0022); - /* Redirect STDIN and STDOUT to the "/dev/null". */ + /* Redirect STDIN and STDOUT to the "/dev/null". */ - fd = open("/dev/null", O_RDWR); - if (fd == -1) { - msg = "open(\"/dev/null\") failed %E"; - goto fail; - } + fd = open("/dev/null", O_RDWR); + if (fd == -1) { + msg = "open(\"/dev/null\") failed %E"; + goto fail; + } - if (dup2(fd, STDIN_FILENO) == -1) { - msg = "dup2(\"/dev/null\", STDIN) failed %E"; - goto fail; - } + if (dup2(fd, STDIN_FILENO) == -1) { + msg = "dup2(\"/dev/null\", STDIN) failed %E"; + goto fail; + } - if (dup2(fd, STDOUT_FILENO) == -1) { - msg = "dup2(\"/dev/null\", STDOUT) failed %E"; - goto fail; - } + if (dup2(fd, STDOUT_FILENO) == -1) { + msg = "dup2(\"/dev/null\", STDOUT) failed %E"; + goto fail; + } - if (fd > STDERR_FILENO) { - nxt_fd_close(fd); - } + if (fd > STDERR_FILENO) { + nxt_fd_close(fd); + } - return NXT_OK; + return NXT_OK; fail: - nxt_alert(task, msg, nxt_errno); + nxt_alert(task, msg, nxt_errno); - if (fd != -1) { - nxt_fd_close(fd); - } + if (fd != -1) { + nxt_fd_close(fd); + } - return NXT_ERROR; + return NXT_ERROR; } +void nxt_nanosleep(nxt_nsec_t ns) { + struct timespec ts; -void -nxt_nanosleep(nxt_nsec_t ns) -{ - struct timespec ts; - - ts.tv_sec = ns / 1000000000; - ts.tv_nsec = ns % 1000000000; + ts.tv_sec = ns / 1000000000; + ts.tv_nsec = ns % 1000000000; - (void) nanosleep(&ts, NULL); + (void)nanosleep(&ts, NULL); } +void nxt_process_port_add(nxt_task_t *task, nxt_process_t *process, + nxt_port_t *port) { + nxt_assert(port->process == NULL); -void -nxt_process_port_add(nxt_task_t *task, nxt_process_t *process, nxt_port_t *port) -{ - nxt_assert(port->process == NULL); - - port->process = process; - nxt_queue_insert_tail(&process->ports, &port->link); + port->process = process; + nxt_queue_insert_tail(&process->ports, &port->link); - nxt_process_use(task, process, 1); + nxt_process_use(task, process, 1); } - -nxt_process_type_t -nxt_process_type(nxt_process_t *process) -{ - return nxt_queue_is_empty(&process->ports) ? 0 : - (nxt_process_port_first(process))->type; +nxt_process_type_t nxt_process_type(nxt_process_t *process) { + return nxt_queue_is_empty(&process->ports) + ? 0 + : (nxt_process_port_first(process))->type; } +void nxt_process_close_ports(nxt_task_t *task, nxt_process_t *process) { + nxt_port_t *port; -void -nxt_process_close_ports(nxt_task_t *task, nxt_process_t *process) -{ - nxt_port_t *port; - - nxt_process_use(task, process, 1); + nxt_process_use(task, process, 1); - nxt_process_port_each(process, port) { + nxt_process_port_each(process, port) { - nxt_port_close(task, port); + nxt_port_close(task, port); - nxt_runtime_port_remove(task, port); + nxt_runtime_port_remove(task, port); + } + nxt_process_port_loop; - } nxt_process_port_loop; - - nxt_process_use(task, process, -1); + nxt_process_use(task, process, -1); } +void nxt_process_quit(nxt_task_t *task, nxt_uint_t exit_status) { + nxt_queue_t *listen; + nxt_queue_link_t *link, *next; + nxt_listen_event_t *lev; -void -nxt_process_quit(nxt_task_t *task, nxt_uint_t exit_status) -{ - nxt_queue_t *listen; - nxt_queue_link_t *link, *next; - nxt_listen_event_t *lev; + nxt_debug(task, "close listen connections"); - nxt_debug(task, "close listen connections"); + listen = &task->thread->engine->listen_connections; - listen = &task->thread->engine->listen_connections; + for (link = nxt_queue_first(listen); link != nxt_queue_tail(listen); + link = next) { + next = nxt_queue_next(link); + lev = nxt_queue_link_data(link, nxt_listen_event_t, link); + nxt_queue_remove(link); - for (link = nxt_queue_first(listen); - link != nxt_queue_tail(listen); - link = next) - { - next = nxt_queue_next(link); - lev = nxt_queue_link_data(link, nxt_listen_event_t, link); - nxt_queue_remove(link); - - nxt_fd_event_close(task->thread->engine, &lev->socket); - } + nxt_fd_event_close(task->thread->engine, &lev->socket); + } - nxt_runtime_quit(task, exit_status); + nxt_runtime_quit(task, exit_status); } diff --git a/src/nxt_process.h b/src/nxt_process.h index 42fd1bed2..ef9838c7c 100644 --- a/src/nxt_process.h +++ b/src/nxt_process.h @@ -12,180 +12,164 @@ #include #endif - -typedef pid_t nxt_pid_t; - +typedef pid_t nxt_pid_t; typedef struct nxt_common_app_conf_s nxt_common_app_conf_t; - typedef struct { - nxt_runtime_t *rt; + nxt_runtime_t *rt; } nxt_discovery_init_t; - typedef struct { - nxt_str_t conf; + nxt_str_t conf; #if (NXT_TLS) - nxt_array_t *certs; + nxt_array_t *certs; #endif #if (NXT_HAVE_NJS) - nxt_array_t *scripts; + nxt_array_t *scripts; #endif } nxt_controller_init_t; - typedef union { - void *discovery; - nxt_controller_init_t controller; - void *router; - nxt_common_app_conf_t *app; + void *discovery; + nxt_controller_init_t controller; + void *router; + nxt_common_app_conf_t *app; } nxt_process_data_t; - typedef enum { - NXT_PROCESS_STATE_CREATING = 0, - NXT_PROCESS_STATE_CREATED, - NXT_PROCESS_STATE_READY, + NXT_PROCESS_STATE_CREATING = 0, + NXT_PROCESS_STATE_CREATED, + NXT_PROCESS_STATE_READY, } nxt_process_state_t; - -typedef struct nxt_port_mmap_s nxt_port_mmap_t; -typedef struct nxt_process_s nxt_process_t; -typedef struct nxt_cgroup_s nxt_cgroup_t; +typedef struct nxt_port_mmap_s nxt_port_mmap_t; +typedef struct nxt_process_s nxt_process_t; +typedef struct nxt_cgroup_s nxt_cgroup_t; typedef void (*nxt_isolation_cleanup_t)(nxt_task_t *task, - nxt_process_t *process); + nxt_process_t *process); typedef void (*nxt_cgroup_cleanup_t)(nxt_task_t *task, - const nxt_process_t *process); - + const nxt_process_t *process); typedef struct { - nxt_thread_mutex_t mutex; - uint32_t size; - uint32_t cap; - nxt_port_mmap_t *elts; + nxt_thread_mutex_t mutex; + uint32_t size; + uint32_t cap; + nxt_port_mmap_t *elts; } nxt_port_mmaps_t; - typedef struct { - uint8_t language_deps; /* 1-bit */ - uint8_t tmpfs; /* 1-bit */ - uint8_t procfs; /* 1-bit */ + uint8_t language_deps; /* 1-bit */ + uint8_t tmpfs; /* 1-bit */ + uint8_t procfs; /* 1-bit */ } nxt_process_automount_t; - struct nxt_cgroup_s { - char *path; + char *path; }; - typedef struct { - u_char *rootfs; - nxt_process_automount_t automount; - nxt_array_t *mounts; /* of nxt_mount_t */ + u_char *rootfs; + nxt_process_automount_t automount; + nxt_array_t *mounts; /* of nxt_mount_t */ - nxt_isolation_cleanup_t cleanup; + nxt_isolation_cleanup_t cleanup; - nxt_cgroup_cleanup_t cgroup_cleanup; + nxt_cgroup_cleanup_t cgroup_cleanup; #if (NXT_HAVE_CGROUP) - nxt_cgroup_t cgroup; + nxt_cgroup_t cgroup; #endif #if (NXT_HAVE_LINUX_NS) - nxt_clone_t clone; + nxt_clone_t clone; #endif #if (NXT_HAVE_PR_SET_NO_NEW_PRIVS) - uint8_t new_privs; /* 1 bit */ + uint8_t new_privs; /* 1 bit */ #endif } nxt_process_isolation_t; - struct nxt_process_s { - nxt_pid_t pid; - nxt_queue_t ports; /* of nxt_port_t.link */ - nxt_process_state_t state; - nxt_bool_t registered; - nxt_int_t use_count; - - nxt_port_mmaps_t incoming; + nxt_pid_t pid; + nxt_queue_t ports; /* of nxt_port_t.link */ + nxt_process_state_t state; + nxt_bool_t registered; + nxt_int_t use_count; + nxt_port_mmaps_t incoming; - nxt_pid_t isolated_pid; - const char *name; - nxt_port_t *parent_port; + nxt_pid_t isolated_pid; + const char *name; + nxt_port_t *parent_port; - uint32_t stream; + uint32_t stream; - nxt_mp_t *mem_pool; - nxt_credential_t *user_cred; + nxt_mp_t *mem_pool; + nxt_credential_t *user_cred; - nxt_queue_t children; /* of nxt_process_t.link */ - nxt_queue_link_t link; /* for nxt_process_t.children */ + nxt_queue_t children; /* of nxt_process_t.link */ + nxt_queue_link_t link; /* for nxt_process_t.children */ - nxt_process_data_t data; + nxt_process_data_t data; - nxt_process_isolation_t isolation; + nxt_process_isolation_t isolation; }; - typedef nxt_int_t (*nxt_process_prefork_t)(nxt_task_t *task, - nxt_process_t *process, nxt_mp_t *mp); + nxt_process_t *process, + nxt_mp_t *mp); typedef nxt_int_t (*nxt_process_postfork_t)(nxt_task_t *task, - nxt_process_t *process, nxt_mp_t *mp); + nxt_process_t *process, + nxt_mp_t *mp); typedef nxt_int_t (*nxt_process_setup_t)(nxt_task_t *task, - nxt_process_t *process); + nxt_process_t *process); typedef nxt_int_t (*nxt_process_start_t)(nxt_task_t *task, - nxt_process_data_t *data); - + nxt_process_data_t *data); typedef struct { - const char *name; - nxt_process_type_t type; + const char *name; + nxt_process_type_t type; - nxt_process_prefork_t prefork; + nxt_process_prefork_t prefork; - nxt_process_setup_t setup; - nxt_process_start_t start; + nxt_process_setup_t setup; + nxt_process_start_t start; - uint8_t restart; /* 1-bit */ + uint8_t restart; /* 1-bit */ - const nxt_port_handlers_t *port_handlers; - const nxt_sig_event_t *signals; + const nxt_port_handlers_t *port_handlers; + const nxt_sig_event_t *signals; - nxt_queue_t *siblings; + nxt_queue_t *siblings; } nxt_process_init_t; - -extern uint8_t nxt_proc_keep_matrix[NXT_PROCESS_MAX][NXT_PROCESS_MAX]; -extern uint8_t nxt_proc_send_matrix[NXT_PROCESS_MAX][NXT_PROCESS_MAX]; -extern uint8_t nxt_proc_remove_notify_matrix[NXT_PROCESS_MAX][NXT_PROCESS_MAX]; +extern uint8_t nxt_proc_keep_matrix[NXT_PROCESS_MAX][NXT_PROCESS_MAX]; +extern uint8_t nxt_proc_send_matrix[NXT_PROCESS_MAX][NXT_PROCESS_MAX]; +extern uint8_t nxt_proc_remove_notify_matrix[NXT_PROCESS_MAX][NXT_PROCESS_MAX]; NXT_EXPORT nxt_pid_t nxt_process_execute(nxt_task_t *task, char *name, - char **argv, char **envp); + char **argv, char **envp); NXT_EXPORT nxt_int_t nxt_process_daemon(nxt_task_t *task); NXT_EXPORT void nxt_nanosleep(nxt_nsec_t ns); NXT_EXPORT void nxt_process_arguments(nxt_task_t *task, char **orig_argv, - char ***orig_envp); + char ***orig_envp); -#define nxt_process_init(process) \ - (nxt_pointer_to(process, sizeof(nxt_process_t))) +#define nxt_process_init(process) \ + (nxt_pointer_to(process, sizeof(nxt_process_t))) -#define nxt_process_port_remove(port) \ - nxt_queue_remove(&port->link) +#define nxt_process_port_remove(port) nxt_queue_remove(&port->link) -#define nxt_process_port_first(process) \ - nxt_queue_link_data(nxt_queue_first(&process->ports), nxt_port_t, link) +#define nxt_process_port_first(process) \ + nxt_queue_link_data(nxt_queue_first(&process->ports), nxt_port_t, link) NXT_EXPORT void nxt_process_port_add(nxt_task_t *task, nxt_process_t *process, - nxt_port_t *port); + nxt_port_t *port); #define nxt_process_port_each(process, port) \ - nxt_queue_each(port, &process->ports, nxt_port_t, link) + nxt_queue_each(port, &process->ports, nxt_port_t, link) -#define nxt_process_port_loop \ - nxt_queue_loop +#define nxt_process_port_loop nxt_queue_loop nxt_process_t *nxt_process_new(nxt_runtime_t *rt); void nxt_process_use(nxt_task_t *task, nxt_process_t *process, int i); @@ -202,40 +186,34 @@ void nxt_signal_quit_handler(nxt_task_t *task, nxt_port_recv_msg_t *msg); nxt_int_t nxt_process_core_setup(nxt_task_t *task, nxt_process_t *process); nxt_int_t nxt_process_creds_set(nxt_task_t *task, nxt_process_t *process, - nxt_str_t *user, nxt_str_t *group); + nxt_str_t *user, nxt_str_t *group); nxt_int_t nxt_process_apply_creds(nxt_task_t *task, nxt_process_t *process); #if (NXT_HAVE_SETPROCTITLE) -#define nxt_process_title(task, fmt, ...) \ - setproctitle(fmt, __VA_ARGS__) +#define nxt_process_title(task, fmt, ...) setproctitle(fmt, __VA_ARGS__) #elif (NXT_LINUX || NXT_SOLARIS || NXT_MACOSX) -#define NXT_SETPROCTITLE_ARGV 1 +#define NXT_SETPROCTITLE_ARGV 1 NXT_EXPORT void nxt_process_title(nxt_task_t *task, const char *fmt, ...); #endif - -#define nxt_sched_yield() \ - sched_yield() +#define nxt_sched_yield() sched_yield() /* * Solaris declares abort() as __NORETURN, * raise(SIGABRT) is mostly the same. */ -#define nxt_abort() \ - (void) raise(SIGABRT) - - -NXT_EXPORT extern nxt_pid_t nxt_pid; -NXT_EXPORT extern nxt_pid_t nxt_ppid; -NXT_EXPORT extern nxt_uid_t nxt_euid; -NXT_EXPORT extern nxt_gid_t nxt_egid; -NXT_EXPORT extern char **nxt_process_argv; -NXT_EXPORT extern char ***nxt_process_environ; +#define nxt_abort() (void)raise(SIGABRT) +NXT_EXPORT extern nxt_pid_t nxt_pid; +NXT_EXPORT extern nxt_pid_t nxt_ppid; +NXT_EXPORT extern nxt_uid_t nxt_euid; +NXT_EXPORT extern nxt_gid_t nxt_egid; +NXT_EXPORT extern char **nxt_process_argv; +NXT_EXPORT extern char ***nxt_process_environ; #endif /* _NXT_PROCESS_H_INCLUDED_ */ diff --git a/src/nxt_process_title.c b/src/nxt_process_title.c index 3c20ac594..4b00b513a 100644 --- a/src/nxt_process_title.c +++ b/src/nxt_process_title.c @@ -6,9 +6,8 @@ #include - /* The arguments passed to main(). */ -char **nxt_process_argv; +char **nxt_process_argv; /* * MacOSX environ(7): @@ -20,8 +19,7 @@ char **nxt_process_argv; * So nxt_process_environ contains an address of environ to allow * change environ[] placement. */ -char ***nxt_process_environ; - +char ***nxt_process_environ; #if (NXT_SETPROCTITLE_ARGV) @@ -37,220 +35,213 @@ char ***nxt_process_environ; * UCB mode: either "/usr/ucb/ps -axwww" or "/usr/bin/ps axwww". */ - -static u_char *nxt_process_title_start; -static u_char *nxt_process_title_end; - - -void -nxt_process_arguments(nxt_task_t *task, char **orig_argv, char ***orig_envp) -{ - u_char *p, *end, *argv_end, **argv, **env; - size_t size, argv_size, environ_size, strings_size; - nxt_uint_t i; - - nxt_process_argv = orig_argv; - nxt_process_environ = orig_envp; - - if (orig_envp == NULL) { - return; - } - - /* - * Set a conservative title space for a case if program argument - * strings and environment strings are not contiguous. - */ - argv = (u_char **) orig_argv; - nxt_process_title_start = argv[0]; - nxt_process_title_end = argv[0] + nxt_strlen(argv[0]); - - end = argv[0]; - strings_size = 0; - argv_size = sizeof(void *); - - for (i = 0; argv[i] != NULL; i++) { - argv_size += sizeof(void *); - - if (argv[i] == end) { - /* Argument strings are contiguous. */ - size = nxt_strlen(argv[i]) + 1; - strings_size += size; - end = argv[i] + size; - } +static u_char *nxt_process_title_start; +static u_char *nxt_process_title_end; + +void nxt_process_arguments(nxt_task_t *task, char **orig_argv, + char ***orig_envp) { + u_char *p, *end, *argv_end, **argv, **env; + size_t size, argv_size, environ_size, strings_size; + nxt_uint_t i; + + nxt_process_argv = orig_argv; + nxt_process_environ = orig_envp; + + if (orig_envp == NULL) { + return; + } + + /* + * Set a conservative title space for a case if program argument + * strings and environment strings are not contiguous. + */ + argv = (u_char **)orig_argv; + nxt_process_title_start = argv[0]; + nxt_process_title_end = argv[0] + nxt_strlen(argv[0]); + + end = argv[0]; + strings_size = 0; + argv_size = sizeof(void *); + + for (i = 0; argv[i] != NULL; i++) { + argv_size += sizeof(void *); + + if (argv[i] == end) { + /* Argument strings are contiguous. */ + size = nxt_strlen(argv[i]) + 1; + strings_size += size; + end = argv[i] + size; } - - argv = nxt_malloc(argv_size); - if (argv == NULL) { - return; + } + + argv = nxt_malloc(argv_size); + if (argv == NULL) { + return; + } + + /* + * Copy the entire original argv[] array. The elements of this array + * can point to copied strings or if original argument strings are not + * contiguous, to the original argument strings. + */ + nxt_memcpy(argv, orig_argv, argv_size); + + /* + * The argv[1] must be set to NULL on Solaris otherwise the "ps" + * command outputs strings pointed by original argv[] elements. + * The original argv[] array has always at least two elements so + * it is safe to set argv[1]. + */ + orig_argv[1] = NULL; + + nxt_process_argv = (char **)argv; + + argv_end = end; + env = (u_char **)*orig_envp; + environ_size = sizeof(void *); + + for (i = 0; env[i] != NULL; i++) { + environ_size += sizeof(void *); + + if (env[i] == end) { + /* Environment strings are contiguous. */ + size = nxt_strlen(env[i]) + 1; + strings_size += size; + end = env[i] + size; } + } - /* - * Copy the entire original argv[] array. The elements of this array - * can point to copied strings or if original argument strings are not - * contiguous, to the original argument strings. - */ - nxt_memcpy(argv, orig_argv, argv_size); + p = nxt_malloc(strings_size); + if (p == NULL) { + return; + } + if (argv_end == end) { /* - * The argv[1] must be set to NULL on Solaris otherwise the "ps" - * command outputs strings pointed by original argv[] elements. - * The original argv[] array has always at least two elements so - * it is safe to set argv[1]. + * There is no reason to modify environ if arguments + * and environment are not contiguous. */ - orig_argv[1] = NULL; + nxt_debug(task, "arguments and environment are not contiguous"); + goto done; + } - nxt_process_argv = (char **) argv; + end = argv[0]; - argv_end = end; - env = (u_char **) *orig_envp; - environ_size = sizeof(void *); + for (i = 0; argv[i] != NULL; i++) { - for (i = 0; env[i] != NULL; i++) { - environ_size += sizeof(void *); - - if (env[i] == end) { - /* Environment strings are contiguous. */ - size = nxt_strlen(env[i]) + 1; - strings_size += size; - end = env[i] + size; - } + if (argv[i] != end) { + /* Argument strings are not contiguous. */ + goto done; } - p = nxt_malloc(strings_size); - if (p == NULL) { - return; - } + size = nxt_strlen(argv[i]) + 1; + nxt_memcpy(p, argv[i], size); - if (argv_end == end) { - /* - * There is no reason to modify environ if arguments - * and environment are not contiguous. - */ - nxt_debug(task, "arguments and environment are not contiguous"); - goto done; - } + end = argv[i] + size; + argv[i] = p; + p += size; + } - end = argv[0]; + env = nxt_malloc(environ_size); + if (env == NULL) { + return; + } - for (i = 0; argv[i] != NULL; i++) { + /* + * Copy the entire original environ[] array. The elements of + * this array can point to copied strings or if original environ + * strings are not contiguous, to the original environ strings. + */ + nxt_memcpy(env, *orig_envp, environ_size); - if (argv[i] != end) { - /* Argument strings are not contiguous. */ - goto done; - } + /* Set the global environ variable to the new array. */ + *orig_envp = (char **)env; - size = nxt_strlen(argv[i]) + 1; - nxt_memcpy(p, argv[i], size); + for (i = 0; env[i] != NULL; i++) { - end = argv[i] + size; - argv[i] = p; - p += size; + if (env[i] != end) { + /* Environment strings are not contiguous. */ + goto done; } - env = nxt_malloc(environ_size); - if (env == NULL) { - return; - } + size = nxt_strlen(env[i]) + 1; + nxt_memcpy(p, env[i], size); - /* - * Copy the entire original environ[] array. The elements of - * this array can point to copied strings or if original environ - * strings are not contiguous, to the original environ strings. - */ - nxt_memcpy(env, *orig_envp, environ_size); - - /* Set the global environ variable to the new array. */ - *orig_envp = (char **) env; - - for (i = 0; env[i] != NULL; i++) { - - if (env[i] != end) { - /* Environment strings are not contiguous. */ - goto done; - } - - size = nxt_strlen(env[i]) + 1; - nxt_memcpy(p, env[i], size); - - end = env[i] + size; - env[i] = p; - p += size; - } + end = env[i] + size; + env[i] = p; + p += size; + } done: - /* Preserve space for the trailing zero. */ - end--; + /* Preserve space for the trailing zero. */ + end--; - nxt_process_title_end = end; + nxt_process_title_end = end; } +void nxt_process_title(nxt_task_t *task, const char *fmt, ...) { + u_char *p, *start, *end; + va_list args; -void -nxt_process_title(nxt_task_t *task, const char *fmt, ...) -{ - u_char *p, *start, *end; - va_list args; + start = nxt_process_title_start; - start = nxt_process_title_start; + if (start == NULL) { + return; + } - if (start == NULL) { - return; - } + end = nxt_process_title_end; - end = nxt_process_title_end; - - va_start(args, fmt); - p = nxt_vsprintf(start, end, fmt, args); - va_end(args); + va_start(args, fmt); + p = nxt_vsprintf(start, end, fmt, args); + va_end(args); #if (NXT_SOLARIS) - /* - * Solaris "ps" command shows a new process title only if it is - * longer than original command line. A simple workaround is just - * to append the original command line in parenthesis to the title. - */ - { - size_t size; - nxt_uint_t i; - - size = 0; - - for (i = 0; nxt_process_argv[i] != NULL; i++) { - size += nxt_strlen(nxt_process_argv[i]); - } + /* + * Solaris "ps" command shows a new process title only if it is + * longer than original command line. A simple workaround is just + * to append the original command line in parenthesis to the title. + */ + { + size_t size; + nxt_uint_t i; + + size = 0; + + for (i = 0; nxt_process_argv[i] != NULL; i++) { + size += nxt_strlen(nxt_process_argv[i]); + } - if (size > (size_t) (p - start)) { + if (size > (size_t)(p - start)) { - p = nxt_sprintf(p, end, " ("); + p = nxt_sprintf(p, end, " ("); - for (i = 0; nxt_process_argv[i] != NULL; i++) { - p = nxt_sprintf(p, end, "%s ", nxt_process_argv[i]); - } + for (i = 0; nxt_process_argv[i] != NULL; i++) { + p = nxt_sprintf(p, end, "%s ", nxt_process_argv[i]); + } - if (*(p - 1) == ' ') { - *(p - 1) = ')'; - } - } + if (*(p - 1) == ' ') { + *(p - 1) = ')'; + } } + } #endif - /* - * A process title must be padded with zeros on MacOSX. Otherwise - * the "ps" command may output parts of environment strings. - */ - nxt_memset(p, '\0', end - p); + /* + * A process title must be padded with zeros on MacOSX. Otherwise + * the "ps" command may output parts of environment strings. + */ + nxt_memset(p, '\0', end - p); - nxt_debug(task, "setproctitle: \"%s\"", start); + nxt_debug(task, "setproctitle: \"%s\"", start); } #else /* !(NXT_SETPROCTITLE_ARGV) */ -void -nxt_process_arguments(nxt_task_t *task, char **orig_argv, char ***orig_envp) -{ - nxt_process_argv = orig_argv; - nxt_process_environ = orig_envp; +void nxt_process_arguments(nxt_task_t *task, char **orig_argv, + char ***orig_envp) { + nxt_process_argv = orig_argv; + nxt_process_environ = orig_envp; } #endif diff --git a/src/nxt_process_type.h b/src/nxt_process_type.h index d0093431e..67e6095a8 100644 --- a/src/nxt_process_type.h +++ b/src/nxt_process_type.h @@ -7,17 +7,15 @@ #ifndef _NXT_PROCESS_TYPE_H_INCLUDED_ #define _NXT_PROCESS_TYPE_H_INCLUDED_ - typedef enum { - NXT_PROCESS_MAIN = 0, - NXT_PROCESS_DISCOVERY, - NXT_PROCESS_CONTROLLER, - NXT_PROCESS_ROUTER, - NXT_PROCESS_PROTOTYPE, - NXT_PROCESS_APP, + NXT_PROCESS_MAIN = 0, + NXT_PROCESS_DISCOVERY, + NXT_PROCESS_CONTROLLER, + NXT_PROCESS_ROUTER, + NXT_PROCESS_PROTOTYPE, + NXT_PROCESS_APP, - NXT_PROCESS_MAX, + NXT_PROCESS_MAX, } nxt_process_type_t; - #endif /* _NXT_PROCESS_TYPE_H_INCLUDED_ */ diff --git a/src/nxt_queue.c b/src/nxt_queue.c index c81356dbd..9db67f99e 100644 --- a/src/nxt_queue.c +++ b/src/nxt_queue.c @@ -4,82 +4,74 @@ * Copyright (C) NGINX, Inc. */ - #include - /* * Find the middle queue element if the queue has odd number of elements, * or the first element of the queue's second part otherwise. */ -nxt_queue_link_t * -nxt_queue_middle(nxt_queue_t *queue) -{ - nxt_queue_link_t *middle, *next; +nxt_queue_link_t *nxt_queue_middle(nxt_queue_t *queue) { + nxt_queue_link_t *middle, *next; - middle = nxt_queue_first(queue); + middle = nxt_queue_first(queue); - if (middle == nxt_queue_last(queue)) { - return middle; - } + if (middle == nxt_queue_last(queue)) { + return middle; + } - next = middle; + next = middle; - for ( ;; ) { - middle = nxt_queue_next(middle); + for (;;) { + middle = nxt_queue_next(middle); - next = nxt_queue_next(next); + next = nxt_queue_next(next); - if (next == nxt_queue_last(queue)) { - return middle; - } + if (next == nxt_queue_last(queue)) { + return middle; + } - next = nxt_queue_next(next); + next = nxt_queue_next(next); - if (next == nxt_queue_last(queue)) { - return middle; - } + if (next == nxt_queue_last(queue)) { + return middle; } + } } - /* * nxt_queue_sort() provides a stable sort because it uses the insertion * sort algorithm. Its worst and average computational complexity is O^2. */ -void -nxt_queue_sort(nxt_queue_t *queue, - nxt_int_t (*cmp)(const void *data, const nxt_queue_link_t *, - const nxt_queue_link_t *), const void *data) -{ - nxt_queue_link_t *link, *prev, *next; +void nxt_queue_sort(nxt_queue_t *queue, + nxt_int_t (*cmp)(const void *data, const nxt_queue_link_t *, + const nxt_queue_link_t *), + const void *data) { + nxt_queue_link_t *link, *prev, *next; - link = nxt_queue_first(queue); + link = nxt_queue_first(queue); - if (link == nxt_queue_last(queue)) { - return; - } + if (link == nxt_queue_last(queue)) { + return; + } - for (link = nxt_queue_next(link); - link != nxt_queue_tail(queue); - link = next) - { - prev = nxt_queue_prev(link); - next = nxt_queue_next(link); + for (link = nxt_queue_next(link); link != nxt_queue_tail(queue); + link = next) { + prev = nxt_queue_prev(link); + next = nxt_queue_next(link); - nxt_queue_remove(link); + nxt_queue_remove(link); - do { - if (cmp(data, prev, link) <= 0) { - break; - } + do { + if (cmp(data, prev, link) <= 0) { + break; + } - prev = nxt_queue_prev(prev); + prev = nxt_queue_prev(prev); - } while (prev != nxt_queue_head(queue)); + } while (prev != nxt_queue_head(queue)); - nxt_queue_insert_after(prev, link); - } + nxt_queue_insert_after(prev, link); + } } diff --git a/src/nxt_queue.h b/src/nxt_queue.h index 6b7f5d577..b7c22c7f8 100644 --- a/src/nxt_queue.h +++ b/src/nxt_queue.h @@ -7,45 +7,37 @@ #ifndef _NXT_QUEUE_H_INCLUDED_ #define _NXT_QUEUE_H_INCLUDED_ - -typedef struct nxt_queue_link_s nxt_queue_link_t; +typedef struct nxt_queue_link_s nxt_queue_link_t; struct nxt_queue_link_s { - nxt_queue_link_t *prev; - nxt_queue_link_t *next; + nxt_queue_link_t *prev; + nxt_queue_link_t *next; }; - typedef struct { - nxt_queue_link_t head; + nxt_queue_link_t head; } nxt_queue_t; +#define nxt_queue_init(queue) \ + do { \ + (queue)->head.prev = &(queue)->head; \ + (queue)->head.next = &(queue)->head; \ + } while (0) -#define nxt_queue_init(queue) \ - do { \ - (queue)->head.prev = &(queue)->head; \ - (queue)->head.next = &(queue)->head; \ - } while (0) - - -#define nxt_queue_sentinel(link) \ - do { \ - (link)->prev = (link); \ - (link)->next = (link); \ - } while (0) - +#define nxt_queue_sentinel(link) \ + do { \ + (link)->prev = (link); \ + (link)->next = (link); \ + } while (0) /* * Short-circuit a queue link to itself to allow once remove safely it * using nxt_queue_remove(). */ -#define nxt_queue_self(link) \ - nxt_queue_sentinel(link) - +#define nxt_queue_self(link) nxt_queue_sentinel(link) -#define nxt_queue_is_empty(queue) \ - (&(queue)->head == (queue)->head.prev) +#define nxt_queue_is_empty(queue) (&(queue)->head == (queue)->head.prev) /* * A loop to iterate all queue links starting from head: @@ -69,111 +61,92 @@ typedef struct { * tp = nxt_queue_link_data(lnk, nxt_type_t, link); */ -#define nxt_queue_first(queue) \ - (queue)->head.next - - -#define nxt_queue_last(queue) \ - (queue)->head.prev - - -#define nxt_queue_head(queue) \ - (&(queue)->head) - - -#define nxt_queue_tail(queue) \ - (&(queue)->head) - +#define nxt_queue_first(queue) (queue)->head.next -#define nxt_queue_next(link) \ - (link)->next +#define nxt_queue_last(queue) (queue)->head.prev +#define nxt_queue_head(queue) (&(queue)->head) -#define nxt_queue_prev(link) \ - (link)->prev +#define nxt_queue_tail(queue) (&(queue)->head) +#define nxt_queue_next(link) (link)->next -#define nxt_queue_insert_head(queue, link) \ - do { \ - (link)->next = (queue)->head.next; \ - (link)->next->prev = (link); \ - (link)->prev = &(queue)->head; \ - (queue)->head.next = (link); \ - } while (0) +#define nxt_queue_prev(link) (link)->prev +#define nxt_queue_insert_head(queue, link) \ + do { \ + (link)->next = (queue)->head.next; \ + (link)->next->prev = (link); \ + (link)->prev = &(queue)->head; \ + (queue)->head.next = (link); \ + } while (0) -#define nxt_queue_insert_tail(queue, link) \ - do { \ - (link)->prev = (queue)->head.prev; \ - (link)->prev->next = (link); \ - (link)->next = &(queue)->head; \ - (queue)->head.prev = (link); \ - } while (0) +#define nxt_queue_insert_tail(queue, link) \ + do { \ + (link)->prev = (queue)->head.prev; \ + (link)->prev->next = (link); \ + (link)->next = &(queue)->head; \ + (queue)->head.prev = (link); \ + } while (0) +#define nxt_queue_insert_after(target, link) \ + do { \ + (link)->next = (target)->next; \ + (link)->next->prev = (link); \ + (link)->prev = (target); \ + (target)->next = (link); \ + } while (0) -#define nxt_queue_insert_after(target, link) \ - do { \ - (link)->next = (target)->next; \ - (link)->next->prev = (link); \ - (link)->prev = (target); \ - (target)->next = (link); \ - } while (0) - - -#define nxt_queue_insert_before(target, link) \ - do { \ - (link)->next = (target); \ - (link)->prev = (target)->prev; \ - (target)->prev = (link); \ - (link)->prev->next = (link); \ - } while (0) - +#define nxt_queue_insert_before(target, link) \ + do { \ + (link)->next = (target); \ + (link)->prev = (target)->prev; \ + (target)->prev = (link); \ + (link)->prev->next = (link); \ + } while (0) #if (NXT_DEBUG) -#define nxt_queue_remove(link) \ - do { \ - (link)->next->prev = (link)->prev; \ - (link)->prev->next = (link)->next; \ - (link)->prev = NULL; \ - (link)->next = NULL; \ - } while (0) +#define nxt_queue_remove(link) \ + do { \ + (link)->next->prev = (link)->prev; \ + (link)->prev->next = (link)->next; \ + (link)->prev = NULL; \ + (link)->next = NULL; \ + } while (0) #else -#define nxt_queue_remove(link) \ - do { \ - (link)->next->prev = (link)->prev; \ - (link)->prev->next = (link)->next; \ - } while (0) +#define nxt_queue_remove(link) \ + do { \ + (link)->next->prev = (link)->prev; \ + (link)->prev->next = (link)->next; \ + } while (0) #endif - /* * Split the queue "queue" starting at the element "link", * the "tail" is the new tail queue. */ -#define nxt_queue_split(queue, link, tail) \ - do { \ - (tail)->head.prev = (queue)->head.prev; \ - (tail)->head.prev->next = &(tail)->head; \ - (tail)->head.next = (link); \ - (queue)->head.prev = (link)->prev; \ - (queue)->head.prev->next = &(queue)->head; \ - (link)->prev = &(tail)->head; \ - } while (0) - +#define nxt_queue_split(queue, link, tail) \ + do { \ + (tail)->head.prev = (queue)->head.prev; \ + (tail)->head.prev->next = &(tail)->head; \ + (tail)->head.next = (link); \ + (queue)->head.prev = (link)->prev; \ + (queue)->head.prev->next = &(queue)->head; \ + (link)->prev = &(tail)->head; \ + } while (0) /* Truncate the queue "queue" starting at element "link". */ -#define nxt_queue_truncate(queue, link) \ - do { \ - (queue)->head.prev = (link)->prev; \ - (queue)->head.prev->next = &(queue)->head; \ - } while (0) - +#define nxt_queue_truncate(queue, link) \ + do { \ + (queue)->head.prev = (link)->prev; \ + (queue)->head.prev->next = &(queue)->head; \ + } while (0) /* * Add the queue "tail" to the queue "queue". @@ -181,39 +154,36 @@ typedef struct { * it must be initiated with nxt_queue_init(tail). */ -#define nxt_queue_add(queue, tail) \ - do { \ - (queue)->head.prev->next = (tail)->head.next; \ - (tail)->head.next->prev = (queue)->head.prev; \ - (queue)->head.prev = (tail)->head.prev; \ - (queue)->head.prev->next = &(queue)->head; \ - } while (0) - - -#define nxt_queue_link_data(lnk, type, link) \ - nxt_container_of(lnk, type, link) +#define nxt_queue_add(queue, tail) \ + do { \ + (queue)->head.prev->next = (tail)->head.next; \ + (tail)->head.next->prev = (queue)->head.prev; \ + (queue)->head.prev = (tail)->head.prev; \ + (queue)->head.prev->next = &(queue)->head; \ + } while (0) +#define nxt_queue_link_data(lnk, type, link) nxt_container_of(lnk, type, link) NXT_EXPORT nxt_queue_link_t *nxt_queue_middle(nxt_queue_t *queue); NXT_EXPORT void nxt_queue_sort(nxt_queue_t *queue, - nxt_int_t (*cmp)(const void *, const nxt_queue_link_t *, - const nxt_queue_link_t *), const void *data); - - -#define nxt_queue_each(elt, queue, type, link) \ - do { \ - nxt_queue_link_t *_lnk, *_nxt; \ - \ - for (_lnk = nxt_queue_first(queue); \ - _lnk != nxt_queue_tail(queue); \ - _lnk = _nxt) { \ - \ - _nxt = nxt_queue_next(_lnk); \ - elt = nxt_queue_link_data(_lnk, type, link); \ - -#define nxt_queue_loop \ - } \ - } while(0) - + nxt_int_t (*cmp)(const void *, + const nxt_queue_link_t *, + const nxt_queue_link_t *), + const void *data); + +#define nxt_queue_each(elt, queue, type, link) \ + do { \ + nxt_queue_link_t *_lnk, *_nxt; \ + \ + for (_lnk = nxt_queue_first(queue); _lnk != nxt_queue_tail(queue); \ + _lnk = _nxt) { \ + \ + _nxt = nxt_queue_next(_lnk); \ + elt = nxt_queue_link_data(_lnk, type, link); + +#define nxt_queue_loop \ + } \ + } \ + while (0) #endif /* _NXT_QUEUE_H_INCLUDED_ */ diff --git a/src/nxt_random.c b/src/nxt_random.c index 8290488c8..136d23102 100644 --- a/src/nxt_random.c +++ b/src/nxt_random.c @@ -4,213 +4,188 @@ * Copyright (C) NGINX, Inc. */ - #include - /* * The pseudorandom generator based on OpenBSD arc4random. Although it is * usually stated that arc4random uses RC4 pseudorandom generation algorithm * they are actually different in nxt_random_add(). */ - -#define NXT_RANDOM_KEY_SIZE 128 - +#define NXT_RANDOM_KEY_SIZE 128 nxt_inline void nxt_random_start_schedule(nxt_random_t *r); static void nxt_random_stir(nxt_random_t *r); static void nxt_random_add(nxt_random_t *r, const u_char *key, uint32_t len); nxt_inline uint8_t nxt_random_byte(nxt_random_t *r); +void nxt_random_init(nxt_random_t *r) { + nxt_random_start_schedule(r); -void -nxt_random_init(nxt_random_t *r) -{ - nxt_random_start_schedule(r); - - nxt_random_stir(r); + nxt_random_stir(r); } +nxt_inline void nxt_random_start_schedule(nxt_random_t *r) { + nxt_uint_t i; -nxt_inline void -nxt_random_start_schedule(nxt_random_t *r) -{ - nxt_uint_t i; + r->i = 0; + r->j = 0; - r->i = 0; - r->j = 0; - - for (i = 0; i < 256; i++) { - r->s[i] = i; - } + for (i = 0; i < 256; i++) { + r->s[i] = i; + } } - -static void -nxt_random_stir(nxt_random_t *r) -{ - int fd; - ssize_t n; - struct timeval tv; - union { - uint32_t value[4]; - u_char bytes[NXT_RANDOM_KEY_SIZE]; - } key; +static void nxt_random_stir(nxt_random_t *r) { + int fd; + ssize_t n; + struct timeval tv; + union { + uint32_t value[4]; + u_char bytes[NXT_RANDOM_KEY_SIZE]; + } key; #if (NXT_HAVE_GETRANDOM) - n = getrandom(&key, NXT_RANDOM_KEY_SIZE, 0); + n = getrandom(&key, NXT_RANDOM_KEY_SIZE, 0); #elif (NXT_HAVE_LINUX_SYS_GETRANDOM) - /* Linux 3.17 SYS_getrandom. */ + /* Linux 3.17 SYS_getrandom. */ - n = syscall(SYS_getrandom, &key, NXT_RANDOM_KEY_SIZE, 0); + n = syscall(SYS_getrandom, &key, NXT_RANDOM_KEY_SIZE, 0); #elif (NXT_HAVE_GETENTROPY || NXT_HAVE_GETENTROPY_SYS_RANDOM) - n = 0; + n = 0; - if (getentropy(&key, NXT_RANDOM_KEY_SIZE) == 0) { - n = NXT_RANDOM_KEY_SIZE; - } + if (getentropy(&key, NXT_RANDOM_KEY_SIZE) == 0) { + n = NXT_RANDOM_KEY_SIZE; + } #else - n = 0; + n = 0; #endif - if (n != NXT_RANDOM_KEY_SIZE) { - fd = open("/dev/urandom", O_RDONLY); + if (n != NXT_RANDOM_KEY_SIZE) { + fd = open("/dev/urandom", O_RDONLY); - if (fd >= 0) { - n = read(fd, &key, NXT_RANDOM_KEY_SIZE); - (void) close(fd); - } + if (fd >= 0) { + n = read(fd, &key, NXT_RANDOM_KEY_SIZE); + (void)close(fd); } + } - if (n != NXT_RANDOM_KEY_SIZE) { - (void) gettimeofday(&tv, NULL); + if (n != NXT_RANDOM_KEY_SIZE) { + (void)gettimeofday(&tv, NULL); - /* XOR with stack garbage. */ + /* XOR with stack garbage. */ - key.value[0] ^= tv.tv_usec; - key.value[1] ^= tv.tv_sec; - key.value[2] ^= nxt_pid; - key.value[3] ^= (uintptr_t) nxt_thread_tid(nxt_thread()); - } + key.value[0] ^= tv.tv_usec; + key.value[1] ^= tv.tv_sec; + key.value[2] ^= nxt_pid; + key.value[3] ^= (uintptr_t)nxt_thread_tid(nxt_thread()); + } - nxt_random_add(r, key.bytes, NXT_RANDOM_KEY_SIZE); + nxt_random_add(r, key.bytes, NXT_RANDOM_KEY_SIZE); - /* Drop the first 3072 bytes. */ - for (n = 3072; n != 0; n--) { - (void) nxt_random_byte(r); - } + /* Drop the first 3072 bytes. */ + for (n = 3072; n != 0; n--) { + (void)nxt_random_byte(r); + } - /* Stir again after 1,600,000 bytes. */ - r->count = 400000; + /* Stir again after 1,600,000 bytes. */ + r->count = 400000; } +static void nxt_random_add(nxt_random_t *r, const u_char *key, uint32_t len) { + uint8_t val; + uint32_t n; -static void -nxt_random_add(nxt_random_t *r, const u_char *key, uint32_t len) -{ - uint8_t val; - uint32_t n; - - for (n = 0; n < 256; n++) { - val = r->s[r->i]; - r->j += val + key[n % len]; + for (n = 0; n < 256; n++) { + val = r->s[r->i]; + r->j += val + key[n % len]; - r->s[r->i] = r->s[r->j]; - r->s[r->j] = val; + r->s[r->i] = r->s[r->j]; + r->s[r->j] = val; - r->i++; - } + r->i++; + } - /* This index is not decremented in RC4 algorithm. */ - r->i--; + /* This index is not decremented in RC4 algorithm. */ + r->i--; - r->j = r->i; + r->j = r->i; } +uint32_t nxt_random(nxt_random_t *r) { + uint32_t val; -uint32_t -nxt_random(nxt_random_t *r) -{ - uint32_t val; - - r->count--; + r->count--; - if (r->count <= 0) { - nxt_random_stir(r); - } + if (r->count <= 0) { + nxt_random_stir(r); + } - val = (uint32_t) nxt_random_byte(r) << 24; - val |= (uint32_t) nxt_random_byte(r) << 16; - val |= (uint32_t) nxt_random_byte(r) << 8; - val |= (uint32_t) nxt_random_byte(r); + val = (uint32_t)nxt_random_byte(r) << 24; + val |= (uint32_t)nxt_random_byte(r) << 16; + val |= (uint32_t)nxt_random_byte(r) << 8; + val |= (uint32_t)nxt_random_byte(r); - return val; + return val; } +nxt_inline uint8_t nxt_random_byte(nxt_random_t *r) { + uint8_t si, sj; -nxt_inline uint8_t -nxt_random_byte(nxt_random_t *r) -{ - uint8_t si, sj; - - r->i++; - si = r->s[r->i]; - r->j += si; + r->i++; + si = r->s[r->i]; + r->j += si; - sj = r->s[r->j]; - r->s[r->i] = sj; - r->s[r->j] = si; + sj = r->s[r->j]; + r->s[r->i] = sj; + r->s[r->j] = si; - si += sj; + si += sj; - return r->s[si]; + return r->s[si]; } - #if (NXT_TESTS) -nxt_int_t -nxt_random_test(nxt_thread_t *thr) -{ - nxt_uint_t n; - nxt_random_t r; +nxt_int_t nxt_random_test(nxt_thread_t *thr) { + nxt_uint_t n; + nxt_random_t r; - nxt_random_start_schedule(&r); + nxt_random_start_schedule(&r); - r.count = 400000; + r.count = 400000; - nxt_random_add(&r, (u_char *) "arc4random", nxt_length("arc4random")); + nxt_random_add(&r, (u_char *)"arc4random", nxt_length("arc4random")); - /* - * Test arc4random() numbers. - * RC4 pseudorandom numbers would be 0x4642AFC3 and 0xBAF0FFF0. - */ + /* + * Test arc4random() numbers. + * RC4 pseudorandom numbers would be 0x4642AFC3 and 0xBAF0FFF0. + */ - if (nxt_random(&r) == 0xD6270B27) { + if (nxt_random(&r) == 0xD6270B27) { - for (n = 100000; n != 0; n--) { - (void) nxt_random(&r); - } + for (n = 100000; n != 0; n--) { + (void)nxt_random(&r); + } - if (nxt_random(&r) == 0x6FCAE186) { - nxt_log_error(NXT_LOG_NOTICE, thr->log, "arc4random test passed"); + if (nxt_random(&r) == 0x6FCAE186) { + nxt_log_error(NXT_LOG_NOTICE, thr->log, "arc4random test passed"); - return NXT_OK; - } + return NXT_OK; } + } - nxt_log_error(NXT_LOG_NOTICE, thr->log, "arc4random test failed"); + nxt_log_error(NXT_LOG_NOTICE, thr->log, "arc4random test failed"); - return NXT_ERROR; + return NXT_ERROR; } #endif diff --git a/src/nxt_random.h b/src/nxt_random.h index 962fdf8fa..c9b0fcb25 100644 --- a/src/nxt_random.h +++ b/src/nxt_random.h @@ -7,15 +7,13 @@ #ifndef _NXT_RANDOM_H_INCLUDED_ #define _NXT_RANDOM_H_INCLUDED_ - typedef struct { - uint8_t i; - uint8_t j; - uint8_t s[256]; - int32_t count; + uint8_t i; + uint8_t j; + uint8_t s[256]; + int32_t count; } nxt_random_t; - void nxt_random_init(nxt_random_t *r); uint32_t nxt_random(nxt_random_t *r); @@ -23,5 +21,4 @@ uint32_t nxt_random(nxt_random_t *r); nxt_int_t nxt_random_test(nxt_thread_t *thr); #endif - #endif /* _NXT_RANDOM_H_INCLUDED_ */ diff --git a/src/nxt_rbtree.c b/src/nxt_rbtree.c index 4a0f9c22a..8189d3a17 100644 --- a/src/nxt_rbtree.c +++ b/src/nxt_rbtree.c @@ -6,528 +6,495 @@ #include - /* * The red-black tree code is based on the algorithm described in * the "Introduction to Algorithms" by Cormen, Leiserson and Rivest. */ - static void nxt_rbtree_insert_fixup(nxt_rbtree_node_t *node); static void nxt_rbtree_delete_fixup(nxt_rbtree_t *tree, - nxt_rbtree_node_t *node); + nxt_rbtree_node_t *node); nxt_inline void nxt_rbtree_left_rotate(nxt_rbtree_node_t *node); nxt_inline void nxt_rbtree_right_rotate(nxt_rbtree_node_t *node); nxt_inline void nxt_rbtree_parent_relink(nxt_rbtree_node_t *subst, - nxt_rbtree_node_t *node); - - -#define NXT_RBTREE_BLACK 0 -#define NXT_RBTREE_RED 1 - - -#define nxt_rbtree_comparison_callback(tree) \ - ((nxt_rbtree_compare_t) (tree)->sentinel.right) - - -void -nxt_rbtree_init(nxt_rbtree_t *tree, nxt_rbtree_compare_t compare) -{ - /* - * The sentinel is used as a leaf node sentinel and as a tree root - * sentinel: it is a parent of a root node and the root node is - * the left child of the sentinel. Combining two sentinels in one - * entry and the fact that the sentinel's left child is a root node - * simplifies nxt_rbtree_node_successor() and eliminates explicit - * root node test before or inside nxt_rbtree_min(). - */ - - /* The root is empty. */ - tree->sentinel.left = &tree->sentinel; - - /* - * The sentinel's right child is never used so - * comparison callback can be safely stored here. - */ - tree->sentinel.right = (void *) compare; - - /* The root and leaf sentinel must be black. */ - tree->sentinel.color = NXT_RBTREE_BLACK; + nxt_rbtree_node_t *node); + +#define NXT_RBTREE_BLACK 0 +#define NXT_RBTREE_RED 1 + +#define nxt_rbtree_comparison_callback(tree) \ + ((nxt_rbtree_compare_t)(tree)->sentinel.right) + +void nxt_rbtree_init(nxt_rbtree_t *tree, nxt_rbtree_compare_t compare) { + /* + * The sentinel is used as a leaf node sentinel and as a tree root + * sentinel: it is a parent of a root node and the root node is + * the left child of the sentinel. Combining two sentinels in one + * entry and the fact that the sentinel's left child is a root node + * simplifies nxt_rbtree_node_successor() and eliminates explicit + * root node test before or inside nxt_rbtree_min(). + */ + + /* The root is empty. */ + tree->sentinel.left = &tree->sentinel; + + /* + * The sentinel's right child is never used so + * comparison callback can be safely stored here. + */ + tree->sentinel.right = (void *)compare; + + /* The root and leaf sentinel must be black. */ + tree->sentinel.color = NXT_RBTREE_BLACK; } +void nxt_rbtree_insert(nxt_rbtree_t *tree, nxt_rbtree_part_t *part) { + nxt_rbtree_node_t *node, *new_node, *sentinel, **child; + nxt_rbtree_compare_t compare; -void -nxt_rbtree_insert(nxt_rbtree_t *tree, nxt_rbtree_part_t *part) -{ - nxt_rbtree_node_t *node, *new_node, *sentinel, **child; - nxt_rbtree_compare_t compare; + new_node = (nxt_rbtree_node_t *)part; - new_node = (nxt_rbtree_node_t *) part; + node = nxt_rbtree_root(tree); + sentinel = nxt_rbtree_sentinel(tree); - node = nxt_rbtree_root(tree); - sentinel = nxt_rbtree_sentinel(tree); + new_node->left = sentinel; + new_node->right = sentinel; + new_node->color = NXT_RBTREE_RED; - new_node->left = sentinel; - new_node->right = sentinel; - new_node->color = NXT_RBTREE_RED; + compare = (nxt_rbtree_compare_t)tree->sentinel.right; + child = &nxt_rbtree_root(tree); - compare = (nxt_rbtree_compare_t) tree->sentinel.right; - child = &nxt_rbtree_root(tree); + while (*child != sentinel) { + node = *child; - while (*child != sentinel) { - node = *child; + nxt_prefetch(node->left); + nxt_prefetch(node->right); - nxt_prefetch(node->left); - nxt_prefetch(node->right); + child = (compare(new_node, node) < 0) ? &node->left : &node->right; + } - child = (compare(new_node, node) < 0) ? &node->left : &node->right; - } - - *child = new_node; - new_node->parent = node; + *child = new_node; + new_node->parent = node; - nxt_rbtree_insert_fixup(new_node); + nxt_rbtree_insert_fixup(new_node); - node = nxt_rbtree_root(tree); - node->color = NXT_RBTREE_BLACK; + node = nxt_rbtree_root(tree); + node->color = NXT_RBTREE_BLACK; } +static void nxt_rbtree_insert_fixup(nxt_rbtree_node_t *node) { + nxt_rbtree_node_t *parent, *grandparent, *uncle; + + /* + * Prefetching parent nodes does not help here because they are + * already traversed during insertion. + */ -static void -nxt_rbtree_insert_fixup(nxt_rbtree_node_t *node) -{ - nxt_rbtree_node_t *parent, *grandparent, *uncle; + for (;;) { + parent = node->parent; /* - * Prefetching parent nodes does not help here because they are - * already traversed during insertion. + * Testing whether a node is a tree root is not required here since + * a root node's parent is the sentinel and it is always black. */ + if (parent->color == NXT_RBTREE_BLACK) { + return; + } - for ( ;; ) { - parent = node->parent; - - /* - * Testing whether a node is a tree root is not required here since - * a root node's parent is the sentinel and it is always black. - */ - if (parent->color == NXT_RBTREE_BLACK) { - return; - } - - grandparent = parent->parent; - - if (parent == grandparent->left) { - uncle = grandparent->right; - - if (uncle->color == NXT_RBTREE_BLACK) { - - if (node == parent->right) { - node = parent; - nxt_rbtree_left_rotate(node); - } - - /* - * nxt_rbtree_left_rotate() swaps parent and - * child whilst keeps grandparent the same. - */ - parent = node->parent; + grandparent = parent->parent; - parent->color = NXT_RBTREE_BLACK; - grandparent->color = NXT_RBTREE_RED; + if (parent == grandparent->left) { + uncle = grandparent->right; - nxt_rbtree_right_rotate(grandparent); - /* - * nxt_rbtree_right_rotate() does not change node->parent - * color which is now black, so testing color is not required - * to return from function. - */ - return; - } + if (uncle->color == NXT_RBTREE_BLACK) { - } else { - uncle = grandparent->left; + if (node == parent->right) { + node = parent; + nxt_rbtree_left_rotate(node); + } - if (uncle->color == NXT_RBTREE_BLACK) { + /* + * nxt_rbtree_left_rotate() swaps parent and + * child whilst keeps grandparent the same. + */ + parent = node->parent; - if (node == parent->left) { - node = parent; - nxt_rbtree_right_rotate(node); - } + parent->color = NXT_RBTREE_BLACK; + grandparent->color = NXT_RBTREE_RED; - /* See the comment in the symmetric branch above. */ - parent = node->parent; + nxt_rbtree_right_rotate(grandparent); + /* + * nxt_rbtree_right_rotate() does not change node->parent + * color which is now black, so testing color is not required + * to return from function. + */ + return; + } - parent->color = NXT_RBTREE_BLACK; - grandparent->color = NXT_RBTREE_RED; + } else { + uncle = grandparent->left; - nxt_rbtree_left_rotate(grandparent); + if (uncle->color == NXT_RBTREE_BLACK) { - /* See the comment in the symmetric branch above. */ - return; - } + if (node == parent->left) { + node = parent; + nxt_rbtree_right_rotate(node); } - uncle->color = NXT_RBTREE_BLACK; + /* See the comment in the symmetric branch above. */ + parent = node->parent; + parent->color = NXT_RBTREE_BLACK; grandparent->color = NXT_RBTREE_RED; - node = grandparent; + nxt_rbtree_left_rotate(grandparent); + + /* See the comment in the symmetric branch above. */ + return; + } } -} + uncle->color = NXT_RBTREE_BLACK; + parent->color = NXT_RBTREE_BLACK; + grandparent->color = NXT_RBTREE_RED; -nxt_rbtree_node_t * -nxt_rbtree_find(nxt_rbtree_t *tree, nxt_rbtree_part_t *part) -{ - intptr_t n; - nxt_rbtree_node_t *node, *next, *sentinel; - nxt_rbtree_compare_t compare; + node = grandparent; + } +} - node = (nxt_rbtree_node_t *) part; +nxt_rbtree_node_t *nxt_rbtree_find(nxt_rbtree_t *tree, + nxt_rbtree_part_t *part) { + intptr_t n; + nxt_rbtree_node_t *node, *next, *sentinel; + nxt_rbtree_compare_t compare; - next = nxt_rbtree_root(tree); - sentinel = nxt_rbtree_sentinel(tree); - compare = nxt_rbtree_comparison_callback(tree); + node = (nxt_rbtree_node_t *)part; - while (next != sentinel) { - nxt_prefetch(next->left); - nxt_prefetch(next->right); + next = nxt_rbtree_root(tree); + sentinel = nxt_rbtree_sentinel(tree); + compare = nxt_rbtree_comparison_callback(tree); - n = compare(node, next); + while (next != sentinel) { + nxt_prefetch(next->left); + nxt_prefetch(next->right); - if (n < 0) { - next = next->left; + n = compare(node, next); - } else if (n > 0) { - next = next->right; + if (n < 0) { + next = next->left; - } else { - return next; - } + } else if (n > 0) { + next = next->right; + + } else { + return next; } + } - return NULL; + return NULL; } +nxt_rbtree_node_t *nxt_rbtree_find_less_or_equal(nxt_rbtree_t *tree, + nxt_rbtree_part_t *part) { + intptr_t n; + nxt_rbtree_node_t *node, *retval, *next, *sentinel; + nxt_rbtree_compare_t compare; -nxt_rbtree_node_t * -nxt_rbtree_find_less_or_equal(nxt_rbtree_t *tree, nxt_rbtree_part_t *part) -{ - intptr_t n; - nxt_rbtree_node_t *node, *retval, *next, *sentinel; - nxt_rbtree_compare_t compare; - - node = (nxt_rbtree_node_t *) part; + node = (nxt_rbtree_node_t *)part; - retval = NULL; - next = nxt_rbtree_root(tree); - sentinel = nxt_rbtree_sentinel(tree); - compare = nxt_rbtree_comparison_callback(tree); + retval = NULL; + next = nxt_rbtree_root(tree); + sentinel = nxt_rbtree_sentinel(tree); + compare = nxt_rbtree_comparison_callback(tree); - while (next != sentinel) { - nxt_prefetch(next->left); - nxt_prefetch(next->right); + while (next != sentinel) { + nxt_prefetch(next->left); + nxt_prefetch(next->right); - n = compare(node, next); + n = compare(node, next); - if (n < 0) { - next = next->left; + if (n < 0) { + next = next->left; - } else if (n > 0) { - retval = next; - next = next->right; + } else if (n > 0) { + retval = next; + next = next->right; - } else { - /* Exact match. */ - return next; - } + } else { + /* Exact match. */ + return next; } + } - return retval; + return retval; } +nxt_rbtree_node_t *nxt_rbtree_find_greater_or_equal(nxt_rbtree_t *tree, + nxt_rbtree_part_t *part) { + intptr_t n; + nxt_rbtree_node_t *node, *retval, *next, *sentinel; + nxt_rbtree_compare_t compare; -nxt_rbtree_node_t * -nxt_rbtree_find_greater_or_equal(nxt_rbtree_t *tree, nxt_rbtree_part_t *part) -{ - intptr_t n; - nxt_rbtree_node_t *node, *retval, *next, *sentinel; - nxt_rbtree_compare_t compare; - - node = (nxt_rbtree_node_t *) part; + node = (nxt_rbtree_node_t *)part; - retval = NULL; - next = nxt_rbtree_root(tree); - sentinel = nxt_rbtree_sentinel(tree); - compare = nxt_rbtree_comparison_callback(tree); + retval = NULL; + next = nxt_rbtree_root(tree); + sentinel = nxt_rbtree_sentinel(tree); + compare = nxt_rbtree_comparison_callback(tree); - while (next != sentinel) { - nxt_prefetch(next->left); - nxt_prefetch(next->right); + while (next != sentinel) { + nxt_prefetch(next->left); + nxt_prefetch(next->right); - n = compare(node, next); + n = compare(node, next); - if (n < 0) { - retval = next; - next = next->left; + if (n < 0) { + retval = next; + next = next->left; - } else if (n > 0) { - next = next->right; + } else if (n > 0) { + next = next->right; - } else { - /* Exact match. */ - return next; - } + } else { + /* Exact match. */ + return next; } + } - return retval; + return retval; } +void nxt_rbtree_delete(nxt_rbtree_t *tree, nxt_rbtree_part_t *part) { + uint8_t color; + nxt_rbtree_node_t *node, *sentinel, *subst, *child; -void -nxt_rbtree_delete(nxt_rbtree_t *tree, nxt_rbtree_part_t *part) -{ - uint8_t color; - nxt_rbtree_node_t *node, *sentinel, *subst, *child; + node = (nxt_rbtree_node_t *)part; - node = (nxt_rbtree_node_t *) part; + subst = node; + sentinel = nxt_rbtree_sentinel(tree); - subst = node; - sentinel = nxt_rbtree_sentinel(tree); + if (node->left == sentinel) { + child = node->right; - if (node->left == sentinel) { - child = node->right; + } else if (node->right == sentinel) { + child = node->left; - } else if (node->right == sentinel) { - child = node->left; + } else { + subst = nxt_rbtree_branch_min(tree, node->right); + child = subst->right; + } - } else { - subst = nxt_rbtree_branch_min(tree, node->right); - child = subst->right; - } + nxt_rbtree_parent_relink(child, subst); - nxt_rbtree_parent_relink(child, subst); + color = subst->color; - color = subst->color; + if (subst != node) { + /* Move the subst node to the deleted node position in the tree. */ - if (subst != node) { - /* Move the subst node to the deleted node position in the tree. */ + subst->color = node->color; - subst->color = node->color; + subst->left = node->left; + subst->left->parent = subst; - subst->left = node->left; - subst->left->parent = subst; + subst->right = node->right; + subst->right->parent = subst; - subst->right = node->right; - subst->right->parent = subst; - - nxt_rbtree_parent_relink(subst, node); - } + nxt_rbtree_parent_relink(subst, node); + } #if (NXT_DEBUG) - node->left = NULL; - node->right = NULL; - node->parent = NULL; + node->left = NULL; + node->right = NULL; + node->parent = NULL; #endif - if (color == NXT_RBTREE_BLACK) { - nxt_rbtree_delete_fixup(tree, child); - } + if (color == NXT_RBTREE_BLACK) { + nxt_rbtree_delete_fixup(tree, child); + } } +static void nxt_rbtree_delete_fixup(nxt_rbtree_t *tree, + nxt_rbtree_node_t *node) { + nxt_rbtree_node_t *parent, *sibling; -static void -nxt_rbtree_delete_fixup(nxt_rbtree_t *tree, nxt_rbtree_node_t *node) -{ - nxt_rbtree_node_t *parent, *sibling; - - while (node != nxt_rbtree_root(tree) && node->color == NXT_RBTREE_BLACK) { - /* - * Prefetching parent nodes does not help here according - * to microbenchmarks. - */ + while (node != nxt_rbtree_root(tree) && node->color == NXT_RBTREE_BLACK) { + /* + * Prefetching parent nodes does not help here according + * to microbenchmarks. + */ - parent = node->parent; + parent = node->parent; - if (node == parent->left) { - sibling = parent->right; + if (node == parent->left) { + sibling = parent->right; - if (sibling->color != NXT_RBTREE_BLACK) { + if (sibling->color != NXT_RBTREE_BLACK) { - sibling->color = NXT_RBTREE_BLACK; - parent->color = NXT_RBTREE_RED; + sibling->color = NXT_RBTREE_BLACK; + parent->color = NXT_RBTREE_RED; - nxt_rbtree_left_rotate(parent); + nxt_rbtree_left_rotate(parent); - sibling = parent->right; - } + sibling = parent->right; + } - if (sibling->right->color == NXT_RBTREE_BLACK) { + if (sibling->right->color == NXT_RBTREE_BLACK) { - sibling->color = NXT_RBTREE_RED; + sibling->color = NXT_RBTREE_RED; - if (sibling->left->color == NXT_RBTREE_BLACK) { - node = parent; - continue; - } + if (sibling->left->color == NXT_RBTREE_BLACK) { + node = parent; + continue; + } - sibling->left->color = NXT_RBTREE_BLACK; + sibling->left->color = NXT_RBTREE_BLACK; - nxt_rbtree_right_rotate(sibling); - /* - * If the node is the leaf sentinel then the right - * rotate above changes its parent so a sibling below - * becames the leaf sentinel as well and this causes - * segmentation fault. This is the reason why usual - * red-black tree implementations with a leaf sentinel - * which does not require to test leaf nodes at all - * nevertheless test the leaf sentinel in the left and - * right rotate procedures. Since according to the - * algorithm node->parent must not be changed by both - * the left and right rotates above, it can be cached - * in a local variable. This not only eliminates the - * sentinel test in nxt_rbtree_parent_relink() but also - * decreases the code size because C forces to reload - * non-restrict pointers. - */ - sibling = parent->right; - } + nxt_rbtree_right_rotate(sibling); + /* + * If the node is the leaf sentinel then the right + * rotate above changes its parent so a sibling below + * becames the leaf sentinel as well and this causes + * segmentation fault. This is the reason why usual + * red-black tree implementations with a leaf sentinel + * which does not require to test leaf nodes at all + * nevertheless test the leaf sentinel in the left and + * right rotate procedures. Since according to the + * algorithm node->parent must not be changed by both + * the left and right rotates above, it can be cached + * in a local variable. This not only eliminates the + * sentinel test in nxt_rbtree_parent_relink() but also + * decreases the code size because C forces to reload + * non-restrict pointers. + */ + sibling = parent->right; + } - sibling->color = parent->color; - parent->color = NXT_RBTREE_BLACK; - sibling->right->color = NXT_RBTREE_BLACK; + sibling->color = parent->color; + parent->color = NXT_RBTREE_BLACK; + sibling->right->color = NXT_RBTREE_BLACK; - nxt_rbtree_left_rotate(parent); + nxt_rbtree_left_rotate(parent); - return; + return; - } else { - sibling = parent->left; + } else { + sibling = parent->left; - if (sibling->color != NXT_RBTREE_BLACK) { + if (sibling->color != NXT_RBTREE_BLACK) { - sibling->color = NXT_RBTREE_BLACK; - parent->color = NXT_RBTREE_RED; + sibling->color = NXT_RBTREE_BLACK; + parent->color = NXT_RBTREE_RED; - nxt_rbtree_right_rotate(parent); + nxt_rbtree_right_rotate(parent); - sibling = parent->left; - } + sibling = parent->left; + } - if (sibling->left->color == NXT_RBTREE_BLACK) { + if (sibling->left->color == NXT_RBTREE_BLACK) { - sibling->color = NXT_RBTREE_RED; + sibling->color = NXT_RBTREE_RED; - if (sibling->right->color == NXT_RBTREE_BLACK) { - node = parent; - continue; - } + if (sibling->right->color == NXT_RBTREE_BLACK) { + node = parent; + continue; + } - sibling->right->color = NXT_RBTREE_BLACK; + sibling->right->color = NXT_RBTREE_BLACK; - nxt_rbtree_left_rotate(sibling); + nxt_rbtree_left_rotate(sibling); - /* See the comment in the symmetric branch above. */ - sibling = parent->left; - } + /* See the comment in the symmetric branch above. */ + sibling = parent->left; + } - sibling->color = parent->color; - parent->color = NXT_RBTREE_BLACK; - sibling->left->color = NXT_RBTREE_BLACK; + sibling->color = parent->color; + parent->color = NXT_RBTREE_BLACK; + sibling->left->color = NXT_RBTREE_BLACK; - nxt_rbtree_right_rotate(parent); + nxt_rbtree_right_rotate(parent); - return; - } + return; } + } - node->color = NXT_RBTREE_BLACK; + node->color = NXT_RBTREE_BLACK; } +nxt_inline void nxt_rbtree_left_rotate(nxt_rbtree_node_t *node) { + nxt_rbtree_node_t *child; -nxt_inline void -nxt_rbtree_left_rotate(nxt_rbtree_node_t *node) -{ - nxt_rbtree_node_t *child; + child = node->right; + node->right = child->left; + child->left->parent = node; + child->left = node; - child = node->right; - node->right = child->left; - child->left->parent = node; - child->left = node; - - nxt_rbtree_parent_relink(child, node); + nxt_rbtree_parent_relink(child, node); - node->parent = child; + node->parent = child; } +nxt_inline void nxt_rbtree_right_rotate(nxt_rbtree_node_t *node) { + nxt_rbtree_node_t *child; -nxt_inline void -nxt_rbtree_right_rotate(nxt_rbtree_node_t *node) -{ - nxt_rbtree_node_t *child; - - child = node->left; - node->left = child->right; - child->right->parent = node; - child->right = node; + child = node->left; + node->left = child->right; + child->right->parent = node; + child->right = node; - nxt_rbtree_parent_relink(child, node); + nxt_rbtree_parent_relink(child, node); - node->parent = child; + node->parent = child; } - /* Relink a parent from the node to the subst node. */ -nxt_inline void -nxt_rbtree_parent_relink(nxt_rbtree_node_t *subst, nxt_rbtree_node_t *node) -{ - nxt_rbtree_node_t *parent, **link; - - parent = node->parent; - /* - * The leaf sentinel's parent can be safely changed here. - * See the comment in nxt_rbtree_delete_fixup() for details. - */ - subst->parent = parent; - /* - * If the node's parent is the root sentinel it is safely changed - * because the root sentinel's left child is the tree root. - */ - link = (node == parent->left) ? &parent->left : &parent->right; - *link = subst; +nxt_inline void nxt_rbtree_parent_relink(nxt_rbtree_node_t *subst, + nxt_rbtree_node_t *node) { + nxt_rbtree_node_t *parent, **link; + + parent = node->parent; + /* + * The leaf sentinel's parent can be safely changed here. + * See the comment in nxt_rbtree_delete_fixup() for details. + */ + subst->parent = parent; + /* + * If the node's parent is the root sentinel it is safely changed + * because the root sentinel's left child is the tree root. + */ + link = (node == parent->left) ? &parent->left : &parent->right; + *link = subst; } +nxt_rbtree_node_t *nxt_rbtree_destroy_next(nxt_rbtree_t *tree, + nxt_rbtree_node_t **next) { + nxt_rbtree_node_t *node, *subst, *parent, *sentinel; -nxt_rbtree_node_t * -nxt_rbtree_destroy_next(nxt_rbtree_t *tree, nxt_rbtree_node_t **next) -{ - nxt_rbtree_node_t *node, *subst, *parent, *sentinel; + sentinel = nxt_rbtree_sentinel(tree); - sentinel = nxt_rbtree_sentinel(tree); + /* Find the leftmost node. */ + for (node = *next; node->left != sentinel; node = node->left) + ; - /* Find the leftmost node. */ - for (node = *next; node->left != sentinel; node = node->left); + /* Replace the leftmost node with its right child. */ + subst = node->right; + parent = node->parent; - /* Replace the leftmost node with its right child. */ - subst = node->right; - parent = node->parent; - - parent->left = subst; - subst->parent = parent; + parent->left = subst; + subst->parent = parent; - /* - * The right child is used as the next start node. If the right child - * is the sentinel then parent of the leftmost node is used as the next - * start node. The parent of the root node is the sentinel so after - * the single root node will be replaced with the sentinel, the next - * start node will be equal to the sentinel and iteration will stop. - */ - if (subst == sentinel) { - subst = parent; - } + /* + * The right child is used as the next start node. If the right child + * is the sentinel then parent of the leftmost node is used as the next + * start node. The parent of the root node is the sentinel so after + * the single root node will be replaced with the sentinel, the next + * start node will be equal to the sentinel and iteration will stop. + */ + if (subst == sentinel) { + subst = parent; + } - *next = subst; + *next = subst; - return node; + return node; } diff --git a/src/nxt_rbtree.h b/src/nxt_rbtree.h index 4bf479ea2..8732b9fe3 100644 --- a/src/nxt_rbtree.h +++ b/src/nxt_rbtree.h @@ -7,113 +7,93 @@ #ifndef _NXT_RBTREE_H_INCLUDED_ #define _NXT_RBTREE_H_INCLUDED_ - -typedef struct nxt_rbtree_node_s nxt_rbtree_node_t; +typedef struct nxt_rbtree_node_s nxt_rbtree_node_t; struct nxt_rbtree_node_s { - nxt_rbtree_node_t *left; - nxt_rbtree_node_t *right; - nxt_rbtree_node_t *parent; + nxt_rbtree_node_t *left; + nxt_rbtree_node_t *right; + nxt_rbtree_node_t *parent; - uint8_t color; + uint8_t color; }; - typedef struct { - nxt_rbtree_node_t *left; - nxt_rbtree_node_t *right; - nxt_rbtree_node_t *parent; + nxt_rbtree_node_t *left; + nxt_rbtree_node_t *right; + nxt_rbtree_node_t *parent; } nxt_rbtree_part_t; +#define NXT_RBTREE_NODE(node) \ + nxt_rbtree_part_t node; \ + uint8_t node##_color -#define NXT_RBTREE_NODE(node) \ - nxt_rbtree_part_t node; \ - uint8_t node##_color - - -#define NXT_RBTREE_NODE_INIT { NULL, NULL, NULL }, 0 - +#define NXT_RBTREE_NODE_INIT {NULL, NULL, NULL}, 0 typedef struct { - nxt_rbtree_node_t sentinel; + nxt_rbtree_node_t sentinel; } nxt_rbtree_t; - /* * A comparison function should return intptr_t result because * this eliminates overhead required to implement correct addresses * comparison without result truncation. */ typedef intptr_t (*nxt_rbtree_compare_t)(nxt_rbtree_node_t *node1, - nxt_rbtree_node_t *node2); + nxt_rbtree_node_t *node2); +#define nxt_rbtree_root(tree) ((tree)->sentinel.left) -#define nxt_rbtree_root(tree) \ - ((tree)->sentinel.left) +#define nxt_rbtree_sentinel(tree) (&(tree)->sentinel) +#define nxt_rbtree_is_empty(tree) \ + (nxt_rbtree_root(tree) == nxt_rbtree_sentinel(tree)) -#define nxt_rbtree_sentinel(tree) \ - (&(tree)->sentinel) +#define nxt_rbtree_min(tree) nxt_rbtree_branch_min(tree, &(tree)->sentinel) +nxt_inline nxt_rbtree_node_t *nxt_rbtree_branch_min(nxt_rbtree_t *tree, + nxt_rbtree_node_t *node) { + while (node->left != nxt_rbtree_sentinel(tree)) { + node = node->left; + } -#define nxt_rbtree_is_empty(tree) \ - (nxt_rbtree_root(tree) == nxt_rbtree_sentinel(tree)) - - -#define nxt_rbtree_min(tree) \ - nxt_rbtree_branch_min(tree, &(tree)->sentinel) - - -nxt_inline nxt_rbtree_node_t * -nxt_rbtree_branch_min(nxt_rbtree_t *tree, nxt_rbtree_node_t *node) -{ - while (node->left != nxt_rbtree_sentinel(tree)) { - node = node->left; - } - - return node; + return node; } - -#define nxt_rbtree_is_there_successor(tree, node) \ - ((node) != nxt_rbtree_sentinel(tree)) - +#define nxt_rbtree_is_there_successor(tree, node) \ + ((node) != nxt_rbtree_sentinel(tree)) nxt_inline nxt_rbtree_node_t * -nxt_rbtree_node_successor(nxt_rbtree_t *tree, nxt_rbtree_node_t *node) -{ - nxt_rbtree_node_t *parent; - - if (node->right != nxt_rbtree_sentinel(tree)) { - return nxt_rbtree_branch_min(tree, node->right); +nxt_rbtree_node_successor(nxt_rbtree_t *tree, nxt_rbtree_node_t *node) { + nxt_rbtree_node_t *parent; + + if (node->right != nxt_rbtree_sentinel(tree)) { + return nxt_rbtree_branch_min(tree, node->right); + } + + for (;;) { + parent = node->parent; + + /* + * Explicit test for a root node is not required here, because + * the root node is always the left child of the sentinel. + */ + if (node == parent->left) { + return parent; } - for ( ;; ) { - parent = node->parent; - - /* - * Explicit test for a root node is not required here, because - * the root node is always the left child of the sentinel. - */ - if (node == parent->left) { - return parent; - } - - node = parent; - } + node = parent; + } } - NXT_EXPORT void nxt_rbtree_init(nxt_rbtree_t *tree, - nxt_rbtree_compare_t compare); + nxt_rbtree_compare_t compare); NXT_EXPORT void nxt_rbtree_insert(nxt_rbtree_t *tree, nxt_rbtree_part_t *node); NXT_EXPORT nxt_rbtree_node_t *nxt_rbtree_find(nxt_rbtree_t *tree, - nxt_rbtree_part_t *node); -NXT_EXPORT nxt_rbtree_node_t *nxt_rbtree_find_less_or_equal(nxt_rbtree_t *tree, - nxt_rbtree_part_t *node); -NXT_EXPORT nxt_rbtree_node_t - *nxt_rbtree_find_greater_or_equal(nxt_rbtree_t *tree, - nxt_rbtree_part_t *node); + nxt_rbtree_part_t *node); +NXT_EXPORT nxt_rbtree_node_t * +nxt_rbtree_find_less_or_equal(nxt_rbtree_t *tree, nxt_rbtree_part_t *node); +NXT_EXPORT nxt_rbtree_node_t * +nxt_rbtree_find_greater_or_equal(nxt_rbtree_t *tree, nxt_rbtree_part_t *node); NXT_EXPORT void nxt_rbtree_delete(nxt_rbtree_t *tree, nxt_rbtree_part_t *node); /* @@ -125,7 +105,6 @@ NXT_EXPORT void nxt_rbtree_delete(nxt_rbtree_t *tree, nxt_rbtree_part_t *node); * operations must be performed on the rbtree while destruction. */ NXT_EXPORT nxt_rbtree_node_t *nxt_rbtree_destroy_next(nxt_rbtree_t *tree, - nxt_rbtree_node_t **next); - + nxt_rbtree_node_t **next); #endif /* _NXT_RBTREE_H_INCLUDED_ */ diff --git a/src/nxt_recvbuf.c b/src/nxt_recvbuf.c index 29a2b65d9..bba28192a 100644 --- a/src/nxt_recvbuf.c +++ b/src/nxt_recvbuf.c @@ -6,77 +6,71 @@ #include +nxt_uint_t nxt_recvbuf_mem_coalesce(nxt_recvbuf_coalesce_t *rb) { + u_char *last; + size_t size, total; + nxt_int_t n; + nxt_buf_t *b; -nxt_uint_t -nxt_recvbuf_mem_coalesce(nxt_recvbuf_coalesce_t *rb) -{ - u_char *last; - size_t size, total; - nxt_int_t n; - nxt_buf_t *b; + total = 0; + last = NULL; + n = -1; - total = 0; - last = NULL; - n = -1; + for (b = rb->buf; b != NULL; b = b->next) { - for (b = rb->buf; b != NULL; b = b->next) { + nxt_prefetch(b->next); - nxt_prefetch(b->next); + size = b->mem.end - b->mem.free; - size = b->mem.end - b->mem.free; + if (b->mem.free != last) { - if (b->mem.free != last) { + if (++n >= rb->nmax) { + goto done; + } - if (++n >= rb->nmax) { - goto done; - } + nxt_iobuf_set(&rb->iobuf[n], b->mem.free, size); - nxt_iobuf_set(&rb->iobuf[n], b->mem.free, size); - - } else { - nxt_iobuf_add(&rb->iobuf[n], size); - } + } else { + nxt_iobuf_add(&rb->iobuf[n], size); + } - nxt_thread_log_debug("recvbuf: %ui, %p, %uz", n, - nxt_iobuf_data(&rb->iobuf[n]), - nxt_iobuf_size(&rb->iobuf[n])); + nxt_thread_log_debug("recvbuf: %ui, %p, %uz", n, + nxt_iobuf_data(&rb->iobuf[n]), + nxt_iobuf_size(&rb->iobuf[n])); - total += size; - last = b->mem.end; - } + total += size; + last = b->mem.end; + } - n++; + n++; done: - rb->size = total; + rb->size = total; - return n; + return n; } +void nxt_recvbuf_update(nxt_buf_t *b, size_t sent) { + size_t size; -void -nxt_recvbuf_update(nxt_buf_t *b, size_t sent) -{ - size_t size; + while (b != NULL && sent != 0) { - while (b != NULL && sent != 0) { + nxt_prefetch(b->next); - nxt_prefetch(b->next); + if (!nxt_buf_is_sync(b)) { - if (!nxt_buf_is_sync(b)) { + size = b->mem.end - b->mem.free; - size = b->mem.end - b->mem.free; + if (sent < size) { + b->mem.free += sent; + return; + } - if (sent < size) { - b->mem.free += sent; - return; - } - - b->mem.free = b->mem.end; - sent -= size; - } - - b = b->next; + b->mem.free = b->mem.end; + sent -= size; } + + b = b->next; + } } diff --git a/src/nxt_recvbuf.h b/src/nxt_recvbuf.h index 69b514987..0f55e53db 100644 --- a/src/nxt_recvbuf.h +++ b/src/nxt_recvbuf.h @@ -7,18 +7,15 @@ #ifndef _NXT_RECVBUF_H_INCLUDED_ #define _NXT_RECVBUF_H_INCLUDED_ - typedef struct { - nxt_buf_t *buf; - nxt_iobuf_t *iobuf; + nxt_buf_t *buf; + nxt_iobuf_t *iobuf; - int32_t nmax; - size_t size; + int32_t nmax; + size_t size; } nxt_recvbuf_coalesce_t; - nxt_uint_t nxt_recvbuf_mem_coalesce(nxt_recvbuf_coalesce_t *rb); void nxt_recvbuf_update(nxt_buf_t *b, size_t sent); - #endif /* _NXT_RECVBUF_H_INCLUDED_ */ diff --git a/src/nxt_regex.h b/src/nxt_regex.h index a24c50f80..bc9eb6685 100644 --- a/src/nxt_regex.h +++ b/src/nxt_regex.h @@ -9,32 +9,31 @@ #if (NXT_HAVE_REGEX) -typedef struct nxt_regex_s nxt_regex_t; +typedef struct nxt_regex_s nxt_regex_t; - #if (NXT_HAVE_PCRE2) -typedef void nxt_regex_match_t; +#if (NXT_HAVE_PCRE2) +typedef void nxt_regex_match_t; #else -typedef struct nxt_regex_match_s nxt_regex_match_t; +typedef struct nxt_regex_match_s nxt_regex_match_t; #endif typedef struct { - size_t offset; + size_t offset; #if (NXT_HAVE_PCRE2) -#define ERR_BUF_SIZE 256 - u_char msg[ERR_BUF_SIZE]; +#define ERR_BUF_SIZE 256 + u_char msg[ERR_BUF_SIZE]; #else - const char *msg; + const char *msg; #endif } nxt_regex_err_t; - NXT_EXPORT void nxt_regex_init(void); NXT_EXPORT nxt_regex_t *nxt_regex_compile(nxt_mp_t *mp, nxt_str_t *source, - nxt_regex_err_t *err); + nxt_regex_err_t *err); NXT_EXPORT nxt_regex_match_t *nxt_regex_match_create(nxt_mp_t *mp, size_t size); NXT_EXPORT nxt_int_t nxt_regex_match(nxt_regex_t *re, u_char *subject, - size_t length, nxt_regex_match_t *match); + size_t length, nxt_regex_match_t *match); #endif /* NXT_HAVE_REGEX */ diff --git a/src/nxt_router.c b/src/nxt_router.c index 076cd134b..9794e01da 100644 --- a/src/nxt_router.c +++ b/src/nxt_router.c @@ -22,1396 +22,1330 @@ #include #include -#define NXT_SHARED_PORT_ID 0xFFFFu +#define NXT_SHARED_PORT_ID 0xFFFFu typedef struct { - nxt_str_t type; - uint32_t processes; - uint32_t max_processes; - uint32_t spare_processes; - nxt_msec_t timeout; - nxt_msec_t idle_timeout; - nxt_conf_value_t *limits_value; - nxt_conf_value_t *processes_value; - nxt_conf_value_t *targets_value; + nxt_str_t type; + uint32_t processes; + uint32_t max_processes; + uint32_t spare_processes; + nxt_msec_t timeout; + nxt_msec_t idle_timeout; + nxt_conf_value_t *limits_value; + nxt_conf_value_t *processes_value; + nxt_conf_value_t *targets_value; } nxt_router_app_conf_t; - typedef struct { - nxt_str_t pass; - nxt_str_t application; - int backlog; + nxt_str_t pass; + nxt_str_t application; + int backlog; } nxt_router_listener_conf_t; - #if (NXT_TLS) typedef struct { - nxt_str_t name; - nxt_socket_conf_t *socket_conf; - nxt_router_temp_conf_t *temp_conf; - nxt_tls_init_t *tls_init; - nxt_bool_t last; + nxt_str_t name; + nxt_socket_conf_t *socket_conf; + nxt_router_temp_conf_t *temp_conf; + nxt_tls_init_t *tls_init; + nxt_bool_t last; - nxt_queue_link_t link; /* for nxt_socket_conf_t.tls */ + nxt_queue_link_t link; /* for nxt_socket_conf_t.tls */ } nxt_router_tlssock_t; #endif - #if (NXT_HAVE_NJS) typedef struct { - nxt_str_t name; - nxt_router_temp_conf_t *temp_conf; - nxt_queue_link_t link; + nxt_str_t name; + nxt_router_temp_conf_t *temp_conf; + nxt_queue_link_t link; } nxt_router_js_module_t; #endif - typedef struct { - nxt_str_t *name; - nxt_socket_conf_t *socket_conf; - nxt_router_temp_conf_t *temp_conf; - nxt_bool_t last; + nxt_str_t *name; + nxt_socket_conf_t *socket_conf; + nxt_router_temp_conf_t *temp_conf; + nxt_bool_t last; } nxt_socket_rpc_t; - typedef struct { - nxt_app_t *app; - nxt_router_temp_conf_t *temp_conf; - uint8_t proto; /* 1 bit */ + nxt_app_t *app; + nxt_router_temp_conf_t *temp_conf; + uint8_t proto; /* 1 bit */ } nxt_app_rpc_t; - typedef struct { - nxt_app_joint_t *app_joint; - uint32_t generation; - uint8_t proto; /* 1 bit */ + nxt_app_joint_t *app_joint; + uint32_t generation; + uint8_t proto; /* 1 bit */ } nxt_app_joint_rpc_t; - static nxt_int_t nxt_router_prefork(nxt_task_t *task, nxt_process_t *process, - nxt_mp_t *mp); + nxt_mp_t *mp); static nxt_int_t nxt_router_start(nxt_task_t *task, nxt_process_data_t *data); static void nxt_router_greet_controller(nxt_task_t *task, - nxt_port_t *controller_port); + nxt_port_t *controller_port); static nxt_int_t nxt_router_start_app_process(nxt_task_t *task, nxt_app_t *app); static void nxt_router_new_port_handler(nxt_task_t *task, - nxt_port_recv_msg_t *msg); + nxt_port_recv_msg_t *msg); static void nxt_router_conf_data_handler(nxt_task_t *task, - nxt_port_recv_msg_t *msg); + nxt_port_recv_msg_t *msg); static void nxt_router_app_restart_handler(nxt_task_t *task, - nxt_port_recv_msg_t *msg); + nxt_port_recv_msg_t *msg); static void nxt_router_status_handler(nxt_task_t *task, - nxt_port_recv_msg_t *msg); + nxt_port_recv_msg_t *msg); static void nxt_router_remove_pid_handler(nxt_task_t *task, - nxt_port_recv_msg_t *msg); + nxt_port_recv_msg_t *msg); static nxt_router_temp_conf_t *nxt_router_temp_conf(nxt_task_t *task); static void nxt_router_conf_ready(nxt_task_t *task, - nxt_router_temp_conf_t *tmcf); -static void nxt_router_conf_send(nxt_task_t *task, - nxt_router_temp_conf_t *tmcf, nxt_port_msg_type_t type); + nxt_router_temp_conf_t *tmcf); +static void nxt_router_conf_send(nxt_task_t *task, nxt_router_temp_conf_t *tmcf, + nxt_port_msg_type_t type); static nxt_int_t nxt_router_conf_create(nxt_task_t *task, - nxt_router_temp_conf_t *tmcf, u_char *start, u_char *end); + nxt_router_temp_conf_t *tmcf, + u_char *start, u_char *end); static nxt_int_t nxt_router_conf_process_static(nxt_task_t *task, - nxt_router_conf_t *rtcf, nxt_conf_value_t *conf); -static nxt_http_forward_t *nxt_router_conf_forward(nxt_task_t *task, - nxt_mp_t *mp, nxt_conf_value_t *conf); + nxt_router_conf_t *rtcf, + nxt_conf_value_t *conf); +static nxt_http_forward_t * +nxt_router_conf_forward(nxt_task_t *task, nxt_mp_t *mp, nxt_conf_value_t *conf); static nxt_int_t nxt_router_conf_forward_header(nxt_mp_t *mp, - nxt_conf_value_t *conf, nxt_http_forward_header_t *fh); + nxt_conf_value_t *conf, + nxt_http_forward_header_t *fh); static nxt_app_t *nxt_router_app_find(nxt_queue_t *queue, nxt_str_t *name); static nxt_int_t nxt_router_apps_hash_test(nxt_lvlhsh_query_t *lhq, void *data); static nxt_int_t nxt_router_apps_hash_add(nxt_router_conf_t *rtcf, - nxt_app_t *app); + nxt_app_t *app); static nxt_app_t *nxt_router_apps_hash_get(nxt_router_conf_t *rtcf, - nxt_str_t *name); + nxt_str_t *name); static void nxt_router_apps_hash_use(nxt_task_t *task, nxt_router_conf_t *rtcf, - int i); + int i); -static nxt_int_t nxt_router_app_queue_init(nxt_task_t *task, - nxt_port_t *port); -static nxt_int_t nxt_router_port_queue_init(nxt_task_t *task, - nxt_port_t *port); -static nxt_int_t nxt_router_port_queue_map(nxt_task_t *task, - nxt_port_t *port, nxt_fd_t fd); +static nxt_int_t nxt_router_app_queue_init(nxt_task_t *task, nxt_port_t *port); +static nxt_int_t nxt_router_port_queue_init(nxt_task_t *task, nxt_port_t *port); +static nxt_int_t nxt_router_port_queue_map(nxt_task_t *task, nxt_port_t *port, + nxt_fd_t fd); static void nxt_router_listen_socket_rpc_create(nxt_task_t *task, - nxt_router_temp_conf_t *tmcf, nxt_socket_conf_t *skcf); + nxt_router_temp_conf_t *tmcf, + nxt_socket_conf_t *skcf); static void nxt_router_listen_socket_ready(nxt_task_t *task, - nxt_port_recv_msg_t *msg, void *data); + nxt_port_recv_msg_t *msg, + void *data); static void nxt_router_listen_socket_error(nxt_task_t *task, - nxt_port_recv_msg_t *msg, void *data); + nxt_port_recv_msg_t *msg, + void *data); #if (NXT_TLS) static void nxt_router_tls_rpc_handler(nxt_task_t *task, - nxt_port_recv_msg_t *msg, void *data); + nxt_port_recv_msg_t *msg, void *data); static nxt_int_t nxt_router_conf_tls_insert(nxt_router_temp_conf_t *tmcf, - nxt_conf_value_t *value, nxt_socket_conf_t *skcf, nxt_tls_init_t *tls_init, - nxt_bool_t last); + nxt_conf_value_t *value, + nxt_socket_conf_t *skcf, + nxt_tls_init_t *tls_init, + nxt_bool_t last); #endif #if (NXT_HAVE_NJS) static void nxt_router_js_module_rpc_handler(nxt_task_t *task, - nxt_port_recv_msg_t *msg, void *data); + nxt_port_recv_msg_t *msg, + void *data); static nxt_int_t nxt_router_js_module_insert(nxt_router_temp_conf_t *tmcf, - nxt_conf_value_t *value); + nxt_conf_value_t *value); #endif static void nxt_router_app_rpc_create(nxt_task_t *task, - nxt_router_temp_conf_t *tmcf, nxt_app_t *app); + nxt_router_temp_conf_t *tmcf, + nxt_app_t *app); static void nxt_router_app_prefork_ready(nxt_task_t *task, - nxt_port_recv_msg_t *msg, void *data); + nxt_port_recv_msg_t *msg, void *data); static void nxt_router_app_prefork_error(nxt_task_t *task, - nxt_port_recv_msg_t *msg, void *data); + nxt_port_recv_msg_t *msg, void *data); static nxt_socket_conf_t *nxt_router_socket_conf(nxt_task_t *task, - nxt_router_temp_conf_t *tmcf, nxt_str_t *name, int backlog); + nxt_router_temp_conf_t *tmcf, + nxt_str_t *name, int backlog); static nxt_int_t nxt_router_listen_socket_find(nxt_router_temp_conf_t *tmcf, - nxt_socket_conf_t *nskcf, nxt_sockaddr_t *sa); + nxt_socket_conf_t *nskcf, + nxt_sockaddr_t *sa); -static nxt_int_t nxt_router_engines_create(nxt_task_t *task, - nxt_router_t *router, nxt_router_temp_conf_t *tmcf, - const nxt_event_interface_t *interface); +static nxt_int_t +nxt_router_engines_create(nxt_task_t *task, nxt_router_t *router, + nxt_router_temp_conf_t *tmcf, + const nxt_event_interface_t *interface); static nxt_int_t nxt_router_engine_conf_create(nxt_router_temp_conf_t *tmcf, - nxt_router_engine_conf_t *recf); + nxt_router_engine_conf_t *recf); static nxt_int_t nxt_router_engine_conf_update(nxt_router_temp_conf_t *tmcf, - nxt_router_engine_conf_t *recf); + nxt_router_engine_conf_t *recf); static nxt_int_t nxt_router_engine_conf_delete(nxt_router_temp_conf_t *tmcf, - nxt_router_engine_conf_t *recf); + nxt_router_engine_conf_t *recf); static nxt_int_t nxt_router_engine_joints_create(nxt_router_temp_conf_t *tmcf, - nxt_router_engine_conf_t *recf, nxt_queue_t *sockets, - nxt_work_handler_t handler); + nxt_router_engine_conf_t *recf, + nxt_queue_t *sockets, + nxt_work_handler_t handler); static nxt_int_t nxt_router_engine_quit(nxt_router_temp_conf_t *tmcf, - nxt_router_engine_conf_t *recf); + nxt_router_engine_conf_t *recf); static nxt_int_t nxt_router_engine_joints_delete(nxt_router_temp_conf_t *tmcf, - nxt_router_engine_conf_t *recf, nxt_queue_t *sockets); + nxt_router_engine_conf_t *recf, + nxt_queue_t *sockets); static nxt_int_t nxt_router_threads_create(nxt_task_t *task, nxt_runtime_t *rt, - nxt_router_temp_conf_t *tmcf); + nxt_router_temp_conf_t *tmcf); static nxt_int_t nxt_router_thread_create(nxt_task_t *task, nxt_runtime_t *rt, - nxt_event_engine_t *engine); + nxt_event_engine_t *engine); static void nxt_router_apps_sort(nxt_task_t *task, nxt_router_t *router, - nxt_router_temp_conf_t *tmcf); + nxt_router_temp_conf_t *tmcf); static void nxt_router_engines_post(nxt_router_t *router, - nxt_router_temp_conf_t *tmcf); + nxt_router_temp_conf_t *tmcf); static void nxt_router_engine_post(nxt_event_engine_t *engine, - nxt_work_t *jobs); + nxt_work_t *jobs); static void nxt_router_thread_start(void *data); -static void nxt_router_rt_add_port(nxt_task_t *task, void *obj, - void *data); +static void nxt_router_rt_add_port(nxt_task_t *task, void *obj, void *data); static void nxt_router_listen_socket_create(nxt_task_t *task, void *obj, - void *data); + void *data); static void nxt_router_listen_socket_update(nxt_task_t *task, void *obj, - void *data); + void *data); static void nxt_router_listen_socket_delete(nxt_task_t *task, void *obj, - void *data); + void *data); static void nxt_router_worker_thread_quit(nxt_task_t *task, void *obj, - void *data); + void *data); static void nxt_router_listen_socket_close(nxt_task_t *task, void *obj, - void *data); + void *data); static void nxt_router_thread_exit_handler(nxt_task_t *task, void *obj, - void *data); -static void nxt_router_req_headers_ack_handler(nxt_task_t *task, - nxt_port_recv_msg_t *msg, nxt_request_rpc_data_t *req_rpc_data); + void *data); +static void +nxt_router_req_headers_ack_handler(nxt_task_t *task, nxt_port_recv_msg_t *msg, + nxt_request_rpc_data_t *req_rpc_data); static void nxt_router_listen_socket_release(nxt_task_t *task, - nxt_socket_conf_t *skcf); + nxt_socket_conf_t *skcf); static void nxt_router_app_port_ready(nxt_task_t *task, - nxt_port_recv_msg_t *msg, void *data); + nxt_port_recv_msg_t *msg, void *data); static void nxt_router_app_port_error(nxt_task_t *task, - nxt_port_recv_msg_t *msg, void *data); + nxt_port_recv_msg_t *msg, void *data); static void nxt_router_app_use(nxt_task_t *task, nxt_app_t *app, int i); static void nxt_router_app_unlink(nxt_task_t *task, nxt_app_t *app); static void nxt_router_app_port_release(nxt_task_t *task, nxt_app_t *app, - nxt_port_t *port, nxt_apr_action_t action); + nxt_port_t *port, + nxt_apr_action_t action); static void nxt_router_app_port_get(nxt_task_t *task, nxt_app_t *app, - nxt_request_rpc_data_t *req_rpc_data); + nxt_request_rpc_data_t *req_rpc_data); static void nxt_router_http_request_error(nxt_task_t *task, void *obj, - void *data); + void *data); static void nxt_router_http_request_done(nxt_task_t *task, void *obj, - void *data); + void *data); -static void nxt_router_app_prepare_request(nxt_task_t *task, - nxt_request_rpc_data_t *req_rpc_data); +static void +nxt_router_app_prepare_request(nxt_task_t *task, + nxt_request_rpc_data_t *req_rpc_data); static nxt_buf_t *nxt_router_prepare_msg(nxt_task_t *task, - nxt_http_request_t *r, nxt_app_t *app, const nxt_str_t *prefix); + nxt_http_request_t *r, nxt_app_t *app, + const nxt_str_t *prefix); static void nxt_router_app_timeout(nxt_task_t *task, void *obj, void *data); static void nxt_router_adjust_idle_timer(nxt_task_t *task, void *obj, - void *data); + void *data); static void nxt_router_app_idle_timeout(nxt_task_t *task, void *obj, - void *data); + void *data); static void nxt_router_app_joint_release_handler(nxt_task_t *task, void *obj, - void *data); + void *data); static void nxt_router_free_app(nxt_task_t *task, void *obj, void *data); -static const nxt_http_request_state_t nxt_http_request_send_state; +static const nxt_http_request_state_t nxt_http_request_send_state; static void nxt_http_request_send_body(nxt_task_t *task, void *obj, void *data); static void nxt_router_app_joint_use(nxt_task_t *task, - nxt_app_joint_t *app_joint, int i); + nxt_app_joint_t *app_joint, int i); static void nxt_router_http_request_release_post(nxt_task_t *task, - nxt_http_request_t *r); + nxt_http_request_t *r); static void nxt_router_http_request_release(nxt_task_t *task, void *obj, - void *data); + void *data); static void nxt_router_oosm_handler(nxt_task_t *task, nxt_port_recv_msg_t *msg); static void nxt_router_get_port_handler(nxt_task_t *task, - nxt_port_recv_msg_t *msg); + nxt_port_recv_msg_t *msg); static void nxt_router_get_mmap_handler(nxt_task_t *task, - nxt_port_recv_msg_t *msg); + nxt_port_recv_msg_t *msg); -extern const nxt_http_request_state_t nxt_http_websocket; +extern const nxt_http_request_state_t nxt_http_websocket; -nxt_router_t *nxt_router; +nxt_router_t *nxt_router; static const nxt_str_t http_prefix = nxt_string("HTTP_"); static const nxt_str_t empty_prefix = nxt_string(""); -static const nxt_str_t *nxt_app_msg_prefix[] = { - [NXT_APP_EXTERNAL] = &empty_prefix, - [NXT_APP_PYTHON] = &empty_prefix, - [NXT_APP_PHP] = &http_prefix, - [NXT_APP_PERL] = &http_prefix, - [NXT_APP_RUBY] = &http_prefix, - [NXT_APP_JAVA] = &empty_prefix, - [NXT_APP_WASM] = &empty_prefix, - [NXT_APP_WASM_WC] = &empty_prefix, +static const nxt_str_t *nxt_app_msg_prefix[] = { + [NXT_APP_EXTERNAL] = &empty_prefix, [NXT_APP_PYTHON] = &empty_prefix, + [NXT_APP_PHP] = &http_prefix, [NXT_APP_PERL] = &http_prefix, + [NXT_APP_RUBY] = &http_prefix, [NXT_APP_JAVA] = &empty_prefix, + [NXT_APP_WASM] = &empty_prefix, [NXT_APP_WASM_WC] = &empty_prefix, }; - -static const nxt_port_handlers_t nxt_router_process_port_handlers = { - .quit = nxt_signal_quit_handler, - .new_port = nxt_router_new_port_handler, - .get_port = nxt_router_get_port_handler, - .change_file = nxt_port_change_log_file_handler, - .mmap = nxt_port_mmap_handler, - .get_mmap = nxt_router_get_mmap_handler, - .data = nxt_router_conf_data_handler, - .app_restart = nxt_router_app_restart_handler, - .status = nxt_router_status_handler, - .remove_pid = nxt_router_remove_pid_handler, - .access_log = nxt_router_access_log_reopen_handler, - .rpc_ready = nxt_port_rpc_handler, - .rpc_error = nxt_port_rpc_handler, - .oosm = nxt_router_oosm_handler, +static const nxt_port_handlers_t nxt_router_process_port_handlers = { + .quit = nxt_signal_quit_handler, + .new_port = nxt_router_new_port_handler, + .get_port = nxt_router_get_port_handler, + .change_file = nxt_port_change_log_file_handler, + .mmap = nxt_port_mmap_handler, + .get_mmap = nxt_router_get_mmap_handler, + .data = nxt_router_conf_data_handler, + .app_restart = nxt_router_app_restart_handler, + .status = nxt_router_status_handler, + .remove_pid = nxt_router_remove_pid_handler, + .access_log = nxt_router_access_log_reopen_handler, + .rpc_ready = nxt_port_rpc_handler, + .rpc_error = nxt_port_rpc_handler, + .oosm = nxt_router_oosm_handler, }; - -const nxt_process_init_t nxt_router_process = { - .name = "router", - .type = NXT_PROCESS_ROUTER, - .prefork = nxt_router_prefork, - .restart = 1, - .setup = nxt_process_core_setup, - .start = nxt_router_start, - .port_handlers = &nxt_router_process_port_handlers, - .signals = nxt_process_signals, +const nxt_process_init_t nxt_router_process = { + .name = "router", + .type = NXT_PROCESS_ROUTER, + .prefork = nxt_router_prefork, + .restart = 1, + .setup = nxt_process_core_setup, + .start = nxt_router_start, + .port_handlers = &nxt_router_process_port_handlers, + .signals = nxt_process_signals, }; - /* Queues of nxt_socket_conf_t */ -nxt_queue_t creating_sockets; -nxt_queue_t pending_sockets; -nxt_queue_t updating_sockets; -nxt_queue_t keeping_sockets; -nxt_queue_t deleting_sockets; +nxt_queue_t creating_sockets; +nxt_queue_t pending_sockets; +nxt_queue_t updating_sockets; +nxt_queue_t keeping_sockets; +nxt_queue_t deleting_sockets; +static nxt_int_t nxt_router_prefork(nxt_task_t *task, nxt_process_t *process, + nxt_mp_t *mp) { + nxt_runtime_stop_app_processes(task, task->thread->runtime); -static nxt_int_t -nxt_router_prefork(nxt_task_t *task, nxt_process_t *process, nxt_mp_t *mp) -{ - nxt_runtime_stop_app_processes(task, task->thread->runtime); - - return NXT_OK; + return NXT_OK; } +static nxt_int_t nxt_router_start(nxt_task_t *task, nxt_process_data_t *data) { + nxt_int_t ret; + nxt_port_t *controller_port; + nxt_router_t *router; + nxt_runtime_t *rt; -static nxt_int_t -nxt_router_start(nxt_task_t *task, nxt_process_data_t *data) -{ - nxt_int_t ret; - nxt_port_t *controller_port; - nxt_router_t *router; - nxt_runtime_t *rt; - - rt = task->thread->runtime; + rt = task->thread->runtime; - nxt_log(task, NXT_LOG_INFO, "router started"); + nxt_log(task, NXT_LOG_INFO, "router started"); #if (NXT_TLS) - rt->tls = nxt_service_get(rt->services, "SSL/TLS", "OpenSSL"); - if (nxt_slow_path(rt->tls == NULL)) { - return NXT_ERROR; - } + rt->tls = nxt_service_get(rt->services, "SSL/TLS", "OpenSSL"); + if (nxt_slow_path(rt->tls == NULL)) { + return NXT_ERROR; + } - ret = rt->tls->library_init(task); - if (nxt_slow_path(ret != NXT_OK)) { - return ret; - } + ret = rt->tls->library_init(task); + if (nxt_slow_path(ret != NXT_OK)) { + return ret; + } #endif - ret = nxt_http_init(task); - if (nxt_slow_path(ret != NXT_OK)) { - return ret; - } + ret = nxt_http_init(task); + if (nxt_slow_path(ret != NXT_OK)) { + return ret; + } - router = nxt_zalloc(sizeof(nxt_router_t)); - if (nxt_slow_path(router == NULL)) { - return NXT_ERROR; - } + router = nxt_zalloc(sizeof(nxt_router_t)); + if (nxt_slow_path(router == NULL)) { + return NXT_ERROR; + } - nxt_queue_init(&router->engines); - nxt_queue_init(&router->sockets); - nxt_queue_init(&router->apps); + nxt_queue_init(&router->engines); + nxt_queue_init(&router->sockets); + nxt_queue_init(&router->apps); - nxt_router = router; + nxt_router = router; - controller_port = rt->port_by_type[NXT_PROCESS_CONTROLLER]; - if (controller_port != NULL) { - nxt_router_greet_controller(task, controller_port); - } + controller_port = rt->port_by_type[NXT_PROCESS_CONTROLLER]; + if (controller_port != NULL) { + nxt_router_greet_controller(task, controller_port); + } - return NXT_OK; + return NXT_OK; } - -static void -nxt_router_greet_controller(nxt_task_t *task, nxt_port_t *controller_port) -{ - nxt_port_socket_write(task, controller_port, NXT_PORT_MSG_PROCESS_READY, - -1, 0, 0, NULL); +static void nxt_router_greet_controller(nxt_task_t *task, + nxt_port_t *controller_port) { + nxt_port_socket_write(task, controller_port, NXT_PORT_MSG_PROCESS_READY, -1, + 0, 0, NULL); } +static void nxt_router_start_app_process_handler(nxt_task_t *task, + nxt_port_t *port, void *data) { + size_t size; + uint32_t stream; + nxt_fd_t port_fd, queue_fd; + nxt_int_t ret; + nxt_app_t *app; + nxt_buf_t *b; + nxt_port_t *dport; + nxt_runtime_t *rt; + nxt_app_joint_rpc_t *app_joint_rpc; -static void -nxt_router_start_app_process_handler(nxt_task_t *task, nxt_port_t *port, - void *data) -{ - size_t size; - uint32_t stream; - nxt_fd_t port_fd, queue_fd; - nxt_int_t ret; - nxt_app_t *app; - nxt_buf_t *b; - nxt_port_t *dport; - nxt_runtime_t *rt; - nxt_app_joint_rpc_t *app_joint_rpc; - - app = data; + app = data; - nxt_thread_mutex_lock(&app->mutex); + nxt_thread_mutex_lock(&app->mutex); - dport = app->proto_port; + dport = app->proto_port; - nxt_thread_mutex_unlock(&app->mutex); + nxt_thread_mutex_unlock(&app->mutex); - if (dport != NULL) { - nxt_debug(task, "app '%V' %p start process", &app->name, app); + if (dport != NULL) { + nxt_debug(task, "app '%V' %p start process", &app->name, app); - b = NULL; - port_fd = -1; - queue_fd = -1; + b = NULL; + port_fd = -1; + queue_fd = -1; - } else { - if (app->proto_port_requests > 0) { - nxt_debug(task, "app '%V' %p wait for prototype process", - &app->name, app); + } else { + if (app->proto_port_requests > 0) { + nxt_debug(task, "app '%V' %p wait for prototype process", &app->name, + app); - app->proto_port_requests++; + app->proto_port_requests++; - goto skip; - } + goto skip; + } - nxt_debug(task, "app '%V' %p start prototype process", &app->name, app); + nxt_debug(task, "app '%V' %p start prototype process", &app->name, app); - rt = task->thread->runtime; - dport = rt->port_by_type[NXT_PROCESS_MAIN]; + rt = task->thread->runtime; + dport = rt->port_by_type[NXT_PROCESS_MAIN]; - size = app->name.length + 1 + app->conf.length; + size = app->name.length + 1 + app->conf.length; - b = nxt_buf_mem_alloc(task->thread->engine->mem_pool, size, 0); - if (nxt_slow_path(b == NULL)) { - goto failed; - } + b = nxt_buf_mem_alloc(task->thread->engine->mem_pool, size, 0); + if (nxt_slow_path(b == NULL)) { + goto failed; + } - nxt_buf_cpystr(b, &app->name); - *b->mem.free++ = '\0'; - nxt_buf_cpystr(b, &app->conf); + nxt_buf_cpystr(b, &app->name); + *b->mem.free++ = '\0'; + nxt_buf_cpystr(b, &app->conf); - port_fd = app->shared_port->pair[0]; - queue_fd = app->shared_port->queue_fd; - } + port_fd = app->shared_port->pair[0]; + queue_fd = app->shared_port->queue_fd; + } - app_joint_rpc = nxt_port_rpc_register_handler_ex(task, port, - nxt_router_app_port_ready, - nxt_router_app_port_error, - sizeof(nxt_app_joint_rpc_t)); - if (nxt_slow_path(app_joint_rpc == NULL)) { - goto failed; - } + app_joint_rpc = nxt_port_rpc_register_handler_ex( + task, port, nxt_router_app_port_ready, nxt_router_app_port_error, + sizeof(nxt_app_joint_rpc_t)); + if (nxt_slow_path(app_joint_rpc == NULL)) { + goto failed; + } - stream = nxt_port_rpc_ex_stream(app_joint_rpc); + stream = nxt_port_rpc_ex_stream(app_joint_rpc); - ret = nxt_port_socket_write2(task, dport, NXT_PORT_MSG_START_PROCESS, - port_fd, queue_fd, stream, port->id, b); - if (nxt_slow_path(ret != NXT_OK)) { - nxt_port_rpc_cancel(task, port, stream); + ret = nxt_port_socket_write2(task, dport, NXT_PORT_MSG_START_PROCESS, port_fd, + queue_fd, stream, port->id, b); + if (nxt_slow_path(ret != NXT_OK)) { + nxt_port_rpc_cancel(task, port, stream); - goto failed; - } + goto failed; + } - app_joint_rpc->app_joint = app->joint; - app_joint_rpc->generation = app->generation; - app_joint_rpc->proto = (b != NULL); + app_joint_rpc->app_joint = app->joint; + app_joint_rpc->generation = app->generation; + app_joint_rpc->proto = (b != NULL); - if (b != NULL) { - app->proto_port_requests++; + if (b != NULL) { + app->proto_port_requests++; - b = NULL; - } + b = NULL; + } - nxt_router_app_joint_use(task, app->joint, 1); + nxt_router_app_joint_use(task, app->joint, 1); failed: - if (b != NULL) { - nxt_mp_free(b->data, b); - } + if (b != NULL) { + nxt_mp_free(b->data, b); + } skip: - nxt_router_app_use(task, app, -1); + nxt_router_app_use(task, app, -1); } +static void nxt_router_app_joint_use(nxt_task_t *task, + nxt_app_joint_t *app_joint, int i) { + app_joint->use_count += i; -static void -nxt_router_app_joint_use(nxt_task_t *task, nxt_app_joint_t *app_joint, int i) -{ - app_joint->use_count += i; - - if (app_joint->use_count == 0) { - nxt_assert(app_joint->app == NULL); + if (app_joint->use_count == 0) { + nxt_assert(app_joint->app == NULL); - nxt_free(app_joint); - } + nxt_free(app_joint); + } } +static nxt_int_t nxt_router_start_app_process(nxt_task_t *task, + nxt_app_t *app) { + nxt_int_t res; + nxt_port_t *router_port; + nxt_runtime_t *rt; -static nxt_int_t -nxt_router_start_app_process(nxt_task_t *task, nxt_app_t *app) -{ - nxt_int_t res; - nxt_port_t *router_port; - nxt_runtime_t *rt; - - nxt_debug(task, "app '%V' start process", &app->name); + nxt_debug(task, "app '%V' start process", &app->name); - rt = task->thread->runtime; - router_port = rt->port_by_type[NXT_PROCESS_ROUTER]; + rt = task->thread->runtime; + router_port = rt->port_by_type[NXT_PROCESS_ROUTER]; - nxt_router_app_use(task, app, 1); + nxt_router_app_use(task, app, 1); - res = nxt_port_post(task, router_port, nxt_router_start_app_process_handler, - app); + res = nxt_port_post(task, router_port, nxt_router_start_app_process_handler, + app); - if (res == NXT_OK) { - return res; - } + if (res == NXT_OK) { + return res; + } - nxt_thread_mutex_lock(&app->mutex); + nxt_thread_mutex_lock(&app->mutex); - app->pending_processes--; + app->pending_processes--; - nxt_thread_mutex_unlock(&app->mutex); + nxt_thread_mutex_unlock(&app->mutex); - nxt_router_app_use(task, app, -1); + nxt_router_app_use(task, app, -1); - return NXT_ERROR; + return NXT_ERROR; } - nxt_inline nxt_bool_t -nxt_router_msg_cancel(nxt_task_t *task, nxt_request_rpc_data_t *req_rpc_data) -{ - nxt_buf_t *b, *next; - nxt_bool_t cancelled; - nxt_port_t *app_port; - nxt_msg_info_t *msg_info; - - msg_info = &req_rpc_data->msg_info; +nxt_router_msg_cancel(nxt_task_t *task, nxt_request_rpc_data_t *req_rpc_data) { + nxt_buf_t *b, *next; + nxt_bool_t cancelled; + nxt_port_t *app_port; + nxt_msg_info_t *msg_info; - if (msg_info->buf == NULL) { - return 0; - } + msg_info = &req_rpc_data->msg_info; - app_port = req_rpc_data->app_port; + if (msg_info->buf == NULL) { + return 0; + } - if (app_port != NULL && app_port->id == NXT_SHARED_PORT_ID) { - cancelled = nxt_app_queue_cancel(app_port->queue, - msg_info->tracking_cookie, - req_rpc_data->stream); + app_port = req_rpc_data->app_port; - if (cancelled) { - nxt_debug(task, "stream #%uD: cancelled by router", - req_rpc_data->stream); - } + if (app_port != NULL && app_port->id == NXT_SHARED_PORT_ID) { + cancelled = nxt_app_queue_cancel(app_port->queue, msg_info->tracking_cookie, + req_rpc_data->stream); - } else { - cancelled = 0; + if (cancelled) { + nxt_debug(task, "stream #%uD: cancelled by router", req_rpc_data->stream); } - for (b = msg_info->buf; b != NULL; b = next) { - next = b->next; - b->next = NULL; + } else { + cancelled = 0; + } - if (b->is_port_mmap_sent) { - b->is_port_mmap_sent = cancelled == 0; - } + for (b = msg_info->buf; b != NULL; b = next) { + next = b->next; + b->next = NULL; - b->completion_handler(task, b, b->parent); + if (b->is_port_mmap_sent) { + b->is_port_mmap_sent = cancelled == 0; } - msg_info->buf = NULL; + b->completion_handler(task, b, b->parent); + } - return cancelled; -} + msg_info->buf = NULL; + return cancelled; +} -nxt_inline nxt_bool_t -nxt_queue_chk_remove(nxt_queue_link_t *lnk) -{ - if (lnk->next != NULL) { - nxt_queue_remove(lnk); +nxt_inline nxt_bool_t nxt_queue_chk_remove(nxt_queue_link_t *lnk) { + if (lnk->next != NULL) { + nxt_queue_remove(lnk); - lnk->next = NULL; + lnk->next = NULL; - return 1; - } + return 1; + } - return 0; + return 0; } - nxt_inline void nxt_request_rpc_data_unlink(nxt_task_t *task, - nxt_request_rpc_data_t *req_rpc_data) -{ - nxt_app_t *app; - nxt_bool_t unlinked; - nxt_http_request_t *r; + nxt_request_rpc_data_t *req_rpc_data) { + nxt_app_t *app; + nxt_bool_t unlinked; + nxt_http_request_t *r; - nxt_router_msg_cancel(task, req_rpc_data); + nxt_router_msg_cancel(task, req_rpc_data); - app = req_rpc_data->app; + app = req_rpc_data->app; - if (req_rpc_data->app_port != NULL) { - nxt_router_app_port_release(task, app, req_rpc_data->app_port, - req_rpc_data->apr_action); + if (req_rpc_data->app_port != NULL) { + nxt_router_app_port_release(task, app, req_rpc_data->app_port, + req_rpc_data->apr_action); - req_rpc_data->app_port = NULL; - } + req_rpc_data->app_port = NULL; + } - r = req_rpc_data->request; + r = req_rpc_data->request; - if (r != NULL) { - r->timer_data = NULL; + if (r != NULL) { + r->timer_data = NULL; - nxt_router_http_request_release_post(task, r); + nxt_router_http_request_release_post(task, r); - r->req_rpc_data = NULL; - req_rpc_data->request = NULL; + r->req_rpc_data = NULL; + req_rpc_data->request = NULL; - if (app != NULL) { - unlinked = 0; + if (app != NULL) { + unlinked = 0; - nxt_thread_mutex_lock(&app->mutex); + nxt_thread_mutex_lock(&app->mutex); - if (r->app_link.next != NULL) { - nxt_queue_remove(&r->app_link); - r->app_link.next = NULL; + if (r->app_link.next != NULL) { + nxt_queue_remove(&r->app_link); + r->app_link.next = NULL; - unlinked = 1; - } + unlinked = 1; + } - nxt_thread_mutex_unlock(&app->mutex); + nxt_thread_mutex_unlock(&app->mutex); - if (unlinked) { - nxt_mp_release(r->mem_pool); - } - } + if (unlinked) { + nxt_mp_release(r->mem_pool); + } } + } - if (app != NULL) { - nxt_router_app_use(task, app, -1); + if (app != NULL) { + nxt_router_app_use(task, app, -1); - req_rpc_data->app = NULL; - } + req_rpc_data->app = NULL; + } - if (req_rpc_data->msg_info.body_fd != -1) { - nxt_fd_close(req_rpc_data->msg_info.body_fd); + if (req_rpc_data->msg_info.body_fd != -1) { + nxt_fd_close(req_rpc_data->msg_info.body_fd); - req_rpc_data->msg_info.body_fd = -1; - } + req_rpc_data->msg_info.body_fd = -1; + } - if (req_rpc_data->rpc_cancel) { - req_rpc_data->rpc_cancel = 0; + if (req_rpc_data->rpc_cancel) { + req_rpc_data->rpc_cancel = 0; - nxt_port_rpc_cancel(task, task->thread->engine->port, - req_rpc_data->stream); - } + nxt_port_rpc_cancel(task, task->thread->engine->port, req_rpc_data->stream); + } } +static void nxt_router_new_port_handler(nxt_task_t *task, + nxt_port_recv_msg_t *msg) { + nxt_int_t res; + nxt_app_t *app; + nxt_port_t *port, *main_app_port; + nxt_runtime_t *rt; -static void -nxt_router_new_port_handler(nxt_task_t *task, nxt_port_recv_msg_t *msg) -{ - nxt_int_t res; - nxt_app_t *app; - nxt_port_t *port, *main_app_port; - nxt_runtime_t *rt; + nxt_port_new_port_handler(task, msg); - nxt_port_new_port_handler(task, msg); + port = msg->u.new_port; - port = msg->u.new_port; + if (port != NULL && port->type == NXT_PROCESS_CONTROLLER) { + nxt_router_greet_controller(task, msg->u.new_port); + } - if (port != NULL && port->type == NXT_PROCESS_CONTROLLER) { - nxt_router_greet_controller(task, msg->u.new_port); - } + if (port != NULL && port->type == NXT_PROCESS_PROTOTYPE) { + nxt_port_rpc_handler(task, msg); - if (port != NULL && port->type == NXT_PROCESS_PROTOTYPE) { - nxt_port_rpc_handler(task, msg); + return; + } - return; - } + if (port == NULL || port->type != NXT_PROCESS_APP) { - if (port == NULL || port->type != NXT_PROCESS_APP) { + if (msg->port_msg.stream == 0) { + return; + } - if (msg->port_msg.stream == 0) { - return; - } + msg->port_msg.type = _NXT_PORT_MSG_RPC_ERROR; - msg->port_msg.type = _NXT_PORT_MSG_RPC_ERROR; + } else { + if (msg->fd[1] != -1) { + res = nxt_router_port_queue_map(task, port, msg->fd[1]); + if (nxt_slow_path(res != NXT_OK)) { + return; + } - } else { - if (msg->fd[1] != -1) { - res = nxt_router_port_queue_map(task, port, msg->fd[1]); - if (nxt_slow_path(res != NXT_OK)) { - return; - } - - nxt_fd_close(msg->fd[1]); - msg->fd[1] = -1; - } + nxt_fd_close(msg->fd[1]); + msg->fd[1] = -1; } + } - if (msg->port_msg.stream != 0) { - nxt_port_rpc_handler(task, msg); - return; - } + if (msg->port_msg.stream != 0) { + nxt_port_rpc_handler(task, msg); + return; + } - nxt_debug(task, "new port id %d (%d)", port->id, port->type); + nxt_debug(task, "new port id %d (%d)", port->id, port->type); - /* - * Port with "id == 0" is application 'main' port and it always - * should come with non-zero stream. - */ - nxt_assert(port->id != 0); + /* + * Port with "id == 0" is application 'main' port and it always + * should come with non-zero stream. + */ + nxt_assert(port->id != 0); - /* Find 'main' app port and get app reference. */ - rt = task->thread->runtime; + /* Find 'main' app port and get app reference. */ + rt = task->thread->runtime; - /* - * It is safe to access 'runtime->ports' hash because 'NEW_PORT' - * sent to main port (with id == 0) and processed in main thread. - */ - main_app_port = nxt_port_hash_find(&rt->ports, port->pid, 0); - nxt_assert(main_app_port != NULL); + /* + * It is safe to access 'runtime->ports' hash because 'NEW_PORT' + * sent to main port (with id == 0) and processed in main thread. + */ + main_app_port = nxt_port_hash_find(&rt->ports, port->pid, 0); + nxt_assert(main_app_port != NULL); - app = main_app_port->app; + app = main_app_port->app; - if (nxt_fast_path(app != NULL)) { - nxt_thread_mutex_lock(&app->mutex); + if (nxt_fast_path(app != NULL)) { + nxt_thread_mutex_lock(&app->mutex); - /* TODO here should be find-and-add code because there can be - port waiters in port_hash */ - nxt_port_hash_add(&app->port_hash, port); - app->port_hash_count++; + /* TODO here should be find-and-add code because there can be + port waiters in port_hash */ + nxt_port_hash_add(&app->port_hash, port); + app->port_hash_count++; - nxt_thread_mutex_unlock(&app->mutex); + nxt_thread_mutex_unlock(&app->mutex); - port->app = app; - } + port->app = app; + } - port->main_app_port = main_app_port; + port->main_app_port = main_app_port; - nxt_port_socket_write(task, port, NXT_PORT_MSG_PORT_ACK, -1, 0, 0, NULL); + nxt_port_socket_write(task, port, NXT_PORT_MSG_PORT_ACK, -1, 0, 0, NULL); } +static void nxt_router_conf_data_handler(nxt_task_t *task, + nxt_port_recv_msg_t *msg) { + void *p; + size_t size; + nxt_int_t ret; + nxt_port_t *port; + nxt_router_temp_conf_t *tmcf; + + port = nxt_runtime_port_find(task->thread->runtime, msg->port_msg.pid, + msg->port_msg.reply_port); + if (nxt_slow_path(port == NULL)) { + nxt_alert(task, "conf_data_handler: reply port not found"); + return; + } -static void -nxt_router_conf_data_handler(nxt_task_t *task, nxt_port_recv_msg_t *msg) -{ - void *p; - size_t size; - nxt_int_t ret; - nxt_port_t *port; - nxt_router_temp_conf_t *tmcf; - - port = nxt_runtime_port_find(task->thread->runtime, - msg->port_msg.pid, - msg->port_msg.reply_port); - if (nxt_slow_path(port == NULL)) { - nxt_alert(task, "conf_data_handler: reply port not found"); - return; - } - - p = MAP_FAILED; + p = MAP_FAILED; - /* - * Ancient compilers like gcc 4.8.5 on CentOS 7 wants 'size' to be - * initialized in 'cleanup' section. - */ - size = 0; + /* + * Ancient compilers like gcc 4.8.5 on CentOS 7 wants 'size' to be + * initialized in 'cleanup' section. + */ + size = 0; - tmcf = nxt_router_temp_conf(task); - if (nxt_slow_path(tmcf == NULL)) { - goto fail; - } + tmcf = nxt_router_temp_conf(task); + if (nxt_slow_path(tmcf == NULL)) { + goto fail; + } - if (nxt_slow_path(msg->fd[0] == -1)) { - nxt_alert(task, "conf_data_handler: invalid shm fd"); - goto fail; - } + if (nxt_slow_path(msg->fd[0] == -1)) { + nxt_alert(task, "conf_data_handler: invalid shm fd"); + goto fail; + } - if (nxt_buf_mem_used_size(&msg->buf->mem) != sizeof(size_t)) { - nxt_alert(task, "conf_data_handler: unexpected buffer size (%d)", - (int) nxt_buf_mem_used_size(&msg->buf->mem)); - goto fail; - } + if (nxt_buf_mem_used_size(&msg->buf->mem) != sizeof(size_t)) { + nxt_alert(task, "conf_data_handler: unexpected buffer size (%d)", + (int)nxt_buf_mem_used_size(&msg->buf->mem)); + goto fail; + } - nxt_memcpy(&size, msg->buf->mem.pos, sizeof(size_t)); + nxt_memcpy(&size, msg->buf->mem.pos, sizeof(size_t)); - p = nxt_mem_mmap(NULL, size, PROT_READ, MAP_SHARED, msg->fd[0], 0); + p = nxt_mem_mmap(NULL, size, PROT_READ, MAP_SHARED, msg->fd[0], 0); - nxt_fd_close(msg->fd[0]); - msg->fd[0] = -1; + nxt_fd_close(msg->fd[0]); + msg->fd[0] = -1; - if (nxt_slow_path(p == MAP_FAILED)) { - goto fail; - } + if (nxt_slow_path(p == MAP_FAILED)) { + goto fail; + } - nxt_debug(task, "conf_data_handler(%uz): %*s", size, size, p); + nxt_debug(task, "conf_data_handler(%uz): %*s", size, size, p); - tmcf->router_conf->router = nxt_router; - tmcf->stream = msg->port_msg.stream; - tmcf->port = port; + tmcf->router_conf->router = nxt_router; + tmcf->stream = msg->port_msg.stream; + tmcf->port = port; - nxt_port_use(task, tmcf->port, 1); + nxt_port_use(task, tmcf->port, 1); - ret = nxt_router_conf_create(task, tmcf, p, nxt_pointer_to(p, size)); + ret = nxt_router_conf_create(task, tmcf, p, nxt_pointer_to(p, size)); - if (nxt_fast_path(ret == NXT_OK)) { - nxt_router_conf_apply(task, tmcf, NULL); + if (nxt_fast_path(ret == NXT_OK)) { + nxt_router_conf_apply(task, tmcf, NULL); - } else { - nxt_router_conf_error(task, tmcf); - } + } else { + nxt_router_conf_error(task, tmcf); + } - goto cleanup; + goto cleanup; fail: - nxt_port_socket_write(task, port, NXT_PORT_MSG_RPC_ERROR, -1, - msg->port_msg.stream, 0, NULL); + nxt_port_socket_write(task, port, NXT_PORT_MSG_RPC_ERROR, -1, + msg->port_msg.stream, 0, NULL); - if (tmcf != NULL) { - nxt_mp_release(tmcf->mem_pool); - } + if (tmcf != NULL) { + nxt_mp_release(tmcf->mem_pool); + } cleanup: - if (p != MAP_FAILED) { - nxt_mem_munmap(p, size); - } + if (p != MAP_FAILED) { + nxt_mem_munmap(p, size); + } - if (msg->fd[0] != -1) { - nxt_fd_close(msg->fd[0]); - msg->fd[0] = -1; - } + if (msg->fd[0] != -1) { + nxt_fd_close(msg->fd[0]); + msg->fd[0] = -1; + } } +static void nxt_router_app_restart_handler(nxt_task_t *task, + nxt_port_recv_msg_t *msg) { + nxt_app_t *app; + nxt_int_t ret; + nxt_str_t app_name; + nxt_port_t *reply_port, *shared_port, *old_shared_port; + nxt_port_t *proto_port; + nxt_port_msg_type_t reply; + + reply_port = nxt_runtime_port_find(task->thread->runtime, msg->port_msg.pid, + msg->port_msg.reply_port); + if (nxt_slow_path(reply_port == NULL)) { + nxt_alert(task, "app_restart_handler: reply port not found"); + return; + } -static void -nxt_router_app_restart_handler(nxt_task_t *task, nxt_port_recv_msg_t *msg) -{ - nxt_app_t *app; - nxt_int_t ret; - nxt_str_t app_name; - nxt_port_t *reply_port, *shared_port, *old_shared_port; - nxt_port_t *proto_port; - nxt_port_msg_type_t reply; - - reply_port = nxt_runtime_port_find(task->thread->runtime, - msg->port_msg.pid, - msg->port_msg.reply_port); - if (nxt_slow_path(reply_port == NULL)) { - nxt_alert(task, "app_restart_handler: reply port not found"); - return; - } - - app_name.length = nxt_buf_mem_used_size(&msg->buf->mem); - app_name.start = msg->buf->mem.pos; + app_name.length = nxt_buf_mem_used_size(&msg->buf->mem); + app_name.start = msg->buf->mem.pos; - nxt_debug(task, "app_restart_handler: %V", &app_name); + nxt_debug(task, "app_restart_handler: %V", &app_name); - app = nxt_router_app_find(&nxt_router->apps, &app_name); + app = nxt_router_app_find(&nxt_router->apps, &app_name); - if (nxt_fast_path(app != NULL)) { - shared_port = nxt_port_new(task, NXT_SHARED_PORT_ID, nxt_pid, - NXT_PROCESS_APP); - if (nxt_slow_path(shared_port == NULL)) { - goto fail; - } + if (nxt_fast_path(app != NULL)) { + shared_port = + nxt_port_new(task, NXT_SHARED_PORT_ID, nxt_pid, NXT_PROCESS_APP); + if (nxt_slow_path(shared_port == NULL)) { + goto fail; + } - ret = nxt_port_socket_init(task, shared_port, 0); - if (nxt_slow_path(ret != NXT_OK)) { - nxt_port_use(task, shared_port, -1); - goto fail; - } + ret = nxt_port_socket_init(task, shared_port, 0); + if (nxt_slow_path(ret != NXT_OK)) { + nxt_port_use(task, shared_port, -1); + goto fail; + } - ret = nxt_router_app_queue_init(task, shared_port); - if (nxt_slow_path(ret != NXT_OK)) { - nxt_port_write_close(shared_port); - nxt_port_read_close(shared_port); - nxt_port_use(task, shared_port, -1); - goto fail; - } + ret = nxt_router_app_queue_init(task, shared_port); + if (nxt_slow_path(ret != NXT_OK)) { + nxt_port_write_close(shared_port); + nxt_port_read_close(shared_port); + nxt_port_use(task, shared_port, -1); + goto fail; + } - nxt_port_write_enable(task, shared_port); + nxt_port_write_enable(task, shared_port); - nxt_thread_mutex_lock(&app->mutex); + nxt_thread_mutex_lock(&app->mutex); - proto_port = app->proto_port; + proto_port = app->proto_port; - if (proto_port != NULL) { - nxt_debug(task, "send QUIT to prototype '%V' pid %PI", &app->name, - proto_port->pid); + if (proto_port != NULL) { + nxt_debug(task, "send QUIT to prototype '%V' pid %PI", &app->name, + proto_port->pid); - app->proto_port = NULL; - proto_port->app = NULL; - } + app->proto_port = NULL; + proto_port->app = NULL; + } - app->generation++; + app->generation++; - shared_port->app = app; + shared_port->app = app; - old_shared_port = app->shared_port; - old_shared_port->app = NULL; + old_shared_port = app->shared_port; + old_shared_port->app = NULL; - app->shared_port = shared_port; + app->shared_port = shared_port; - nxt_thread_mutex_unlock(&app->mutex); + nxt_thread_mutex_unlock(&app->mutex); - nxt_port_close(task, old_shared_port); - nxt_port_use(task, old_shared_port, -1); + nxt_port_close(task, old_shared_port); + nxt_port_use(task, old_shared_port, -1); - if (proto_port != NULL) { - (void) nxt_port_socket_write(task, proto_port, NXT_PORT_MSG_QUIT, - -1, 0, 0, NULL); + if (proto_port != NULL) { + (void)nxt_port_socket_write(task, proto_port, NXT_PORT_MSG_QUIT, -1, 0, 0, + NULL); - nxt_port_close(task, proto_port); + nxt_port_close(task, proto_port); - nxt_port_use(task, proto_port, -1); - } + nxt_port_use(task, proto_port, -1); + } - reply = NXT_PORT_MSG_RPC_READY_LAST; + reply = NXT_PORT_MSG_RPC_READY_LAST; - } else { + } else { -fail: + fail: - reply = NXT_PORT_MSG_RPC_ERROR; - } + reply = NXT_PORT_MSG_RPC_ERROR; + } - nxt_port_socket_write(task, reply_port, reply, -1, msg->port_msg.stream, - 0, NULL); + nxt_port_socket_write(task, reply_port, reply, -1, msg->port_msg.stream, 0, + NULL); } +static void nxt_router_status_handler(nxt_task_t *task, + nxt_port_recv_msg_t *msg) { + u_char *p; + size_t alloc; + nxt_app_t *app; + nxt_buf_t *b; + nxt_uint_t type; + nxt_port_t *port; + nxt_status_app_t *app_stat; + nxt_event_engine_t *engine; + nxt_status_report_t *report; + + port = nxt_runtime_port_find(task->thread->runtime, msg->port_msg.pid, + msg->port_msg.reply_port); + if (nxt_slow_path(port == NULL)) { + nxt_alert(task, "nxt_router_status_handler(): reply port not found"); + return; + } -static void -nxt_router_status_handler(nxt_task_t *task, nxt_port_recv_msg_t *msg) -{ - u_char *p; - size_t alloc; - nxt_app_t *app; - nxt_buf_t *b; - nxt_uint_t type; - nxt_port_t *port; - nxt_status_app_t *app_stat; - nxt_event_engine_t *engine; - nxt_status_report_t *report; - - port = nxt_runtime_port_find(task->thread->runtime, - msg->port_msg.pid, - msg->port_msg.reply_port); - if (nxt_slow_path(port == NULL)) { - nxt_alert(task, "nxt_router_status_handler(): reply port not found"); - return; - } - - alloc = sizeof(nxt_status_report_t); - - nxt_queue_each(app, &nxt_router->apps, nxt_app_t, link) { - - alloc += sizeof(nxt_status_app_t) + app->name.length; + alloc = sizeof(nxt_status_report_t); - } nxt_queue_loop; + nxt_queue_each(app, &nxt_router->apps, nxt_app_t, link) { - b = nxt_buf_mem_alloc(port->mem_pool, alloc, 0); - if (nxt_slow_path(b == NULL)) { - type = NXT_PORT_MSG_RPC_ERROR; - goto fail; - } + alloc += sizeof(nxt_status_app_t) + app->name.length; + } + nxt_queue_loop; - report = (nxt_status_report_t *) b->mem.free; - b->mem.free = b->mem.end; + b = nxt_buf_mem_alloc(port->mem_pool, alloc, 0); + if (nxt_slow_path(b == NULL)) { + type = NXT_PORT_MSG_RPC_ERROR; + goto fail; + } - nxt_memzero(report, sizeof(nxt_status_report_t)); + report = (nxt_status_report_t *)b->mem.free; + b->mem.free = b->mem.end; - nxt_queue_each(engine, &nxt_router->engines, nxt_event_engine_t, link0) { + nxt_memzero(report, sizeof(nxt_status_report_t)); - report->accepted_conns += engine->accepted_conns_cnt; - report->idle_conns += engine->idle_conns_cnt; - report->closed_conns += engine->closed_conns_cnt; - report->requests += engine->requests_cnt; + nxt_queue_each(engine, &nxt_router->engines, nxt_event_engine_t, link0) { - } nxt_queue_loop; + report->accepted_conns += engine->accepted_conns_cnt; + report->idle_conns += engine->idle_conns_cnt; + report->closed_conns += engine->closed_conns_cnt; + report->requests += engine->requests_cnt; + } + nxt_queue_loop; - report->apps_count = 0; - app_stat = report->apps; - p = b->mem.end; + report->apps_count = 0; + app_stat = report->apps; + p = b->mem.end; - nxt_queue_each(app, &nxt_router->apps, nxt_app_t, link) { - p -= app->name.length; + nxt_queue_each(app, &nxt_router->apps, nxt_app_t, link) { + p -= app->name.length; - nxt_memcpy(p, app->name.start, app->name.length); + nxt_memcpy(p, app->name.start, app->name.length); - app_stat->name.length = app->name.length; - app_stat->name.start = (u_char *) (p - b->mem.pos); + app_stat->name.length = app->name.length; + app_stat->name.start = (u_char *)(p - b->mem.pos); - app_stat->active_requests = app->active_requests; - app_stat->pending_processes = app->pending_processes; - app_stat->processes = app->processes; - app_stat->idle_processes = app->idle_processes; + app_stat->active_requests = app->active_requests; + app_stat->pending_processes = app->pending_processes; + app_stat->processes = app->processes; + app_stat->idle_processes = app->idle_processes; - report->apps_count++; - app_stat++; - } nxt_queue_loop; + report->apps_count++; + app_stat++; + } + nxt_queue_loop; - type = NXT_PORT_MSG_RPC_READY_LAST; + type = NXT_PORT_MSG_RPC_READY_LAST; fail: - nxt_port_socket_write(task, port, type, -1, msg->port_msg.stream, 0, b); + nxt_port_socket_write(task, port, type, -1, msg->port_msg.stream, 0, b); } +static void nxt_router_app_process_remove_pid(nxt_task_t *task, + nxt_port_t *port, void *data) { + union { + nxt_pid_t removed_pid; + void *data; + } u; -static void -nxt_router_app_process_remove_pid(nxt_task_t *task, nxt_port_t *port, - void *data) -{ - union { - nxt_pid_t removed_pid; - void *data; - } u; - - u.data = data; + u.data = data; - nxt_port_rpc_remove_peer(task, port, u.removed_pid); + nxt_port_rpc_remove_peer(task, port, u.removed_pid); } +static void nxt_router_remove_pid_handler(nxt_task_t *task, + nxt_port_recv_msg_t *msg) { + nxt_event_engine_t *engine; -static void -nxt_router_remove_pid_handler(nxt_task_t *task, nxt_port_recv_msg_t *msg) -{ - nxt_event_engine_t *engine; - - nxt_port_remove_pid_handler(task, msg); + nxt_port_remove_pid_handler(task, msg); - nxt_queue_each(engine, &nxt_router->engines, nxt_event_engine_t, link0) - { - if (nxt_fast_path(engine->port != NULL)) { - nxt_port_post(task, engine->port, nxt_router_app_process_remove_pid, - msg->u.data); - } + nxt_queue_each(engine, &nxt_router->engines, nxt_event_engine_t, link0) { + if (nxt_fast_path(engine->port != NULL)) { + nxt_port_post(task, engine->port, nxt_router_app_process_remove_pid, + msg->u.data); } - nxt_queue_loop; + } + nxt_queue_loop; - if (msg->port_msg.stream == 0) { - return; - } + if (msg->port_msg.stream == 0) { + return; + } - msg->port_msg.type = _NXT_PORT_MSG_RPC_ERROR; + msg->port_msg.type = _NXT_PORT_MSG_RPC_ERROR; - nxt_port_rpc_handler(task, msg); + nxt_port_rpc_handler(task, msg); } +static nxt_router_temp_conf_t *nxt_router_temp_conf(nxt_task_t *task) { + nxt_mp_t *mp, *tmp; + nxt_router_conf_t *rtcf; + nxt_router_temp_conf_t *tmcf; -static nxt_router_temp_conf_t * -nxt_router_temp_conf(nxt_task_t *task) -{ - nxt_mp_t *mp, *tmp; - nxt_router_conf_t *rtcf; - nxt_router_temp_conf_t *tmcf; - - mp = nxt_mp_create(1024, 128, 256, 32); - if (nxt_slow_path(mp == NULL)) { - return NULL; - } + mp = nxt_mp_create(1024, 128, 256, 32); + if (nxt_slow_path(mp == NULL)) { + return NULL; + } - rtcf = nxt_mp_zget(mp, sizeof(nxt_router_conf_t)); - if (nxt_slow_path(rtcf == NULL)) { - goto out_free_mp; - } + rtcf = nxt_mp_zget(mp, sizeof(nxt_router_conf_t)); + if (nxt_slow_path(rtcf == NULL)) { + goto out_free_mp; + } - rtcf->mem_pool = mp; + rtcf->mem_pool = mp; - rtcf->tstr_state = nxt_tstr_state_new(mp, 0); - if (nxt_slow_path(rtcf->tstr_state == NULL)) { - goto out_free_mp; - } + rtcf->tstr_state = nxt_tstr_state_new(mp, 0); + if (nxt_slow_path(rtcf->tstr_state == NULL)) { + goto out_free_mp; + } #if (NXT_HAVE_NJS) - nxt_http_register_js_proto(rtcf->tstr_state->jcf); + nxt_http_register_js_proto(rtcf->tstr_state->jcf); #endif - tmp = nxt_mp_create(1024, 128, 256, 32); - if (nxt_slow_path(tmp == NULL)) { - goto out_free_tstr_state; - } - - tmcf = nxt_mp_zget(tmp, sizeof(nxt_router_temp_conf_t)); - if (nxt_slow_path(tmcf == NULL)) { - goto out_free; - } - - tmcf->mem_pool = tmp; - tmcf->router_conf = rtcf; - tmcf->count = 1; - tmcf->engine = task->thread->engine; - - tmcf->engines = nxt_array_create(tmcf->mem_pool, 4, - sizeof(nxt_router_engine_conf_t)); - if (nxt_slow_path(tmcf->engines == NULL)) { - goto out_free; - } - - nxt_queue_init(&creating_sockets); - nxt_queue_init(&pending_sockets); - nxt_queue_init(&updating_sockets); - nxt_queue_init(&keeping_sockets); - nxt_queue_init(&deleting_sockets); + tmp = nxt_mp_create(1024, 128, 256, 32); + if (nxt_slow_path(tmp == NULL)) { + goto out_free_tstr_state; + } + + tmcf = nxt_mp_zget(tmp, sizeof(nxt_router_temp_conf_t)); + if (nxt_slow_path(tmcf == NULL)) { + goto out_free; + } + + tmcf->mem_pool = tmp; + tmcf->router_conf = rtcf; + tmcf->count = 1; + tmcf->engine = task->thread->engine; + + tmcf->engines = + nxt_array_create(tmcf->mem_pool, 4, sizeof(nxt_router_engine_conf_t)); + if (nxt_slow_path(tmcf->engines == NULL)) { + goto out_free; + } + + nxt_queue_init(&creating_sockets); + nxt_queue_init(&pending_sockets); + nxt_queue_init(&updating_sockets); + nxt_queue_init(&keeping_sockets); + nxt_queue_init(&deleting_sockets); #if (NXT_TLS) - nxt_queue_init(&tmcf->tls); + nxt_queue_init(&tmcf->tls); #endif #if (NXT_HAVE_NJS) - nxt_queue_init(&tmcf->js_modules); + nxt_queue_init(&tmcf->js_modules); #endif - nxt_queue_init(&tmcf->apps); - nxt_queue_init(&tmcf->previous); + nxt_queue_init(&tmcf->apps); + nxt_queue_init(&tmcf->previous); - return tmcf; + return tmcf; out_free: - nxt_mp_destroy(tmp); + nxt_mp_destroy(tmp); out_free_tstr_state: - if (rtcf->tstr_state != NULL) { - nxt_tstr_state_release(rtcf->tstr_state); - } + if (rtcf->tstr_state != NULL) { + nxt_tstr_state_release(rtcf->tstr_state); + } out_free_mp: - nxt_mp_destroy(mp); + nxt_mp_destroy(mp); - return NULL; + return NULL; } - -nxt_inline nxt_bool_t -nxt_router_app_can_start(nxt_app_t *app) -{ - return app->processes + app->pending_processes < app->max_processes - && app->pending_processes < app->max_pending_processes; +nxt_inline nxt_bool_t nxt_router_app_can_start(nxt_app_t *app) { + return app->processes + app->pending_processes < app->max_processes && + app->pending_processes < app->max_pending_processes; } - -nxt_inline nxt_bool_t -nxt_router_app_need_start(nxt_app_t *app) -{ - return (app->active_requests - > app->port_hash_count + app->pending_processes) - || (app->spare_processes - > app->idle_processes + app->pending_processes); +nxt_inline nxt_bool_t nxt_router_app_need_start(nxt_app_t *app) { + return (app->active_requests > + app->port_hash_count + app->pending_processes) || + (app->spare_processes > app->idle_processes + app->pending_processes); } - -void -nxt_router_conf_apply(nxt_task_t *task, void *obj, void *data) -{ - nxt_int_t ret; - nxt_app_t *app; - nxt_router_t *router; - nxt_runtime_t *rt; - nxt_queue_link_t *qlk; - nxt_socket_conf_t *skcf; - nxt_router_conf_t *rtcf; - nxt_router_temp_conf_t *tmcf; - const nxt_event_interface_t *interface; +void nxt_router_conf_apply(nxt_task_t *task, void *obj, void *data) { + nxt_int_t ret; + nxt_app_t *app; + nxt_router_t *router; + nxt_runtime_t *rt; + nxt_queue_link_t *qlk; + nxt_socket_conf_t *skcf; + nxt_router_conf_t *rtcf; + nxt_router_temp_conf_t *tmcf; + const nxt_event_interface_t *interface; #if (NXT_TLS) - nxt_router_tlssock_t *tls; + nxt_router_tlssock_t *tls; #endif #if (NXT_HAVE_NJS) - nxt_router_js_module_t *js_module; + nxt_router_js_module_t *js_module; #endif - tmcf = obj; + tmcf = obj; - qlk = nxt_queue_first(&pending_sockets); + qlk = nxt_queue_first(&pending_sockets); - if (qlk != nxt_queue_tail(&pending_sockets)) { - nxt_queue_remove(qlk); - nxt_queue_insert_tail(&creating_sockets, qlk); + if (qlk != nxt_queue_tail(&pending_sockets)) { + nxt_queue_remove(qlk); + nxt_queue_insert_tail(&creating_sockets, qlk); - skcf = nxt_queue_link_data(qlk, nxt_socket_conf_t, link); + skcf = nxt_queue_link_data(qlk, nxt_socket_conf_t, link); - nxt_router_listen_socket_rpc_create(task, tmcf, skcf); + nxt_router_listen_socket_rpc_create(task, tmcf, skcf); - return; - } + return; + } #if (NXT_TLS) - qlk = nxt_queue_last(&tmcf->tls); + qlk = nxt_queue_last(&tmcf->tls); - if (qlk != nxt_queue_head(&tmcf->tls)) { - nxt_queue_remove(qlk); + if (qlk != nxt_queue_head(&tmcf->tls)) { + nxt_queue_remove(qlk); - tls = nxt_queue_link_data(qlk, nxt_router_tlssock_t, link); + tls = nxt_queue_link_data(qlk, nxt_router_tlssock_t, link); - nxt_cert_store_get(task, &tls->name, tmcf->mem_pool, - nxt_router_tls_rpc_handler, tls); - return; - } + nxt_cert_store_get(task, &tls->name, tmcf->mem_pool, + nxt_router_tls_rpc_handler, tls); + return; + } #endif #if (NXT_HAVE_NJS) - qlk = nxt_queue_last(&tmcf->js_modules); + qlk = nxt_queue_last(&tmcf->js_modules); - if (qlk != nxt_queue_head(&tmcf->js_modules)) { - nxt_queue_remove(qlk); + if (qlk != nxt_queue_head(&tmcf->js_modules)) { + nxt_queue_remove(qlk); - js_module = nxt_queue_link_data(qlk, nxt_router_js_module_t, link); + js_module = nxt_queue_link_data(qlk, nxt_router_js_module_t, link); - nxt_script_store_get(task, &js_module->name, tmcf->mem_pool, - nxt_router_js_module_rpc_handler, js_module); - return; - } + nxt_script_store_get(task, &js_module->name, tmcf->mem_pool, + nxt_router_js_module_rpc_handler, js_module); + return; + } #endif - rtcf = tmcf->router_conf; + rtcf = tmcf->router_conf; - ret = nxt_tstr_state_done(rtcf->tstr_state, NULL); - if (nxt_slow_path(ret != NXT_OK)) { - goto fail; + ret = nxt_tstr_state_done(rtcf->tstr_state, NULL); + if (nxt_slow_path(ret != NXT_OK)) { + goto fail; + } + + nxt_queue_each(app, &tmcf->apps, nxt_app_t, link) { + + if (nxt_router_app_need_start(app)) { + nxt_router_app_rpc_create(task, tmcf, app); + return; } + } + nxt_queue_loop; - nxt_queue_each(app, &tmcf->apps, nxt_app_t, link) { + if (rtcf->access_log != NULL && rtcf->access_log->fd == -1) { + nxt_router_access_log_open(task, tmcf); + return; + } - if (nxt_router_app_need_start(app)) { - nxt_router_app_rpc_create(task, tmcf, app); - return; - } + rt = task->thread->runtime; - } nxt_queue_loop; + interface = nxt_service_get(rt->services, "engine", NULL); - if (rtcf->access_log != NULL && rtcf->access_log->fd == -1) { - nxt_router_access_log_open(task, tmcf); - return; - } + router = rtcf->router; - rt = task->thread->runtime; + ret = nxt_router_engines_create(task, router, tmcf, interface); + if (nxt_slow_path(ret != NXT_OK)) { + goto fail; + } - interface = nxt_service_get(rt->services, "engine", NULL); + ret = nxt_router_threads_create(task, rt, tmcf); + if (nxt_slow_path(ret != NXT_OK)) { + goto fail; + } - router = rtcf->router; + nxt_router_apps_sort(task, router, tmcf); - ret = nxt_router_engines_create(task, router, tmcf, interface); - if (nxt_slow_path(ret != NXT_OK)) { - goto fail; - } + nxt_router_apps_hash_use(task, rtcf, 1); - ret = nxt_router_threads_create(task, rt, tmcf); - if (nxt_slow_path(ret != NXT_OK)) { - goto fail; - } + nxt_router_engines_post(router, tmcf); - nxt_router_apps_sort(task, router, tmcf); + nxt_queue_add(&router->sockets, &updating_sockets); + nxt_queue_add(&router->sockets, &creating_sockets); - nxt_router_apps_hash_use(task, rtcf, 1); + if (router->access_log != rtcf->access_log) { + nxt_router_access_log_use(&router->lock, rtcf->access_log); - nxt_router_engines_post(router, tmcf); + nxt_router_access_log_release(task, &router->lock, router->access_log); - nxt_queue_add(&router->sockets, &updating_sockets); - nxt_queue_add(&router->sockets, &creating_sockets); + router->access_log = rtcf->access_log; + } - if (router->access_log != rtcf->access_log) { - nxt_router_access_log_use(&router->lock, rtcf->access_log); + nxt_router_conf_ready(task, tmcf); - nxt_router_access_log_release(task, &router->lock, router->access_log); - - router->access_log = rtcf->access_log; - } - - nxt_router_conf_ready(task, tmcf); - - return; + return; fail: - nxt_router_conf_error(task, tmcf); + nxt_router_conf_error(task, tmcf); - return; + return; } +static void nxt_router_conf_wait(nxt_task_t *task, void *obj, void *data) { + nxt_joint_job_t *job; -static void -nxt_router_conf_wait(nxt_task_t *task, void *obj, void *data) -{ - nxt_joint_job_t *job; - - job = obj; + job = obj; - nxt_router_conf_ready(task, job->tmcf); + nxt_router_conf_ready(task, job->tmcf); } +static void nxt_router_conf_ready(nxt_task_t *task, + nxt_router_temp_conf_t *tmcf) { + uint32_t count; + nxt_router_conf_t *rtcf; + nxt_thread_spinlock_t *lock; -static void -nxt_router_conf_ready(nxt_task_t *task, nxt_router_temp_conf_t *tmcf) -{ - uint32_t count; - nxt_router_conf_t *rtcf; - nxt_thread_spinlock_t *lock; - - nxt_debug(task, "temp conf %p count: %D", tmcf, tmcf->count); + nxt_debug(task, "temp conf %p count: %D", tmcf, tmcf->count); - if (--tmcf->count > 0) { - return; - } + if (--tmcf->count > 0) { + return; + } - nxt_router_conf_send(task, tmcf, NXT_PORT_MSG_RPC_READY_LAST); + nxt_router_conf_send(task, tmcf, NXT_PORT_MSG_RPC_READY_LAST); - rtcf = tmcf->router_conf; + rtcf = tmcf->router_conf; - lock = &rtcf->router->lock; + lock = &rtcf->router->lock; - nxt_thread_spin_lock(lock); + nxt_thread_spin_lock(lock); - count = rtcf->count; + count = rtcf->count; - nxt_thread_spin_unlock(lock); + nxt_thread_spin_unlock(lock); - nxt_debug(task, "rtcf %p: %D", rtcf, count); + nxt_debug(task, "rtcf %p: %D", rtcf, count); - if (count == 0) { - nxt_router_apps_hash_use(task, rtcf, -1); + if (count == 0) { + nxt_router_apps_hash_use(task, rtcf, -1); - nxt_router_access_log_release(task, lock, rtcf->access_log); + nxt_router_access_log_release(task, lock, rtcf->access_log); - nxt_mp_destroy(rtcf->mem_pool); - } + nxt_mp_destroy(rtcf->mem_pool); + } - nxt_mp_release(tmcf->mem_pool); + nxt_mp_release(tmcf->mem_pool); } +void nxt_router_conf_error(nxt_task_t *task, nxt_router_temp_conf_t *tmcf) { + nxt_app_t *app; + nxt_socket_t s; + nxt_router_t *router; + nxt_queue_link_t *qlk; + nxt_socket_conf_t *skcf; + nxt_router_conf_t *rtcf; -void -nxt_router_conf_error(nxt_task_t *task, nxt_router_temp_conf_t *tmcf) -{ - nxt_app_t *app; - nxt_socket_t s; - nxt_router_t *router; - nxt_queue_link_t *qlk; - nxt_socket_conf_t *skcf; - nxt_router_conf_t *rtcf; - - nxt_alert(task, "failed to apply new conf"); - - for (qlk = nxt_queue_first(&creating_sockets); - qlk != nxt_queue_tail(&creating_sockets); - qlk = nxt_queue_next(qlk)) - { - skcf = nxt_queue_link_data(qlk, nxt_socket_conf_t, link); - s = skcf->listen->socket; + nxt_alert(task, "failed to apply new conf"); - if (s != -1) { - nxt_socket_close(task, s); - } + for (qlk = nxt_queue_first(&creating_sockets); + qlk != nxt_queue_tail(&creating_sockets); qlk = nxt_queue_next(qlk)) { + skcf = nxt_queue_link_data(qlk, nxt_socket_conf_t, link); + s = skcf->listen->socket; - nxt_free(skcf->listen); + if (s != -1) { + nxt_socket_close(task, s); } - rtcf = tmcf->router_conf; + nxt_free(skcf->listen); + } - nxt_queue_each(app, &tmcf->apps, nxt_app_t, link) { + rtcf = tmcf->router_conf; - nxt_router_app_unlink(task, app); + nxt_queue_each(app, &tmcf->apps, nxt_app_t, link) { - } nxt_queue_loop; + nxt_router_app_unlink(task, app); + } + nxt_queue_loop; - router = rtcf->router; + router = rtcf->router; - nxt_queue_add(&router->sockets, &keeping_sockets); - nxt_queue_add(&router->sockets, &deleting_sockets); + nxt_queue_add(&router->sockets, &keeping_sockets); + nxt_queue_add(&router->sockets, &deleting_sockets); - nxt_queue_add(&router->apps, &tmcf->previous); + nxt_queue_add(&router->apps, &tmcf->previous); - // TODO: new engines and threads + // TODO: new engines and threads - nxt_router_access_log_release(task, &router->lock, rtcf->access_log); + nxt_router_access_log_release(task, &router->lock, rtcf->access_log); - nxt_mp_destroy(rtcf->mem_pool); + nxt_mp_destroy(rtcf->mem_pool); - nxt_router_conf_send(task, tmcf, NXT_PORT_MSG_RPC_ERROR); + nxt_router_conf_send(task, tmcf, NXT_PORT_MSG_RPC_ERROR); - nxt_mp_release(tmcf->mem_pool); + nxt_mp_release(tmcf->mem_pool); } +static void nxt_router_conf_send(nxt_task_t *task, nxt_router_temp_conf_t *tmcf, + nxt_port_msg_type_t type) { + nxt_port_socket_write(task, tmcf->port, type, -1, tmcf->stream, 0, NULL); -static void -nxt_router_conf_send(nxt_task_t *task, nxt_router_temp_conf_t *tmcf, - nxt_port_msg_type_t type) -{ - nxt_port_socket_write(task, tmcf->port, type, -1, tmcf->stream, 0, NULL); - - nxt_port_use(task, tmcf->port, -1); + nxt_port_use(task, tmcf->port, -1); - tmcf->port = NULL; + tmcf->port = NULL; } - -static nxt_conf_map_t nxt_router_conf[] = { +static nxt_conf_map_t nxt_router_conf[] = { { nxt_string("listen_threads"), NXT_CONF_MAP_INT32, @@ -1419,8 +1353,7 @@ static nxt_conf_map_t nxt_router_conf[] = { }, }; - -static nxt_conf_map_t nxt_router_app_conf[] = { +static nxt_conf_map_t nxt_router_app_conf[] = { { nxt_string("type"), NXT_CONF_MAP_STR, @@ -1452,8 +1385,7 @@ static nxt_conf_map_t nxt_router_app_conf[] = { }, }; - -static nxt_conf_map_t nxt_router_app_limits_conf[] = { +static nxt_conf_map_t nxt_router_app_limits_conf[] = { { nxt_string("timeout"), NXT_CONF_MAP_MSEC, @@ -1461,8 +1393,7 @@ static nxt_conf_map_t nxt_router_app_limits_conf[] = { }, }; - -static nxt_conf_map_t nxt_router_app_processes_conf[] = { +static nxt_conf_map_t nxt_router_app_processes_conf[] = { { nxt_string("spare"), NXT_CONF_MAP_INT32, @@ -1482,8 +1413,7 @@ static nxt_conf_map_t nxt_router_app_processes_conf[] = { }, }; - -static nxt_conf_map_t nxt_router_listener_conf[] = { +static nxt_conf_map_t nxt_router_listener_conf[] = { { nxt_string("pass"), NXT_CONF_MAP_STR_COPY, @@ -1503,8 +1433,7 @@ static nxt_conf_map_t nxt_router_listener_conf[] = { }, }; - -static nxt_conf_map_t nxt_router_http_conf[] = { +static nxt_conf_map_t nxt_router_http_conf[] = { { nxt_string("header_buffer_size"), NXT_CONF_MAP_SIZE, @@ -1590,8 +1519,7 @@ static nxt_conf_map_t nxt_router_http_conf[] = { }, }; - -static nxt_conf_map_t nxt_router_websocket_conf[] = { +static nxt_conf_map_t nxt_router_websocket_conf[] = { { nxt_string("max_frame_size"), NXT_CONF_MAP_SIZE, @@ -1612,349 +1540,339 @@ static nxt_conf_map_t nxt_router_websocket_conf[] = { }; - -static nxt_int_t -nxt_router_conf_create(nxt_task_t *task, nxt_router_temp_conf_t *tmcf, - u_char *start, u_char *end) -{ - u_char *p; - size_t size; - nxt_mp_t *mp, *app_mp; - uint32_t next, next_target; - nxt_int_t ret; - nxt_str_t name, target; - nxt_app_t *app, *prev; - nxt_str_t *t, *s, *targets; - nxt_uint_t n, i; - nxt_port_t *port; - nxt_router_t *router; - nxt_app_joint_t *app_joint; +static nxt_int_t nxt_router_conf_create(nxt_task_t *task, + nxt_router_temp_conf_t *tmcf, + u_char *start, u_char *end) { + u_char *p; + size_t size; + nxt_mp_t *mp, *app_mp; + uint32_t next, next_target; + nxt_int_t ret; + nxt_str_t name, target; + nxt_app_t *app, *prev; + nxt_str_t *t, *s, *targets; + nxt_uint_t n, i; + nxt_port_t *port; + nxt_router_t *router; + nxt_app_joint_t *app_joint; #if (NXT_TLS) - nxt_tls_init_t *tls_init; - nxt_conf_value_t *certificate; + nxt_tls_init_t *tls_init; + nxt_conf_value_t *certificate; #endif #if (NXT_HAVE_NJS) - nxt_conf_value_t *js_module; + nxt_conf_value_t *js_module; #endif - nxt_conf_value_t *root, *conf, *http, *value, *websocket; - nxt_conf_value_t *applications, *application, *settings; - nxt_conf_value_t *listeners, *listener; - nxt_socket_conf_t *skcf; - nxt_router_conf_t *rtcf; - nxt_http_routes_t *routes; - nxt_event_engine_t *engine; - nxt_app_lang_module_t *lang; - nxt_router_app_conf_t apcf; - nxt_router_listener_conf_t lscf; - - static const nxt_str_t settings_path = nxt_string("/settings"); - static const nxt_str_t http_path = nxt_string("/settings/http"); - static const nxt_str_t applications_path = nxt_string("/applications"); - static const nxt_str_t listeners_path = nxt_string("/listeners"); - static const nxt_str_t routes_path = nxt_string("/routes"); - static const nxt_str_t access_log_path = nxt_string("/access_log"); + nxt_conf_value_t *root, *conf, *http, *value, *websocket; + nxt_conf_value_t *applications, *application, *settings; + nxt_conf_value_t *listeners, *listener; + nxt_socket_conf_t *skcf; + nxt_router_conf_t *rtcf; + nxt_http_routes_t *routes; + nxt_event_engine_t *engine; + nxt_app_lang_module_t *lang; + nxt_router_app_conf_t apcf; + nxt_router_listener_conf_t lscf; + + static const nxt_str_t settings_path = nxt_string("/settings"); + static const nxt_str_t http_path = nxt_string("/settings/http"); + static const nxt_str_t applications_path = nxt_string("/applications"); + static const nxt_str_t listeners_path = nxt_string("/listeners"); + static const nxt_str_t routes_path = nxt_string("/routes"); + static const nxt_str_t access_log_path = nxt_string("/access_log"); #if (NXT_TLS) - static const nxt_str_t certificate_path = nxt_string("/tls/certificate"); - static const nxt_str_t conf_commands_path = - nxt_string("/tls/conf_commands"); - static const nxt_str_t conf_cache_path = - nxt_string("/tls/session/cache_size"); - static const nxt_str_t conf_timeout_path = - nxt_string("/tls/session/timeout"); - static const nxt_str_t conf_tickets = nxt_string("/tls/session/tickets"); + static const nxt_str_t certificate_path = nxt_string("/tls/certificate"); + static const nxt_str_t conf_commands_path = nxt_string("/tls/conf_commands"); + static const nxt_str_t conf_cache_path = + nxt_string("/tls/session/cache_size"); + static const nxt_str_t conf_timeout_path = nxt_string("/tls/session/timeout"); + static const nxt_str_t conf_tickets = nxt_string("/tls/session/tickets"); #endif #if (NXT_HAVE_NJS) - static const nxt_str_t js_module_path = nxt_string("/settings/js_module"); + static const nxt_str_t js_module_path = nxt_string("/settings/js_module"); #endif - static const nxt_str_t static_path = nxt_string("/settings/http/static"); - static const nxt_str_t websocket_path = - nxt_string("/settings/http/websocket"); - static const nxt_str_t forwarded_path = nxt_string("/forwarded"); - static const nxt_str_t client_ip_path = nxt_string("/client_ip"); - - root = nxt_conf_json_parse(tmcf->mem_pool, start, end, NULL); - if (root == NULL) { - nxt_alert(task, "configuration parsing error"); - return NXT_ERROR; - } + static const nxt_str_t static_path = nxt_string("/settings/http/static"); + static const nxt_str_t websocket_path = + nxt_string("/settings/http/websocket"); + static const nxt_str_t forwarded_path = nxt_string("/forwarded"); + static const nxt_str_t client_ip_path = nxt_string("/client_ip"); + + root = nxt_conf_json_parse(tmcf->mem_pool, start, end, NULL); + if (root == NULL) { + nxt_alert(task, "configuration parsing error"); + return NXT_ERROR; + } - rtcf = tmcf->router_conf; - mp = rtcf->mem_pool; + rtcf = tmcf->router_conf; + mp = rtcf->mem_pool; - settings = nxt_conf_get_path(root, &settings_path); - if (settings != NULL) { - ret = nxt_conf_map_object(mp, settings, nxt_router_conf, - nxt_nitems(nxt_router_conf), rtcf); - if (ret != NXT_OK) { - nxt_alert(task, "router_conf map error"); - return NXT_ERROR; - } + settings = nxt_conf_get_path(root, &settings_path); + if (settings != NULL) { + ret = nxt_conf_map_object(mp, settings, nxt_router_conf, + nxt_nitems(nxt_router_conf), rtcf); + if (ret != NXT_OK) { + nxt_alert(task, "router_conf map error"); + return NXT_ERROR; } + } - if (rtcf->threads == 0) { - rtcf->threads = nxt_ncpu; - } + if (rtcf->threads == 0) { + rtcf->threads = nxt_ncpu; + } - conf = nxt_conf_get_path(root, &static_path); + conf = nxt_conf_get_path(root, &static_path); - ret = nxt_router_conf_process_static(task, rtcf, conf); - if (nxt_slow_path(ret != NXT_OK)) { - return NXT_ERROR; - } + ret = nxt_router_conf_process_static(task, rtcf, conf); + if (nxt_slow_path(ret != NXT_OK)) { + return NXT_ERROR; + } + + router = rtcf->router; - router = rtcf->router; + applications = nxt_conf_get_path(root, &applications_path); - applications = nxt_conf_get_path(root, &applications_path); + if (applications != NULL) { + next = 0; - if (applications != NULL) { - next = 0; + for (;;) { + application = nxt_conf_next_object_member(applications, &name, &next); + if (application == NULL) { + break; + } + + nxt_debug(task, "application \"%V\"", &name); - for ( ;; ) { - application = nxt_conf_next_object_member(applications, - &name, &next); - if (application == NULL) { - break; - } + size = nxt_conf_json_length(application, NULL); + + app_mp = nxt_mp_create(4096, 128, 1024, 64); + if (nxt_slow_path(app_mp == NULL)) { + goto fail; + } - nxt_debug(task, "application \"%V\"", &name); + app = nxt_mp_get(app_mp, sizeof(nxt_app_t) + name.length + size); + if (app == NULL) { + goto app_fail; + } - size = nxt_conf_json_length(application, NULL); + nxt_memzero(app, sizeof(nxt_app_t)); - app_mp = nxt_mp_create(4096, 128, 1024, 64); - if (nxt_slow_path(app_mp == NULL)) { - goto fail; - } - - app = nxt_mp_get(app_mp, sizeof(nxt_app_t) + name.length + size); - if (app == NULL) { - goto app_fail; - } + app->mem_pool = app_mp; - nxt_memzero(app, sizeof(nxt_app_t)); + app->name.start = nxt_pointer_to(app, sizeof(nxt_app_t)); + app->conf.start = nxt_pointer_to(app, sizeof(nxt_app_t) + name.length); - app->mem_pool = app_mp; + p = nxt_conf_json_print(app->conf.start, application, NULL); + app->conf.length = p - app->conf.start; - app->name.start = nxt_pointer_to(app, sizeof(nxt_app_t)); - app->conf.start = nxt_pointer_to(app, sizeof(nxt_app_t) - + name.length); + nxt_assert(app->conf.length <= size); - p = nxt_conf_json_print(app->conf.start, application, NULL); - app->conf.length = p - app->conf.start; - - nxt_assert(app->conf.length <= size); + nxt_debug(task, "application conf \"%V\"", &app->conf); - nxt_debug(task, "application conf \"%V\"", &app->conf); - - prev = nxt_router_app_find(&router->apps, &name); + prev = nxt_router_app_find(&router->apps, &name); - if (prev != NULL && nxt_strstr_eq(&app->conf, &prev->conf)) { - nxt_mp_destroy(app_mp); + if (prev != NULL && nxt_strstr_eq(&app->conf, &prev->conf)) { + nxt_mp_destroy(app_mp); - nxt_queue_remove(&prev->link); - nxt_queue_insert_tail(&tmcf->previous, &prev->link); + nxt_queue_remove(&prev->link); + nxt_queue_insert_tail(&tmcf->previous, &prev->link); - ret = nxt_router_apps_hash_add(rtcf, prev); - if (nxt_slow_path(ret != NXT_OK)) { - goto fail; - } + ret = nxt_router_apps_hash_add(rtcf, prev); + if (nxt_slow_path(ret != NXT_OK)) { + goto fail; + } - continue; - } + continue; + } + + apcf.processes = 1; + apcf.max_processes = 1; + apcf.spare_processes = 0; + apcf.timeout = 0; + apcf.idle_timeout = 15000; + apcf.limits_value = NULL; + apcf.processes_value = NULL; + apcf.targets_value = NULL; + + app_joint = nxt_malloc(sizeof(nxt_app_joint_t)); + if (nxt_slow_path(app_joint == NULL)) { + goto app_fail; + } + + nxt_memzero(app_joint, sizeof(nxt_app_joint_t)); + + ret = nxt_conf_map_object(mp, application, nxt_router_app_conf, + nxt_nitems(nxt_router_app_conf), &apcf); + if (ret != NXT_OK) { + nxt_alert(task, "application map error"); + goto app_fail; + } + + if (apcf.limits_value != NULL) { + + if (nxt_conf_type(apcf.limits_value) != NXT_CONF_OBJECT) { + nxt_alert(task, "application limits is not object"); + goto app_fail; + } - apcf.processes = 1; - apcf.max_processes = 1; - apcf.spare_processes = 0; - apcf.timeout = 0; - apcf.idle_timeout = 15000; - apcf.limits_value = NULL; - apcf.processes_value = NULL; - apcf.targets_value = NULL; + ret = nxt_conf_map_object( + mp, apcf.limits_value, nxt_router_app_limits_conf, + nxt_nitems(nxt_router_app_limits_conf), &apcf); + if (ret != NXT_OK) { + nxt_alert(task, "application limits map error"); + goto app_fail; + } + } - app_joint = nxt_malloc(sizeof(nxt_app_joint_t)); - if (nxt_slow_path(app_joint == NULL)) { - goto app_fail; - } - - nxt_memzero(app_joint, sizeof(nxt_app_joint_t)); - - ret = nxt_conf_map_object(mp, application, nxt_router_app_conf, - nxt_nitems(nxt_router_app_conf), &apcf); - if (ret != NXT_OK) { - nxt_alert(task, "application map error"); - goto app_fail; - } + if (apcf.processes_value != NULL && + nxt_conf_type(apcf.processes_value) == NXT_CONF_OBJECT) { + ret = nxt_conf_map_object( + mp, apcf.processes_value, nxt_router_app_processes_conf, + nxt_nitems(nxt_router_app_processes_conf), &apcf); + if (ret != NXT_OK) { + nxt_alert(task, "application processes map error"); + goto app_fail; + } - if (apcf.limits_value != NULL) { + } else { + apcf.max_processes = apcf.processes; + apcf.spare_processes = apcf.processes; + } - if (nxt_conf_type(apcf.limits_value) != NXT_CONF_OBJECT) { - nxt_alert(task, "application limits is not object"); - goto app_fail; - } + if (apcf.targets_value != NULL) { + n = nxt_conf_object_members_count(apcf.targets_value); - ret = nxt_conf_map_object(mp, apcf.limits_value, - nxt_router_app_limits_conf, - nxt_nitems(nxt_router_app_limits_conf), - &apcf); - if (ret != NXT_OK) { - nxt_alert(task, "application limits map error"); - goto app_fail; - } - } + targets = nxt_mp_get(app_mp, sizeof(nxt_str_t) * n); + if (nxt_slow_path(targets == NULL)) { + goto app_fail; + } - if (apcf.processes_value != NULL - && nxt_conf_type(apcf.processes_value) == NXT_CONF_OBJECT) - { - ret = nxt_conf_map_object(mp, apcf.processes_value, - nxt_router_app_processes_conf, - nxt_nitems(nxt_router_app_processes_conf), - &apcf); - if (ret != NXT_OK) { - nxt_alert(task, "application processes map error"); - goto app_fail; - } + next_target = 0; - } else { - apcf.max_processes = apcf.processes; - apcf.spare_processes = apcf.processes; - } + for (i = 0; i < n; i++) { + (void)nxt_conf_next_object_member(apcf.targets_value, &target, + &next_target); - if (apcf.targets_value != NULL) { - n = nxt_conf_object_members_count(apcf.targets_value); - - targets = nxt_mp_get(app_mp, sizeof(nxt_str_t) * n); - if (nxt_slow_path(targets == NULL)) { - goto app_fail; - } - - next_target = 0; - - for (i = 0; i < n; i++) { - (void) nxt_conf_next_object_member(apcf.targets_value, - &target, &next_target); - - s = nxt_str_dup(app_mp, &targets[i], &target); - if (nxt_slow_path(s == NULL)) { - goto app_fail; - } - } - - } else { - targets = NULL; - } - - nxt_debug(task, "application type: %V", &apcf.type); - nxt_debug(task, "application processes: %D", apcf.processes); - nxt_debug(task, "application request timeout: %M", apcf.timeout); - - lang = nxt_app_lang_module(task->thread->runtime, &apcf.type); - - if (lang == NULL) { - nxt_alert(task, "unknown application type: \"%V\"", &apcf.type); - goto app_fail; - } - - nxt_debug(task, "application language module: \"%s\"", lang->file); - - ret = nxt_thread_mutex_create(&app->mutex); - if (ret != NXT_OK) { - goto app_fail; - } - - nxt_queue_init(&app->ports); - nxt_queue_init(&app->spare_ports); - nxt_queue_init(&app->idle_ports); - nxt_queue_init(&app->ack_waiting_req); - - app->name.length = name.length; - nxt_memcpy(app->name.start, name.start, name.length); - - app->type = lang->type; - app->max_processes = apcf.max_processes; - app->spare_processes = apcf.spare_processes; - app->max_pending_processes = apcf.spare_processes - ? apcf.spare_processes : 1; - app->timeout = apcf.timeout; - app->idle_timeout = apcf.idle_timeout; - - app->targets = targets; - - engine = task->thread->engine; - - app->engine = engine; - - app->adjust_idle_work.handler = nxt_router_adjust_idle_timer; - app->adjust_idle_work.task = &engine->task; - app->adjust_idle_work.obj = app; - - nxt_queue_insert_tail(&tmcf->apps, &app->link); - - ret = nxt_router_apps_hash_add(rtcf, app); - if (nxt_slow_path(ret != NXT_OK)) { - goto app_fail; - } - - nxt_router_app_use(task, app, 1); - - app->joint = app_joint; - - app_joint->use_count = 1; - app_joint->app = app; - - app_joint->idle_timer.bias = NXT_TIMER_DEFAULT_BIAS; - app_joint->idle_timer.work_queue = &engine->fast_work_queue; - app_joint->idle_timer.handler = nxt_router_app_idle_timeout; - app_joint->idle_timer.task = &engine->task; - app_joint->idle_timer.log = app_joint->idle_timer.task->log; + s = nxt_str_dup(app_mp, &targets[i], &target); + if (nxt_slow_path(s == NULL)) { + goto app_fail; + } + } - app_joint->free_app_work.handler = nxt_router_free_app; - app_joint->free_app_work.task = &engine->task; - app_joint->free_app_work.obj = app_joint; + } else { + targets = NULL; + } - port = nxt_port_new(task, NXT_SHARED_PORT_ID, nxt_pid, - NXT_PROCESS_APP); - if (nxt_slow_path(port == NULL)) { - return NXT_ERROR; - } + nxt_debug(task, "application type: %V", &apcf.type); + nxt_debug(task, "application processes: %D", apcf.processes); + nxt_debug(task, "application request timeout: %M", apcf.timeout); - ret = nxt_port_socket_init(task, port, 0); - if (nxt_slow_path(ret != NXT_OK)) { - nxt_port_use(task, port, -1); - return NXT_ERROR; - } + lang = nxt_app_lang_module(task->thread->runtime, &apcf.type); - ret = nxt_router_app_queue_init(task, port); - if (nxt_slow_path(ret != NXT_OK)) { - nxt_port_write_close(port); - nxt_port_read_close(port); - nxt_port_use(task, port, -1); - return NXT_ERROR; - } + if (lang == NULL) { + nxt_alert(task, "unknown application type: \"%V\"", &apcf.type); + goto app_fail; + } - nxt_port_write_enable(task, port); - port->app = app; + nxt_debug(task, "application language module: \"%s\"", lang->file); - app->shared_port = port; + ret = nxt_thread_mutex_create(&app->mutex); + if (ret != NXT_OK) { + goto app_fail; + } - nxt_thread_mutex_create(&app->outgoing.mutex); - } - } + nxt_queue_init(&app->ports); + nxt_queue_init(&app->spare_ports); + nxt_queue_init(&app->idle_ports); + nxt_queue_init(&app->ack_waiting_req); - conf = nxt_conf_get_path(root, &routes_path); - if (nxt_fast_path(conf != NULL)) { - routes = nxt_http_routes_create(task, tmcf, conf); - if (nxt_slow_path(routes == NULL)) { - return NXT_ERROR; - } + app->name.length = name.length; + nxt_memcpy(app->name.start, name.start, name.length); - rtcf->routes = routes; + app->type = lang->type; + app->max_processes = apcf.max_processes; + app->spare_processes = apcf.spare_processes; + app->max_pending_processes = + apcf.spare_processes ? apcf.spare_processes : 1; + app->timeout = apcf.timeout; + app->idle_timeout = apcf.idle_timeout; + + app->targets = targets; + + engine = task->thread->engine; + + app->engine = engine; + + app->adjust_idle_work.handler = nxt_router_adjust_idle_timer; + app->adjust_idle_work.task = &engine->task; + app->adjust_idle_work.obj = app; + + nxt_queue_insert_tail(&tmcf->apps, &app->link); + + ret = nxt_router_apps_hash_add(rtcf, app); + if (nxt_slow_path(ret != NXT_OK)) { + goto app_fail; + } + + nxt_router_app_use(task, app, 1); + + app->joint = app_joint; + + app_joint->use_count = 1; + app_joint->app = app; + + app_joint->idle_timer.bias = NXT_TIMER_DEFAULT_BIAS; + app_joint->idle_timer.work_queue = &engine->fast_work_queue; + app_joint->idle_timer.handler = nxt_router_app_idle_timeout; + app_joint->idle_timer.task = &engine->task; + app_joint->idle_timer.log = app_joint->idle_timer.task->log; + + app_joint->free_app_work.handler = nxt_router_free_app; + app_joint->free_app_work.task = &engine->task; + app_joint->free_app_work.obj = app_joint; + + port = nxt_port_new(task, NXT_SHARED_PORT_ID, nxt_pid, NXT_PROCESS_APP); + if (nxt_slow_path(port == NULL)) { + return NXT_ERROR; + } + + ret = nxt_port_socket_init(task, port, 0); + if (nxt_slow_path(ret != NXT_OK)) { + nxt_port_use(task, port, -1); + return NXT_ERROR; + } + + ret = nxt_router_app_queue_init(task, port); + if (nxt_slow_path(ret != NXT_OK)) { + nxt_port_write_close(port); + nxt_port_read_close(port); + nxt_port_use(task, port, -1); + return NXT_ERROR; + } + + nxt_port_write_enable(task, port); + port->app = app; + + app->shared_port = port; + + nxt_thread_mutex_create(&app->outgoing.mutex); } + } - ret = nxt_upstreams_create(task, tmcf, root); - if (nxt_slow_path(ret != NXT_OK)) { - return ret; + conf = nxt_conf_get_path(root, &routes_path); + if (nxt_fast_path(conf != NULL)) { + routes = nxt_http_routes_create(task, tmcf, conf); + if (nxt_slow_path(routes == NULL)) { + return NXT_ERROR; } - http = nxt_conf_get_path(root, &http_path); + rtcf->routes = routes; + } + + ret = nxt_upstreams_create(task, tmcf, root); + if (nxt_slow_path(ret != NXT_OK)) { + return ret; + } + + http = nxt_conf_get_path(root, &http_path); #if 0 if (http == NULL) { nxt_alert(task, "no \"http\" block"); @@ -1962,961 +1880,907 @@ nxt_router_conf_create(nxt_task_t *task, nxt_router_temp_conf_t *tmcf, } #endif - websocket = nxt_conf_get_path(root, &websocket_path); - - listeners = nxt_conf_get_path(root, &listeners_path); - - if (listeners != NULL) { - next = 0; - - for ( ;; ) { - listener = nxt_conf_next_object_member(listeners, &name, &next); - if (listener == NULL) { - break; - } - - nxt_memzero(&lscf, sizeof(lscf)); - - lscf.backlog = -1; - - ret = nxt_conf_map_object(mp, listener, nxt_router_listener_conf, - nxt_nitems(nxt_router_listener_conf), - &lscf); - if (ret != NXT_OK) { - nxt_alert(task, "listener map error"); - goto fail; - } - - nxt_debug(task, "application: %V", &lscf.application); - - skcf = nxt_router_socket_conf(task, tmcf, &name, lscf.backlog); - if (skcf == NULL) { - goto fail; - } - - // STUB, default values if http block is not defined. - skcf->header_buffer_size = 2048; - skcf->large_header_buffer_size = 8192; - skcf->large_header_buffers = 4; - skcf->discard_unsafe_fields = 1; - skcf->body_buffer_size = 16 * 1024; - skcf->max_body_size = 8 * 1024 * 1024; - skcf->proxy_header_buffer_size = 64 * 1024; - skcf->proxy_buffer_size = 4096; - skcf->proxy_buffers = 256; - skcf->idle_timeout = 180 * 1000; - skcf->header_read_timeout = 30 * 1000; - skcf->body_read_timeout = 30 * 1000; - skcf->send_timeout = 30 * 1000; - skcf->proxy_timeout = 60 * 1000; - skcf->proxy_send_timeout = 30 * 1000; - skcf->proxy_read_timeout = 30 * 1000; - - skcf->server_version = 1; - skcf->chunked_transform = 0; - - skcf->websocket_conf.max_frame_size = 1024 * 1024; - skcf->websocket_conf.read_timeout = 60 * 1000; - skcf->websocket_conf.keepalive_interval = 30 * 1000; - - nxt_str_null(&skcf->body_temp_path); - - if (http != NULL) { - ret = nxt_conf_map_object(mp, http, nxt_router_http_conf, - nxt_nitems(nxt_router_http_conf), - skcf); - if (ret != NXT_OK) { - nxt_alert(task, "http map error"); - goto fail; - } - } - - if (websocket != NULL) { - ret = nxt_conf_map_object(mp, websocket, - nxt_router_websocket_conf, - nxt_nitems(nxt_router_websocket_conf), - &skcf->websocket_conf); - if (ret != NXT_OK) { - nxt_alert(task, "websocket map error"); - goto fail; - } - } - - t = &skcf->body_temp_path; - - if (t->length == 0) { - t->start = (u_char *) task->thread->runtime->tmp; - t->length = nxt_strlen(t->start); - } - - conf = nxt_conf_get_path(listener, &forwarded_path); - - if (conf != NULL) { - skcf->forwarded = nxt_router_conf_forward(task, mp, conf); - if (nxt_slow_path(skcf->forwarded == NULL)) { - return NXT_ERROR; - } - } - - conf = nxt_conf_get_path(listener, &client_ip_path); - - if (conf != NULL) { - skcf->client_ip = nxt_router_conf_forward(task, mp, conf); - if (nxt_slow_path(skcf->client_ip == NULL)) { - return NXT_ERROR; - } - } + websocket = nxt_conf_get_path(root, &websocket_path); -#if (NXT_TLS) - certificate = nxt_conf_get_path(listener, &certificate_path); - - if (certificate != NULL) { - tls_init = nxt_mp_get(tmcf->mem_pool, sizeof(nxt_tls_init_t)); - if (nxt_slow_path(tls_init == NULL)) { - return NXT_ERROR; - } - - tls_init->cache_size = 0; - tls_init->timeout = 300; - - value = nxt_conf_get_path(listener, &conf_cache_path); - if (value != NULL) { - tls_init->cache_size = nxt_conf_get_number(value); - } - - value = nxt_conf_get_path(listener, &conf_timeout_path); - if (value != NULL) { - tls_init->timeout = nxt_conf_get_number(value); - } - - tls_init->conf_cmds = nxt_conf_get_path(listener, - &conf_commands_path); - - tls_init->tickets_conf = nxt_conf_get_path(listener, - &conf_tickets); - - n = nxt_conf_array_elements_count_or_1(certificate); - - for (i = 0; i < n; i++) { - value = nxt_conf_get_array_element_or_itself(certificate, - i); - nxt_assert(value != NULL); - - ret = nxt_router_conf_tls_insert(tmcf, value, skcf, - tls_init, i == 0); - if (nxt_slow_path(ret != NXT_OK)) { - goto fail; - } - } - } -#endif + listeners = nxt_conf_get_path(root, &listeners_path); - skcf->listen->handler = nxt_http_conn_init; - skcf->router_conf = rtcf; - skcf->router_conf->count++; + if (listeners != NULL) { + next = 0; - if (lscf.pass.length != 0) { - skcf->action = nxt_http_action_create(task, tmcf, &lscf.pass); + for (;;) { + listener = nxt_conf_next_object_member(listeners, &name, &next); + if (listener == NULL) { + break; + } - /* COMPATIBILITY: listener application. */ - } else if (lscf.application.length > 0) { - skcf->action = nxt_http_pass_application(task, rtcf, - &lscf.application); - } + nxt_memzero(&lscf, sizeof(lscf)); - if (nxt_slow_path(skcf->action == NULL)) { - goto fail; - } - } - } + lscf.backlog = -1; - ret = nxt_http_routes_resolve(task, tmcf); - if (nxt_slow_path(ret != NXT_OK)) { + ret = nxt_conf_map_object(mp, listener, nxt_router_listener_conf, + nxt_nitems(nxt_router_listener_conf), &lscf); + if (ret != NXT_OK) { + nxt_alert(task, "listener map error"); goto fail; - } + } - value = nxt_conf_get_path(root, &access_log_path); + nxt_debug(task, "application: %V", &lscf.application); - if (value != NULL) { - ret = nxt_router_access_log_create(task, rtcf, value); - if (nxt_slow_path(ret != NXT_OK)) { - goto fail; + skcf = nxt_router_socket_conf(task, tmcf, &name, lscf.backlog); + if (skcf == NULL) { + goto fail; + } + + // STUB, default values if http block is not defined. + skcf->header_buffer_size = 2048; + skcf->large_header_buffer_size = 8192; + skcf->large_header_buffers = 4; + skcf->discard_unsafe_fields = 1; + skcf->body_buffer_size = 16 * 1024; + skcf->max_body_size = 8 * 1024 * 1024; + skcf->proxy_header_buffer_size = 64 * 1024; + skcf->proxy_buffer_size = 4096; + skcf->proxy_buffers = 256; + skcf->idle_timeout = 180 * 1000; + skcf->header_read_timeout = 30 * 1000; + skcf->body_read_timeout = 30 * 1000; + skcf->send_timeout = 30 * 1000; + skcf->proxy_timeout = 60 * 1000; + skcf->proxy_send_timeout = 30 * 1000; + skcf->proxy_read_timeout = 30 * 1000; + + skcf->server_version = 1; + skcf->chunked_transform = 0; + + skcf->websocket_conf.max_frame_size = 1024 * 1024; + skcf->websocket_conf.read_timeout = 60 * 1000; + skcf->websocket_conf.keepalive_interval = 30 * 1000; + + nxt_str_null(&skcf->body_temp_path); + + if (http != NULL) { + ret = nxt_conf_map_object(mp, http, nxt_router_http_conf, + nxt_nitems(nxt_router_http_conf), skcf); + if (ret != NXT_OK) { + nxt_alert(task, "http map error"); + goto fail; } - } - -#if (NXT_HAVE_NJS) - js_module = nxt_conf_get_path(root, &js_module_path); + } - if (js_module != NULL) { - if (nxt_conf_type(js_module) == NXT_CONF_ARRAY) { - n = nxt_conf_array_elements_count(js_module); + if (websocket != NULL) { + ret = nxt_conf_map_object(mp, websocket, nxt_router_websocket_conf, + nxt_nitems(nxt_router_websocket_conf), + &skcf->websocket_conf); + if (ret != NXT_OK) { + nxt_alert(task, "websocket map error"); + goto fail; + } + } - for (i = 0; i < n; i++) { - value = nxt_conf_get_array_element(js_module, i); + t = &skcf->body_temp_path; - ret = nxt_router_js_module_insert(tmcf, value); - if (nxt_slow_path(ret != NXT_OK)) { - goto fail; - } - } + if (t->length == 0) { + t->start = (u_char *)task->thread->runtime->tmp; + t->length = nxt_strlen(t->start); + } - } else { - /* NXT_CONF_STRING */ + conf = nxt_conf_get_path(listener, &forwarded_path); - ret = nxt_router_js_module_insert(tmcf, js_module); - if (nxt_slow_path(ret != NXT_OK)) { - goto fail; - } + if (conf != NULL) { + skcf->forwarded = nxt_router_conf_forward(task, mp, conf); + if (nxt_slow_path(skcf->forwarded == NULL)) { + return NXT_ERROR; } - } + } -#endif + conf = nxt_conf_get_path(listener, &client_ip_path); - nxt_queue_add(&deleting_sockets, &router->sockets); - nxt_queue_init(&router->sockets); + if (conf != NULL) { + skcf->client_ip = nxt_router_conf_forward(task, mp, conf); + if (nxt_slow_path(skcf->client_ip == NULL)) { + return NXT_ERROR; + } + } - return NXT_OK; +#if (NXT_TLS) + certificate = nxt_conf_get_path(listener, &certificate_path); -app_fail: + if (certificate != NULL) { + tls_init = nxt_mp_get(tmcf->mem_pool, sizeof(nxt_tls_init_t)); + if (nxt_slow_path(tls_init == NULL)) { + return NXT_ERROR; + } - nxt_mp_destroy(app_mp); + tls_init->cache_size = 0; + tls_init->timeout = 300; -fail: + value = nxt_conf_get_path(listener, &conf_cache_path); + if (value != NULL) { + tls_init->cache_size = nxt_conf_get_number(value); + } - nxt_queue_each(app, &tmcf->apps, nxt_app_t, link) { + value = nxt_conf_get_path(listener, &conf_timeout_path); + if (value != NULL) { + tls_init->timeout = nxt_conf_get_number(value); + } - nxt_queue_remove(&app->link); - nxt_thread_mutex_destroy(&app->mutex); - nxt_mp_destroy(app->mem_pool); + tls_init->conf_cmds = nxt_conf_get_path(listener, &conf_commands_path); - } nxt_queue_loop; + tls_init->tickets_conf = nxt_conf_get_path(listener, &conf_tickets); - return NXT_ERROR; -} + n = nxt_conf_array_elements_count_or_1(certificate); + for (i = 0; i < n; i++) { + value = nxt_conf_get_array_element_or_itself(certificate, i); + nxt_assert(value != NULL); -#if (NXT_TLS) + ret = nxt_router_conf_tls_insert(tmcf, value, skcf, tls_init, i == 0); + if (nxt_slow_path(ret != NXT_OK)) { + goto fail; + } + } + } +#endif -static nxt_int_t -nxt_router_conf_tls_insert(nxt_router_temp_conf_t *tmcf, - nxt_conf_value_t *value, nxt_socket_conf_t *skcf, - nxt_tls_init_t *tls_init, nxt_bool_t last) -{ - nxt_router_tlssock_t *tls; - - tls = nxt_mp_get(tmcf->mem_pool, sizeof(nxt_router_tlssock_t)); - if (nxt_slow_path(tls == NULL)) { - return NXT_ERROR; - } + skcf->listen->handler = nxt_http_conn_init; + skcf->router_conf = rtcf; + skcf->router_conf->count++; - tls->tls_init = tls_init; - tls->socket_conf = skcf; - tls->temp_conf = tmcf; - tls->last = last; - nxt_conf_get_string(value, &tls->name); + if (lscf.pass.length != 0) { + skcf->action = nxt_http_action_create(task, tmcf, &lscf.pass); - nxt_queue_insert_tail(&tmcf->tls, &tls->link); + /* COMPATIBILITY: listener application. */ + } else if (lscf.application.length > 0) { + skcf->action = nxt_http_pass_application(task, rtcf, &lscf.application); + } - return NXT_OK; -} + if (nxt_slow_path(skcf->action == NULL)) { + goto fail; + } + } + } -#endif + ret = nxt_http_routes_resolve(task, tmcf); + if (nxt_slow_path(ret != NXT_OK)) { + goto fail; + } + value = nxt_conf_get_path(root, &access_log_path); + + if (value != NULL) { + ret = nxt_router_access_log_create(task, rtcf, value); + if (nxt_slow_path(ret != NXT_OK)) { + goto fail; + } + } #if (NXT_HAVE_NJS) + js_module = nxt_conf_get_path(root, &js_module_path); -static void -nxt_router_js_module_rpc_handler(nxt_task_t *task, nxt_port_recv_msg_t *msg, - void *data) -{ - nxt_int_t ret; - nxt_str_t text; - nxt_router_conf_t *rtcf; - nxt_router_temp_conf_t *tmcf; - nxt_router_js_module_t *js_module; + if (js_module != NULL) { + if (nxt_conf_type(js_module) == NXT_CONF_ARRAY) { + n = nxt_conf_array_elements_count(js_module); - nxt_debug(task, "auto module rpc handler"); + for (i = 0; i < n; i++) { + value = nxt_conf_get_array_element(js_module, i); + + ret = nxt_router_js_module_insert(tmcf, value); + if (nxt_slow_path(ret != NXT_OK)) { + goto fail; + } + } - js_module = data; - tmcf = js_module->temp_conf; + } else { + /* NXT_CONF_STRING */ - if (msg == NULL || msg->port_msg.type == _NXT_PORT_MSG_RPC_ERROR) { + ret = nxt_router_js_module_insert(tmcf, js_module); + if (nxt_slow_path(ret != NXT_OK)) { goto fail; + } } + } - rtcf = tmcf->router_conf; - - ret = nxt_script_file_read(msg->fd[0], &text); +#endif - nxt_fd_close(msg->fd[0]); + nxt_queue_add(&deleting_sockets, &router->sockets); + nxt_queue_init(&router->sockets); - if (nxt_slow_path(ret == NXT_ERROR)) { - goto fail; - } + return NXT_OK; - if (text.length > 0) { - ret = nxt_js_add_module(rtcf->tstr_state->jcf, &js_module->name, &text); +app_fail: - nxt_free(text.start); + nxt_mp_destroy(app_mp); - if (nxt_slow_path(ret == NXT_ERROR)) { - goto fail; - } - } +fail: - nxt_work_queue_add(&task->thread->engine->fast_work_queue, - nxt_router_conf_apply, task, tmcf, NULL); - return; + nxt_queue_each(app, &tmcf->apps, nxt_app_t, link) { -fail: + nxt_queue_remove(&app->link); + nxt_thread_mutex_destroy(&app->mutex); + nxt_mp_destroy(app->mem_pool); + } + nxt_queue_loop; - nxt_router_conf_error(task, tmcf); + return NXT_ERROR; } +#if (NXT_TLS) -static nxt_int_t -nxt_router_js_module_insert(nxt_router_temp_conf_t *tmcf, - nxt_conf_value_t *value) -{ - nxt_router_js_module_t *js_module; - - js_module = nxt_mp_get(tmcf->mem_pool, sizeof(nxt_router_js_module_t)); - if (nxt_slow_path(js_module == NULL)) { - return NXT_ERROR; - } +static nxt_int_t nxt_router_conf_tls_insert(nxt_router_temp_conf_t *tmcf, + nxt_conf_value_t *value, + nxt_socket_conf_t *skcf, + nxt_tls_init_t *tls_init, + nxt_bool_t last) { + nxt_router_tlssock_t *tls; + + tls = nxt_mp_get(tmcf->mem_pool, sizeof(nxt_router_tlssock_t)); + if (nxt_slow_path(tls == NULL)) { + return NXT_ERROR; + } - js_module->temp_conf = tmcf; - nxt_conf_get_string(value, &js_module->name); + tls->tls_init = tls_init; + tls->socket_conf = skcf; + tls->temp_conf = tmcf; + tls->last = last; + nxt_conf_get_string(value, &tls->name); - nxt_queue_insert_tail(&tmcf->js_modules, &js_module->link); + nxt_queue_insert_tail(&tmcf->tls, &tls->link); - return NXT_OK; + return NXT_OK; } #endif +#if (NXT_HAVE_NJS) -static nxt_int_t -nxt_router_conf_process_static(nxt_task_t *task, nxt_router_conf_t *rtcf, - nxt_conf_value_t *conf) -{ - uint32_t next, i; - nxt_mp_t *mp; - nxt_str_t *type, exten, str, *s; - nxt_int_t ret; - nxt_uint_t exts; - nxt_conf_value_t *mtypes_conf, *ext_conf, *value; +static void nxt_router_js_module_rpc_handler(nxt_task_t *task, + nxt_port_recv_msg_t *msg, + void *data) { + nxt_int_t ret; + nxt_str_t text; + nxt_router_conf_t *rtcf; + nxt_router_temp_conf_t *tmcf; + nxt_router_js_module_t *js_module; - static const nxt_str_t mtypes_path = nxt_string("/mime_types"); + nxt_debug(task, "auto module rpc handler"); - mp = rtcf->mem_pool; + js_module = data; + tmcf = js_module->temp_conf; - ret = nxt_http_static_mtypes_init(mp, &rtcf->mtypes_hash); - if (nxt_slow_path(ret != NXT_OK)) { - return NXT_ERROR; - } + if (msg == NULL || msg->port_msg.type == _NXT_PORT_MSG_RPC_ERROR) { + goto fail; + } - if (conf == NULL) { - return NXT_OK; - } + rtcf = tmcf->router_conf; - mtypes_conf = nxt_conf_get_path(conf, &mtypes_path); + ret = nxt_script_file_read(msg->fd[0], &text); - if (mtypes_conf != NULL) { - next = 0; + nxt_fd_close(msg->fd[0]); - for ( ;; ) { - ext_conf = nxt_conf_next_object_member(mtypes_conf, &str, &next); + if (nxt_slow_path(ret == NXT_ERROR)) { + goto fail; + } - if (ext_conf == NULL) { - break; - } + if (text.length > 0) { + ret = nxt_js_add_module(rtcf->tstr_state->jcf, &js_module->name, &text); - type = nxt_str_dup(mp, NULL, &str); - if (nxt_slow_path(type == NULL)) { - return NXT_ERROR; - } + nxt_free(text.start); + + if (nxt_slow_path(ret == NXT_ERROR)) { + goto fail; + } + } - if (nxt_conf_type(ext_conf) == NXT_CONF_STRING) { - s = nxt_conf_get_string_dup(ext_conf, mp, &exten); - if (nxt_slow_path(s == NULL)) { - return NXT_ERROR; - } + nxt_work_queue_add(&task->thread->engine->fast_work_queue, + nxt_router_conf_apply, task, tmcf, NULL); + return; - ret = nxt_http_static_mtypes_hash_add(mp, &rtcf->mtypes_hash, - &exten, type); - if (nxt_slow_path(ret != NXT_OK)) { - return NXT_ERROR; - } +fail: - continue; - } + nxt_router_conf_error(task, tmcf); +} - exts = nxt_conf_array_elements_count(ext_conf); +static nxt_int_t nxt_router_js_module_insert(nxt_router_temp_conf_t *tmcf, + nxt_conf_value_t *value) { + nxt_router_js_module_t *js_module; - for (i = 0; i < exts; i++) { - value = nxt_conf_get_array_element(ext_conf, i); + js_module = nxt_mp_get(tmcf->mem_pool, sizeof(nxt_router_js_module_t)); + if (nxt_slow_path(js_module == NULL)) { + return NXT_ERROR; + } - s = nxt_conf_get_string_dup(value, mp, &exten); - if (nxt_slow_path(s == NULL)) { - return NXT_ERROR; - } + js_module->temp_conf = tmcf; + nxt_conf_get_string(value, &js_module->name); - ret = nxt_http_static_mtypes_hash_add(mp, &rtcf->mtypes_hash, - &exten, type); - if (nxt_slow_path(ret != NXT_OK)) { - return NXT_ERROR; - } - } - } - } + nxt_queue_insert_tail(&tmcf->js_modules, &js_module->link); - return NXT_OK; + return NXT_OK; } +#endif -static nxt_http_forward_t * -nxt_router_conf_forward(nxt_task_t *task, nxt_mp_t *mp, nxt_conf_value_t *conf) -{ - nxt_int_t ret; - nxt_conf_value_t *header_conf, *client_ip_conf, *protocol_conf; - nxt_conf_value_t *source_conf, *recursive_conf; - nxt_http_forward_t *forward; - nxt_http_route_addr_rule_t *source; - - static const nxt_str_t header_path = nxt_string("/header"); - static const nxt_str_t client_ip_path = nxt_string("/client_ip"); - static const nxt_str_t protocol_path = nxt_string("/protocol"); - static const nxt_str_t source_path = nxt_string("/source"); - static const nxt_str_t recursive_path = nxt_string("/recursive"); - - header_conf = nxt_conf_get_path(conf, &header_path); - - if (header_conf != NULL) { - client_ip_conf = nxt_conf_get_path(conf, &header_path); - protocol_conf = NULL; +static nxt_int_t nxt_router_conf_process_static(nxt_task_t *task, + nxt_router_conf_t *rtcf, + nxt_conf_value_t *conf) { + uint32_t next, i; + nxt_mp_t *mp; + nxt_str_t *type, exten, str, *s; + nxt_int_t ret; + nxt_uint_t exts; + nxt_conf_value_t *mtypes_conf, *ext_conf, *value; - } else { - client_ip_conf = nxt_conf_get_path(conf, &client_ip_path); - protocol_conf = nxt_conf_get_path(conf, &protocol_path); - } + static const nxt_str_t mtypes_path = nxt_string("/mime_types"); - source_conf = nxt_conf_get_path(conf, &source_path); - recursive_conf = nxt_conf_get_path(conf, &recursive_path); + mp = rtcf->mem_pool; - if (source_conf == NULL - || (protocol_conf == NULL && client_ip_conf == NULL)) - { - return NULL; - } + ret = nxt_http_static_mtypes_init(mp, &rtcf->mtypes_hash); + if (nxt_slow_path(ret != NXT_OK)) { + return NXT_ERROR; + } - forward = nxt_mp_zget(mp, sizeof(nxt_http_forward_t)); - if (nxt_slow_path(forward == NULL)) { - return NULL; - } + if (conf == NULL) { + return NXT_OK; + } - source = nxt_http_route_addr_rule_create(task, mp, source_conf); - if (nxt_slow_path(source == NULL)) { - return NULL; - } + mtypes_conf = nxt_conf_get_path(conf, &mtypes_path); - forward->source = source; + if (mtypes_conf != NULL) { + next = 0; - if (recursive_conf != NULL) { - forward->recursive = nxt_conf_get_boolean(recursive_conf); - } + for (;;) { + ext_conf = nxt_conf_next_object_member(mtypes_conf, &str, &next); - if (client_ip_conf != NULL) { - ret = nxt_router_conf_forward_header(mp, client_ip_conf, - &forward->client_ip); + if (ext_conf == NULL) { + break; + } + + type = nxt_str_dup(mp, NULL, &str); + if (nxt_slow_path(type == NULL)) { + return NXT_ERROR; + } + + if (nxt_conf_type(ext_conf) == NXT_CONF_STRING) { + s = nxt_conf_get_string_dup(ext_conf, mp, &exten); + if (nxt_slow_path(s == NULL)) { + return NXT_ERROR; + } + + ret = nxt_http_static_mtypes_hash_add(mp, &rtcf->mtypes_hash, &exten, + type); if (nxt_slow_path(ret != NXT_OK)) { - return NULL; + return NXT_ERROR; } - } - if (protocol_conf != NULL) { - ret = nxt_router_conf_forward_header(mp, protocol_conf, - &forward->protocol); + continue; + } + + exts = nxt_conf_array_elements_count(ext_conf); + + for (i = 0; i < exts; i++) { + value = nxt_conf_get_array_element(ext_conf, i); + + s = nxt_conf_get_string_dup(value, mp, &exten); + if (nxt_slow_path(s == NULL)) { + return NXT_ERROR; + } + + ret = nxt_http_static_mtypes_hash_add(mp, &rtcf->mtypes_hash, &exten, + type); if (nxt_slow_path(ret != NXT_OK)) { - return NULL; + return NXT_ERROR; } + } } + } - return forward; + return NXT_OK; } +static nxt_http_forward_t *nxt_router_conf_forward(nxt_task_t *task, + nxt_mp_t *mp, + nxt_conf_value_t *conf) { + nxt_int_t ret; + nxt_conf_value_t *header_conf, *client_ip_conf, *protocol_conf; + nxt_conf_value_t *source_conf, *recursive_conf; + nxt_http_forward_t *forward; + nxt_http_route_addr_rule_t *source; + + static const nxt_str_t header_path = nxt_string("/header"); + static const nxt_str_t client_ip_path = nxt_string("/client_ip"); + static const nxt_str_t protocol_path = nxt_string("/protocol"); + static const nxt_str_t source_path = nxt_string("/source"); + static const nxt_str_t recursive_path = nxt_string("/recursive"); + + header_conf = nxt_conf_get_path(conf, &header_path); + + if (header_conf != NULL) { + client_ip_conf = nxt_conf_get_path(conf, &header_path); + protocol_conf = NULL; + + } else { + client_ip_conf = nxt_conf_get_path(conf, &client_ip_path); + protocol_conf = nxt_conf_get_path(conf, &protocol_path); + } + + source_conf = nxt_conf_get_path(conf, &source_path); + recursive_conf = nxt_conf_get_path(conf, &recursive_path); + + if (source_conf == NULL || + (protocol_conf == NULL && client_ip_conf == NULL)) { + return NULL; + } -static nxt_int_t -nxt_router_conf_forward_header(nxt_mp_t *mp, nxt_conf_value_t *conf, - nxt_http_forward_header_t *fh) -{ - char c; - size_t i; - uint32_t hash; - - fh->header = nxt_conf_get_string_dup(conf, mp, NULL); - if (nxt_slow_path(fh->header == NULL)) { - return NXT_ERROR; - } + forward = nxt_mp_zget(mp, sizeof(nxt_http_forward_t)); + if (nxt_slow_path(forward == NULL)) { + return NULL; + } - hash = NXT_HTTP_FIELD_HASH_INIT; + source = nxt_http_route_addr_rule_create(task, mp, source_conf); + if (nxt_slow_path(source == NULL)) { + return NULL; + } - for (i = 0; i < fh->header->length; i++) { - c = fh->header->start[i]; - hash = nxt_http_field_hash_char(hash, nxt_lowcase(c)); - } + forward->source = source; - hash = nxt_http_field_hash_end(hash) & 0xFFFF; + if (recursive_conf != NULL) { + forward->recursive = nxt_conf_get_boolean(recursive_conf); + } - fh->header_hash = hash; + if (client_ip_conf != NULL) { + ret = + nxt_router_conf_forward_header(mp, client_ip_conf, &forward->client_ip); + if (nxt_slow_path(ret != NXT_OK)) { + return NULL; + } + } - return NXT_OK; + if (protocol_conf != NULL) { + ret = nxt_router_conf_forward_header(mp, protocol_conf, &forward->protocol); + if (nxt_slow_path(ret != NXT_OK)) { + return NULL; + } + } + + return forward; } +static nxt_int_t nxt_router_conf_forward_header(nxt_mp_t *mp, + nxt_conf_value_t *conf, + nxt_http_forward_header_t *fh) { + char c; + size_t i; + uint32_t hash; + + fh->header = nxt_conf_get_string_dup(conf, mp, NULL); + if (nxt_slow_path(fh->header == NULL)) { + return NXT_ERROR; + } -static nxt_app_t * -nxt_router_app_find(nxt_queue_t *queue, nxt_str_t *name) -{ - nxt_app_t *app; + hash = NXT_HTTP_FIELD_HASH_INIT; - nxt_queue_each(app, queue, nxt_app_t, link) { + for (i = 0; i < fh->header->length; i++) { + c = fh->header->start[i]; + hash = nxt_http_field_hash_char(hash, nxt_lowcase(c)); + } - if (nxt_strstr_eq(name, &app->name)) { - return app; - } + hash = nxt_http_field_hash_end(hash) & 0xFFFF; - } nxt_queue_loop; + fh->header_hash = hash; - return NULL; + return NXT_OK; } +static nxt_app_t *nxt_router_app_find(nxt_queue_t *queue, nxt_str_t *name) { + nxt_app_t *app; -static nxt_int_t -nxt_router_app_queue_init(nxt_task_t *task, nxt_port_t *port) -{ - void *mem; - nxt_int_t fd; + nxt_queue_each(app, queue, nxt_app_t, link) { - fd = nxt_shm_open(task, sizeof(nxt_app_queue_t)); - if (nxt_slow_path(fd == -1)) { - return NXT_ERROR; + if (nxt_strstr_eq(name, &app->name)) { + return app; } + } + nxt_queue_loop; - mem = nxt_mem_mmap(NULL, sizeof(nxt_app_queue_t), - PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); - if (nxt_slow_path(mem == MAP_FAILED)) { - nxt_fd_close(fd); + return NULL; +} - return NXT_ERROR; - } +static nxt_int_t nxt_router_app_queue_init(nxt_task_t *task, nxt_port_t *port) { + void *mem; + nxt_int_t fd; - nxt_app_queue_init(mem); + fd = nxt_shm_open(task, sizeof(nxt_app_queue_t)); + if (nxt_slow_path(fd == -1)) { + return NXT_ERROR; + } - port->queue_fd = fd; - port->queue = mem; + mem = nxt_mem_mmap(NULL, sizeof(nxt_app_queue_t), PROT_READ | PROT_WRITE, + MAP_SHARED, fd, 0); + if (nxt_slow_path(mem == MAP_FAILED)) { + nxt_fd_close(fd); - return NXT_OK; -} + return NXT_ERROR; + } + nxt_app_queue_init(mem); -static nxt_int_t -nxt_router_port_queue_init(nxt_task_t *task, nxt_port_t *port) -{ - void *mem; - nxt_int_t fd; + port->queue_fd = fd; + port->queue = mem; - fd = nxt_shm_open(task, sizeof(nxt_port_queue_t)); - if (nxt_slow_path(fd == -1)) { - return NXT_ERROR; - } + return NXT_OK; +} + +static nxt_int_t nxt_router_port_queue_init(nxt_task_t *task, + nxt_port_t *port) { + void *mem; + nxt_int_t fd; - mem = nxt_mem_mmap(NULL, sizeof(nxt_port_queue_t), - PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); - if (nxt_slow_path(mem == MAP_FAILED)) { - nxt_fd_close(fd); + fd = nxt_shm_open(task, sizeof(nxt_port_queue_t)); + if (nxt_slow_path(fd == -1)) { + return NXT_ERROR; + } - return NXT_ERROR; - } + mem = nxt_mem_mmap(NULL, sizeof(nxt_port_queue_t), PROT_READ | PROT_WRITE, + MAP_SHARED, fd, 0); + if (nxt_slow_path(mem == MAP_FAILED)) { + nxt_fd_close(fd); - nxt_port_queue_init(mem); + return NXT_ERROR; + } - port->queue_fd = fd; - port->queue = mem; + nxt_port_queue_init(mem); - return NXT_OK; -} + port->queue_fd = fd; + port->queue = mem; + return NXT_OK; +} -static nxt_int_t -nxt_router_port_queue_map(nxt_task_t *task, nxt_port_t *port, nxt_fd_t fd) -{ - void *mem; +static nxt_int_t nxt_router_port_queue_map(nxt_task_t *task, nxt_port_t *port, + nxt_fd_t fd) { + void *mem; - nxt_assert(fd != -1); + nxt_assert(fd != -1); - mem = nxt_mem_mmap(NULL, sizeof(nxt_port_queue_t), - PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); - if (nxt_slow_path(mem == MAP_FAILED)) { + mem = nxt_mem_mmap(NULL, sizeof(nxt_port_queue_t), PROT_READ | PROT_WRITE, + MAP_SHARED, fd, 0); + if (nxt_slow_path(mem == MAP_FAILED)) { - return NXT_ERROR; - } + return NXT_ERROR; + } - port->queue = mem; + port->queue = mem; - return NXT_OK; + return NXT_OK; } - -static const nxt_lvlhsh_proto_t nxt_router_apps_hash_proto nxt_aligned(64) = { +static const nxt_lvlhsh_proto_t nxt_router_apps_hash_proto nxt_aligned(64) = { NXT_LVLHSH_DEFAULT, nxt_router_apps_hash_test, nxt_mp_lvlhsh_alloc, nxt_mp_lvlhsh_free, }; +static nxt_int_t nxt_router_apps_hash_test(nxt_lvlhsh_query_t *lhq, + void *data) { + nxt_app_t *app; -static nxt_int_t -nxt_router_apps_hash_test(nxt_lvlhsh_query_t *lhq, void *data) -{ - nxt_app_t *app; - - app = data; + app = data; - return nxt_strstr_eq(&lhq->key, &app->name) ? NXT_OK : NXT_DECLINED; + return nxt_strstr_eq(&lhq->key, &app->name) ? NXT_OK : NXT_DECLINED; } +static nxt_int_t nxt_router_apps_hash_add(nxt_router_conf_t *rtcf, + nxt_app_t *app) { + nxt_lvlhsh_query_t lhq; -static nxt_int_t -nxt_router_apps_hash_add(nxt_router_conf_t *rtcf, nxt_app_t *app) -{ - nxt_lvlhsh_query_t lhq; - - lhq.key_hash = nxt_djb_hash(app->name.start, app->name.length); - lhq.replace = 0; - lhq.key = app->name; - lhq.value = app; - lhq.proto = &nxt_router_apps_hash_proto; - lhq.pool = rtcf->mem_pool; - - switch (nxt_lvlhsh_insert(&rtcf->apps_hash, &lhq)) { - - case NXT_OK: - return NXT_OK; - - case NXT_DECLINED: - nxt_thread_log_alert("router app hash adding failed: " - "\"%V\" is already in hash", &lhq.key); - /* Fall through. */ - default: - return NXT_ERROR; - } -} + lhq.key_hash = nxt_djb_hash(app->name.start, app->name.length); + lhq.replace = 0; + lhq.key = app->name; + lhq.value = app; + lhq.proto = &nxt_router_apps_hash_proto; + lhq.pool = rtcf->mem_pool; + switch (nxt_lvlhsh_insert(&rtcf->apps_hash, &lhq)) { -static nxt_app_t * -nxt_router_apps_hash_get(nxt_router_conf_t *rtcf, nxt_str_t *name) -{ - nxt_lvlhsh_query_t lhq; + case NXT_OK: + return NXT_OK; - lhq.key_hash = nxt_djb_hash(name->start, name->length); - lhq.key = *name; - lhq.proto = &nxt_router_apps_hash_proto; + case NXT_DECLINED: + nxt_thread_log_alert("router app hash adding failed: " + "\"%V\" is already in hash", + &lhq.key); + /* Fall through. */ + default: + return NXT_ERROR; + } +} - if (nxt_lvlhsh_find(&rtcf->apps_hash, &lhq) != NXT_OK) { - return NULL; - } +static nxt_app_t *nxt_router_apps_hash_get(nxt_router_conf_t *rtcf, + nxt_str_t *name) { + nxt_lvlhsh_query_t lhq; - return lhq.value; -} + lhq.key_hash = nxt_djb_hash(name->start, name->length); + lhq.key = *name; + lhq.proto = &nxt_router_apps_hash_proto; + if (nxt_lvlhsh_find(&rtcf->apps_hash, &lhq) != NXT_OK) { + return NULL; + } -static void -nxt_router_apps_hash_use(nxt_task_t *task, nxt_router_conf_t *rtcf, int i) -{ - nxt_app_t *app; - nxt_lvlhsh_each_t lhe; + return lhq.value; +} - nxt_lvlhsh_each_init(&lhe, &nxt_router_apps_hash_proto); +static void nxt_router_apps_hash_use(nxt_task_t *task, nxt_router_conf_t *rtcf, + int i) { + nxt_app_t *app; + nxt_lvlhsh_each_t lhe; - for ( ;; ) { - app = nxt_lvlhsh_each(&rtcf->apps_hash, &lhe); + nxt_lvlhsh_each_init(&lhe, &nxt_router_apps_hash_proto); - if (app == NULL) { - break; - } + for (;;) { + app = nxt_lvlhsh_each(&rtcf->apps_hash, &lhe); - nxt_router_app_use(task, app, i); + if (app == NULL) { + break; } -} + nxt_router_app_use(task, app, i); + } +} typedef struct { - nxt_app_t *app; - nxt_int_t target; + nxt_app_t *app; + nxt_int_t target; } nxt_http_app_conf_t; +nxt_int_t nxt_router_application_init(nxt_router_conf_t *rtcf, nxt_str_t *name, + nxt_str_t *target, + nxt_http_action_t *action) { + nxt_app_t *app; + nxt_str_t *targets; + nxt_uint_t i; + nxt_http_app_conf_t *conf; -nxt_int_t -nxt_router_application_init(nxt_router_conf_t *rtcf, nxt_str_t *name, - nxt_str_t *target, nxt_http_action_t *action) -{ - nxt_app_t *app; - nxt_str_t *targets; - nxt_uint_t i; - nxt_http_app_conf_t *conf; - - app = nxt_router_apps_hash_get(rtcf, name); - if (app == NULL) { - return NXT_DECLINED; - } + app = nxt_router_apps_hash_get(rtcf, name); + if (app == NULL) { + return NXT_DECLINED; + } - conf = nxt_mp_get(rtcf->mem_pool, sizeof(nxt_http_app_conf_t)); - if (nxt_slow_path(conf == NULL)) { - return NXT_ERROR; - } + conf = nxt_mp_get(rtcf->mem_pool, sizeof(nxt_http_app_conf_t)); + if (nxt_slow_path(conf == NULL)) { + return NXT_ERROR; + } - action->handler = nxt_http_application_handler; - action->u.conf = conf; + action->handler = nxt_http_application_handler; + action->u.conf = conf; - conf->app = app; + conf->app = app; - if (target != NULL && target->length != 0) { - targets = app->targets; + if (target != NULL && target->length != 0) { + targets = app->targets; - for (i = 0; !nxt_strstr_eq(target, &targets[i]); i++); + for (i = 0; !nxt_strstr_eq(target, &targets[i]); i++) + ; - conf->target = i; + conf->target = i; - } else { - conf->target = 0; - } + } else { + conf->target = 0; + } - return NXT_OK; + return NXT_OK; } +static nxt_socket_conf_t *nxt_router_socket_conf(nxt_task_t *task, + nxt_router_temp_conf_t *tmcf, + nxt_str_t *name, int backlog) { + size_t size; + nxt_int_t ret; + nxt_bool_t wildcard; + nxt_sockaddr_t *sa; + nxt_socket_conf_t *skcf; + nxt_listen_socket_t *ls; + + sa = nxt_sockaddr_parse(tmcf->mem_pool, name); + if (nxt_slow_path(sa == NULL)) { + nxt_alert(task, "invalid listener \"%V\"", name); + return NULL; + } -static nxt_socket_conf_t * -nxt_router_socket_conf(nxt_task_t *task, nxt_router_temp_conf_t *tmcf, - nxt_str_t *name, int backlog) -{ - size_t size; - nxt_int_t ret; - nxt_bool_t wildcard; - nxt_sockaddr_t *sa; - nxt_socket_conf_t *skcf; - nxt_listen_socket_t *ls; - - sa = nxt_sockaddr_parse(tmcf->mem_pool, name); - if (nxt_slow_path(sa == NULL)) { - nxt_alert(task, "invalid listener \"%V\"", name); - return NULL; - } - - sa->type = SOCK_STREAM; + sa->type = SOCK_STREAM; - nxt_debug(task, "router listener: \"%*s\"", - (size_t) sa->length, nxt_sockaddr_start(sa)); + nxt_debug(task, "router listener: \"%*s\"", (size_t)sa->length, + nxt_sockaddr_start(sa)); - skcf = nxt_mp_zget(tmcf->router_conf->mem_pool, sizeof(nxt_socket_conf_t)); - if (nxt_slow_path(skcf == NULL)) { - return NULL; - } + skcf = nxt_mp_zget(tmcf->router_conf->mem_pool, sizeof(nxt_socket_conf_t)); + if (nxt_slow_path(skcf == NULL)) { + return NULL; + } - size = nxt_sockaddr_size(sa); + size = nxt_sockaddr_size(sa); - ret = nxt_router_listen_socket_find(tmcf, skcf, sa); + ret = nxt_router_listen_socket_find(tmcf, skcf, sa); - if (ret != NXT_OK) { + if (ret != NXT_OK) { - ls = nxt_zalloc(sizeof(nxt_listen_socket_t) + size); - if (nxt_slow_path(ls == NULL)) { - return NULL; - } + ls = nxt_zalloc(sizeof(nxt_listen_socket_t) + size); + if (nxt_slow_path(ls == NULL)) { + return NULL; + } - skcf->listen = ls; + skcf->listen = ls; - ls->sockaddr = nxt_pointer_to(ls, sizeof(nxt_listen_socket_t)); - nxt_memcpy(ls->sockaddr, sa, size); + ls->sockaddr = nxt_pointer_to(ls, sizeof(nxt_listen_socket_t)); + nxt_memcpy(ls->sockaddr, sa, size); - nxt_listen_socket_remote_size(ls); + nxt_listen_socket_remote_size(ls); - ls->socket = -1; - ls->backlog = backlog > -1 ? backlog : NXT_LISTEN_BACKLOG; - ls->flags = NXT_NONBLOCK; - ls->read_after_accept = 1; - } + ls->socket = -1; + ls->backlog = backlog > -1 ? backlog : NXT_LISTEN_BACKLOG; + ls->flags = NXT_NONBLOCK; + ls->read_after_accept = 1; + } - switch (sa->u.sockaddr.sa_family) { + switch (sa->u.sockaddr.sa_family) { #if (NXT_HAVE_UNIX_DOMAIN) - case AF_UNIX: - wildcard = 0; - break; + case AF_UNIX: + wildcard = 0; + break; #endif #if (NXT_INET6) - case AF_INET6: - wildcard = IN6_IS_ADDR_UNSPECIFIED(&sa->u.sockaddr_in6.sin6_addr); - break; + case AF_INET6: + wildcard = IN6_IS_ADDR_UNSPECIFIED(&sa->u.sockaddr_in6.sin6_addr); + break; #endif - case AF_INET: - default: - wildcard = (sa->u.sockaddr_in.sin_addr.s_addr == INADDR_ANY); - break; - } - - if (!wildcard) { - skcf->sockaddr = nxt_mp_zget(tmcf->router_conf->mem_pool, size); - if (nxt_slow_path(skcf->sockaddr == NULL)) { - return NULL; - } + case AF_INET: + default: + wildcard = (sa->u.sockaddr_in.sin_addr.s_addr == INADDR_ANY); + break; + } - nxt_memcpy(skcf->sockaddr, sa, size); + if (!wildcard) { + skcf->sockaddr = nxt_mp_zget(tmcf->router_conf->mem_pool, size); + if (nxt_slow_path(skcf->sockaddr == NULL)) { + return NULL; } - return skcf; + nxt_memcpy(skcf->sockaddr, sa, size); + } + + return skcf; } +static nxt_int_t nxt_router_listen_socket_find(nxt_router_temp_conf_t *tmcf, + nxt_socket_conf_t *nskcf, + nxt_sockaddr_t *sa) { + nxt_router_t *router; + nxt_queue_link_t *qlk; + nxt_socket_conf_t *skcf; -static nxt_int_t -nxt_router_listen_socket_find(nxt_router_temp_conf_t *tmcf, - nxt_socket_conf_t *nskcf, nxt_sockaddr_t *sa) -{ - nxt_router_t *router; - nxt_queue_link_t *qlk; - nxt_socket_conf_t *skcf; - - router = tmcf->router_conf->router; - - for (qlk = nxt_queue_first(&router->sockets); - qlk != nxt_queue_tail(&router->sockets); - qlk = nxt_queue_next(qlk)) - { - skcf = nxt_queue_link_data(qlk, nxt_socket_conf_t, link); + router = tmcf->router_conf->router; - if (nxt_sockaddr_cmp(skcf->listen->sockaddr, sa)) { - nskcf->listen = skcf->listen; + for (qlk = nxt_queue_first(&router->sockets); + qlk != nxt_queue_tail(&router->sockets); qlk = nxt_queue_next(qlk)) { + skcf = nxt_queue_link_data(qlk, nxt_socket_conf_t, link); - nxt_queue_remove(qlk); - nxt_queue_insert_tail(&keeping_sockets, qlk); + if (nxt_sockaddr_cmp(skcf->listen->sockaddr, sa)) { + nskcf->listen = skcf->listen; - nxt_queue_insert_tail(&updating_sockets, &nskcf->link); + nxt_queue_remove(qlk); + nxt_queue_insert_tail(&keeping_sockets, qlk); - return NXT_OK; - } + nxt_queue_insert_tail(&updating_sockets, &nskcf->link); + + return NXT_OK; } + } - nxt_queue_insert_tail(&pending_sockets, &nskcf->link); + nxt_queue_insert_tail(&pending_sockets, &nskcf->link); - return NXT_DECLINED; + return NXT_DECLINED; } +static void nxt_router_listen_socket_rpc_create(nxt_task_t *task, + nxt_router_temp_conf_t *tmcf, + nxt_socket_conf_t *skcf) { + size_t size; + uint32_t stream; + nxt_int_t ret; + nxt_buf_t *b; + nxt_port_t *main_port, *router_port; + nxt_runtime_t *rt; + nxt_socket_rpc_t *rpc; + + rpc = nxt_mp_alloc(tmcf->mem_pool, sizeof(nxt_socket_rpc_t)); + if (rpc == NULL) { + goto fail; + } -static void -nxt_router_listen_socket_rpc_create(nxt_task_t *task, - nxt_router_temp_conf_t *tmcf, nxt_socket_conf_t *skcf) -{ - size_t size; - uint32_t stream; - nxt_int_t ret; - nxt_buf_t *b; - nxt_port_t *main_port, *router_port; - nxt_runtime_t *rt; - nxt_socket_rpc_t *rpc; - - rpc = nxt_mp_alloc(tmcf->mem_pool, sizeof(nxt_socket_rpc_t)); - if (rpc == NULL) { - goto fail; - } + rpc->socket_conf = skcf; + rpc->temp_conf = tmcf; - rpc->socket_conf = skcf; - rpc->temp_conf = tmcf; + size = nxt_sockaddr_size(skcf->listen->sockaddr); - size = nxt_sockaddr_size(skcf->listen->sockaddr); + b = nxt_buf_mem_alloc(tmcf->mem_pool, size, 0); + if (b == NULL) { + goto fail; + } - b = nxt_buf_mem_alloc(tmcf->mem_pool, size, 0); - if (b == NULL) { - goto fail; - } + b->completion_handler = nxt_buf_dummy_completion; - b->completion_handler = nxt_buf_dummy_completion; + b->mem.free = nxt_cpymem(b->mem.free, skcf->listen->sockaddr, size); - b->mem.free = nxt_cpymem(b->mem.free, skcf->listen->sockaddr, size); + rt = task->thread->runtime; + main_port = rt->port_by_type[NXT_PROCESS_MAIN]; + router_port = rt->port_by_type[NXT_PROCESS_ROUTER]; - rt = task->thread->runtime; - main_port = rt->port_by_type[NXT_PROCESS_MAIN]; - router_port = rt->port_by_type[NXT_PROCESS_ROUTER]; - - stream = nxt_port_rpc_register_handler(task, router_port, - nxt_router_listen_socket_ready, - nxt_router_listen_socket_error, - main_port->pid, rpc); - if (nxt_slow_path(stream == 0)) { - goto fail; - } + stream = nxt_port_rpc_register_handler( + task, router_port, nxt_router_listen_socket_ready, + nxt_router_listen_socket_error, main_port->pid, rpc); + if (nxt_slow_path(stream == 0)) { + goto fail; + } - ret = nxt_port_socket_write(task, main_port, NXT_PORT_MSG_SOCKET, -1, - stream, router_port->id, b); + ret = nxt_port_socket_write(task, main_port, NXT_PORT_MSG_SOCKET, -1, stream, + router_port->id, b); - if (nxt_slow_path(ret != NXT_OK)) { - nxt_port_rpc_cancel(task, router_port, stream); - goto fail; - } + if (nxt_slow_path(ret != NXT_OK)) { + nxt_port_rpc_cancel(task, router_port, stream); + goto fail; + } - return; + return; fail: - nxt_router_conf_error(task, tmcf); + nxt_router_conf_error(task, tmcf); } +static void nxt_router_listen_socket_ready(nxt_task_t *task, + nxt_port_recv_msg_t *msg, + void *data) { + nxt_int_t ret; + nxt_socket_t s; + nxt_socket_rpc_t *rpc; -static void -nxt_router_listen_socket_ready(nxt_task_t *task, nxt_port_recv_msg_t *msg, - void *data) -{ - nxt_int_t ret; - nxt_socket_t s; - nxt_socket_rpc_t *rpc; + rpc = data; - rpc = data; + s = msg->fd[0]; - s = msg->fd[0]; + ret = nxt_socket_nonblocking(task, s); + if (nxt_slow_path(ret != NXT_OK)) { + goto fail; + } - ret = nxt_socket_nonblocking(task, s); - if (nxt_slow_path(ret != NXT_OK)) { - goto fail; - } + nxt_socket_defer_accept(task, s, rpc->socket_conf->listen->sockaddr); - nxt_socket_defer_accept(task, s, rpc->socket_conf->listen->sockaddr); + ret = nxt_listen_socket(task, s, rpc->socket_conf->listen->backlog); + if (nxt_slow_path(ret != NXT_OK)) { + goto fail; + } - ret = nxt_listen_socket(task, s, rpc->socket_conf->listen->backlog); - if (nxt_slow_path(ret != NXT_OK)) { - goto fail; - } + rpc->socket_conf->listen->socket = s; - rpc->socket_conf->listen->socket = s; + nxt_work_queue_add(&task->thread->engine->fast_work_queue, + nxt_router_conf_apply, task, rpc->temp_conf, NULL); - nxt_work_queue_add(&task->thread->engine->fast_work_queue, - nxt_router_conf_apply, task, rpc->temp_conf, NULL); - - return; + return; fail: - nxt_socket_close(task, s); + nxt_socket_close(task, s); - nxt_router_conf_error(task, rpc->temp_conf); + nxt_router_conf_error(task, rpc->temp_conf); } +static void nxt_router_listen_socket_error(nxt_task_t *task, + nxt_port_recv_msg_t *msg, + void *data) { + nxt_socket_rpc_t *rpc; + nxt_router_temp_conf_t *tmcf; -static void -nxt_router_listen_socket_error(nxt_task_t *task, nxt_port_recv_msg_t *msg, - void *data) -{ - nxt_socket_rpc_t *rpc; - nxt_router_temp_conf_t *tmcf; - - rpc = data; - tmcf = rpc->temp_conf; + rpc = data; + tmcf = rpc->temp_conf; #if 0 u_char *p; @@ -2965,2940 +2829,2743 @@ nxt_router_listen_socket_error(nxt_task_t *task, nxt_port_recv_msg_t *msg, nxt_debug(task, "%*s", out->mem.free - out->mem.pos, out->mem.pos); #endif - nxt_router_conf_error(task, tmcf); + nxt_router_conf_error(task, tmcf); } - #if (NXT_TLS) -static void -nxt_router_tls_rpc_handler(nxt_task_t *task, nxt_port_recv_msg_t *msg, - void *data) -{ - nxt_mp_t *mp; - nxt_int_t ret; - nxt_tls_conf_t *tlscf; - nxt_router_tlssock_t *tls; - nxt_tls_bundle_conf_t *bundle; - nxt_router_temp_conf_t *tmcf; - - nxt_debug(task, "tls rpc handler"); - - tls = data; - tmcf = tls->temp_conf; - - if (msg == NULL || msg->port_msg.type == _NXT_PORT_MSG_RPC_ERROR) { - goto fail; - } +static void nxt_router_tls_rpc_handler(nxt_task_t *task, + nxt_port_recv_msg_t *msg, void *data) { + nxt_mp_t *mp; + nxt_int_t ret; + nxt_tls_conf_t *tlscf; + nxt_router_tlssock_t *tls; + nxt_tls_bundle_conf_t *bundle; + nxt_router_temp_conf_t *tmcf; - mp = tmcf->router_conf->mem_pool; + nxt_debug(task, "tls rpc handler"); - if (tls->socket_conf->tls == NULL) { - tlscf = nxt_mp_zget(mp, sizeof(nxt_tls_conf_t)); - if (nxt_slow_path(tlscf == NULL)) { - goto fail; - } + tls = data; + tmcf = tls->temp_conf; - tlscf->no_wait_shutdown = 1; - tls->socket_conf->tls = tlscf; + if (msg == NULL || msg->port_msg.type == _NXT_PORT_MSG_RPC_ERROR) { + goto fail; + } - } else { - tlscf = tls->socket_conf->tls; + mp = tmcf->router_conf->mem_pool; + + if (tls->socket_conf->tls == NULL) { + tlscf = nxt_mp_zget(mp, sizeof(nxt_tls_conf_t)); + if (nxt_slow_path(tlscf == NULL)) { + goto fail; } - tls->tls_init->conf = tlscf; + tlscf->no_wait_shutdown = 1; + tls->socket_conf->tls = tlscf; - bundle = nxt_mp_get(mp, sizeof(nxt_tls_bundle_conf_t)); - if (nxt_slow_path(bundle == NULL)) { - goto fail; - } + } else { + tlscf = tls->socket_conf->tls; + } - if (nxt_slow_path(nxt_str_dup(mp, &bundle->name, &tls->name) == NULL)) { - goto fail; - } + tls->tls_init->conf = tlscf; - bundle->chain_file = msg->fd[0]; - bundle->next = tlscf->bundle; - tlscf->bundle = bundle; + bundle = nxt_mp_get(mp, sizeof(nxt_tls_bundle_conf_t)); + if (nxt_slow_path(bundle == NULL)) { + goto fail; + } - ret = task->thread->runtime->tls->server_init(task, mp, tls->tls_init, - tls->last); - if (nxt_slow_path(ret != NXT_OK)) { - goto fail; - } + if (nxt_slow_path(nxt_str_dup(mp, &bundle->name, &tls->name) == NULL)) { + goto fail; + } - nxt_work_queue_add(&task->thread->engine->fast_work_queue, - nxt_router_conf_apply, task, tmcf, NULL); - return; + bundle->chain_file = msg->fd[0]; + bundle->next = tlscf->bundle; + tlscf->bundle = bundle; + + ret = task->thread->runtime->tls->server_init(task, mp, tls->tls_init, + tls->last); + if (nxt_slow_path(ret != NXT_OK)) { + goto fail; + } + + nxt_work_queue_add(&task->thread->engine->fast_work_queue, + nxt_router_conf_apply, task, tmcf, NULL); + return; fail: - nxt_router_conf_error(task, tmcf); + nxt_router_conf_error(task, tmcf); } #endif +static void nxt_router_app_rpc_create(nxt_task_t *task, + nxt_router_temp_conf_t *tmcf, + nxt_app_t *app) { + size_t size; + uint32_t stream; + nxt_fd_t port_fd, queue_fd; + nxt_int_t ret; + nxt_buf_t *b; + nxt_port_t *router_port, *dport; + nxt_runtime_t *rt; + nxt_app_rpc_t *rpc; -static void -nxt_router_app_rpc_create(nxt_task_t *task, - nxt_router_temp_conf_t *tmcf, nxt_app_t *app) -{ - size_t size; - uint32_t stream; - nxt_fd_t port_fd, queue_fd; - nxt_int_t ret; - nxt_buf_t *b; - nxt_port_t *router_port, *dport; - nxt_runtime_t *rt; - nxt_app_rpc_t *rpc; - - rt = task->thread->runtime; + rt = task->thread->runtime; - dport = app->proto_port; + dport = app->proto_port; - if (dport == NULL) { - nxt_debug(task, "app '%V' prototype prefork", &app->name); + if (dport == NULL) { + nxt_debug(task, "app '%V' prototype prefork", &app->name); - size = app->name.length + 1 + app->conf.length; + size = app->name.length + 1 + app->conf.length; - b = nxt_buf_mem_alloc(tmcf->mem_pool, size, 0); - if (nxt_slow_path(b == NULL)) { - goto fail; - } + b = nxt_buf_mem_alloc(tmcf->mem_pool, size, 0); + if (nxt_slow_path(b == NULL)) { + goto fail; + } - b->completion_handler = nxt_buf_dummy_completion; + b->completion_handler = nxt_buf_dummy_completion; - nxt_buf_cpystr(b, &app->name); - *b->mem.free++ = '\0'; - nxt_buf_cpystr(b, &app->conf); + nxt_buf_cpystr(b, &app->name); + *b->mem.free++ = '\0'; + nxt_buf_cpystr(b, &app->conf); - dport = rt->port_by_type[NXT_PROCESS_MAIN]; + dport = rt->port_by_type[NXT_PROCESS_MAIN]; - port_fd = app->shared_port->pair[0]; - queue_fd = app->shared_port->queue_fd; + port_fd = app->shared_port->pair[0]; + queue_fd = app->shared_port->queue_fd; - } else { - nxt_debug(task, "app '%V' prefork", &app->name); + } else { + nxt_debug(task, "app '%V' prefork", &app->name); - b = NULL; - port_fd = -1; - queue_fd = -1; - } + b = NULL; + port_fd = -1; + queue_fd = -1; + } - router_port = rt->port_by_type[NXT_PROCESS_ROUTER]; + router_port = rt->port_by_type[NXT_PROCESS_ROUTER]; - rpc = nxt_port_rpc_register_handler_ex(task, router_port, - nxt_router_app_prefork_ready, - nxt_router_app_prefork_error, - sizeof(nxt_app_rpc_t)); - if (nxt_slow_path(rpc == NULL)) { - goto fail; - } + rpc = nxt_port_rpc_register_handler_ex( + task, router_port, nxt_router_app_prefork_ready, + nxt_router_app_prefork_error, sizeof(nxt_app_rpc_t)); + if (nxt_slow_path(rpc == NULL)) { + goto fail; + } - rpc->app = app; - rpc->temp_conf = tmcf; - rpc->proto = (b != NULL); + rpc->app = app; + rpc->temp_conf = tmcf; + rpc->proto = (b != NULL); - stream = nxt_port_rpc_ex_stream(rpc); + stream = nxt_port_rpc_ex_stream(rpc); - ret = nxt_port_socket_write2(task, dport, NXT_PORT_MSG_START_PROCESS, - port_fd, queue_fd, stream, router_port->id, b); - if (nxt_slow_path(ret != NXT_OK)) { - nxt_port_rpc_cancel(task, router_port, stream); - goto fail; - } + ret = nxt_port_socket_write2(task, dport, NXT_PORT_MSG_START_PROCESS, port_fd, + queue_fd, stream, router_port->id, b); + if (nxt_slow_path(ret != NXT_OK)) { + nxt_port_rpc_cancel(task, router_port, stream); + goto fail; + } - if (b == NULL) { - nxt_port_rpc_ex_set_peer(task, router_port, rpc, dport->pid); + if (b == NULL) { + nxt_port_rpc_ex_set_peer(task, router_port, rpc, dport->pid); - app->pending_processes++; - } + app->pending_processes++; + } - return; + return; fail: - nxt_router_conf_error(task, tmcf); + nxt_router_conf_error(task, tmcf); } +static void nxt_router_app_prefork_ready(nxt_task_t *task, + nxt_port_recv_msg_t *msg, void *data) { + nxt_app_t *app; + nxt_port_t *port; + nxt_app_rpc_t *rpc; + nxt_event_engine_t *engine; -static void -nxt_router_app_prefork_ready(nxt_task_t *task, nxt_port_recv_msg_t *msg, - void *data) -{ - nxt_app_t *app; - nxt_port_t *port; - nxt_app_rpc_t *rpc; - nxt_event_engine_t *engine; + rpc = data; + app = rpc->app; - rpc = data; - app = rpc->app; + port = msg->u.new_port; - port = msg->u.new_port; + nxt_assert(port != NULL); + nxt_assert(port->id == 0); - nxt_assert(port != NULL); - nxt_assert(port->id == 0); + if (rpc->proto) { + nxt_assert(app->proto_port == NULL); + nxt_assert(port->type == NXT_PROCESS_PROTOTYPE); - if (rpc->proto) { - nxt_assert(app->proto_port == NULL); - nxt_assert(port->type == NXT_PROCESS_PROTOTYPE); + nxt_port_inc_use(port); - nxt_port_inc_use(port); + app->proto_port = port; + port->app = app; - app->proto_port = port; - port->app = app; + nxt_router_app_rpc_create(task, rpc->temp_conf, app); - nxt_router_app_rpc_create(task, rpc->temp_conf, app); + return; + } - return; - } + nxt_assert(port->type == NXT_PROCESS_APP); - nxt_assert(port->type == NXT_PROCESS_APP); + port->app = app; + port->main_app_port = port; - port->app = app; - port->main_app_port = port; + app->pending_processes--; + app->processes++; + app->idle_processes++; - app->pending_processes--; - app->processes++; - app->idle_processes++; + engine = task->thread->engine; - engine = task->thread->engine; + nxt_queue_insert_tail(&app->ports, &port->app_link); + nxt_queue_insert_tail(&app->spare_ports, &port->idle_link); - nxt_queue_insert_tail(&app->ports, &port->app_link); - nxt_queue_insert_tail(&app->spare_ports, &port->idle_link); + nxt_debug(task, "app '%V' move new port %PI:%d to spare_ports", &app->name, + port->pid, port->id); - nxt_debug(task, "app '%V' move new port %PI:%d to spare_ports", - &app->name, port->pid, port->id); + nxt_port_hash_add(&app->port_hash, port); + app->port_hash_count++; - nxt_port_hash_add(&app->port_hash, port); - app->port_hash_count++; + port->idle_start = 0; - port->idle_start = 0; - - nxt_port_inc_use(port); + nxt_port_inc_use(port); - nxt_port_socket_write(task, port, NXT_PORT_MSG_PORT_ACK, -1, 0, 0, NULL); + nxt_port_socket_write(task, port, NXT_PORT_MSG_PORT_ACK, -1, 0, 0, NULL); - nxt_work_queue_add(&engine->fast_work_queue, - nxt_router_conf_apply, task, rpc->temp_conf, NULL); + nxt_work_queue_add(&engine->fast_work_queue, nxt_router_conf_apply, task, + rpc->temp_conf, NULL); } +static void nxt_router_app_prefork_error(nxt_task_t *task, + nxt_port_recv_msg_t *msg, void *data) { + nxt_app_t *app; + nxt_app_rpc_t *rpc; + nxt_router_temp_conf_t *tmcf; -static void -nxt_router_app_prefork_error(nxt_task_t *task, nxt_port_recv_msg_t *msg, - void *data) -{ - nxt_app_t *app; - nxt_app_rpc_t *rpc; - nxt_router_temp_conf_t *tmcf; - - rpc = data; - app = rpc->app; - tmcf = rpc->temp_conf; + rpc = data; + app = rpc->app; + tmcf = rpc->temp_conf; - if (rpc->proto) { - nxt_log(task, NXT_LOG_WARN, "failed to start prototype \"%V\"", - &app->name); + if (rpc->proto) { + nxt_log(task, NXT_LOG_WARN, "failed to start prototype \"%V\"", &app->name); - } else { - nxt_log(task, NXT_LOG_WARN, "failed to start application \"%V\"", - &app->name); + } else { + nxt_log(task, NXT_LOG_WARN, "failed to start application \"%V\"", + &app->name); - app->pending_processes--; - } + app->pending_processes--; + } - nxt_router_conf_error(task, tmcf); + nxt_router_conf_error(task, tmcf); } - static nxt_int_t nxt_router_engines_create(nxt_task_t *task, nxt_router_t *router, - nxt_router_temp_conf_t *tmcf, const nxt_event_interface_t *interface) -{ - nxt_int_t ret; - nxt_uint_t n, threads; - nxt_queue_link_t *qlk; - nxt_router_engine_conf_t *recf; - - threads = tmcf->router_conf->threads; - - tmcf->engines = nxt_array_create(tmcf->mem_pool, threads, - sizeof(nxt_router_engine_conf_t)); - if (nxt_slow_path(tmcf->engines == NULL)) { - return NXT_ERROR; - } - - n = 0; - - for (qlk = nxt_queue_first(&router->engines); - qlk != nxt_queue_tail(&router->engines); - qlk = nxt_queue_next(qlk)) - { - recf = nxt_array_zero_add(tmcf->engines); - if (nxt_slow_path(recf == NULL)) { - return NXT_ERROR; - } + nxt_router_temp_conf_t *tmcf, + const nxt_event_interface_t *interface) { + nxt_int_t ret; + nxt_uint_t n, threads; + nxt_queue_link_t *qlk; + nxt_router_engine_conf_t *recf; + + threads = tmcf->router_conf->threads; + + tmcf->engines = nxt_array_create(tmcf->mem_pool, threads, + sizeof(nxt_router_engine_conf_t)); + if (nxt_slow_path(tmcf->engines == NULL)) { + return NXT_ERROR; + } - recf->engine = nxt_queue_link_data(qlk, nxt_event_engine_t, link0); + n = 0; - if (n < threads) { - recf->action = NXT_ROUTER_ENGINE_KEEP; - ret = nxt_router_engine_conf_update(tmcf, recf); + for (qlk = nxt_queue_first(&router->engines); + qlk != nxt_queue_tail(&router->engines); qlk = nxt_queue_next(qlk)) { + recf = nxt_array_zero_add(tmcf->engines); + if (nxt_slow_path(recf == NULL)) { + return NXT_ERROR; + } - } else { - recf->action = NXT_ROUTER_ENGINE_DELETE; - ret = nxt_router_engine_conf_delete(tmcf, recf); - } + recf->engine = nxt_queue_link_data(qlk, nxt_event_engine_t, link0); - if (nxt_slow_path(ret != NXT_OK)) { - return ret; - } + if (n < threads) { + recf->action = NXT_ROUTER_ENGINE_KEEP; + ret = nxt_router_engine_conf_update(tmcf, recf); - n++; + } else { + recf->action = NXT_ROUTER_ENGINE_DELETE; + ret = nxt_router_engine_conf_delete(tmcf, recf); } - tmcf->new_threads = n; + if (nxt_slow_path(ret != NXT_OK)) { + return ret; + } - while (n < threads) { - recf = nxt_array_zero_add(tmcf->engines); - if (nxt_slow_path(recf == NULL)) { - return NXT_ERROR; - } + n++; + } - recf->action = NXT_ROUTER_ENGINE_ADD; + tmcf->new_threads = n; - recf->engine = nxt_event_engine_create(task, interface, NULL, 0, 0); - if (nxt_slow_path(recf->engine == NULL)) { - return NXT_ERROR; - } + while (n < threads) { + recf = nxt_array_zero_add(tmcf->engines); + if (nxt_slow_path(recf == NULL)) { + return NXT_ERROR; + } - ret = nxt_router_engine_conf_create(tmcf, recf); - if (nxt_slow_path(ret != NXT_OK)) { - return ret; - } + recf->action = NXT_ROUTER_ENGINE_ADD; - n++; + recf->engine = nxt_event_engine_create(task, interface, NULL, 0, 0); + if (nxt_slow_path(recf->engine == NULL)) { + return NXT_ERROR; } - return NXT_OK; -} + ret = nxt_router_engine_conf_create(tmcf, recf); + if (nxt_slow_path(ret != NXT_OK)) { + return ret; + } + n++; + } -static nxt_int_t -nxt_router_engine_conf_create(nxt_router_temp_conf_t *tmcf, - nxt_router_engine_conf_t *recf) -{ - nxt_int_t ret; + return NXT_OK; +} - ret = nxt_router_engine_joints_create(tmcf, recf, &creating_sockets, - nxt_router_listen_socket_create); - if (nxt_slow_path(ret != NXT_OK)) { - return ret; - } +static nxt_int_t nxt_router_engine_conf_create(nxt_router_temp_conf_t *tmcf, + nxt_router_engine_conf_t *recf) { + nxt_int_t ret; - ret = nxt_router_engine_joints_create(tmcf, recf, &updating_sockets, - nxt_router_listen_socket_create); - if (nxt_slow_path(ret != NXT_OK)) { - return ret; - } + ret = nxt_router_engine_joints_create(tmcf, recf, &creating_sockets, + nxt_router_listen_socket_create); + if (nxt_slow_path(ret != NXT_OK)) { + return ret; + } + ret = nxt_router_engine_joints_create(tmcf, recf, &updating_sockets, + nxt_router_listen_socket_create); + if (nxt_slow_path(ret != NXT_OK)) { return ret; + } + + return ret; } +static nxt_int_t nxt_router_engine_conf_update(nxt_router_temp_conf_t *tmcf, + nxt_router_engine_conf_t *recf) { + nxt_int_t ret; -static nxt_int_t -nxt_router_engine_conf_update(nxt_router_temp_conf_t *tmcf, - nxt_router_engine_conf_t *recf) -{ - nxt_int_t ret; + ret = nxt_router_engine_joints_create(tmcf, recf, &creating_sockets, + nxt_router_listen_socket_create); + if (nxt_slow_path(ret != NXT_OK)) { + return ret; + } - ret = nxt_router_engine_joints_create(tmcf, recf, &creating_sockets, - nxt_router_listen_socket_create); - if (nxt_slow_path(ret != NXT_OK)) { - return ret; - } + ret = nxt_router_engine_joints_create(tmcf, recf, &updating_sockets, + nxt_router_listen_socket_update); + if (nxt_slow_path(ret != NXT_OK)) { + return ret; + } - ret = nxt_router_engine_joints_create(tmcf, recf, &updating_sockets, - nxt_router_listen_socket_update); - if (nxt_slow_path(ret != NXT_OK)) { - return ret; - } + ret = nxt_router_engine_joints_delete(tmcf, recf, &deleting_sockets); + if (nxt_slow_path(ret != NXT_OK)) { + return ret; + } - ret = nxt_router_engine_joints_delete(tmcf, recf, &deleting_sockets); - if (nxt_slow_path(ret != NXT_OK)) { - return ret; - } + return ret; +} +static nxt_int_t nxt_router_engine_conf_delete(nxt_router_temp_conf_t *tmcf, + nxt_router_engine_conf_t *recf) { + nxt_int_t ret; + + ret = nxt_router_engine_quit(tmcf, recf); + if (nxt_slow_path(ret != NXT_OK)) { return ret; -} + } + ret = nxt_router_engine_joints_delete(tmcf, recf, &updating_sockets); + if (nxt_slow_path(ret != NXT_OK)) { + return ret; + } -static nxt_int_t -nxt_router_engine_conf_delete(nxt_router_temp_conf_t *tmcf, - nxt_router_engine_conf_t *recf) -{ - nxt_int_t ret; + return nxt_router_engine_joints_delete(tmcf, recf, &deleting_sockets); +} - ret = nxt_router_engine_quit(tmcf, recf); - if (nxt_slow_path(ret != NXT_OK)) { - return ret; +static nxt_int_t nxt_router_engine_joints_create(nxt_router_temp_conf_t *tmcf, + nxt_router_engine_conf_t *recf, + nxt_queue_t *sockets, + nxt_work_handler_t handler) { + nxt_int_t ret; + nxt_joint_job_t *job; + nxt_queue_link_t *qlk; + nxt_socket_conf_t *skcf; + nxt_socket_conf_joint_t *joint; + + for (qlk = nxt_queue_first(sockets); qlk != nxt_queue_tail(sockets); + qlk = nxt_queue_next(qlk)) { + job = nxt_mp_get(tmcf->mem_pool, sizeof(nxt_joint_job_t)); + if (nxt_slow_path(job == NULL)) { + return NXT_ERROR; } - ret = nxt_router_engine_joints_delete(tmcf, recf, &updating_sockets); - if (nxt_slow_path(ret != NXT_OK)) { - return ret; - } + job->work.next = recf->jobs; + recf->jobs = &job->work; - return nxt_router_engine_joints_delete(tmcf, recf, &deleting_sockets); -} + job->task = tmcf->engine->task; + job->work.handler = handler; + job->work.task = &job->task; + job->work.obj = job; + job->tmcf = tmcf; + tmcf->count++; -static nxt_int_t -nxt_router_engine_joints_create(nxt_router_temp_conf_t *tmcf, - nxt_router_engine_conf_t *recf, nxt_queue_t *sockets, - nxt_work_handler_t handler) -{ - nxt_int_t ret; - nxt_joint_job_t *job; - nxt_queue_link_t *qlk; - nxt_socket_conf_t *skcf; - nxt_socket_conf_joint_t *joint; - - for (qlk = nxt_queue_first(sockets); - qlk != nxt_queue_tail(sockets); - qlk = nxt_queue_next(qlk)) - { - job = nxt_mp_get(tmcf->mem_pool, sizeof(nxt_joint_job_t)); - if (nxt_slow_path(job == NULL)) { - return NXT_ERROR; - } + joint = nxt_mp_alloc(tmcf->router_conf->mem_pool, + sizeof(nxt_socket_conf_joint_t)); + if (nxt_slow_path(joint == NULL)) { + return NXT_ERROR; + } - job->work.next = recf->jobs; - recf->jobs = &job->work; + job->work.data = joint; - job->task = tmcf->engine->task; - job->work.handler = handler; - job->work.task = &job->task; - job->work.obj = job; - job->tmcf = tmcf; + ret = nxt_upstreams_joint_create(tmcf, &joint->upstreams); + if (nxt_slow_path(ret != NXT_OK)) { + return ret; + } - tmcf->count++; + joint->count = 1; - joint = nxt_mp_alloc(tmcf->router_conf->mem_pool, - sizeof(nxt_socket_conf_joint_t)); - if (nxt_slow_path(joint == NULL)) { - return NXT_ERROR; - } + skcf = nxt_queue_link_data(qlk, nxt_socket_conf_t, link); + skcf->count++; + joint->socket_conf = skcf; - job->work.data = joint; + joint->engine = recf->engine; + } - ret = nxt_upstreams_joint_create(tmcf, &joint->upstreams); - if (nxt_slow_path(ret != NXT_OK)) { - return ret; - } + return NXT_OK; +} - joint->count = 1; +static nxt_int_t nxt_router_engine_quit(nxt_router_temp_conf_t *tmcf, + nxt_router_engine_conf_t *recf) { + nxt_joint_job_t *job; - skcf = nxt_queue_link_data(qlk, nxt_socket_conf_t, link); - skcf->count++; - joint->socket_conf = skcf; + job = nxt_mp_get(tmcf->mem_pool, sizeof(nxt_joint_job_t)); + if (nxt_slow_path(job == NULL)) { + return NXT_ERROR; + } - joint->engine = recf->engine; - } + job->work.next = recf->jobs; + recf->jobs = &job->work; - return NXT_OK; -} + job->task = tmcf->engine->task; + job->work.handler = nxt_router_worker_thread_quit; + job->work.task = &job->task; + job->work.obj = NULL; + job->work.data = NULL; + job->tmcf = NULL; + return NXT_OK; +} -static nxt_int_t -nxt_router_engine_quit(nxt_router_temp_conf_t *tmcf, - nxt_router_engine_conf_t *recf) -{ - nxt_joint_job_t *job; +static nxt_int_t nxt_router_engine_joints_delete(nxt_router_temp_conf_t *tmcf, + nxt_router_engine_conf_t *recf, + nxt_queue_t *sockets) { + nxt_joint_job_t *job; + nxt_queue_link_t *qlk; + for (qlk = nxt_queue_first(sockets); qlk != nxt_queue_tail(sockets); + qlk = nxt_queue_next(qlk)) { job = nxt_mp_get(tmcf->mem_pool, sizeof(nxt_joint_job_t)); if (nxt_slow_path(job == NULL)) { - return NXT_ERROR; + return NXT_ERROR; } job->work.next = recf->jobs; recf->jobs = &job->work; job->task = tmcf->engine->task; - job->work.handler = nxt_router_worker_thread_quit; + job->work.handler = nxt_router_listen_socket_delete; job->work.task = &job->task; - job->work.obj = NULL; - job->work.data = NULL; - job->tmcf = NULL; - - return NXT_OK; -} - + job->work.obj = job; + job->work.data = nxt_queue_link_data(qlk, nxt_socket_conf_t, link); + job->tmcf = tmcf; -static nxt_int_t -nxt_router_engine_joints_delete(nxt_router_temp_conf_t *tmcf, - nxt_router_engine_conf_t *recf, nxt_queue_t *sockets) -{ - nxt_joint_job_t *job; - nxt_queue_link_t *qlk; - - for (qlk = nxt_queue_first(sockets); - qlk != nxt_queue_tail(sockets); - qlk = nxt_queue_next(qlk)) - { - job = nxt_mp_get(tmcf->mem_pool, sizeof(nxt_joint_job_t)); - if (nxt_slow_path(job == NULL)) { - return NXT_ERROR; - } - - job->work.next = recf->jobs; - recf->jobs = &job->work; + tmcf->count++; + } - job->task = tmcf->engine->task; - job->work.handler = nxt_router_listen_socket_delete; - job->work.task = &job->task; - job->work.obj = job; - job->work.data = nxt_queue_link_data(qlk, nxt_socket_conf_t, link); - job->tmcf = tmcf; - - tmcf->count++; - } - - return NXT_OK; + return NXT_OK; } +static nxt_int_t nxt_router_threads_create(nxt_task_t *task, nxt_runtime_t *rt, + nxt_router_temp_conf_t *tmcf) { + nxt_int_t ret; + nxt_uint_t i, threads; + nxt_router_engine_conf_t *recf; -static nxt_int_t -nxt_router_threads_create(nxt_task_t *task, nxt_runtime_t *rt, - nxt_router_temp_conf_t *tmcf) -{ - nxt_int_t ret; - nxt_uint_t i, threads; - nxt_router_engine_conf_t *recf; - - recf = tmcf->engines->elts; - threads = tmcf->router_conf->threads; - - for (i = tmcf->new_threads; i < threads; i++) { - ret = nxt_router_thread_create(task, rt, recf[i].engine); - if (nxt_slow_path(ret != NXT_OK)) { - return ret; - } + recf = tmcf->engines->elts; + threads = tmcf->router_conf->threads; + + for (i = tmcf->new_threads; i < threads; i++) { + ret = nxt_router_thread_create(task, rt, recf[i].engine); + if (nxt_slow_path(ret != NXT_OK)) { + return ret; } + } - return NXT_OK; + return NXT_OK; } +static nxt_int_t nxt_router_thread_create(nxt_task_t *task, nxt_runtime_t *rt, + nxt_event_engine_t *engine) { + nxt_int_t ret; + nxt_thread_link_t *link; + nxt_thread_handle_t handle; -static nxt_int_t -nxt_router_thread_create(nxt_task_t *task, nxt_runtime_t *rt, - nxt_event_engine_t *engine) -{ - nxt_int_t ret; - nxt_thread_link_t *link; - nxt_thread_handle_t handle; - - link = nxt_zalloc(sizeof(nxt_thread_link_t)); + link = nxt_zalloc(sizeof(nxt_thread_link_t)); - if (nxt_slow_path(link == NULL)) { - return NXT_ERROR; - } + if (nxt_slow_path(link == NULL)) { + return NXT_ERROR; + } - link->start = nxt_router_thread_start; - link->engine = engine; - link->work.handler = nxt_router_thread_exit_handler; - link->work.task = task; - link->work.data = link; + link->start = nxt_router_thread_start; + link->engine = engine; + link->work.handler = nxt_router_thread_exit_handler; + link->work.task = task; + link->work.data = link; - nxt_queue_insert_tail(&rt->engines, &engine->link); + nxt_queue_insert_tail(&rt->engines, &engine->link); - ret = nxt_thread_create(&handle, link); + ret = nxt_thread_create(&handle, link); - if (nxt_slow_path(ret != NXT_OK)) { - nxt_queue_remove(&engine->link); - } + if (nxt_slow_path(ret != NXT_OK)) { + nxt_queue_remove(&engine->link); + } - return ret; + return ret; } +static void nxt_router_apps_sort(nxt_task_t *task, nxt_router_t *router, + nxt_router_temp_conf_t *tmcf) { + nxt_app_t *app; -static void -nxt_router_apps_sort(nxt_task_t *task, nxt_router_t *router, - nxt_router_temp_conf_t *tmcf) -{ - nxt_app_t *app; - - nxt_queue_each(app, &router->apps, nxt_app_t, link) { - - nxt_router_app_unlink(task, app); + nxt_queue_each(app, &router->apps, nxt_app_t, link) { - } nxt_queue_loop; + nxt_router_app_unlink(task, app); + } + nxt_queue_loop; - nxt_queue_add(&router->apps, &tmcf->previous); - nxt_queue_add(&router->apps, &tmcf->apps); + nxt_queue_add(&router->apps, &tmcf->previous); + nxt_queue_add(&router->apps, &tmcf->apps); } +static void nxt_router_engines_post(nxt_router_t *router, + nxt_router_temp_conf_t *tmcf) { + nxt_uint_t n; + nxt_event_engine_t *engine; + nxt_router_engine_conf_t *recf; -static void -nxt_router_engines_post(nxt_router_t *router, nxt_router_temp_conf_t *tmcf) -{ - nxt_uint_t n; - nxt_event_engine_t *engine; - nxt_router_engine_conf_t *recf; - - recf = tmcf->engines->elts; + recf = tmcf->engines->elts; - for (n = tmcf->engines->nelts; n != 0; n--) { - engine = recf->engine; + for (n = tmcf->engines->nelts; n != 0; n--) { + engine = recf->engine; - switch (recf->action) { + switch (recf->action) { - case NXT_ROUTER_ENGINE_KEEP: - break; + case NXT_ROUTER_ENGINE_KEEP: + break; - case NXT_ROUTER_ENGINE_ADD: - nxt_queue_insert_tail(&router->engines, &engine->link0); - break; + case NXT_ROUTER_ENGINE_ADD: + nxt_queue_insert_tail(&router->engines, &engine->link0); + break; - case NXT_ROUTER_ENGINE_DELETE: - nxt_queue_remove(&engine->link0); - break; - } + case NXT_ROUTER_ENGINE_DELETE: + nxt_queue_remove(&engine->link0); + break; + } - nxt_router_engine_post(engine, recf->jobs); + nxt_router_engine_post(engine, recf->jobs); - recf++; - } + recf++; + } } +static void nxt_router_engine_post(nxt_event_engine_t *engine, + nxt_work_t *jobs) { + nxt_work_t *work, *next; -static void -nxt_router_engine_post(nxt_event_engine_t *engine, nxt_work_t *jobs) -{ - nxt_work_t *work, *next; - - for (work = jobs; work != NULL; work = next) { - next = work->next; - work->next = NULL; + for (work = jobs; work != NULL; work = next) { + next = work->next; + work->next = NULL; - nxt_event_engine_post(engine, work); - } + nxt_event_engine_post(engine, work); + } } - -static nxt_port_handlers_t nxt_router_app_port_handlers = { - .rpc_error = nxt_port_rpc_handler, - .mmap = nxt_port_mmap_handler, - .data = nxt_port_rpc_handler, - .oosm = nxt_router_oosm_handler, +static nxt_port_handlers_t nxt_router_app_port_handlers = { + .rpc_error = nxt_port_rpc_handler, + .mmap = nxt_port_mmap_handler, + .data = nxt_port_rpc_handler, + .oosm = nxt_router_oosm_handler, .req_headers_ack = nxt_port_rpc_handler, }; +static void nxt_router_thread_start(void *data) { + nxt_int_t ret; + nxt_port_t *port; + nxt_task_t *task; + nxt_work_t *work; + nxt_thread_t *thread; + nxt_thread_link_t *link; + nxt_event_engine_t *engine; -static void -nxt_router_thread_start(void *data) -{ - nxt_int_t ret; - nxt_port_t *port; - nxt_task_t *task; - nxt_work_t *work; - nxt_thread_t *thread; - nxt_thread_link_t *link; - nxt_event_engine_t *engine; - - link = data; - engine = link->engine; - task = &engine->task; - - thread = nxt_thread(); - - nxt_event_engine_thread_adopt(engine); - - /* STUB */ - thread->runtime = engine->task.thread->runtime; - - engine->task.thread = thread; - engine->task.log = thread->log; - thread->engine = engine; - thread->task = &engine->task; + link = data; + engine = link->engine; + task = &engine->task; + + thread = nxt_thread(); + + nxt_event_engine_thread_adopt(engine); + + /* STUB */ + thread->runtime = engine->task.thread->runtime; + + engine->task.thread = thread; + engine->task.log = thread->log; + thread->engine = engine; + thread->task = &engine->task; #if 0 thread->fiber = &engine->fibers->fiber; #endif - engine->mem_pool = nxt_mp_create(4096, 128, 1024, 64); - if (nxt_slow_path(engine->mem_pool == NULL)) { - return; - } + engine->mem_pool = nxt_mp_create(4096, 128, 1024, 64); + if (nxt_slow_path(engine->mem_pool == NULL)) { + return; + } - port = nxt_port_new(task, nxt_port_get_next_id(), nxt_pid, - NXT_PROCESS_ROUTER); - if (nxt_slow_path(port == NULL)) { - return; - } + port = + nxt_port_new(task, nxt_port_get_next_id(), nxt_pid, NXT_PROCESS_ROUTER); + if (nxt_slow_path(port == NULL)) { + return; + } - ret = nxt_port_socket_init(task, port, 0); - if (nxt_slow_path(ret != NXT_OK)) { - nxt_port_use(task, port, -1); - return; - } + ret = nxt_port_socket_init(task, port, 0); + if (nxt_slow_path(ret != NXT_OK)) { + nxt_port_use(task, port, -1); + return; + } - ret = nxt_router_port_queue_init(task, port); - if (nxt_slow_path(ret != NXT_OK)) { - nxt_port_use(task, port, -1); - return; - } + ret = nxt_router_port_queue_init(task, port); + if (nxt_slow_path(ret != NXT_OK)) { + nxt_port_use(task, port, -1); + return; + } - engine->port = port; + engine->port = port; - nxt_port_enable(task, port, &nxt_router_app_port_handlers); + nxt_port_enable(task, port, &nxt_router_app_port_handlers); - work = nxt_zalloc(sizeof(nxt_work_t)); - if (nxt_slow_path(work == NULL)) { - return; - } + work = nxt_zalloc(sizeof(nxt_work_t)); + if (nxt_slow_path(work == NULL)) { + return; + } - work->handler = nxt_router_rt_add_port; - work->task = link->work.task; - work->obj = work; - work->data = port; + work->handler = nxt_router_rt_add_port; + work->task = link->work.task; + work->obj = work; + work->data = port; - nxt_event_engine_post(link->work.task->thread->engine, work); + nxt_event_engine_post(link->work.task->thread->engine, work); - nxt_event_engine_start(engine); + nxt_event_engine_start(engine); } +static void nxt_router_rt_add_port(nxt_task_t *task, void *obj, void *data) { + nxt_int_t res; + nxt_port_t *port; + nxt_runtime_t *rt; -static void -nxt_router_rt_add_port(nxt_task_t *task, void *obj, void *data) -{ - nxt_int_t res; - nxt_port_t *port; - nxt_runtime_t *rt; - - rt = task->thread->runtime; - port = data; + rt = task->thread->runtime; + port = data; - nxt_free(obj); + nxt_free(obj); - res = nxt_port_hash_add(&rt->ports, port); + res = nxt_port_hash_add(&rt->ports, port); - if (nxt_fast_path(res == NXT_OK)) { - nxt_port_use(task, port, 1); - } + if (nxt_fast_path(res == NXT_OK)) { + nxt_port_use(task, port, 1); + } } +static void nxt_router_listen_socket_create(nxt_task_t *task, void *obj, + void *data) { + nxt_joint_job_t *job; + nxt_socket_conf_t *skcf; + nxt_listen_event_t *lev; + nxt_listen_socket_t *ls; + nxt_thread_spinlock_t *lock; + nxt_socket_conf_joint_t *joint; -static void -nxt_router_listen_socket_create(nxt_task_t *task, void *obj, void *data) -{ - nxt_joint_job_t *job; - nxt_socket_conf_t *skcf; - nxt_listen_event_t *lev; - nxt_listen_socket_t *ls; - nxt_thread_spinlock_t *lock; - nxt_socket_conf_joint_t *joint; - - job = obj; - joint = data; - - nxt_queue_insert_tail(&task->thread->engine->joints, &joint->link); - - skcf = joint->socket_conf; - ls = skcf->listen; - - lev = nxt_listen_event(task, ls); - if (nxt_slow_path(lev == NULL)) { - nxt_router_listen_socket_release(task, skcf); - return; - } + job = obj; + joint = data; - lev->socket.data = joint; + nxt_queue_insert_tail(&task->thread->engine->joints, &joint->link); - lock = &skcf->router_conf->router->lock; + skcf = joint->socket_conf; + ls = skcf->listen; - nxt_thread_spin_lock(lock); - ls->count++; - nxt_thread_spin_unlock(lock); + lev = nxt_listen_event(task, ls); + if (nxt_slow_path(lev == NULL)) { + nxt_router_listen_socket_release(task, skcf); + return; + } - job->work.next = NULL; - job->work.handler = nxt_router_conf_wait; + lev->socket.data = joint; - nxt_event_engine_post(job->tmcf->engine, &job->work); -} + lock = &skcf->router_conf->router->lock; + nxt_thread_spin_lock(lock); + ls->count++; + nxt_thread_spin_unlock(lock); + + job->work.next = NULL; + job->work.handler = nxt_router_conf_wait; + + nxt_event_engine_post(job->tmcf->engine, &job->work); +} nxt_inline nxt_listen_event_t * nxt_router_listen_event(nxt_queue_t *listen_connections, - nxt_socket_conf_t *skcf) -{ - nxt_socket_t fd; - nxt_queue_link_t *qlk; - nxt_listen_event_t *lev; + nxt_socket_conf_t *skcf) { + nxt_socket_t fd; + nxt_queue_link_t *qlk; + nxt_listen_event_t *lev; - fd = skcf->listen->socket; + fd = skcf->listen->socket; - for (qlk = nxt_queue_first(listen_connections); - qlk != nxt_queue_tail(listen_connections); - qlk = nxt_queue_next(qlk)) - { - lev = nxt_queue_link_data(qlk, nxt_listen_event_t, link); + for (qlk = nxt_queue_first(listen_connections); + qlk != nxt_queue_tail(listen_connections); qlk = nxt_queue_next(qlk)) { + lev = nxt_queue_link_data(qlk, nxt_listen_event_t, link); - if (fd == lev->socket.fd) { - return lev; - } + if (fd == lev->socket.fd) { + return lev; } + } - return NULL; + return NULL; } +static void nxt_router_listen_socket_update(nxt_task_t *task, void *obj, + void *data) { + nxt_joint_job_t *job; + nxt_event_engine_t *engine; + nxt_listen_event_t *lev; + nxt_socket_conf_joint_t *joint, *old; -static void -nxt_router_listen_socket_update(nxt_task_t *task, void *obj, void *data) -{ - nxt_joint_job_t *job; - nxt_event_engine_t *engine; - nxt_listen_event_t *lev; - nxt_socket_conf_joint_t *joint, *old; - - job = obj; - joint = data; + job = obj; + joint = data; - engine = task->thread->engine; + engine = task->thread->engine; - nxt_queue_insert_tail(&engine->joints, &joint->link); + nxt_queue_insert_tail(&engine->joints, &joint->link); - lev = nxt_router_listen_event(&engine->listen_connections, - joint->socket_conf); + lev = + nxt_router_listen_event(&engine->listen_connections, joint->socket_conf); - old = lev->socket.data; - lev->socket.data = joint; - lev->listen = joint->socket_conf->listen; + old = lev->socket.data; + lev->socket.data = joint; + lev->listen = joint->socket_conf->listen; - job->work.next = NULL; - job->work.handler = nxt_router_conf_wait; + job->work.next = NULL; + job->work.handler = nxt_router_conf_wait; - nxt_event_engine_post(job->tmcf->engine, &job->work); + nxt_event_engine_post(job->tmcf->engine, &job->work); - /* - * The task is allocated from configuration temporary - * memory pool so it can be freed after engine post operation. - */ + /* + * The task is allocated from configuration temporary + * memory pool so it can be freed after engine post operation. + */ - nxt_router_conf_release(&engine->task, old); + nxt_router_conf_release(&engine->task, old); } +static void nxt_router_listen_socket_delete(nxt_task_t *task, void *obj, + void *data) { + nxt_socket_conf_t *skcf; + nxt_listen_event_t *lev; + nxt_event_engine_t *engine; + nxt_socket_conf_joint_t *joint; -static void -nxt_router_listen_socket_delete(nxt_task_t *task, void *obj, void *data) -{ - nxt_socket_conf_t *skcf; - nxt_listen_event_t *lev; - nxt_event_engine_t *engine; - nxt_socket_conf_joint_t *joint; - - skcf = data; + skcf = data; - engine = task->thread->engine; + engine = task->thread->engine; - lev = nxt_router_listen_event(&engine->listen_connections, skcf); + lev = nxt_router_listen_event(&engine->listen_connections, skcf); - nxt_fd_event_delete(engine, &lev->socket); + nxt_fd_event_delete(engine, &lev->socket); - nxt_debug(task, "engine %p: listen socket delete: %d", engine, - lev->socket.fd); + nxt_debug(task, "engine %p: listen socket delete: %d", engine, + lev->socket.fd); - joint = lev->socket.data; - joint->close_job = obj; + joint = lev->socket.data; + joint->close_job = obj; - lev->timer.handler = nxt_router_listen_socket_close; - lev->timer.work_queue = &engine->fast_work_queue; + lev->timer.handler = nxt_router_listen_socket_close; + lev->timer.work_queue = &engine->fast_work_queue; - nxt_timer_add(engine, &lev->timer, 0); + nxt_timer_add(engine, &lev->timer, 0); } +static void nxt_router_worker_thread_quit(nxt_task_t *task, void *obj, + void *data) { + nxt_event_engine_t *engine; -static void -nxt_router_worker_thread_quit(nxt_task_t *task, void *obj, void *data) -{ - nxt_event_engine_t *engine; - - nxt_debug(task, "router worker thread quit"); + nxt_debug(task, "router worker thread quit"); - engine = task->thread->engine; + engine = task->thread->engine; - engine->shutdown = 1; + engine->shutdown = 1; - if (nxt_queue_is_empty(&engine->joints)) { - nxt_thread_exit(task->thread); - } + if (nxt_queue_is_empty(&engine->joints)) { + nxt_thread_exit(task->thread); + } } +static void nxt_router_listen_socket_close(nxt_task_t *task, void *obj, + void *data) { + nxt_timer_t *timer; + nxt_joint_job_t *job; + nxt_listen_event_t *lev; + nxt_socket_conf_joint_t *joint; -static void -nxt_router_listen_socket_close(nxt_task_t *task, void *obj, void *data) -{ - nxt_timer_t *timer; - nxt_joint_job_t *job; - nxt_listen_event_t *lev; - nxt_socket_conf_joint_t *joint; - - timer = obj; - lev = nxt_timer_data(timer, nxt_listen_event_t, timer); + timer = obj; + lev = nxt_timer_data(timer, nxt_listen_event_t, timer); - nxt_debug(task, "engine %p: listen socket close: %d", task->thread->engine, - lev->socket.fd); + nxt_debug(task, "engine %p: listen socket close: %d", task->thread->engine, + lev->socket.fd); - nxt_queue_remove(&lev->link); + nxt_queue_remove(&lev->link); - joint = lev->socket.data; - lev->socket.data = NULL; + joint = lev->socket.data; + lev->socket.data = NULL; - /* 'task' refers to lev->task and we cannot use after nxt_free() */ - task = &task->thread->engine->task; + /* 'task' refers to lev->task and we cannot use after nxt_free() */ + task = &task->thread->engine->task; - nxt_router_listen_socket_release(task, joint->socket_conf); + nxt_router_listen_socket_release(task, joint->socket_conf); - job = joint->close_job; - job->work.next = NULL; - job->work.handler = nxt_router_conf_wait; + job = joint->close_job; + job->work.next = NULL; + job->work.handler = nxt_router_conf_wait; - nxt_event_engine_post(job->tmcf->engine, &job->work); + nxt_event_engine_post(job->tmcf->engine, &job->work); - nxt_router_listen_event_release(task, lev, joint); + nxt_router_listen_event_release(task, lev, joint); } - -static void -nxt_router_listen_socket_release(nxt_task_t *task, nxt_socket_conf_t *skcf) -{ +static void nxt_router_listen_socket_release(nxt_task_t *task, + nxt_socket_conf_t *skcf) { #if (NXT_HAVE_UNIX_DOMAIN) - size_t size; - nxt_buf_t *b; - nxt_port_t *main_port; - nxt_runtime_t *rt; - nxt_sockaddr_t *sa; + size_t size; + nxt_buf_t *b; + nxt_port_t *main_port; + nxt_runtime_t *rt; + nxt_sockaddr_t *sa; #endif - nxt_listen_socket_t *ls; - nxt_thread_spinlock_t *lock; + nxt_listen_socket_t *ls; + nxt_thread_spinlock_t *lock; - ls = skcf->listen; - lock = &skcf->router_conf->router->lock; + ls = skcf->listen; + lock = &skcf->router_conf->router->lock; - nxt_thread_spin_lock(lock); + nxt_thread_spin_lock(lock); - nxt_debug(task, "engine %p: listen socket release: ls->count %D", - task->thread->engine, ls->count); + nxt_debug(task, "engine %p: listen socket release: ls->count %D", + task->thread->engine, ls->count); - if (--ls->count != 0) { - ls = NULL; - } + if (--ls->count != 0) { + ls = NULL; + } - nxt_thread_spin_unlock(lock); + nxt_thread_spin_unlock(lock); - if (ls == NULL) { - return; - } + if (ls == NULL) { + return; + } - nxt_socket_close(task, ls->socket); + nxt_socket_close(task, ls->socket); #if (NXT_HAVE_UNIX_DOMAIN) - sa = ls->sockaddr; - if (sa->u.sockaddr.sa_family != AF_UNIX - || sa->u.sockaddr_un.sun_path[0] == '\0') - { - goto out_free_ls; - } + sa = ls->sockaddr; + if (sa->u.sockaddr.sa_family != AF_UNIX || + sa->u.sockaddr_un.sun_path[0] == '\0') { + goto out_free_ls; + } - size = nxt_sockaddr_size(ls->sockaddr); + size = nxt_sockaddr_size(ls->sockaddr); - b = nxt_buf_mem_alloc(task->thread->engine->mem_pool, size, 0); - if (b == NULL) { - goto out_free_ls; - } + b = nxt_buf_mem_alloc(task->thread->engine->mem_pool, size, 0); + if (b == NULL) { + goto out_free_ls; + } - b->mem.free = nxt_cpymem(b->mem.free, ls->sockaddr, size); + b->mem.free = nxt_cpymem(b->mem.free, ls->sockaddr, size); - rt = task->thread->runtime; - main_port = rt->port_by_type[NXT_PROCESS_MAIN]; + rt = task->thread->runtime; + main_port = rt->port_by_type[NXT_PROCESS_MAIN]; - (void) nxt_port_socket_write(task, main_port, NXT_PORT_MSG_SOCKET_UNLINK, - -1, 0, 0, b); + (void)nxt_port_socket_write(task, main_port, NXT_PORT_MSG_SOCKET_UNLINK, -1, + 0, 0, b); out_free_ls: #endif - nxt_free(ls); + nxt_free(ls); } +void nxt_router_listen_event_release(nxt_task_t *task, nxt_listen_event_t *lev, + nxt_socket_conf_joint_t *joint) { + nxt_event_engine_t *engine; -void -nxt_router_listen_event_release(nxt_task_t *task, nxt_listen_event_t *lev, - nxt_socket_conf_joint_t *joint) -{ - nxt_event_engine_t *engine; - - nxt_debug(task, "listen event count: %D", lev->count); + nxt_debug(task, "listen event count: %D", lev->count); - engine = task->thread->engine; + engine = task->thread->engine; - if (--lev->count == 0) { - if (lev->next != NULL) { - nxt_sockaddr_cache_free(engine, lev->next); + if (--lev->count == 0) { + if (lev->next != NULL) { + nxt_sockaddr_cache_free(engine, lev->next); - nxt_conn_free(task, lev->next); - } - - nxt_free(lev); + nxt_conn_free(task, lev->next); } - if (joint != NULL) { - nxt_router_conf_release(task, joint); - } + nxt_free(lev); + } - if (engine->shutdown && nxt_queue_is_empty(&engine->joints)) { - nxt_thread_exit(task->thread); - } -} + if (joint != NULL) { + nxt_router_conf_release(task, joint); + } + if (engine->shutdown && nxt_queue_is_empty(&engine->joints)) { + nxt_thread_exit(task->thread); + } +} -void -nxt_router_conf_release(nxt_task_t *task, nxt_socket_conf_joint_t *joint) -{ - nxt_socket_conf_t *skcf; - nxt_router_conf_t *rtcf; - nxt_thread_spinlock_t *lock; +void nxt_router_conf_release(nxt_task_t *task, nxt_socket_conf_joint_t *joint) { + nxt_socket_conf_t *skcf; + nxt_router_conf_t *rtcf; + nxt_thread_spinlock_t *lock; - nxt_debug(task, "conf joint %p count: %D", joint, joint->count); + nxt_debug(task, "conf joint %p count: %D", joint, joint->count); - if (--joint->count != 0) { - return; - } + if (--joint->count != 0) { + return; + } - nxt_queue_remove(&joint->link); + nxt_queue_remove(&joint->link); - /* - * The joint content can not be safely used after the critical - * section protected by the spinlock because its memory pool may - * be already destroyed by another thread. - */ - skcf = joint->socket_conf; - rtcf = skcf->router_conf; - lock = &rtcf->router->lock; + /* + * The joint content can not be safely used after the critical + * section protected by the spinlock because its memory pool may + * be already destroyed by another thread. + */ + skcf = joint->socket_conf; + rtcf = skcf->router_conf; + lock = &rtcf->router->lock; - nxt_thread_spin_lock(lock); + nxt_thread_spin_lock(lock); - nxt_debug(task, "conf skcf %p: %D, rtcf %p: %D", skcf, skcf->count, - rtcf, rtcf->count); + nxt_debug(task, "conf skcf %p: %D, rtcf %p: %D", skcf, skcf->count, rtcf, + rtcf->count); - if (--skcf->count != 0) { - skcf = NULL; - rtcf = NULL; + if (--skcf->count != 0) { + skcf = NULL; + rtcf = NULL; - } else { - nxt_queue_remove(&skcf->link); + } else { + nxt_queue_remove(&skcf->link); - if (--rtcf->count != 0) { - rtcf = NULL; - } + if (--rtcf->count != 0) { + rtcf = NULL; } + } - nxt_thread_spin_unlock(lock); + nxt_thread_spin_unlock(lock); #if (NXT_TLS) - if (skcf != NULL && skcf->tls != NULL) { - task->thread->runtime->tls->server_free(task, skcf->tls); - } + if (skcf != NULL && skcf->tls != NULL) { + task->thread->runtime->tls->server_free(task, skcf->tls); + } #endif - /* TODO remove engine->port */ + /* TODO remove engine->port */ - if (rtcf != NULL) { - nxt_debug(task, "old router conf is destroyed"); + if (rtcf != NULL) { + nxt_debug(task, "old router conf is destroyed"); - nxt_router_apps_hash_use(task, rtcf, -1); + nxt_router_apps_hash_use(task, rtcf, -1); - nxt_router_access_log_release(task, lock, rtcf->access_log); + nxt_router_access_log_release(task, lock, rtcf->access_log); - nxt_tstr_state_release(rtcf->tstr_state); + nxt_tstr_state_release(rtcf->tstr_state); - nxt_mp_thread_adopt(rtcf->mem_pool); + nxt_mp_thread_adopt(rtcf->mem_pool); - nxt_mp_destroy(rtcf->mem_pool); - } + nxt_mp_destroy(rtcf->mem_pool); + } } +static void nxt_router_thread_exit_handler(nxt_task_t *task, void *obj, + void *data) { + nxt_port_t *port; + nxt_thread_link_t *link; + nxt_event_engine_t *engine; + nxt_thread_handle_t handle; -static void -nxt_router_thread_exit_handler(nxt_task_t *task, void *obj, void *data) -{ - nxt_port_t *port; - nxt_thread_link_t *link; - nxt_event_engine_t *engine; - nxt_thread_handle_t handle; - - handle = (nxt_thread_handle_t) (uintptr_t) obj; - link = data; + handle = (nxt_thread_handle_t)(uintptr_t)obj; + link = data; - nxt_thread_wait(handle); + nxt_thread_wait(handle); - engine = link->engine; + engine = link->engine; - nxt_queue_remove(&engine->link); + nxt_queue_remove(&engine->link); - port = engine->port; + port = engine->port; - // TODO notify all apps + // TODO notify all apps - port->engine = task->thread->engine; - nxt_mp_thread_adopt(port->mem_pool); - nxt_port_use(task, port, -1); + port->engine = task->thread->engine; + nxt_mp_thread_adopt(port->mem_pool); + nxt_port_use(task, port, -1); - nxt_mp_thread_adopt(engine->mem_pool); - nxt_mp_destroy(engine->mem_pool); + nxt_mp_thread_adopt(engine->mem_pool); + nxt_mp_destroy(engine->mem_pool); - nxt_event_engine_free(engine); + nxt_event_engine_free(engine); - nxt_free(link); + nxt_free(link); } +static void nxt_router_response_ready_handler(nxt_task_t *task, + nxt_port_recv_msg_t *msg, + void *data) { + size_t b_size, count; + nxt_int_t ret; + nxt_app_t *app; + nxt_buf_t *b, *next; + nxt_port_t *app_port; + nxt_unit_field_t *f; + nxt_http_field_t *field; + nxt_http_request_t *r; + nxt_unit_response_t *resp; + nxt_request_rpc_data_t *req_rpc_data; + + req_rpc_data = data; + + r = req_rpc_data->request; + if (nxt_slow_path(r == NULL)) { + return; + } -static void -nxt_router_response_ready_handler(nxt_task_t *task, nxt_port_recv_msg_t *msg, - void *data) -{ - size_t b_size, count; - nxt_int_t ret; - nxt_app_t *app; - nxt_buf_t *b, *next; - nxt_port_t *app_port; - nxt_unit_field_t *f; - nxt_http_field_t *field; - nxt_http_request_t *r; - nxt_unit_response_t *resp; - nxt_request_rpc_data_t *req_rpc_data; - - req_rpc_data = data; - - r = req_rpc_data->request; - if (nxt_slow_path(r == NULL)) { - return; - } - - if (r->error) { - nxt_request_rpc_data_unlink(task, req_rpc_data); - return; - } + if (r->error) { + nxt_request_rpc_data_unlink(task, req_rpc_data); + return; + } - app = req_rpc_data->app; - nxt_assert(app != NULL); + app = req_rpc_data->app; + nxt_assert(app != NULL); - if (msg->port_msg.type == _NXT_PORT_MSG_REQ_HEADERS_ACK) { - nxt_router_req_headers_ack_handler(task, msg, req_rpc_data); + if (msg->port_msg.type == _NXT_PORT_MSG_REQ_HEADERS_ACK) { + nxt_router_req_headers_ack_handler(task, msg, req_rpc_data); - return; - } + return; + } - b = (msg->size == 0) ? NULL : msg->buf; + b = (msg->size == 0) ? NULL : msg->buf; - if (msg->port_msg.last != 0) { - nxt_debug(task, "router data create last buf"); + if (msg->port_msg.last != 0) { + nxt_debug(task, "router data create last buf"); - nxt_buf_chain_add(&b, nxt_http_buf_last(r)); + nxt_buf_chain_add(&b, nxt_http_buf_last(r)); - req_rpc_data->rpc_cancel = 0; + req_rpc_data->rpc_cancel = 0; - if (req_rpc_data->apr_action == NXT_APR_REQUEST_FAILED) { - req_rpc_data->apr_action = NXT_APR_GOT_RESPONSE; - } + if (req_rpc_data->apr_action == NXT_APR_REQUEST_FAILED) { + req_rpc_data->apr_action = NXT_APR_GOT_RESPONSE; + } - nxt_request_rpc_data_unlink(task, req_rpc_data); + nxt_request_rpc_data_unlink(task, req_rpc_data); - } else { - if (app->timeout != 0) { - r->timer.handler = nxt_router_app_timeout; - r->timer_data = req_rpc_data; - nxt_timer_add(task->thread->engine, &r->timer, app->timeout); - } + } else { + if (app->timeout != 0) { + r->timer.handler = nxt_router_app_timeout; + r->timer_data = req_rpc_data; + nxt_timer_add(task->thread->engine, &r->timer, app->timeout); } + } - if (b == NULL) { - return; - } + if (b == NULL) { + return; + } - if (msg->buf == b) { - /* Disable instant buffer completion/re-using by port. */ - msg->buf = NULL; - } + if (msg->buf == b) { + /* Disable instant buffer completion/re-using by port. */ + msg->buf = NULL; + } - if (r->header_sent) { - nxt_buf_chain_add(&r->out, b); - nxt_http_request_send_body(task, r, NULL); + if (r->header_sent) { + nxt_buf_chain_add(&r->out, b); + nxt_http_request_send_body(task, r, NULL); - } else { - b_size = nxt_buf_is_mem(b) ? nxt_buf_mem_used_size(&b->mem) : 0; + } else { + b_size = nxt_buf_is_mem(b) ? nxt_buf_mem_used_size(&b->mem) : 0; - if (nxt_slow_path(b_size < sizeof(nxt_unit_response_t))) { - nxt_alert(task, "response buffer too small: %z", b_size); - goto fail; - } + if (nxt_slow_path(b_size < sizeof(nxt_unit_response_t))) { + nxt_alert(task, "response buffer too small: %z", b_size); + goto fail; + } - resp = (void *) b->mem.pos; - count = (b_size - sizeof(nxt_unit_response_t)) - / sizeof(nxt_unit_field_t); + resp = (void *)b->mem.pos; + count = (b_size - sizeof(nxt_unit_response_t)) / sizeof(nxt_unit_field_t); - if (nxt_slow_path(count < resp->fields_count)) { - nxt_alert(task, "response buffer too small for fields count: %D", - resp->fields_count); - goto fail; - } + if (nxt_slow_path(count < resp->fields_count)) { + nxt_alert(task, "response buffer too small for fields count: %D", + resp->fields_count); + goto fail; + } - field = NULL; + field = NULL; - for (f = resp->fields; f < resp->fields + resp->fields_count; f++) { - if (f->skip) { - continue; - } + for (f = resp->fields; f < resp->fields + resp->fields_count; f++) { + if (f->skip) { + continue; + } - field = nxt_list_add(r->resp.fields); + field = nxt_list_add(r->resp.fields); - if (nxt_slow_path(field == NULL)) { - goto fail; - } + if (nxt_slow_path(field == NULL)) { + goto fail; + } - field->hash = f->hash; - field->skip = 0; - field->hopbyhop = 0; + field->hash = f->hash; + field->skip = 0; + field->hopbyhop = 0; - field->name_length = f->name_length; - field->value_length = f->value_length; - field->name = nxt_unit_sptr_get(&f->name); - field->value = nxt_unit_sptr_get(&f->value); + field->name_length = f->name_length; + field->value_length = f->value_length; + field->name = nxt_unit_sptr_get(&f->name); + field->value = nxt_unit_sptr_get(&f->value); - ret = nxt_http_field_process(field, &nxt_response_fields_hash, r); - if (nxt_slow_path(ret != NXT_OK)) { - goto fail; - } + ret = nxt_http_field_process(field, &nxt_response_fields_hash, r); + if (nxt_slow_path(ret != NXT_OK)) { + goto fail; + } - nxt_debug(task, "header%s: %*s: %*s", - (field->skip ? " skipped" : ""), - (size_t) field->name_length, field->name, - (size_t) field->value_length, field->value); + nxt_debug(task, "header%s: %*s: %*s", (field->skip ? " skipped" : ""), + (size_t)field->name_length, field->name, + (size_t)field->value_length, field->value); - if (field->skip) { - r->resp.fields->last->nelts--; - } - } + if (field->skip) { + r->resp.fields->last->nelts--; + } + } - r->status = resp->status; + r->status = resp->status; - if (resp->piggyback_content_length != 0) { - b->mem.pos = nxt_unit_sptr_get(&resp->piggyback_content); - b->mem.free = b->mem.pos + resp->piggyback_content_length; + if (resp->piggyback_content_length != 0) { + b->mem.pos = nxt_unit_sptr_get(&resp->piggyback_content); + b->mem.free = b->mem.pos + resp->piggyback_content_length; - } else { - b->mem.pos = b->mem.free; - } + } else { + b->mem.pos = b->mem.free; + } - if (nxt_buf_mem_used_size(&b->mem) == 0) { - next = b->next; - b->next = NULL; + if (nxt_buf_mem_used_size(&b->mem) == 0) { + next = b->next; + b->next = NULL; - nxt_work_queue_add(&task->thread->engine->fast_work_queue, - b->completion_handler, task, b, b->parent); + nxt_work_queue_add(&task->thread->engine->fast_work_queue, + b->completion_handler, task, b, b->parent); - b = next; - } + b = next; + } - if (b != NULL) { - nxt_buf_chain_add(&r->out, b); - } + if (b != NULL) { + nxt_buf_chain_add(&r->out, b); + } - nxt_http_request_header_send(task, r, nxt_http_request_send_body, NULL); + nxt_http_request_header_send(task, r, nxt_http_request_send_body, NULL); - if (r->websocket_handshake - && r->status == NXT_HTTP_SWITCHING_PROTOCOLS) - { - app_port = req_rpc_data->app_port; - if (nxt_slow_path(app_port == NULL)) { - goto fail; - } + if (r->websocket_handshake && r->status == NXT_HTTP_SWITCHING_PROTOCOLS) { + app_port = req_rpc_data->app_port; + if (nxt_slow_path(app_port == NULL)) { + goto fail; + } - nxt_thread_mutex_lock(&app->mutex); + nxt_thread_mutex_lock(&app->mutex); - app_port->main_app_port->active_websockets++; + app_port->main_app_port->active_websockets++; - nxt_thread_mutex_unlock(&app->mutex); + nxt_thread_mutex_unlock(&app->mutex); - nxt_router_app_port_release(task, app, app_port, NXT_APR_UPGRADE); - req_rpc_data->apr_action = NXT_APR_CLOSE; + nxt_router_app_port_release(task, app, app_port, NXT_APR_UPGRADE); + req_rpc_data->apr_action = NXT_APR_CLOSE; - nxt_debug(task, "stream #%uD upgrade", req_rpc_data->stream); + nxt_debug(task, "stream #%uD upgrade", req_rpc_data->stream); - r->state = &nxt_http_websocket; + r->state = &nxt_http_websocket; - } else { - r->state = &nxt_http_request_send_state; - } + } else { + r->state = &nxt_http_request_send_state; } + } - return; + return; fail: - nxt_http_request_error(task, r, NXT_HTTP_SERVICE_UNAVAILABLE); + nxt_http_request_error(task, r, NXT_HTTP_SERVICE_UNAVAILABLE); - nxt_request_rpc_data_unlink(task, req_rpc_data); + nxt_request_rpc_data_unlink(task, req_rpc_data); } - static void -nxt_router_req_headers_ack_handler(nxt_task_t *task, - nxt_port_recv_msg_t *msg, nxt_request_rpc_data_t *req_rpc_data) -{ - int res; - nxt_app_t *app; - nxt_buf_t *b; - nxt_bool_t start_process, unlinked; - nxt_port_t *app_port, *main_app_port, *idle_port; - nxt_queue_link_t *idle_lnk; - nxt_http_request_t *r; - - nxt_debug(task, "stream #%uD: got ack from %PI:%d", - req_rpc_data->stream, - msg->port_msg.pid, msg->port_msg.reply_port); +nxt_router_req_headers_ack_handler(nxt_task_t *task, nxt_port_recv_msg_t *msg, + nxt_request_rpc_data_t *req_rpc_data) { + int res; + nxt_app_t *app; + nxt_buf_t *b; + nxt_bool_t start_process, unlinked; + nxt_port_t *app_port, *main_app_port, *idle_port; + nxt_queue_link_t *idle_lnk; + nxt_http_request_t *r; - nxt_port_rpc_ex_set_peer(task, msg->port, req_rpc_data, - msg->port_msg.pid); + nxt_debug(task, "stream #%uD: got ack from %PI:%d", req_rpc_data->stream, + msg->port_msg.pid, msg->port_msg.reply_port); - app = req_rpc_data->app; - r = req_rpc_data->request; + nxt_port_rpc_ex_set_peer(task, msg->port, req_rpc_data, msg->port_msg.pid); - start_process = 0; - unlinked = 0; + app = req_rpc_data->app; + r = req_rpc_data->request; - nxt_thread_mutex_lock(&app->mutex); + start_process = 0; + unlinked = 0; - if (r->app_link.next != NULL) { - nxt_queue_remove(&r->app_link); - r->app_link.next = NULL; + nxt_thread_mutex_lock(&app->mutex); - unlinked = 1; - } + if (r->app_link.next != NULL) { + nxt_queue_remove(&r->app_link); + r->app_link.next = NULL; - app_port = nxt_port_hash_find(&app->port_hash, msg->port_msg.pid, - msg->port_msg.reply_port); - if (nxt_slow_path(app_port == NULL)) { - nxt_thread_mutex_unlock(&app->mutex); + unlinked = 1; + } - nxt_http_request_error(task, r, NXT_HTTP_INTERNAL_SERVER_ERROR); + app_port = nxt_port_hash_find(&app->port_hash, msg->port_msg.pid, + msg->port_msg.reply_port); + if (nxt_slow_path(app_port == NULL)) { + nxt_thread_mutex_unlock(&app->mutex); - if (unlinked) { - nxt_mp_release(r->mem_pool); - } + nxt_http_request_error(task, r, NXT_HTTP_INTERNAL_SERVER_ERROR); - return; + if (unlinked) { + nxt_mp_release(r->mem_pool); } - main_app_port = app_port->main_app_port; + return; + } - if (nxt_queue_chk_remove(&main_app_port->idle_link)) { - app->idle_processes--; + main_app_port = app_port->main_app_port; - nxt_debug(task, "app '%V' move port %PI:%d out of %s (ack)", - &app->name, main_app_port->pid, main_app_port->id, - (main_app_port->idle_start ? "idle_ports" : "spare_ports")); + if (nxt_queue_chk_remove(&main_app_port->idle_link)) { + app->idle_processes--; - /* Check port was in 'spare_ports' using idle_start field. */ - if (main_app_port->idle_start == 0 - && app->idle_processes >= app->spare_processes) - { - /* - * If there is a vacant space in spare ports, - * move the last idle to spare_ports. - */ - nxt_assert(!nxt_queue_is_empty(&app->idle_ports)); + nxt_debug(task, "app '%V' move port %PI:%d out of %s (ack)", &app->name, + main_app_port->pid, main_app_port->id, + (main_app_port->idle_start ? "idle_ports" : "spare_ports")); - idle_lnk = nxt_queue_last(&app->idle_ports); - idle_port = nxt_queue_link_data(idle_lnk, nxt_port_t, idle_link); - nxt_queue_remove(idle_lnk); + /* Check port was in 'spare_ports' using idle_start field. */ + if (main_app_port->idle_start == 0 && + app->idle_processes >= app->spare_processes) { + /* + * If there is a vacant space in spare ports, + * move the last idle to spare_ports. + */ + nxt_assert(!nxt_queue_is_empty(&app->idle_ports)); - nxt_queue_insert_tail(&app->spare_ports, idle_lnk); + idle_lnk = nxt_queue_last(&app->idle_ports); + idle_port = nxt_queue_link_data(idle_lnk, nxt_port_t, idle_link); + nxt_queue_remove(idle_lnk); - idle_port->idle_start = 0; + nxt_queue_insert_tail(&app->spare_ports, idle_lnk); - nxt_debug(task, "app '%V' move port %PI:%d from idle_ports " - "to spare_ports", - &app->name, idle_port->pid, idle_port->id); - } + idle_port->idle_start = 0; - if (nxt_router_app_can_start(app) && nxt_router_app_need_start(app)) { - app->pending_processes++; - start_process = 1; - } + nxt_debug(task, + "app '%V' move port %PI:%d from idle_ports " + "to spare_ports", + &app->name, idle_port->pid, idle_port->id); } - main_app_port->active_requests++; - - nxt_port_inc_use(app_port); + if (nxt_router_app_can_start(app) && nxt_router_app_need_start(app)) { + app->pending_processes++; + start_process = 1; + } + } - nxt_thread_mutex_unlock(&app->mutex); + main_app_port->active_requests++; - if (unlinked) { - nxt_mp_release(r->mem_pool); - } + nxt_port_inc_use(app_port); - if (start_process) { - nxt_router_start_app_process(task, app); - } + nxt_thread_mutex_unlock(&app->mutex); - nxt_port_use(task, req_rpc_data->app_port, -1); + if (unlinked) { + nxt_mp_release(r->mem_pool); + } - req_rpc_data->app_port = app_port; + if (start_process) { + nxt_router_start_app_process(task, app); + } - b = req_rpc_data->msg_info.buf; + nxt_port_use(task, req_rpc_data->app_port, -1); - if (b != NULL) { - /* First buffer is already sent. Start from second. */ - b = b->next; + req_rpc_data->app_port = app_port; - req_rpc_data->msg_info.buf->next = NULL; - } + b = req_rpc_data->msg_info.buf; - if (req_rpc_data->msg_info.body_fd != -1 || b != NULL) { - nxt_debug(task, "stream #%uD: send body fd %d", req_rpc_data->stream, - req_rpc_data->msg_info.body_fd); + if (b != NULL) { + /* First buffer is already sent. Start from second. */ + b = b->next; - if (req_rpc_data->msg_info.body_fd != -1) { - lseek(req_rpc_data->msg_info.body_fd, 0, SEEK_SET); - } + req_rpc_data->msg_info.buf->next = NULL; + } - res = nxt_port_socket_write(task, app_port, NXT_PORT_MSG_REQ_BODY, - req_rpc_data->msg_info.body_fd, - req_rpc_data->stream, - task->thread->engine->port->id, b); + if (req_rpc_data->msg_info.body_fd != -1 || b != NULL) { + nxt_debug(task, "stream #%uD: send body fd %d", req_rpc_data->stream, + req_rpc_data->msg_info.body_fd); - if (nxt_slow_path(res != NXT_OK)) { - nxt_http_request_error(task, r, NXT_HTTP_INTERNAL_SERVER_ERROR); - } + if (req_rpc_data->msg_info.body_fd != -1) { + lseek(req_rpc_data->msg_info.body_fd, 0, SEEK_SET); } - if (app->timeout != 0) { - r->timer.handler = nxt_router_app_timeout; - r->timer_data = req_rpc_data; - nxt_timer_add(task->thread->engine, &r->timer, app->timeout); + res = nxt_port_socket_write( + task, app_port, NXT_PORT_MSG_REQ_BODY, req_rpc_data->msg_info.body_fd, + req_rpc_data->stream, task->thread->engine->port->id, b); + + if (nxt_slow_path(res != NXT_OK)) { + nxt_http_request_error(task, r, NXT_HTTP_INTERNAL_SERVER_ERROR); } -} + } + if (app->timeout != 0) { + r->timer.handler = nxt_router_app_timeout; + r->timer_data = req_rpc_data; + nxt_timer_add(task->thread->engine, &r->timer, app->timeout); + } +} -static const nxt_http_request_state_t nxt_http_request_send_state - nxt_aligned(64) = -{ - .error_handler = nxt_http_request_error_handler, +static const nxt_http_request_state_t + nxt_http_request_send_state nxt_aligned(64) = { + .error_handler = nxt_http_request_error_handler, }; +static void nxt_http_request_send_body(nxt_task_t *task, void *obj, + void *data) { + nxt_buf_t *out; + nxt_http_request_t *r; -static void -nxt_http_request_send_body(nxt_task_t *task, void *obj, void *data) -{ - nxt_buf_t *out; - nxt_http_request_t *r; - - r = obj; + r = obj; - out = r->out; + out = r->out; - if (out != NULL) { - r->out = NULL; - nxt_http_request_send(task, r, out); - } + if (out != NULL) { + r->out = NULL; + nxt_http_request_send(task, r, out); + } } +static void nxt_router_response_error_handler(nxt_task_t *task, + nxt_port_recv_msg_t *msg, + void *data) { + nxt_request_rpc_data_t *req_rpc_data; -static void -nxt_router_response_error_handler(nxt_task_t *task, nxt_port_recv_msg_t *msg, - void *data) -{ - nxt_request_rpc_data_t *req_rpc_data; - - req_rpc_data = data; + req_rpc_data = data; - req_rpc_data->rpc_cancel = 0; + req_rpc_data->rpc_cancel = 0; - /* TODO cancel message and return if cancelled. */ - // nxt_router_msg_cancel(task, &req_rpc_data->msg_info, req_rpc_data->stream); + /* TODO cancel message and return if cancelled. */ + // nxt_router_msg_cancel(task, &req_rpc_data->msg_info, req_rpc_data->stream); - if (req_rpc_data->request != NULL) { - nxt_http_request_error(task, req_rpc_data->request, - NXT_HTTP_SERVICE_UNAVAILABLE); - } + if (req_rpc_data->request != NULL) { + nxt_http_request_error(task, req_rpc_data->request, + NXT_HTTP_SERVICE_UNAVAILABLE); + } - nxt_request_rpc_data_unlink(task, req_rpc_data); + nxt_request_rpc_data_unlink(task, req_rpc_data); } +static void nxt_router_app_port_ready(nxt_task_t *task, + nxt_port_recv_msg_t *msg, void *data) { + uint32_t n; + nxt_app_t *app; + nxt_bool_t start_process, restarted; + nxt_port_t *port; + nxt_app_joint_t *app_joint; + nxt_app_joint_rpc_t *app_joint_rpc; -static void -nxt_router_app_port_ready(nxt_task_t *task, nxt_port_recv_msg_t *msg, - void *data) -{ - uint32_t n; - nxt_app_t *app; - nxt_bool_t start_process, restarted; - nxt_port_t *port; - nxt_app_joint_t *app_joint; - nxt_app_joint_rpc_t *app_joint_rpc; - - nxt_assert(data != NULL); - - app_joint_rpc = data; - app_joint = app_joint_rpc->app_joint; - port = msg->u.new_port; + nxt_assert(data != NULL); - nxt_assert(app_joint != NULL); - nxt_assert(port != NULL); - nxt_assert(port->id == 0); + app_joint_rpc = data; + app_joint = app_joint_rpc->app_joint; + port = msg->u.new_port; - app = app_joint->app; + nxt_assert(app_joint != NULL); + nxt_assert(port != NULL); + nxt_assert(port->id == 0); - nxt_router_app_joint_use(task, app_joint, -1); + app = app_joint->app; - if (nxt_slow_path(app == NULL)) { - nxt_debug(task, "new port ready for released app, send QUIT"); + nxt_router_app_joint_use(task, app_joint, -1); - nxt_port_socket_write(task, port, NXT_PORT_MSG_QUIT, -1, 0, 0, NULL); + if (nxt_slow_path(app == NULL)) { + nxt_debug(task, "new port ready for released app, send QUIT"); - return; - } + nxt_port_socket_write(task, port, NXT_PORT_MSG_QUIT, -1, 0, 0, NULL); - nxt_thread_mutex_lock(&app->mutex); + return; + } - restarted = (app->generation != app_joint_rpc->generation); + nxt_thread_mutex_lock(&app->mutex); - if (app_joint_rpc->proto) { - nxt_assert(app->proto_port == NULL); - nxt_assert(port->type == NXT_PROCESS_PROTOTYPE); + restarted = (app->generation != app_joint_rpc->generation); - n = app->proto_port_requests; - app->proto_port_requests = 0; + if (app_joint_rpc->proto) { + nxt_assert(app->proto_port == NULL); + nxt_assert(port->type == NXT_PROCESS_PROTOTYPE); - if (nxt_slow_path(restarted)) { - nxt_thread_mutex_unlock(&app->mutex); + n = app->proto_port_requests; + app->proto_port_requests = 0; - nxt_debug(task, "proto port ready for restarted app, send QUIT"); + if (nxt_slow_path(restarted)) { + nxt_thread_mutex_unlock(&app->mutex); - nxt_port_socket_write(task, port, NXT_PORT_MSG_QUIT, -1, 0, 0, - NULL); + nxt_debug(task, "proto port ready for restarted app, send QUIT"); - } else { - port->app = app; - app->proto_port = port; + nxt_port_socket_write(task, port, NXT_PORT_MSG_QUIT, -1, 0, 0, NULL); - nxt_thread_mutex_unlock(&app->mutex); + } else { + port->app = app; + app->proto_port = port; - nxt_port_use(task, port, 1); - } + nxt_thread_mutex_unlock(&app->mutex); - port = task->thread->runtime->port_by_type[NXT_PROCESS_ROUTER]; + nxt_port_use(task, port, 1); + } - while (n > 0) { - nxt_router_app_use(task, app, 1); + port = task->thread->runtime->port_by_type[NXT_PROCESS_ROUTER]; - nxt_router_start_app_process_handler(task, port, app); + while (n > 0) { + nxt_router_app_use(task, app, 1); - n--; - } + nxt_router_start_app_process_handler(task, port, app); - return; + n--; } - nxt_assert(port->type == NXT_PROCESS_APP); - nxt_assert(app->pending_processes != 0); - - app->pending_processes--; - - if (nxt_slow_path(restarted)) { - nxt_debug(task, "new port ready for restarted app, send QUIT"); - - start_process = !task->thread->engine->shutdown - && nxt_router_app_can_start(app) - && nxt_router_app_need_start(app); + return; + } - if (start_process) { - app->pending_processes++; - } + nxt_assert(port->type == NXT_PROCESS_APP); + nxt_assert(app->pending_processes != 0); - nxt_thread_mutex_unlock(&app->mutex); + app->pending_processes--; - nxt_port_socket_write(task, port, NXT_PORT_MSG_QUIT, -1, 0, 0, NULL); + if (nxt_slow_path(restarted)) { + nxt_debug(task, "new port ready for restarted app, send QUIT"); - if (start_process) { - nxt_router_start_app_process(task, app); - } + start_process = !task->thread->engine->shutdown && + nxt_router_app_can_start(app) && + nxt_router_app_need_start(app); - return; + if (start_process) { + app->pending_processes++; } - port->app = app; - port->main_app_port = port; - - app->processes++; - nxt_port_hash_add(&app->port_hash, port); - app->port_hash_count++; - nxt_thread_mutex_unlock(&app->mutex); - nxt_debug(task, "app '%V' new port ready, pid %PI, %d/%d", - &app->name, port->pid, app->processes, app->pending_processes); - - nxt_port_socket_write(task, port, NXT_PORT_MSG_PORT_ACK, -1, 0, 0, NULL); - - nxt_router_app_port_release(task, app, port, NXT_APR_NEW_PORT); -} + nxt_port_socket_write(task, port, NXT_PORT_MSG_QUIT, -1, 0, 0, NULL); + if (start_process) { + nxt_router_start_app_process(task, app); + } -static void -nxt_router_app_port_error(nxt_task_t *task, nxt_port_recv_msg_t *msg, - void *data) -{ - nxt_app_t *app; - nxt_app_joint_t *app_joint; - nxt_queue_link_t *link; - nxt_http_request_t *r; - nxt_app_joint_rpc_t *app_joint_rpc; + return; + } - nxt_assert(data != NULL); + port->app = app; + port->main_app_port = port; - app_joint_rpc = data; - app_joint = app_joint_rpc->app_joint; + app->processes++; + nxt_port_hash_add(&app->port_hash, port); + app->port_hash_count++; - nxt_assert(app_joint != NULL); + nxt_thread_mutex_unlock(&app->mutex); - app = app_joint->app; + nxt_debug(task, "app '%V' new port ready, pid %PI, %d/%d", &app->name, + port->pid, app->processes, app->pending_processes); - nxt_router_app_joint_use(task, app_joint, -1); + nxt_port_socket_write(task, port, NXT_PORT_MSG_PORT_ACK, -1, 0, 0, NULL); - if (nxt_slow_path(app == NULL)) { - nxt_debug(task, "start error for released app"); + nxt_router_app_port_release(task, app, port, NXT_APR_NEW_PORT); +} - return; - } +static void nxt_router_app_port_error(nxt_task_t *task, + nxt_port_recv_msg_t *msg, void *data) { + nxt_app_t *app; + nxt_app_joint_t *app_joint; + nxt_queue_link_t *link; + nxt_http_request_t *r; + nxt_app_joint_rpc_t *app_joint_rpc; - nxt_debug(task, "app '%V' %p start error", &app->name, app); + nxt_assert(data != NULL); - link = NULL; + app_joint_rpc = data; + app_joint = app_joint_rpc->app_joint; - nxt_thread_mutex_lock(&app->mutex); + nxt_assert(app_joint != NULL); - nxt_assert(app->pending_processes != 0); + app = app_joint->app; - app->pending_processes--; + nxt_router_app_joint_use(task, app_joint, -1); - if (app->processes == 0 && !nxt_queue_is_empty(&app->ack_waiting_req)) { - link = nxt_queue_first(&app->ack_waiting_req); + if (nxt_slow_path(app == NULL)) { + nxt_debug(task, "start error for released app"); - nxt_queue_remove(link); - link->next = NULL; - } + return; + } - nxt_thread_mutex_unlock(&app->mutex); + nxt_debug(task, "app '%V' %p start error", &app->name, app); - while (link != NULL) { - r = nxt_container_of(link, nxt_http_request_t, app_link); + link = NULL; - nxt_event_engine_post(r->engine, &r->err_work); + nxt_thread_mutex_lock(&app->mutex); - link = NULL; + nxt_assert(app->pending_processes != 0); - nxt_thread_mutex_lock(&app->mutex); + app->pending_processes--; - if (app->processes == 0 && app->pending_processes == 0 - && !nxt_queue_is_empty(&app->ack_waiting_req)) - { - link = nxt_queue_first(&app->ack_waiting_req); + if (app->processes == 0 && !nxt_queue_is_empty(&app->ack_waiting_req)) { + link = nxt_queue_first(&app->ack_waiting_req); - nxt_queue_remove(link); - link->next = NULL; - } + nxt_queue_remove(link); + link->next = NULL; + } - nxt_thread_mutex_unlock(&app->mutex); - } -} + nxt_thread_mutex_unlock(&app->mutex); + while (link != NULL) { + r = nxt_container_of(link, nxt_http_request_t, app_link); -nxt_inline nxt_port_t * -nxt_router_app_get_port_for_quit(nxt_task_t *task, nxt_app_t *app) -{ - nxt_port_t *port; + nxt_event_engine_post(r->engine, &r->err_work); - port = NULL; + link = NULL; nxt_thread_mutex_lock(&app->mutex); - nxt_queue_each(port, &app->ports, nxt_port_t, app_link) { - - /* Caller is responsible to decrease port use count. */ - nxt_queue_chk_remove(&port->app_link); - - if (nxt_queue_chk_remove(&port->idle_link)) { - app->idle_processes--; - - nxt_debug(task, "app '%V' move port %PI:%d out of %s for quit", - &app->name, port->pid, port->id, - (port->idle_start ? "idle_ports" : "spare_ports")); - } - - nxt_port_hash_remove(&app->port_hash, port); - app->port_hash_count--; - - port->app = NULL; - app->processes--; - - break; + if (app->processes == 0 && app->pending_processes == 0 && + !nxt_queue_is_empty(&app->ack_waiting_req)) { + link = nxt_queue_first(&app->ack_waiting_req); - } nxt_queue_loop; + nxt_queue_remove(link); + link->next = NULL; + } nxt_thread_mutex_unlock(&app->mutex); - - return port; + } } +nxt_inline nxt_port_t *nxt_router_app_get_port_for_quit(nxt_task_t *task, + nxt_app_t *app) { + nxt_port_t *port; -static void -nxt_router_app_use(nxt_task_t *task, nxt_app_t *app, int i) -{ - int c; + port = NULL; - c = nxt_atomic_fetch_add(&app->use_count, i); + nxt_thread_mutex_lock(&app->mutex); - if (i < 0 && c == -i) { + nxt_queue_each(port, &app->ports, nxt_port_t, app_link) { - if (task->thread->engine != app->engine) { - nxt_event_engine_post(app->engine, &app->joint->free_app_work); + /* Caller is responsible to decrease port use count. */ + nxt_queue_chk_remove(&port->app_link); - } else { - nxt_router_free_app(task, app->joint, NULL); - } + if (nxt_queue_chk_remove(&port->idle_link)) { + app->idle_processes--; + + nxt_debug(task, "app '%V' move port %PI:%d out of %s for quit", + &app->name, port->pid, port->id, + (port->idle_start ? "idle_ports" : "spare_ports")); } -} + nxt_port_hash_remove(&app->port_hash, port); + app->port_hash_count--; + + port->app = NULL; + app->processes--; -static void -nxt_router_app_unlink(nxt_task_t *task, nxt_app_t *app) -{ - nxt_debug(task, "app '%V' %p unlink", &app->name, app); + break; + } + nxt_queue_loop; - nxt_queue_remove(&app->link); + nxt_thread_mutex_unlock(&app->mutex); - nxt_router_app_use(task, app, -1); + return port; } +static void nxt_router_app_use(nxt_task_t *task, nxt_app_t *app, int i) { + int c; -static void -nxt_router_app_port_release(nxt_task_t *task, nxt_app_t *app, nxt_port_t *port, - nxt_apr_action_t action) -{ - int inc_use; - uint32_t got_response, dec_requests; - nxt_bool_t adjust_idle_timer; - nxt_port_t *main_app_port; - - nxt_assert(port != NULL); - - inc_use = 0; - got_response = 0; - dec_requests = 0; - - switch (action) { - case NXT_APR_NEW_PORT: - break; - case NXT_APR_REQUEST_FAILED: - dec_requests = 1; - inc_use = -1; - break; - case NXT_APR_GOT_RESPONSE: - got_response = 1; - inc_use = -1; - break; - case NXT_APR_UPGRADE: - got_response = 1; - break; - case NXT_APR_CLOSE: - inc_use = -1; - break; - } + c = nxt_atomic_fetch_add(&app->use_count, i); - nxt_debug(task, "app '%V' release port %PI:%d: %d %d", &app->name, - port->pid, port->id, - (int) inc_use, (int) got_response); + if (i < 0 && c == -i) { - if (port->id == NXT_SHARED_PORT_ID) { - nxt_thread_mutex_lock(&app->mutex); + if (task->thread->engine != app->engine) { + nxt_event_engine_post(app->engine, &app->joint->free_app_work); - app->active_requests -= got_response + dec_requests; + } else { + nxt_router_free_app(task, app->joint, NULL); + } + } +} - nxt_thread_mutex_unlock(&app->mutex); +static void nxt_router_app_unlink(nxt_task_t *task, nxt_app_t *app) { + nxt_debug(task, "app '%V' %p unlink", &app->name, app); - goto adjust_use; - } + nxt_queue_remove(&app->link); - main_app_port = port->main_app_port; + nxt_router_app_use(task, app, -1); +} +static void nxt_router_app_port_release(nxt_task_t *task, nxt_app_t *app, + nxt_port_t *port, + nxt_apr_action_t action) { + int inc_use; + uint32_t got_response, dec_requests; + nxt_bool_t adjust_idle_timer; + nxt_port_t *main_app_port; + + nxt_assert(port != NULL); + + inc_use = 0; + got_response = 0; + dec_requests = 0; + + switch (action) { + case NXT_APR_NEW_PORT: + break; + case NXT_APR_REQUEST_FAILED: + dec_requests = 1; + inc_use = -1; + break; + case NXT_APR_GOT_RESPONSE: + got_response = 1; + inc_use = -1; + break; + case NXT_APR_UPGRADE: + got_response = 1; + break; + case NXT_APR_CLOSE: + inc_use = -1; + break; + } + + nxt_debug(task, "app '%V' release port %PI:%d: %d %d", &app->name, port->pid, + port->id, (int)inc_use, (int)got_response); + + if (port->id == NXT_SHARED_PORT_ID) { nxt_thread_mutex_lock(&app->mutex); - main_app_port->active_requests -= got_response + dec_requests; app->active_requests -= got_response + dec_requests; - if (main_app_port->pair[1] != -1 && main_app_port->app_link.next == NULL) { - nxt_queue_insert_tail(&app->ports, &main_app_port->app_link); + nxt_thread_mutex_unlock(&app->mutex); - nxt_port_inc_use(main_app_port); - } + goto adjust_use; + } - adjust_idle_timer = 0; + main_app_port = port->main_app_port; - if (main_app_port->pair[1] != -1 - && main_app_port->active_requests == 0 - && main_app_port->active_websockets == 0 - && main_app_port->idle_link.next == NULL) - { - if (app->idle_processes == app->spare_processes - && app->adjust_idle_work.data == NULL) - { - adjust_idle_timer = 1; - app->adjust_idle_work.data = app; - app->adjust_idle_work.next = NULL; - } + nxt_thread_mutex_lock(&app->mutex); - if (app->idle_processes < app->spare_processes) { - nxt_queue_insert_tail(&app->spare_ports, &main_app_port->idle_link); + main_app_port->active_requests -= got_response + dec_requests; + app->active_requests -= got_response + dec_requests; - nxt_debug(task, "app '%V' move port %PI:%d to spare_ports", - &app->name, main_app_port->pid, main_app_port->id); - } else { - nxt_queue_insert_tail(&app->idle_ports, &main_app_port->idle_link); + if (main_app_port->pair[1] != -1 && main_app_port->app_link.next == NULL) { + nxt_queue_insert_tail(&app->ports, &main_app_port->app_link); - main_app_port->idle_start = task->thread->engine->timers.now; + nxt_port_inc_use(main_app_port); + } - nxt_debug(task, "app '%V' move port %PI:%d to idle_ports", - &app->name, main_app_port->pid, main_app_port->id); - } + adjust_idle_timer = 0; - app->idle_processes++; + if (main_app_port->pair[1] != -1 && main_app_port->active_requests == 0 && + main_app_port->active_websockets == 0 && + main_app_port->idle_link.next == NULL) { + if (app->idle_processes == app->spare_processes && + app->adjust_idle_work.data == NULL) { + adjust_idle_timer = 1; + app->adjust_idle_work.data = app; + app->adjust_idle_work.next = NULL; } - nxt_thread_mutex_unlock(&app->mutex); + if (app->idle_processes < app->spare_processes) { + nxt_queue_insert_tail(&app->spare_ports, &main_app_port->idle_link); - if (adjust_idle_timer) { - nxt_router_app_use(task, app, 1); - nxt_event_engine_post(app->engine, &app->adjust_idle_work); - } + nxt_debug(task, "app '%V' move port %PI:%d to spare_ports", &app->name, + main_app_port->pid, main_app_port->id); + } else { + nxt_queue_insert_tail(&app->idle_ports, &main_app_port->idle_link); - /* ? */ - if (main_app_port->pair[1] == -1) { - nxt_debug(task, "app '%V' %p port %p already closed (pid %PI dead?)", - &app->name, app, main_app_port, main_app_port->pid); + main_app_port->idle_start = task->thread->engine->timers.now; - goto adjust_use; + nxt_debug(task, "app '%V' move port %PI:%d to idle_ports", &app->name, + main_app_port->pid, main_app_port->id); } - nxt_debug(task, "app '%V' %p requests queue is empty, keep the port", - &app->name, app); - -adjust_use: - - nxt_port_use(task, port, inc_use); -} + app->idle_processes++; + } + nxt_thread_mutex_unlock(&app->mutex); -void -nxt_router_app_port_close(nxt_task_t *task, nxt_port_t *port) -{ - nxt_app_t *app; - nxt_bool_t unchain, start_process; - nxt_port_t *idle_port; - nxt_queue_link_t *idle_lnk; + if (adjust_idle_timer) { + nxt_router_app_use(task, app, 1); + nxt_event_engine_post(app->engine, &app->adjust_idle_work); + } - app = port->app; + /* ? */ + if (main_app_port->pair[1] == -1) { + nxt_debug(task, "app '%V' %p port %p already closed (pid %PI dead?)", + &app->name, app, main_app_port, main_app_port->pid); - nxt_assert(app != NULL); + goto adjust_use; + } - nxt_thread_mutex_lock(&app->mutex); + nxt_debug(task, "app '%V' %p requests queue is empty, keep the port", + &app->name, app); - if (port == app->proto_port) { - app->proto_port = NULL; - port->app = NULL; +adjust_use: - nxt_thread_mutex_unlock(&app->mutex); + nxt_port_use(task, port, inc_use); +} - nxt_debug(task, "app '%V' prototype pid %PI closed", &app->name, - port->pid); +void nxt_router_app_port_close(nxt_task_t *task, nxt_port_t *port) { + nxt_app_t *app; + nxt_bool_t unchain, start_process; + nxt_port_t *idle_port; + nxt_queue_link_t *idle_lnk; - nxt_port_use(task, port, -1); + app = port->app; - return; - } + nxt_assert(app != NULL); - nxt_port_hash_remove(&app->port_hash, port); - app->port_hash_count--; + nxt_thread_mutex_lock(&app->mutex); - if (port->id != 0) { - nxt_thread_mutex_unlock(&app->mutex); + if (port == app->proto_port) { + app->proto_port = NULL; + port->app = NULL; - nxt_debug(task, "app '%V' port (%PI, %d) closed", &app->name, - port->pid, port->id); + nxt_thread_mutex_unlock(&app->mutex); - return; - } + nxt_debug(task, "app '%V' prototype pid %PI closed", &app->name, port->pid); - unchain = nxt_queue_chk_remove(&port->app_link); + nxt_port_use(task, port, -1); - if (nxt_queue_chk_remove(&port->idle_link)) { - app->idle_processes--; + return; + } - nxt_debug(task, "app '%V' move port %PI:%d out of %s before close", - &app->name, port->pid, port->id, - (port->idle_start ? "idle_ports" : "spare_ports")); + nxt_port_hash_remove(&app->port_hash, port); + app->port_hash_count--; - if (port->idle_start == 0 - && app->idle_processes >= app->spare_processes) - { - nxt_assert(!nxt_queue_is_empty(&app->idle_ports)); + if (port->id != 0) { + nxt_thread_mutex_unlock(&app->mutex); - idle_lnk = nxt_queue_last(&app->idle_ports); - idle_port = nxt_queue_link_data(idle_lnk, nxt_port_t, idle_link); - nxt_queue_remove(idle_lnk); + nxt_debug(task, "app '%V' port (%PI, %d) closed", &app->name, port->pid, + port->id); - nxt_queue_insert_tail(&app->spare_ports, idle_lnk); + return; + } - idle_port->idle_start = 0; + unchain = nxt_queue_chk_remove(&port->app_link); - nxt_debug(task, "app '%V' move port %PI:%d from idle_ports " - "to spare_ports", - &app->name, idle_port->pid, idle_port->id); - } - } + if (nxt_queue_chk_remove(&port->idle_link)) { + app->idle_processes--; - app->processes--; + nxt_debug(task, "app '%V' move port %PI:%d out of %s before close", + &app->name, port->pid, port->id, + (port->idle_start ? "idle_ports" : "spare_ports")); - start_process = !task->thread->engine->shutdown - && nxt_router_app_can_start(app) - && nxt_router_app_need_start(app); + if (port->idle_start == 0 && app->idle_processes >= app->spare_processes) { + nxt_assert(!nxt_queue_is_empty(&app->idle_ports)); - if (start_process) { - app->pending_processes++; - } + idle_lnk = nxt_queue_last(&app->idle_ports); + idle_port = nxt_queue_link_data(idle_lnk, nxt_port_t, idle_link); + nxt_queue_remove(idle_lnk); - nxt_thread_mutex_unlock(&app->mutex); + nxt_queue_insert_tail(&app->spare_ports, idle_lnk); - nxt_debug(task, "app '%V' pid %PI closed", &app->name, port->pid); + idle_port->idle_start = 0; - if (unchain) { - nxt_port_use(task, port, -1); + nxt_debug(task, + "app '%V' move port %PI:%d from idle_ports " + "to spare_ports", + &app->name, idle_port->pid, idle_port->id); } + } - if (start_process) { - nxt_router_start_app_process(task, app); - } -} + app->processes--; + start_process = !task->thread->engine->shutdown && + nxt_router_app_can_start(app) && + nxt_router_app_need_start(app); -static void -nxt_router_adjust_idle_timer(nxt_task_t *task, void *obj, void *data) -{ - nxt_app_t *app; - nxt_bool_t queued; - nxt_port_t *port; - nxt_msec_t timeout, threshold; - nxt_queue_link_t *lnk; - nxt_event_engine_t *engine; + if (start_process) { + app->pending_processes++; + } - app = obj; - queued = (data == app); + nxt_thread_mutex_unlock(&app->mutex); - nxt_debug(task, "nxt_router_adjust_idle_timer: app \"%V\", queued %b", - &app->name, queued); + nxt_debug(task, "app '%V' pid %PI closed", &app->name, port->pid); - engine = task->thread->engine; + if (unchain) { + nxt_port_use(task, port, -1); + } - nxt_assert(app->engine == engine); + if (start_process) { + nxt_router_start_app_process(task, app); + } +} - threshold = engine->timers.now + app->joint->idle_timer.bias; - timeout = 0; +static void nxt_router_adjust_idle_timer(nxt_task_t *task, void *obj, + void *data) { + nxt_app_t *app; + nxt_bool_t queued; + nxt_port_t *port; + nxt_msec_t timeout, threshold; + nxt_queue_link_t *lnk; + nxt_event_engine_t *engine; - nxt_thread_mutex_lock(&app->mutex); + app = obj; + queued = (data == app); - if (queued) { - app->adjust_idle_work.data = NULL; - } + nxt_debug(task, "nxt_router_adjust_idle_timer: app \"%V\", queued %b", + &app->name, queued); - nxt_debug(task, "app '%V' idle_processes %d, spare_processes %d", - &app->name, - (int) app->idle_processes, (int) app->spare_processes); + engine = task->thread->engine; - while (app->idle_processes > app->spare_processes) { + nxt_assert(app->engine == engine); - nxt_assert(!nxt_queue_is_empty(&app->idle_ports)); + threshold = engine->timers.now + app->joint->idle_timer.bias; + timeout = 0; - lnk = nxt_queue_first(&app->idle_ports); - port = nxt_queue_link_data(lnk, nxt_port_t, idle_link); + nxt_thread_mutex_lock(&app->mutex); - timeout = port->idle_start + app->idle_timeout; + if (queued) { + app->adjust_idle_work.data = NULL; + } - nxt_debug(task, "app '%V' pid %PI, start %M, timeout %M, threshold %M", - &app->name, port->pid, - port->idle_start, timeout, threshold); + nxt_debug(task, "app '%V' idle_processes %d, spare_processes %d", &app->name, + (int)app->idle_processes, (int)app->spare_processes); - if (timeout > threshold) { - break; - } + while (app->idle_processes > app->spare_processes) { - nxt_queue_remove(lnk); - lnk->next = NULL; + nxt_assert(!nxt_queue_is_empty(&app->idle_ports)); - nxt_debug(task, "app '%V' move port %PI:%d out of idle_ports (timeout)", - &app->name, port->pid, port->id); + lnk = nxt_queue_first(&app->idle_ports); + port = nxt_queue_link_data(lnk, nxt_port_t, idle_link); - nxt_queue_chk_remove(&port->app_link); + timeout = port->idle_start + app->idle_timeout; - nxt_port_hash_remove(&app->port_hash, port); - app->port_hash_count--; + nxt_debug(task, "app '%V' pid %PI, start %M, timeout %M, threshold %M", + &app->name, port->pid, port->idle_start, timeout, threshold); - app->idle_processes--; - app->processes--; - port->app = NULL; + if (timeout > threshold) { + break; + } - nxt_thread_mutex_unlock(&app->mutex); + nxt_queue_remove(lnk); + lnk->next = NULL; - nxt_debug(task, "app '%V' send QUIT to idle port %PI", - &app->name, port->pid); + nxt_debug(task, "app '%V' move port %PI:%d out of idle_ports (timeout)", + &app->name, port->pid, port->id); - nxt_port_socket_write(task, port, NXT_PORT_MSG_QUIT, -1, 0, 0, NULL); + nxt_queue_chk_remove(&port->app_link); - nxt_port_use(task, port, -1); + nxt_port_hash_remove(&app->port_hash, port); + app->port_hash_count--; - nxt_thread_mutex_lock(&app->mutex); - } + app->idle_processes--; + app->processes--; + port->app = NULL; nxt_thread_mutex_unlock(&app->mutex); - if (timeout > threshold) { - nxt_timer_add(engine, &app->joint->idle_timer, timeout - threshold); - - } else { - nxt_timer_disable(engine, &app->joint->idle_timer); - } - - if (queued) { - nxt_router_app_use(task, app, -1); - } -} + nxt_debug(task, "app '%V' send QUIT to idle port %PI", &app->name, + port->pid); + nxt_port_socket_write(task, port, NXT_PORT_MSG_QUIT, -1, 0, 0, NULL); -static void -nxt_router_app_idle_timeout(nxt_task_t *task, void *obj, void *data) -{ - nxt_timer_t *timer; - nxt_app_joint_t *app_joint; - - timer = obj; - app_joint = nxt_container_of(timer, nxt_app_joint_t, idle_timer); + nxt_port_use(task, port, -1); - if (nxt_fast_path(app_joint->app != NULL)) { - nxt_router_adjust_idle_timer(task, app_joint->app, NULL); - } -} + nxt_thread_mutex_lock(&app->mutex); + } + nxt_thread_mutex_unlock(&app->mutex); -static void -nxt_router_app_joint_release_handler(nxt_task_t *task, void *obj, void *data) -{ - nxt_timer_t *timer; - nxt_app_joint_t *app_joint; + if (timeout > threshold) { + nxt_timer_add(engine, &app->joint->idle_timer, timeout - threshold); - timer = obj; - app_joint = nxt_container_of(timer, nxt_app_joint_t, idle_timer); + } else { + nxt_timer_disable(engine, &app->joint->idle_timer); + } - nxt_router_app_joint_use(task, app_joint, -1); + if (queued) { + nxt_router_app_use(task, app, -1); + } } +static void nxt_router_app_idle_timeout(nxt_task_t *task, void *obj, + void *data) { + nxt_timer_t *timer; + nxt_app_joint_t *app_joint; -static void -nxt_router_free_app(nxt_task_t *task, void *obj, void *data) -{ - nxt_app_t *app; - nxt_port_t *port, *proto_port; - nxt_app_joint_t *app_joint; - - app_joint = obj; - app = app_joint->app; - - for ( ;; ) { - port = nxt_router_app_get_port_for_quit(task, app); - if (port == NULL) { - break; - } + timer = obj; + app_joint = nxt_container_of(timer, nxt_app_joint_t, idle_timer); - nxt_port_use(task, port, -1); - } + if (nxt_fast_path(app_joint->app != NULL)) { + nxt_router_adjust_idle_timer(task, app_joint->app, NULL); + } +} - nxt_thread_mutex_lock(&app->mutex); +static void nxt_router_app_joint_release_handler(nxt_task_t *task, void *obj, + void *data) { + nxt_timer_t *timer; + nxt_app_joint_t *app_joint; - for ( ;; ) { - port = nxt_port_hash_retrieve(&app->port_hash); - if (port == NULL) { - break; - } + timer = obj; + app_joint = nxt_container_of(timer, nxt_app_joint_t, idle_timer); - app->port_hash_count--; + nxt_router_app_joint_use(task, app_joint, -1); +} - port->app = NULL; +static void nxt_router_free_app(nxt_task_t *task, void *obj, void *data) { + nxt_app_t *app; + nxt_port_t *port, *proto_port; + nxt_app_joint_t *app_joint; - nxt_port_close(task, port); + app_joint = obj; + app = app_joint->app; - nxt_port_use(task, port, -1); + for (;;) { + port = nxt_router_app_get_port_for_quit(task, app); + if (port == NULL) { + break; } - proto_port = app->proto_port; + nxt_port_use(task, port, -1); + } - if (proto_port != NULL) { - nxt_debug(task, "send QUIT to prototype '%V' pid %PI", &app->name, - proto_port->pid); + nxt_thread_mutex_lock(&app->mutex); - app->proto_port = NULL; - proto_port->app = NULL; + for (;;) { + port = nxt_port_hash_retrieve(&app->port_hash); + if (port == NULL) { + break; } - nxt_thread_mutex_unlock(&app->mutex); + app->port_hash_count--; - if (proto_port != NULL) { - nxt_port_socket_write(task, proto_port, NXT_PORT_MSG_QUIT, - -1, 0, 0, NULL); + port->app = NULL; - nxt_port_close(task, proto_port); + nxt_port_close(task, port); - nxt_port_use(task, proto_port, -1); - } + nxt_port_use(task, port, -1); + } - nxt_assert(app->proto_port == NULL); - nxt_assert(app->processes == 0); - nxt_assert(app->active_requests == 0); - nxt_assert(app->port_hash_count == 0); - nxt_assert(app->idle_processes == 0); - nxt_assert(nxt_queue_is_empty(&app->ports)); - nxt_assert(nxt_queue_is_empty(&app->spare_ports)); - nxt_assert(nxt_queue_is_empty(&app->idle_ports)); + proto_port = app->proto_port; - nxt_port_mmaps_destroy(&app->outgoing, 1); + if (proto_port != NULL) { + nxt_debug(task, "send QUIT to prototype '%V' pid %PI", &app->name, + proto_port->pid); - nxt_thread_mutex_destroy(&app->outgoing.mutex); + app->proto_port = NULL; + proto_port->app = NULL; + } - if (app->shared_port != NULL) { - app->shared_port->app = NULL; - nxt_port_close(task, app->shared_port); - nxt_port_use(task, app->shared_port, -1); + nxt_thread_mutex_unlock(&app->mutex); - app->shared_port = NULL; - } + if (proto_port != NULL) { + nxt_port_socket_write(task, proto_port, NXT_PORT_MSG_QUIT, -1, 0, 0, NULL); - nxt_thread_mutex_destroy(&app->mutex); - nxt_mp_destroy(app->mem_pool); + nxt_port_close(task, proto_port); - app_joint->app = NULL; + nxt_port_use(task, proto_port, -1); + } - if (nxt_timer_delete(task->thread->engine, &app_joint->idle_timer)) { - app_joint->idle_timer.handler = nxt_router_app_joint_release_handler; - nxt_timer_add(task->thread->engine, &app_joint->idle_timer, 0); + nxt_assert(app->proto_port == NULL); + nxt_assert(app->processes == 0); + nxt_assert(app->active_requests == 0); + nxt_assert(app->port_hash_count == 0); + nxt_assert(app->idle_processes == 0); + nxt_assert(nxt_queue_is_empty(&app->ports)); + nxt_assert(nxt_queue_is_empty(&app->spare_ports)); + nxt_assert(nxt_queue_is_empty(&app->idle_ports)); - } else { - nxt_router_app_joint_use(task, app_joint, -1); - } -} + nxt_port_mmaps_destroy(&app->outgoing, 1); + nxt_thread_mutex_destroy(&app->outgoing.mutex); -static void -nxt_router_app_port_get(nxt_task_t *task, nxt_app_t *app, - nxt_request_rpc_data_t *req_rpc_data) -{ - nxt_bool_t start_process; - nxt_port_t *port; - nxt_http_request_t *r; + if (app->shared_port != NULL) { + app->shared_port->app = NULL; + nxt_port_close(task, app->shared_port); + nxt_port_use(task, app->shared_port, -1); - start_process = 0; + app->shared_port = NULL; + } - nxt_thread_mutex_lock(&app->mutex); + nxt_thread_mutex_destroy(&app->mutex); + nxt_mp_destroy(app->mem_pool); - port = app->shared_port; - nxt_port_inc_use(port); + app_joint->app = NULL; - app->active_requests++; + if (nxt_timer_delete(task->thread->engine, &app_joint->idle_timer)) { + app_joint->idle_timer.handler = nxt_router_app_joint_release_handler; + nxt_timer_add(task->thread->engine, &app_joint->idle_timer, 0); - if (nxt_router_app_can_start(app) && nxt_router_app_need_start(app)) { - app->pending_processes++; - start_process = 1; - } + } else { + nxt_router_app_joint_use(task, app_joint, -1); + } +} - r = req_rpc_data->request; +static void nxt_router_app_port_get(nxt_task_t *task, nxt_app_t *app, + nxt_request_rpc_data_t *req_rpc_data) { + nxt_bool_t start_process; + nxt_port_t *port; + nxt_http_request_t *r; - /* - * Put request into application-wide list to be able to cancel request - * if something goes wrong with application processes. - */ - nxt_queue_insert_tail(&app->ack_waiting_req, &r->app_link); + start_process = 0; - nxt_thread_mutex_unlock(&app->mutex); + nxt_thread_mutex_lock(&app->mutex); - /* - * Retain request memory pool while request is linked in ack_waiting_req - * to guarantee request structure memory is accessble. - */ - nxt_mp_retain(r->mem_pool); + port = app->shared_port; + nxt_port_inc_use(port); - req_rpc_data->app_port = port; - req_rpc_data->apr_action = NXT_APR_REQUEST_FAILED; + app->active_requests++; - if (start_process) { - nxt_router_start_app_process(task, app); - } -} + if (nxt_router_app_can_start(app) && nxt_router_app_need_start(app)) { + app->pending_processes++; + start_process = 1; + } + r = req_rpc_data->request; -void -nxt_router_process_http_request(nxt_task_t *task, nxt_http_request_t *r, - nxt_http_action_t *action) -{ - nxt_event_engine_t *engine; - nxt_http_app_conf_t *conf; - nxt_request_rpc_data_t *req_rpc_data; + /* + * Put request into application-wide list to be able to cancel request + * if something goes wrong with application processes. + */ + nxt_queue_insert_tail(&app->ack_waiting_req, &r->app_link); - conf = action->u.conf; - engine = task->thread->engine; + nxt_thread_mutex_unlock(&app->mutex); - r->app_target = conf->target; + /* + * Retain request memory pool while request is linked in ack_waiting_req + * to guarantee request structure memory is accessble. + */ + nxt_mp_retain(r->mem_pool); - req_rpc_data = nxt_port_rpc_register_handler_ex(task, engine->port, - nxt_router_response_ready_handler, - nxt_router_response_error_handler, - sizeof(nxt_request_rpc_data_t)); - if (nxt_slow_path(req_rpc_data == NULL)) { - nxt_http_request_error(task, r, NXT_HTTP_INTERNAL_SERVER_ERROR); - return; - } + req_rpc_data->app_port = port; + req_rpc_data->apr_action = NXT_APR_REQUEST_FAILED; - /* - * At this point we have request req_rpc_data allocated and registered - * in port handlers. Need to fixup request memory pool. Counterpart - * release will be called via following call chain: - * nxt_request_rpc_data_unlink() -> - * nxt_router_http_request_release_post() -> - * nxt_router_http_request_release() - */ - nxt_mp_retain(r->mem_pool); - - r->timer.task = &engine->task; - r->timer.work_queue = &engine->fast_work_queue; - r->timer.log = engine->task.log; - r->timer.bias = NXT_TIMER_DEFAULT_BIAS; - - r->engine = engine; - r->err_work.handler = nxt_router_http_request_error; - r->err_work.task = task; - r->err_work.obj = r; - - req_rpc_data->stream = nxt_port_rpc_ex_stream(req_rpc_data); - req_rpc_data->app = conf->app; - req_rpc_data->msg_info.body_fd = -1; - req_rpc_data->rpc_cancel = 1; + if (start_process) { + nxt_router_start_app_process(task, app); + } +} - nxt_router_app_use(task, conf->app, 1); +void nxt_router_process_http_request(nxt_task_t *task, nxt_http_request_t *r, + nxt_http_action_t *action) { + nxt_event_engine_t *engine; + nxt_http_app_conf_t *conf; + nxt_request_rpc_data_t *req_rpc_data; - req_rpc_data->request = r; - r->req_rpc_data = req_rpc_data; + conf = action->u.conf; + engine = task->thread->engine; - if (r->last != NULL) { - r->last->completion_handler = nxt_router_http_request_done; - } + r->app_target = conf->target; - nxt_router_app_port_get(task, conf->app, req_rpc_data); - nxt_router_app_prepare_request(task, req_rpc_data); + req_rpc_data = nxt_port_rpc_register_handler_ex( + task, engine->port, nxt_router_response_ready_handler, + nxt_router_response_error_handler, sizeof(nxt_request_rpc_data_t)); + if (nxt_slow_path(req_rpc_data == NULL)) { + nxt_http_request_error(task, r, NXT_HTTP_INTERNAL_SERVER_ERROR); + return; + } + + /* + * At this point we have request req_rpc_data allocated and registered + * in port handlers. Need to fixup request memory pool. Counterpart + * release will be called via following call chain: + * nxt_request_rpc_data_unlink() -> + * nxt_router_http_request_release_post() -> + * nxt_router_http_request_release() + */ + nxt_mp_retain(r->mem_pool); + + r->timer.task = &engine->task; + r->timer.work_queue = &engine->fast_work_queue; + r->timer.log = engine->task.log; + r->timer.bias = NXT_TIMER_DEFAULT_BIAS; + + r->engine = engine; + r->err_work.handler = nxt_router_http_request_error; + r->err_work.task = task; + r->err_work.obj = r; + + req_rpc_data->stream = nxt_port_rpc_ex_stream(req_rpc_data); + req_rpc_data->app = conf->app; + req_rpc_data->msg_info.body_fd = -1; + req_rpc_data->rpc_cancel = 1; + + nxt_router_app_use(task, conf->app, 1); + + req_rpc_data->request = r; + r->req_rpc_data = req_rpc_data; + + if (r->last != NULL) { + r->last->completion_handler = nxt_router_http_request_done; + } + + nxt_router_app_port_get(task, conf->app, req_rpc_data); + nxt_router_app_prepare_request(task, req_rpc_data); } +static void nxt_router_http_request_error(nxt_task_t *task, void *obj, + void *data) { + nxt_http_request_t *r; -static void -nxt_router_http_request_error(nxt_task_t *task, void *obj, void *data) -{ - nxt_http_request_t *r; - - r = obj; + r = obj; - nxt_debug(task, "router http request error (rpc_data %p)", r->req_rpc_data); + nxt_debug(task, "router http request error (rpc_data %p)", r->req_rpc_data); - nxt_http_request_error(task, r, NXT_HTTP_SERVICE_UNAVAILABLE); + nxt_http_request_error(task, r, NXT_HTTP_SERVICE_UNAVAILABLE); - if (r->req_rpc_data != NULL) { - nxt_request_rpc_data_unlink(task, r->req_rpc_data); - } + if (r->req_rpc_data != NULL) { + nxt_request_rpc_data_unlink(task, r->req_rpc_data); + } - nxt_mp_release(r->mem_pool); + nxt_mp_release(r->mem_pool); } +static void nxt_router_http_request_done(nxt_task_t *task, void *obj, + void *data) { + nxt_http_request_t *r; -static void -nxt_router_http_request_done(nxt_task_t *task, void *obj, void *data) -{ - nxt_http_request_t *r; - - r = data; + r = data; - nxt_debug(task, "router http request done (rpc_data %p)", r->req_rpc_data); + nxt_debug(task, "router http request done (rpc_data %p)", r->req_rpc_data); - if (r->req_rpc_data != NULL) { - nxt_request_rpc_data_unlink(task, r->req_rpc_data); - } + if (r->req_rpc_data != NULL) { + nxt_request_rpc_data_unlink(task, r->req_rpc_data); + } - nxt_http_request_close_handler(task, r, r->proto.any); + nxt_http_request_close_handler(task, r, r->proto.any); } - static void nxt_router_app_prepare_request(nxt_task_t *task, - nxt_request_rpc_data_t *req_rpc_data) -{ - nxt_app_t *app; - nxt_buf_t *buf, *body; - nxt_int_t res; - nxt_port_t *port, *reply_port; + nxt_request_rpc_data_t *req_rpc_data) { + nxt_app_t *app; + nxt_buf_t *buf, *body; + nxt_int_t res; + nxt_port_t *port, *reply_port; - int notify; - struct { - nxt_port_msg_t pm; - nxt_port_mmap_msg_t mm; - } msg; + int notify; + struct { + nxt_port_msg_t pm; + nxt_port_mmap_msg_t mm; + } msg; + app = req_rpc_data->app; - app = req_rpc_data->app; + nxt_assert(app != NULL); - nxt_assert(app != NULL); + port = req_rpc_data->app_port; - port = req_rpc_data->app_port; + nxt_assert(port != NULL); + nxt_assert(port->queue != NULL); - nxt_assert(port != NULL); - nxt_assert(port->queue != NULL); + reply_port = task->thread->engine->port; - reply_port = task->thread->engine->port; + buf = nxt_router_prepare_msg(task, req_rpc_data->request, app, + nxt_app_msg_prefix[app->type]); + if (nxt_slow_path(buf == NULL)) { + nxt_alert(task, "stream #%uD, app '%V': failed to prepare app message", + req_rpc_data->stream, &app->name); - buf = nxt_router_prepare_msg(task, req_rpc_data->request, app, - nxt_app_msg_prefix[app->type]); - if (nxt_slow_path(buf == NULL)) { - nxt_alert(task, "stream #%uD, app '%V': failed to prepare app message", - req_rpc_data->stream, &app->name); + nxt_http_request_error(task, req_rpc_data->request, + NXT_HTTP_INTERNAL_SERVER_ERROR); - nxt_http_request_error(task, req_rpc_data->request, - NXT_HTTP_INTERNAL_SERVER_ERROR); + return; + } - return; - } + nxt_debug(task, "about to send %O bytes buffer to app process port %d", + nxt_buf_used_size(buf), port->socket.fd); - nxt_debug(task, "about to send %O bytes buffer to app process port %d", - nxt_buf_used_size(buf), - port->socket.fd); + req_rpc_data->msg_info.buf = buf; - req_rpc_data->msg_info.buf = buf; + body = req_rpc_data->request->body; - body = req_rpc_data->request->body; + if (body != NULL && nxt_buf_is_file(body)) { + req_rpc_data->msg_info.body_fd = body->file->fd; - if (body != NULL && nxt_buf_is_file(body)) { - req_rpc_data->msg_info.body_fd = body->file->fd; + body->file->fd = -1; - body->file->fd = -1; + } else { + req_rpc_data->msg_info.body_fd = -1; + } + + msg.pm.stream = req_rpc_data->stream; + msg.pm.pid = reply_port->pid; + msg.pm.reply_port = reply_port->id; + msg.pm.type = NXT_PORT_MSG_REQ_HEADERS; + msg.pm.last = 0; + msg.pm.mmap = 1; + msg.pm.nf = 0; + msg.pm.mf = 0; + + nxt_port_mmap_handler_t *mmap_handler = buf->parent; + nxt_port_mmap_header_t *hdr = mmap_handler->hdr; + + msg.mm.mmap_id = hdr->id; + msg.mm.chunk_id = nxt_port_mmap_chunk_id(hdr, buf->mem.pos); + msg.mm.size = nxt_buf_used_size(buf); + + res = nxt_app_queue_send(port->queue, &msg, sizeof(msg), req_rpc_data->stream, + ¬ify, &req_rpc_data->msg_info.tracking_cookie); + if (nxt_fast_path(res == NXT_OK)) { + if (notify != 0) { + (void)nxt_port_socket_write(task, port, NXT_PORT_MSG_READ_QUEUE, -1, + req_rpc_data->stream, reply_port->id, NULL); } else { - req_rpc_data->msg_info.body_fd = -1; + nxt_debug(task, "queue is not empty"); } - msg.pm.stream = req_rpc_data->stream; - msg.pm.pid = reply_port->pid; - msg.pm.reply_port = reply_port->id; - msg.pm.type = NXT_PORT_MSG_REQ_HEADERS; - msg.pm.last = 0; - msg.pm.mmap = 1; - msg.pm.nf = 0; - msg.pm.mf = 0; - - nxt_port_mmap_handler_t *mmap_handler = buf->parent; - nxt_port_mmap_header_t *hdr = mmap_handler->hdr; - - msg.mm.mmap_id = hdr->id; - msg.mm.chunk_id = nxt_port_mmap_chunk_id(hdr, buf->mem.pos); - msg.mm.size = nxt_buf_used_size(buf); - - res = nxt_app_queue_send(port->queue, &msg, sizeof(msg), - req_rpc_data->stream, ¬ify, - &req_rpc_data->msg_info.tracking_cookie); - if (nxt_fast_path(res == NXT_OK)) { - if (notify != 0) { - (void) nxt_port_socket_write(task, port, - NXT_PORT_MSG_READ_QUEUE, - -1, req_rpc_data->stream, - reply_port->id, NULL); - - } else { - nxt_debug(task, "queue is not empty"); - } - - buf->is_port_mmap_sent = 1; - buf->mem.pos = buf->mem.free; + buf->is_port_mmap_sent = 1; + buf->mem.pos = buf->mem.free; - } else { - nxt_alert(task, "stream #%uD, app '%V': failed to send app message", - req_rpc_data->stream, &app->name); + } else { + nxt_alert(task, "stream #%uD, app '%V': failed to send app message", + req_rpc_data->stream, &app->name); - nxt_http_request_error(task, req_rpc_data->request, - NXT_HTTP_INTERNAL_SERVER_ERROR); - } + nxt_http_request_error(task, req_rpc_data->request, + NXT_HTTP_INTERNAL_SERVER_ERROR); + } } - struct nxt_fields_iter_s { - nxt_list_part_t *part; - nxt_http_field_t *field; + nxt_list_part_t *part; + nxt_http_field_t *field; }; -typedef struct nxt_fields_iter_s nxt_fields_iter_t; +typedef struct nxt_fields_iter_s nxt_fields_iter_t; +static nxt_http_field_t *nxt_fields_part_first(nxt_list_part_t *part, + nxt_fields_iter_t *i) { + if (part == NULL) { + return NULL; + } -static nxt_http_field_t * -nxt_fields_part_first(nxt_list_part_t *part, nxt_fields_iter_t *i) -{ + while (part->nelts == 0) { + part = part->next; if (part == NULL) { - return NULL; - } - - while (part->nelts == 0) { - part = part->next; - if (part == NULL) { - return NULL; - } + return NULL; } + } - i->part = part; - i->field = nxt_list_data(i->part); + i->part = part; + i->field = nxt_list_data(i->part); - return i->field; + return i->field; } - -static nxt_http_field_t * -nxt_fields_first(nxt_list_t *fields, nxt_fields_iter_t *i) -{ - return nxt_fields_part_first(nxt_list_part(fields), i); +static nxt_http_field_t *nxt_fields_first(nxt_list_t *fields, + nxt_fields_iter_t *i) { + return nxt_fields_part_first(nxt_list_part(fields), i); } +static nxt_http_field_t *nxt_fields_next(nxt_fields_iter_t *i) { + nxt_http_field_t *end = nxt_list_data(i->part); -static nxt_http_field_t * -nxt_fields_next(nxt_fields_iter_t *i) -{ - nxt_http_field_t *end = nxt_list_data(i->part); + end += i->part->nelts; + i->field++; - end += i->part->nelts; - i->field++; - - if (i->field < end) { - return i->field; - } + if (i->field < end) { + return i->field; + } - return nxt_fields_part_first(i->part->next, i); + return nxt_fields_part_first(i->part->next, i); } +static nxt_buf_t *nxt_router_prepare_msg(nxt_task_t *task, + nxt_http_request_t *r, nxt_app_t *app, + const nxt_str_t *prefix) { + void *target_pos, *query_pos; + u_char *pos, *end, *p, c; + size_t fields_count, req_size, size, free_size; + size_t copy_size; + nxt_off_t content_length; + nxt_buf_t *b, *buf, *out, **tail; + nxt_http_field_t *field, *dup; + nxt_unit_field_t *dst_field; + nxt_fields_iter_t iter, dup_iter; + nxt_unit_request_t *req; + + req_size = sizeof(nxt_unit_request_t) + r->method->length + 1 + + r->version.length + 1 + r->remote->address_length + 1 + + r->local->address_length + 1 + nxt_sockaddr_port_length(r->local) + + 1 + r->server_name.length + 1 + r->target.length + 1 + + (r->path->start != r->target.start ? r->path->length + 1 : 0); + + content_length = r->content_length_n < 0 ? 0 : r->content_length_n; + fields_count = 0; + + nxt_list_each(field, r->fields) { + fields_count++; + + req_size += + field->name_length + prefix->length + 1 + field->value_length + 1; + } + nxt_list_loop; + + req_size += fields_count * sizeof(nxt_unit_field_t); + + if (nxt_slow_path(req_size > PORT_MMAP_DATA_SIZE)) { + nxt_alert(task, "headers to big to fit in shared memory (%d)", + (int)req_size); -static nxt_buf_t * -nxt_router_prepare_msg(nxt_task_t *task, nxt_http_request_t *r, - nxt_app_t *app, const nxt_str_t *prefix) -{ - void *target_pos, *query_pos; - u_char *pos, *end, *p, c; - size_t fields_count, req_size, size, free_size; - size_t copy_size; - nxt_off_t content_length; - nxt_buf_t *b, *buf, *out, **tail; - nxt_http_field_t *field, *dup; - nxt_unit_field_t *dst_field; - nxt_fields_iter_t iter, dup_iter; - nxt_unit_request_t *req; - - req_size = sizeof(nxt_unit_request_t) - + r->method->length + 1 - + r->version.length + 1 - + r->remote->address_length + 1 - + r->local->address_length + 1 - + nxt_sockaddr_port_length(r->local) + 1 - + r->server_name.length + 1 - + r->target.length + 1 - + (r->path->start != r->target.start ? r->path->length + 1 : 0); - - content_length = r->content_length_n < 0 ? 0 : r->content_length_n; - fields_count = 0; - - nxt_list_each(field, r->fields) { - fields_count++; - - req_size += field->name_length + prefix->length + 1 - + field->value_length + 1; - } nxt_list_loop; - - req_size += fields_count * sizeof(nxt_unit_field_t); - - if (nxt_slow_path(req_size > PORT_MMAP_DATA_SIZE)) { - nxt_alert(task, "headers to big to fit in shared memory (%d)", - (int) req_size); - - return NULL; - } - - out = nxt_port_mmap_get_buf(task, &app->outgoing, - nxt_min(req_size + content_length, PORT_MMAP_DATA_SIZE)); - if (nxt_slow_path(out == NULL)) { - return NULL; - } - - req = (nxt_unit_request_t *) out->mem.free; - out->mem.free += req_size; - - req->app_target = r->app_target; + return NULL; + } - req->content_length = content_length; + out = nxt_port_mmap_get_buf( + task, &app->outgoing, + nxt_min(req_size + content_length, PORT_MMAP_DATA_SIZE)); + if (nxt_slow_path(out == NULL)) { + return NULL; + } - p = (u_char *) (req->fields + fields_count); + req = (nxt_unit_request_t *)out->mem.free; + out->mem.free += req_size; - nxt_debug(task, "fields_count=%d", (int) fields_count); + req->app_target = r->app_target; - req->method_length = r->method->length; - nxt_unit_sptr_set(&req->method, p); - p = nxt_cpymem(p, r->method->start, r->method->length); - *p++ = '\0'; + req->content_length = content_length; - req->version_length = r->version.length; - nxt_unit_sptr_set(&req->version, p); - p = nxt_cpymem(p, r->version.start, r->version.length); - *p++ = '\0'; + p = (u_char *)(req->fields + fields_count); - req->remote_length = r->remote->address_length; - nxt_unit_sptr_set(&req->remote, p); - p = nxt_cpymem(p, nxt_sockaddr_address(r->remote), - r->remote->address_length); - *p++ = '\0'; + nxt_debug(task, "fields_count=%d", (int)fields_count); - req->local_addr_length = r->local->address_length; - nxt_unit_sptr_set(&req->local_addr, p); - p = nxt_cpymem(p, nxt_sockaddr_address(r->local), r->local->address_length); - *p++ = '\0'; + req->method_length = r->method->length; + nxt_unit_sptr_set(&req->method, p); + p = nxt_cpymem(p, r->method->start, r->method->length); + *p++ = '\0'; - req->local_port_length = nxt_sockaddr_port_length(r->local); - nxt_unit_sptr_set(&req->local_port, p); - p = nxt_cpymem(p, nxt_sockaddr_port(r->local), - nxt_sockaddr_port_length(r->local)); - *p++ = '\0'; + req->version_length = r->version.length; + nxt_unit_sptr_set(&req->version, p); + p = nxt_cpymem(p, r->version.start, r->version.length); + *p++ = '\0'; - req->tls = r->tls; - req->websocket_handshake = r->websocket_handshake; + req->remote_length = r->remote->address_length; + nxt_unit_sptr_set(&req->remote, p); + p = nxt_cpymem(p, nxt_sockaddr_address(r->remote), r->remote->address_length); + *p++ = '\0'; - req->server_name_length = r->server_name.length; - nxt_unit_sptr_set(&req->server_name, p); - p = nxt_cpymem(p, r->server_name.start, r->server_name.length); - *p++ = '\0'; + req->local_addr_length = r->local->address_length; + nxt_unit_sptr_set(&req->local_addr, p); + p = nxt_cpymem(p, nxt_sockaddr_address(r->local), r->local->address_length); + *p++ = '\0'; - target_pos = p; - req->target_length = (uint32_t) r->target.length; - nxt_unit_sptr_set(&req->target, p); - p = nxt_cpymem(p, r->target.start, r->target.length); - *p++ = '\0'; + req->local_port_length = nxt_sockaddr_port_length(r->local); + nxt_unit_sptr_set(&req->local_port, p); + p = nxt_cpymem(p, nxt_sockaddr_port(r->local), + nxt_sockaddr_port_length(r->local)); + *p++ = '\0'; - req->path_length = (uint32_t) r->path->length; - if (r->path->start == r->target.start) { - nxt_unit_sptr_set(&req->path, target_pos); + req->tls = r->tls; + req->websocket_handshake = r->websocket_handshake; - } else { - nxt_unit_sptr_set(&req->path, p); - p = nxt_cpymem(p, r->path->start, r->path->length); - *p++ = '\0'; - } + req->server_name_length = r->server_name.length; + nxt_unit_sptr_set(&req->server_name, p); + p = nxt_cpymem(p, r->server_name.start, r->server_name.length); + *p++ = '\0'; - req->query_length = (uint32_t) r->args->length; - if (r->args->start != NULL) { - query_pos = nxt_pointer_to(target_pos, - r->args->start - r->target.start); + target_pos = p; + req->target_length = (uint32_t)r->target.length; + nxt_unit_sptr_set(&req->target, p); + p = nxt_cpymem(p, r->target.start, r->target.length); + *p++ = '\0'; - nxt_unit_sptr_set(&req->query, query_pos); + req->path_length = (uint32_t)r->path->length; + if (r->path->start == r->target.start) { + nxt_unit_sptr_set(&req->path, target_pos); - } else { - req->query.offset = 0; - } + } else { + nxt_unit_sptr_set(&req->path, p); + p = nxt_cpymem(p, r->path->start, r->path->length); + *p++ = '\0'; + } - req->content_length_field = NXT_UNIT_NONE_FIELD; - req->content_type_field = NXT_UNIT_NONE_FIELD; - req->cookie_field = NXT_UNIT_NONE_FIELD; - req->authorization_field = NXT_UNIT_NONE_FIELD; + req->query_length = (uint32_t)r->args->length; + if (r->args->start != NULL) { + query_pos = nxt_pointer_to(target_pos, r->args->start - r->target.start); - dst_field = req->fields; + nxt_unit_sptr_set(&req->query, query_pos); - for (field = nxt_fields_first(r->fields, &iter); - field != NULL; - field = nxt_fields_next(&iter)) - { - if (field->skip) { - continue; - } + } else { + req->query.offset = 0; + } - dst_field->hash = field->hash; - dst_field->skip = 0; - dst_field->name_length = field->name_length + prefix->length; - dst_field->value_length = field->value_length; + req->content_length_field = NXT_UNIT_NONE_FIELD; + req->content_type_field = NXT_UNIT_NONE_FIELD; + req->cookie_field = NXT_UNIT_NONE_FIELD; + req->authorization_field = NXT_UNIT_NONE_FIELD; - if (field == r->content_length) { - req->content_length_field = dst_field - req->fields; + dst_field = req->fields; - } else if (field == r->content_type) { - req->content_type_field = dst_field - req->fields; + for (field = nxt_fields_first(r->fields, &iter); field != NULL; + field = nxt_fields_next(&iter)) { + if (field->skip) { + continue; + } - } else if (field == r->cookie) { - req->cookie_field = dst_field - req->fields; + dst_field->hash = field->hash; + dst_field->skip = 0; + dst_field->name_length = field->name_length + prefix->length; + dst_field->value_length = field->value_length; - } else if (field == r->authorization) { - req->authorization_field = dst_field - req->fields; - } + if (field == r->content_length) { + req->content_length_field = dst_field - req->fields; - nxt_debug(task, "add field 0x%04Xd, %d, %d, %p : %d %p", - (int) field->hash, (int) field->skip, - (int) field->name_length, field->name, - (int) field->value_length, field->value); + } else if (field == r->content_type) { + req->content_type_field = dst_field - req->fields; - if (prefix->length != 0) { - nxt_unit_sptr_set(&dst_field->name, p); - p = nxt_cpymem(p, prefix->start, prefix->length); + } else if (field == r->cookie) { + req->cookie_field = dst_field - req->fields; - end = field->name + field->name_length; - for (pos = field->name; pos < end; pos++) { - c = *pos; + } else if (field == r->authorization) { + req->authorization_field = dst_field - req->fields; + } - if (c >= 'a' && c <= 'z') { - *p++ = (c & ~0x20); - continue; - } + nxt_debug(task, "add field 0x%04Xd, %d, %d, %p : %d %p", (int)field->hash, + (int)field->skip, (int)field->name_length, field->name, + (int)field->value_length, field->value); - if (c == '-') { - *p++ = '_'; - continue; - } + if (prefix->length != 0) { + nxt_unit_sptr_set(&dst_field->name, p); + p = nxt_cpymem(p, prefix->start, prefix->length); - *p++ = c; - } + end = field->name + field->name_length; + for (pos = field->name; pos < end; pos++) { + c = *pos; - } else { - nxt_unit_sptr_set(&dst_field->name, p); - p = nxt_cpymem(p, field->name, field->name_length); + if (c >= 'a' && c <= 'z') { + *p++ = (c & ~0x20); + continue; } - *p++ = '\0'; + if (c == '-') { + *p++ = '_'; + continue; + } - nxt_unit_sptr_set(&dst_field->value, p); - p = nxt_cpymem(p, field->value, field->value_length); + *p++ = c; + } - if (prefix->length != 0) { - dup_iter = iter; + } else { + nxt_unit_sptr_set(&dst_field->name, p); + p = nxt_cpymem(p, field->name, field->name_length); + } - for (dup = nxt_fields_next(&dup_iter); - dup != NULL; - dup = nxt_fields_next(&dup_iter)) - { - if (dup->name_length != field->name_length - || dup->skip - || dup->hash != field->hash - || nxt_memcasecmp(dup->name, field->name, dup->name_length)) - { - continue; - } + *p++ = '\0'; - p = nxt_cpymem(p, ", ", 2); - p = nxt_cpymem(p, dup->value, dup->value_length); + nxt_unit_sptr_set(&dst_field->value, p); + p = nxt_cpymem(p, field->value, field->value_length); - dst_field->value_length += 2 + dup->value_length; + if (prefix->length != 0) { + dup_iter = iter; - dup->skip = 1; - } + for (dup = nxt_fields_next(&dup_iter); dup != NULL; + dup = nxt_fields_next(&dup_iter)) { + if (dup->name_length != field->name_length || dup->skip || + dup->hash != field->hash || + nxt_memcasecmp(dup->name, field->name, dup->name_length)) { + continue; } - *p++ = '\0'; + p = nxt_cpymem(p, ", ", 2); + p = nxt_cpymem(p, dup->value, dup->value_length); + + dst_field->value_length += 2 + dup->value_length; - dst_field++; + dup->skip = 1; + } } - req->fields_count = (uint32_t) (dst_field - req->fields); + *p++ = '\0'; + + dst_field++; + } - nxt_unit_sptr_set(&req->preread_content, out->mem.free); + req->fields_count = (uint32_t)(dst_field - req->fields); - buf = out; - tail = &buf->next; + nxt_unit_sptr_set(&req->preread_content, out->mem.free); - for (b = r->body; b != NULL; b = b->next) { - size = nxt_buf_mem_used_size(&b->mem); - pos = b->mem.pos; + buf = out; + tail = &buf->next; - while (size > 0) { - if (buf == NULL) { - free_size = nxt_min(size, PORT_MMAP_DATA_SIZE); + for (b = r->body; b != NULL; b = b->next) { + size = nxt_buf_mem_used_size(&b->mem); + pos = b->mem.pos; - buf = nxt_port_mmap_get_buf(task, &app->outgoing, free_size); - if (nxt_slow_path(buf == NULL)) { - while (out != NULL) { - buf = out->next; - out->next = NULL; - out->completion_handler(task, out, out->parent); - out = buf; - } - return NULL; - } + while (size > 0) { + if (buf == NULL) { + free_size = nxt_min(size, PORT_MMAP_DATA_SIZE); - *tail = buf; - tail = &buf->next; + buf = nxt_port_mmap_get_buf(task, &app->outgoing, free_size); + if (nxt_slow_path(buf == NULL)) { + while (out != NULL) { + buf = out->next; + out->next = NULL; + out->completion_handler(task, out, out->parent); + out = buf; + } + return NULL; + } - } else { - free_size = nxt_buf_mem_free_size(&buf->mem); - if (free_size < size - && nxt_port_mmap_increase_buf(task, buf, size, 1) - == NXT_OK) - { - free_size = nxt_buf_mem_free_size(&buf->mem); - } - } + *tail = buf; + tail = &buf->next; - if (free_size > 0) { - copy_size = nxt_min(free_size, size); + } else { + free_size = nxt_buf_mem_free_size(&buf->mem); + if (free_size < size && + nxt_port_mmap_increase_buf(task, buf, size, 1) == NXT_OK) { + free_size = nxt_buf_mem_free_size(&buf->mem); + } + } - buf->mem.free = nxt_cpymem(buf->mem.free, pos, copy_size); + if (free_size > 0) { + copy_size = nxt_min(free_size, size); - size -= copy_size; - pos += copy_size; + buf->mem.free = nxt_cpymem(buf->mem.free, pos, copy_size); - if (size == 0) { - break; - } - } + size -= copy_size; + pos += copy_size; - buf = NULL; + if (size == 0) { + break; } + } + + buf = NULL; } + } - return out; + return out; } +static void nxt_router_app_timeout(nxt_task_t *task, void *obj, void *data) { + nxt_timer_t *timer; + nxt_http_request_t *r; + nxt_request_rpc_data_t *req_rpc_data; -static void -nxt_router_app_timeout(nxt_task_t *task, void *obj, void *data) -{ - nxt_timer_t *timer; - nxt_http_request_t *r; - nxt_request_rpc_data_t *req_rpc_data; - - timer = obj; + timer = obj; - nxt_debug(task, "router app timeout"); + nxt_debug(task, "router app timeout"); - r = nxt_timer_data(timer, nxt_http_request_t, timer); - req_rpc_data = r->timer_data; + r = nxt_timer_data(timer, nxt_http_request_t, timer); + req_rpc_data = r->timer_data; - nxt_http_request_error(task, r, NXT_HTTP_SERVICE_UNAVAILABLE); + nxt_http_request_error(task, r, NXT_HTTP_SERVICE_UNAVAILABLE); - nxt_request_rpc_data_unlink(task, req_rpc_data); + nxt_request_rpc_data_unlink(task, req_rpc_data); } - -static void -nxt_router_http_request_release_post(nxt_task_t *task, nxt_http_request_t *r) -{ - r->timer.handler = nxt_router_http_request_release; - nxt_timer_add(task->thread->engine, &r->timer, 0); +static void nxt_router_http_request_release_post(nxt_task_t *task, + nxt_http_request_t *r) { + r->timer.handler = nxt_router_http_request_release; + nxt_timer_add(task->thread->engine, &r->timer, 0); } +static void nxt_router_http_request_release(nxt_task_t *task, void *obj, + void *data) { + nxt_http_request_t *r; -static void -nxt_router_http_request_release(nxt_task_t *task, void *obj, void *data) -{ - nxt_http_request_t *r; - - nxt_debug(task, "http request pool release"); + nxt_debug(task, "http request pool release"); - r = nxt_timer_data(obj, nxt_http_request_t, timer); + r = nxt_timer_data(obj, nxt_http_request_t, timer); - nxt_mp_release(r->mem_pool); + nxt_mp_release(r->mem_pool); } +static void nxt_router_oosm_handler(nxt_task_t *task, + nxt_port_recv_msg_t *msg) { + size_t mi; + uint32_t i; + nxt_bool_t ack; + nxt_process_t *process; + nxt_free_map_t *m; + nxt_port_mmap_handler_t *mmap_handler; -static void -nxt_router_oosm_handler(nxt_task_t *task, nxt_port_recv_msg_t *msg) -{ - size_t mi; - uint32_t i; - nxt_bool_t ack; - nxt_process_t *process; - nxt_free_map_t *m; - nxt_port_mmap_handler_t *mmap_handler; - - nxt_debug(task, "oosm in %PI", msg->port_msg.pid); - - process = nxt_runtime_process_find(task->thread->runtime, - msg->port_msg.pid); - if (nxt_slow_path(process == NULL)) { - return; - } - - ack = 0; + nxt_debug(task, "oosm in %PI", msg->port_msg.pid); - /* - * To mitigate possible racing condition (when OOSM message received - * after some of the memory was already freed), need to try to find - * first free segment in shared memory and send ACK if found. - */ + process = nxt_runtime_process_find(task->thread->runtime, msg->port_msg.pid); + if (nxt_slow_path(process == NULL)) { + return; + } - nxt_thread_mutex_lock(&process->incoming.mutex); + ack = 0; - for (i = 0; i < process->incoming.size; i++) { - mmap_handler = process->incoming.elts[i].mmap_handler; + /* + * To mitigate possible racing condition (when OOSM message received + * after some of the memory was already freed), need to try to find + * first free segment in shared memory and send ACK if found. + */ - if (nxt_slow_path(mmap_handler == NULL)) { - continue; - } + nxt_thread_mutex_lock(&process->incoming.mutex); - m = mmap_handler->hdr->free_map; + for (i = 0; i < process->incoming.size; i++) { + mmap_handler = process->incoming.elts[i].mmap_handler; - for (mi = 0; mi < MAX_FREE_IDX; mi++) { - if (m[mi] != 0) { - ack = 1; + if (nxt_slow_path(mmap_handler == NULL)) { + continue; + } - nxt_debug(task, "oosm: already free #%uD %uz = 0x%08xA", - i, mi, m[mi]); + m = mmap_handler->hdr->free_map; - break; - } - } - } + for (mi = 0; mi < MAX_FREE_IDX; mi++) { + if (m[mi] != 0) { + ack = 1; - nxt_thread_mutex_unlock(&process->incoming.mutex); + nxt_debug(task, "oosm: already free #%uD %uz = 0x%08xA", i, mi, m[mi]); - if (ack) { - nxt_process_broadcast_shm_ack(task, process); + break; + } } -} + } + nxt_thread_mutex_unlock(&process->incoming.mutex); -static void -nxt_router_get_mmap_handler(nxt_task_t *task, nxt_port_recv_msg_t *msg) -{ - nxt_fd_t fd; - nxt_port_t *port; - nxt_runtime_t *rt; - nxt_port_mmaps_t *mmaps; - nxt_port_msg_get_mmap_t *get_mmap_msg; - nxt_port_mmap_handler_t *mmap_handler; - - rt = task->thread->runtime; + if (ack) { + nxt_process_broadcast_shm_ack(task, process); + } +} - port = nxt_runtime_port_find(rt, msg->port_msg.pid, - msg->port_msg.reply_port); - if (nxt_slow_path(port == NULL)) { - nxt_alert(task, "get_mmap_handler: reply_port %PI:%d not found", - msg->port_msg.pid, msg->port_msg.reply_port); +static void nxt_router_get_mmap_handler(nxt_task_t *task, + nxt_port_recv_msg_t *msg) { + nxt_fd_t fd; + nxt_port_t *port; + nxt_runtime_t *rt; + nxt_port_mmaps_t *mmaps; + nxt_port_msg_get_mmap_t *get_mmap_msg; + nxt_port_mmap_handler_t *mmap_handler; + + rt = task->thread->runtime; + + port = nxt_runtime_port_find(rt, msg->port_msg.pid, msg->port_msg.reply_port); + if (nxt_slow_path(port == NULL)) { + nxt_alert(task, "get_mmap_handler: reply_port %PI:%d not found", + msg->port_msg.pid, msg->port_msg.reply_port); - return; - } + return; + } - if (nxt_slow_path(nxt_buf_used_size(msg->buf) - < (int) sizeof(nxt_port_msg_get_mmap_t))) - { - nxt_alert(task, "get_mmap_handler: message buffer too small (%d)", - (int) nxt_buf_used_size(msg->buf)); + if (nxt_slow_path(nxt_buf_used_size(msg->buf) < + (int)sizeof(nxt_port_msg_get_mmap_t))) { + nxt_alert(task, "get_mmap_handler: message buffer too small (%d)", + (int)nxt_buf_used_size(msg->buf)); - return; - } + return; + } - get_mmap_msg = (nxt_port_msg_get_mmap_t *) msg->buf->mem.pos; + get_mmap_msg = (nxt_port_msg_get_mmap_t *)msg->buf->mem.pos; - nxt_assert(port->type == NXT_PROCESS_APP); + nxt_assert(port->type == NXT_PROCESS_APP); - if (nxt_slow_path(port->app == NULL)) { - nxt_alert(task, "get_mmap_handler: app == NULL for reply port %PI:%d", - port->pid, port->id); + if (nxt_slow_path(port->app == NULL)) { + nxt_alert(task, "get_mmap_handler: app == NULL for reply port %PI:%d", + port->pid, port->id); - // FIXME - nxt_port_socket_write(task, port, NXT_PORT_MSG_RPC_ERROR, - -1, msg->port_msg.stream, 0, NULL); + // FIXME + nxt_port_socket_write(task, port, NXT_PORT_MSG_RPC_ERROR, -1, + msg->port_msg.stream, 0, NULL); - return; - } + return; + } - mmaps = &port->app->outgoing; - nxt_thread_mutex_lock(&mmaps->mutex); + mmaps = &port->app->outgoing; + nxt_thread_mutex_lock(&mmaps->mutex); - if (nxt_slow_path(get_mmap_msg->id >= mmaps->size)) { - nxt_thread_mutex_unlock(&mmaps->mutex); + if (nxt_slow_path(get_mmap_msg->id >= mmaps->size)) { + nxt_thread_mutex_unlock(&mmaps->mutex); - nxt_alert(task, "get_mmap_handler: mmap id is too big (%d)", - (int) get_mmap_msg->id); + nxt_alert(task, "get_mmap_handler: mmap id is too big (%d)", + (int)get_mmap_msg->id); - // FIXME - nxt_port_socket_write(task, port, NXT_PORT_MSG_RPC_ERROR, - -1, msg->port_msg.stream, 0, NULL); - return; - } + // FIXME + nxt_port_socket_write(task, port, NXT_PORT_MSG_RPC_ERROR, -1, + msg->port_msg.stream, 0, NULL); + return; + } - mmap_handler = mmaps->elts[get_mmap_msg->id].mmap_handler; + mmap_handler = mmaps->elts[get_mmap_msg->id].mmap_handler; - fd = mmap_handler->fd; + fd = mmap_handler->fd; - nxt_thread_mutex_unlock(&mmaps->mutex); + nxt_thread_mutex_unlock(&mmaps->mutex); - nxt_debug(task, "get mmap %PI:%d found", - msg->port_msg.pid, (int) get_mmap_msg->id); + nxt_debug(task, "get mmap %PI:%d found", msg->port_msg.pid, + (int)get_mmap_msg->id); - (void) nxt_port_socket_write(task, port, NXT_PORT_MSG_MMAP, fd, 0, 0, NULL); + (void)nxt_port_socket_write(task, port, NXT_PORT_MSG_MMAP, fd, 0, 0, NULL); } +static void nxt_router_get_port_handler(nxt_task_t *task, + nxt_port_recv_msg_t *msg) { + nxt_port_t *port, *reply_port; + nxt_runtime_t *rt; + nxt_port_msg_get_port_t *get_port_msg; -static void -nxt_router_get_port_handler(nxt_task_t *task, nxt_port_recv_msg_t *msg) -{ - nxt_port_t *port, *reply_port; - nxt_runtime_t *rt; - nxt_port_msg_get_port_t *get_port_msg; - - rt = task->thread->runtime; + rt = task->thread->runtime; - reply_port = nxt_runtime_port_find(rt, msg->port_msg.pid, - msg->port_msg.reply_port); - if (nxt_slow_path(reply_port == NULL)) { - nxt_alert(task, "get_port_handler: reply_port %PI:%d not found", - msg->port_msg.pid, msg->port_msg.reply_port); + reply_port = + nxt_runtime_port_find(rt, msg->port_msg.pid, msg->port_msg.reply_port); + if (nxt_slow_path(reply_port == NULL)) { + nxt_alert(task, "get_port_handler: reply_port %PI:%d not found", + msg->port_msg.pid, msg->port_msg.reply_port); - return; - } + return; + } - if (nxt_slow_path(nxt_buf_used_size(msg->buf) - < (int) sizeof(nxt_port_msg_get_port_t))) - { - nxt_alert(task, "get_port_handler: message buffer too small (%d)", - (int) nxt_buf_used_size(msg->buf)); + if (nxt_slow_path(nxt_buf_used_size(msg->buf) < + (int)sizeof(nxt_port_msg_get_port_t))) { + nxt_alert(task, "get_port_handler: message buffer too small (%d)", + (int)nxt_buf_used_size(msg->buf)); - return; - } + return; + } - get_port_msg = (nxt_port_msg_get_port_t *) msg->buf->mem.pos; + get_port_msg = (nxt_port_msg_get_port_t *)msg->buf->mem.pos; - port = nxt_runtime_port_find(rt, get_port_msg->pid, get_port_msg->id); - if (nxt_slow_path(port == NULL)) { - nxt_alert(task, "get_port_handler: port %PI:%d not found", - get_port_msg->pid, get_port_msg->id); + port = nxt_runtime_port_find(rt, get_port_msg->pid, get_port_msg->id); + if (nxt_slow_path(port == NULL)) { + nxt_alert(task, "get_port_handler: port %PI:%d not found", + get_port_msg->pid, get_port_msg->id); - return; - } + return; + } - nxt_debug(task, "get port %PI:%d found", get_port_msg->pid, - get_port_msg->id); + nxt_debug(task, "get port %PI:%d found", get_port_msg->pid, get_port_msg->id); - (void) nxt_port_send_port(task, reply_port, port, msg->port_msg.stream); + (void)nxt_port_send_port(task, reply_port, port, msg->port_msg.stream); } diff --git a/src/nxt_router.h b/src/nxt_router.h index 06c6bb32a..2cca634ed 100644 --- a/src/nxt_router.h +++ b/src/nxt_router.h @@ -7,265 +7,250 @@ #ifndef _NXT_ROUTER_H_INCLUDED_ #define _NXT_ROUTER_H_INCLUDED_ - #include #include #include -typedef struct nxt_http_request_s nxt_http_request_t; +typedef struct nxt_http_request_s nxt_http_request_t; #include +typedef struct nxt_http_action_s nxt_http_action_t; +typedef struct nxt_http_routes_s nxt_http_routes_t; +typedef struct nxt_http_forward_s nxt_http_forward_t; +typedef struct nxt_upstream_s nxt_upstream_t; +typedef struct nxt_upstreams_s nxt_upstreams_t; +typedef struct nxt_router_access_log_s nxt_router_access_log_t; -typedef struct nxt_http_action_s nxt_http_action_t; -typedef struct nxt_http_routes_s nxt_http_routes_t; -typedef struct nxt_http_forward_s nxt_http_forward_t; -typedef struct nxt_upstream_s nxt_upstream_t; -typedef struct nxt_upstreams_s nxt_upstreams_t; -typedef struct nxt_router_access_log_s nxt_router_access_log_t; - - -#define NXT_HTTP_ACTION_ERROR ((nxt_http_action_t *) -1) - +#define NXT_HTTP_ACTION_ERROR ((nxt_http_action_t *)-1) typedef struct { - nxt_thread_spinlock_t lock; - nxt_queue_t engines; + nxt_thread_spinlock_t lock; + nxt_queue_t engines; - nxt_queue_t sockets; /* of nxt_socket_conf_t */ - nxt_queue_t apps; /* of nxt_app_t */ + nxt_queue_t sockets; /* of nxt_socket_conf_t */ + nxt_queue_t apps; /* of nxt_app_t */ - nxt_router_access_log_t *access_log; + nxt_router_access_log_t *access_log; } nxt_router_t; - typedef struct { - uint32_t count; - uint32_t threads; + uint32_t count; + uint32_t threads; - nxt_mp_t *mem_pool; - nxt_tstr_state_t *tstr_state; + nxt_mp_t *mem_pool; + nxt_tstr_state_t *tstr_state; - nxt_router_t *router; - nxt_http_routes_t *routes; - nxt_upstreams_t *upstreams; + nxt_router_t *router; + nxt_http_routes_t *routes; + nxt_upstreams_t *upstreams; - nxt_lvlhsh_t mtypes_hash; - nxt_lvlhsh_t apps_hash; + nxt_lvlhsh_t mtypes_hash; + nxt_lvlhsh_t apps_hash; - nxt_router_access_log_t *access_log; - nxt_tstr_t *log_format; - nxt_tstr_cond_t log_cond; + nxt_router_access_log_t *access_log; + nxt_tstr_t *log_format; + nxt_tstr_cond_t log_cond; } nxt_router_conf_t; - typedef struct { - nxt_event_engine_t *engine; - nxt_work_t *jobs; - - enum { - NXT_ROUTER_ENGINE_KEEP = 0, - NXT_ROUTER_ENGINE_ADD, - NXT_ROUTER_ENGINE_DELETE, - } action; + nxt_event_engine_t *engine; + nxt_work_t *jobs; + + enum { + NXT_ROUTER_ENGINE_KEEP = 0, + NXT_ROUTER_ENGINE_ADD, + NXT_ROUTER_ENGINE_DELETE, + } action; } nxt_router_engine_conf_t; - typedef struct { #if (NXT_TLS) - nxt_queue_t tls; /* of nxt_router_tlssock_t */ + nxt_queue_t tls; /* of nxt_router_tlssock_t */ #endif #if (NXT_HAVE_NJS) - nxt_queue_t js_modules; + nxt_queue_t js_modules; #endif - nxt_queue_t apps; /* of nxt_app_t */ - nxt_queue_t previous; /* of nxt_app_t */ + nxt_queue_t apps; /* of nxt_app_t */ + nxt_queue_t previous; /* of nxt_app_t */ - uint32_t new_threads; - uint32_t stream; - uint32_t count; + uint32_t new_threads; + uint32_t stream; + uint32_t count; - nxt_event_engine_t *engine; - nxt_port_t *port; - nxt_array_t *engines; - nxt_router_conf_t *router_conf; - nxt_mp_t *mem_pool; + nxt_event_engine_t *engine; + nxt_port_t *port; + nxt_array_t *engines; + nxt_router_conf_t *router_conf; + nxt_mp_t *mem_pool; } nxt_router_temp_conf_t; - typedef struct { - nxt_task_t task; - nxt_work_t work; - nxt_router_temp_conf_t *tmcf; + nxt_task_t task; + nxt_work_t work; + nxt_router_temp_conf_t *tmcf; } nxt_joint_job_t; - typedef struct { - uint32_t use_count; - nxt_app_t *app; - nxt_timer_t idle_timer; - nxt_work_t free_app_work; + uint32_t use_count; + nxt_app_t *app; + nxt_timer_t idle_timer; + nxt_work_t free_app_work; } nxt_app_joint_t; - struct nxt_app_s { - nxt_thread_mutex_t mutex; /* Protects ports queue. */ - nxt_queue_t ports; /* of nxt_port_t.app_link */ - nxt_lvlhsh_t port_hash; /* of nxt_port_t */ + nxt_thread_mutex_t mutex; /* Protects ports queue. */ + nxt_queue_t ports; /* of nxt_port_t.app_link */ + nxt_lvlhsh_t port_hash; /* of nxt_port_t */ - nxt_queue_t spare_ports; /* of nxt_port_t.idle_link */ - nxt_queue_t idle_ports; /* of nxt_port_t.idle_link */ - nxt_work_t adjust_idle_work; - nxt_event_engine_t *engine; + nxt_queue_t spare_ports; /* of nxt_port_t.idle_link */ + nxt_queue_t idle_ports; /* of nxt_port_t.idle_link */ + nxt_work_t adjust_idle_work; + nxt_event_engine_t *engine; - nxt_str_t name; + nxt_str_t name; - uint32_t port_hash_count; + uint32_t port_hash_count; - uint32_t active_requests; - uint32_t pending_processes; - uint32_t processes; - uint32_t idle_processes; + uint32_t active_requests; + uint32_t pending_processes; + uint32_t processes; + uint32_t idle_processes; - uint32_t max_processes; - uint32_t spare_processes; - uint32_t max_pending_processes; + uint32_t max_processes; + uint32_t spare_processes; + uint32_t max_pending_processes; - uint32_t generation; - uint32_t proto_port_requests; + uint32_t generation; + uint32_t proto_port_requests; - nxt_msec_t timeout; - nxt_msec_t idle_timeout; + nxt_msec_t timeout; + nxt_msec_t idle_timeout; - nxt_str_t *targets; + nxt_str_t *targets; - nxt_app_type_t type:8; + nxt_app_type_t type : 8; - nxt_mp_t *mem_pool; - nxt_queue_link_t link; + nxt_mp_t *mem_pool; + nxt_queue_link_t link; - nxt_str_t conf; + nxt_str_t conf; - nxt_atomic_t use_count; - nxt_queue_t ack_waiting_req; /* of nxt_http_request_t.app_link */ + nxt_atomic_t use_count; + nxt_queue_t ack_waiting_req; /* of nxt_http_request_t.app_link */ - nxt_app_joint_t *joint; - nxt_port_t *shared_port; - nxt_port_t *proto_port; + nxt_app_joint_t *joint; + nxt_port_t *shared_port; + nxt_port_t *proto_port; - nxt_port_mmaps_t outgoing; + nxt_port_mmaps_t outgoing; }; - typedef struct { - size_t max_frame_size; - nxt_msec_t read_timeout; - nxt_msec_t keepalive_interval; + size_t max_frame_size; + nxt_msec_t read_timeout; + nxt_msec_t keepalive_interval; } nxt_websocket_conf_t; - typedef struct { - uint32_t count; - nxt_queue_link_t link; - nxt_router_conf_t *router_conf; + uint32_t count; + nxt_queue_link_t link; + nxt_router_conf_t *router_conf; - nxt_http_action_t *action; + nxt_http_action_t *action; - /* - * A listen socket time can be shorter than socket configuration life - * time, so a copy of the non-wildcard socket sockaddr is stored here - * to be used as a local sockaddr in connections. - */ - nxt_sockaddr_t *sockaddr; + /* + * A listen socket time can be shorter than socket configuration life + * time, so a copy of the non-wildcard socket sockaddr is stored here + * to be used as a local sockaddr in connections. + */ + nxt_sockaddr_t *sockaddr; - nxt_listen_socket_t *listen; + nxt_listen_socket_t *listen; - size_t header_buffer_size; - size_t large_header_buffer_size; - size_t large_header_buffers; - size_t body_buffer_size; - size_t max_body_size; - size_t proxy_header_buffer_size; - size_t proxy_buffer_size; - size_t proxy_buffers; + size_t header_buffer_size; + size_t large_header_buffer_size; + size_t large_header_buffers; + size_t body_buffer_size; + size_t max_body_size; + size_t proxy_header_buffer_size; + size_t proxy_buffer_size; + size_t proxy_buffers; - nxt_msec_t idle_timeout; - nxt_msec_t header_read_timeout; - nxt_msec_t body_read_timeout; - nxt_msec_t send_timeout; - nxt_msec_t proxy_timeout; - nxt_msec_t proxy_send_timeout; - nxt_msec_t proxy_read_timeout; + nxt_msec_t idle_timeout; + nxt_msec_t header_read_timeout; + nxt_msec_t body_read_timeout; + nxt_msec_t send_timeout; + nxt_msec_t proxy_timeout; + nxt_msec_t proxy_send_timeout; + nxt_msec_t proxy_read_timeout; - nxt_websocket_conf_t websocket_conf; + nxt_websocket_conf_t websocket_conf; - nxt_str_t body_temp_path; + nxt_str_t body_temp_path; - uint8_t log_route; /* 1 bit */ + uint8_t log_route; /* 1 bit */ - uint8_t discard_unsafe_fields; /* 1 bit */ + uint8_t discard_unsafe_fields; /* 1 bit */ - uint8_t server_version; /* 1 bit */ - uint8_t chunked_transform; /* 1 bit */ + uint8_t server_version; /* 1 bit */ + uint8_t chunked_transform; /* 1 bit */ - nxt_http_forward_t *forwarded; - nxt_http_forward_t *client_ip; + nxt_http_forward_t *forwarded; + nxt_http_forward_t *client_ip; #if (NXT_TLS) - nxt_tls_conf_t *tls; + nxt_tls_conf_t *tls; #endif } nxt_socket_conf_t; - typedef struct { - uint32_t count; - nxt_queue_link_t link; - nxt_event_engine_t *engine; - nxt_socket_conf_t *socket_conf; + uint32_t count; + nxt_queue_link_t link; + nxt_event_engine_t *engine; + nxt_socket_conf_t *socket_conf; - nxt_joint_job_t *close_job; + nxt_joint_job_t *close_job; - nxt_upstream_t **upstreams; + nxt_upstream_t **upstreams; - /* Modules configuraitons. */ + /* Modules configuraitons. */ } nxt_socket_conf_joint_t; - struct nxt_router_access_log_s { - void (*handler)(nxt_task_t *task, nxt_http_request_t *r, - nxt_router_access_log_t *access_log, - nxt_tstr_t *format); - nxt_fd_t fd; - nxt_str_t path; - uint32_t count; + void (*handler)(nxt_task_t *task, nxt_http_request_t *r, + nxt_router_access_log_t *access_log, nxt_tstr_t *format); + nxt_fd_t fd; + nxt_str_t path; + uint32_t count; }; - void nxt_router_process_http_request(nxt_task_t *task, nxt_http_request_t *r, - nxt_http_action_t *action); + nxt_http_action_t *action); void nxt_router_app_port_close(nxt_task_t *task, nxt_port_t *port); nxt_int_t nxt_router_application_init(nxt_router_conf_t *rtcf, nxt_str_t *name, - nxt_str_t *target, nxt_http_action_t *action); + nxt_str_t *target, + nxt_http_action_t *action); void nxt_router_listen_event_release(nxt_task_t *task, nxt_listen_event_t *lev, - nxt_socket_conf_joint_t *joint); + nxt_socket_conf_joint_t *joint); void nxt_router_conf_apply(nxt_task_t *task, void *obj, void *data); void nxt_router_conf_error(nxt_task_t *task, nxt_router_temp_conf_t *tmcf); void nxt_router_conf_release(nxt_task_t *task, nxt_socket_conf_joint_t *joint); nxt_int_t nxt_router_access_log_create(nxt_task_t *task, - nxt_router_conf_t *rtcf, nxt_conf_value_t *value); + nxt_router_conf_t *rtcf, + nxt_conf_value_t *value); void nxt_router_access_log_open(nxt_task_t *task, nxt_router_temp_conf_t *tmcf); void nxt_router_access_log_use(nxt_thread_spinlock_t *lock, - nxt_router_access_log_t *access_log); + nxt_router_access_log_t *access_log); void nxt_router_access_log_release(nxt_task_t *task, - nxt_thread_spinlock_t *lock, nxt_router_access_log_t *access_log); + nxt_thread_spinlock_t *lock, + nxt_router_access_log_t *access_log); void nxt_router_access_log_reopen_handler(nxt_task_t *task, - nxt_port_recv_msg_t *msg); - - -extern nxt_router_t *nxt_router; + nxt_port_recv_msg_t *msg); +extern nxt_router_t *nxt_router; -#endif /* _NXT_ROUTER_H_INCLUDED_ */ +#endif /* _NXT_ROUTER_H_INCLUDED_ */ diff --git a/src/nxt_router_access_log.c b/src/nxt_router_access_log.c index 024bff395..50fdd9a81 100644 --- a/src/nxt_router_access_log.c +++ b/src/nxt_router_access_log.c @@ -9,38 +9,37 @@ #include #include - typedef struct { - nxt_str_t path; - nxt_str_t format; - nxt_conf_value_t *expr; + nxt_str_t path; + nxt_str_t format; + nxt_conf_value_t *expr; } nxt_router_access_log_conf_t; - typedef struct { - nxt_str_t text; - nxt_router_access_log_t *access_log; + nxt_str_t text; + nxt_router_access_log_t *access_log; } nxt_router_access_log_ctx_t; - static void nxt_router_access_log_writer(nxt_task_t *task, - nxt_http_request_t *r, nxt_router_access_log_t *access_log, - nxt_tstr_t *format); + nxt_http_request_t *r, + nxt_router_access_log_t *access_log, + nxt_tstr_t *format); static void nxt_router_access_log_write(nxt_task_t *task, nxt_http_request_t *r, - nxt_router_access_log_ctx_t *ctx); + nxt_router_access_log_ctx_t *ctx); static void nxt_router_access_log_ready(nxt_task_t *task, - nxt_port_recv_msg_t *msg, void *data); + nxt_port_recv_msg_t *msg, void *data); static void nxt_router_access_log_error(nxt_task_t *task, - nxt_port_recv_msg_t *msg, void *data); + nxt_port_recv_msg_t *msg, void *data); static void nxt_router_access_log_reopen_completion(nxt_task_t *task, void *obj, - void *data); + void *data); static void nxt_router_access_log_reopen_ready(nxt_task_t *task, - nxt_port_recv_msg_t *msg, void *data); + nxt_port_recv_msg_t *msg, + void *data); static void nxt_router_access_log_reopen_error(nxt_task_t *task, - nxt_port_recv_msg_t *msg, void *data); - + nxt_port_recv_msg_t *msg, + void *data); -static nxt_conf_map_t nxt_router_access_log_conf[] = { +static nxt_conf_map_t nxt_router_access_log_conf[] = { { nxt_string("path"), NXT_CONF_MAP_STR, @@ -60,379 +59,347 @@ static nxt_conf_map_t nxt_router_access_log_conf[] = { }, }; - -nxt_int_t -nxt_router_access_log_create(nxt_task_t *task, nxt_router_conf_t *rtcf, - nxt_conf_value_t *value) -{ - nxt_int_t ret; - nxt_str_t str; - nxt_tstr_t *format; - nxt_router_t *router; - nxt_router_access_log_t *access_log; - nxt_router_access_log_conf_t alcf; - - static const nxt_str_t log_format_str = nxt_string("$remote_addr - - " - "[$time_local] \"$request_line\" $status $body_bytes_sent " - "\"$header_referer\" \"$header_user_agent\""); - - nxt_memzero(&alcf, sizeof(nxt_router_access_log_conf_t)); - - alcf.format = log_format_str; - - if (nxt_conf_type(value) == NXT_CONF_STRING) { - nxt_conf_get_string(value, &alcf.path); - - } else { - ret = nxt_conf_map_object(rtcf->mem_pool, value, - nxt_router_access_log_conf, - nxt_nitems(nxt_router_access_log_conf), - &alcf); - if (ret != NXT_OK) { - nxt_alert(task, "access log map error"); - return NXT_ERROR; - } +nxt_int_t nxt_router_access_log_create(nxt_task_t *task, + nxt_router_conf_t *rtcf, + nxt_conf_value_t *value) { + nxt_int_t ret; + nxt_str_t str; + nxt_tstr_t *format; + nxt_router_t *router; + nxt_router_access_log_t *access_log; + nxt_router_access_log_conf_t alcf; + + static const nxt_str_t log_format_str = + nxt_string("$remote_addr - - " + "[$time_local] \"$request_line\" $status $body_bytes_sent " + "\"$header_referer\" \"$header_user_agent\""); + + nxt_memzero(&alcf, sizeof(nxt_router_access_log_conf_t)); + + alcf.format = log_format_str; + + if (nxt_conf_type(value) == NXT_CONF_STRING) { + nxt_conf_get_string(value, &alcf.path); + + } else { + ret = nxt_conf_map_object(rtcf->mem_pool, value, nxt_router_access_log_conf, + nxt_nitems(nxt_router_access_log_conf), &alcf); + if (ret != NXT_OK) { + nxt_alert(task, "access log map error"); + return NXT_ERROR; } + } - router = nxt_router; + router = nxt_router; - access_log = router->access_log; + access_log = router->access_log; - if (access_log != NULL && nxt_strstr_eq(&alcf.path, &access_log->path)) { - nxt_router_access_log_use(&router->lock, access_log); + if (access_log != NULL && nxt_strstr_eq(&alcf.path, &access_log->path)) { + nxt_router_access_log_use(&router->lock, access_log); - } else { - access_log = nxt_malloc(sizeof(nxt_router_access_log_t) - + alcf.path.length); - if (access_log == NULL) { - nxt_alert(task, "failed to allocate access log structure"); - return NXT_ERROR; - } + } else { + access_log = nxt_malloc(sizeof(nxt_router_access_log_t) + alcf.path.length); + if (access_log == NULL) { + nxt_alert(task, "failed to allocate access log structure"); + return NXT_ERROR; + } - access_log->fd = -1; - access_log->handler = &nxt_router_access_log_writer; - access_log->count = 1; + access_log->fd = -1; + access_log->handler = &nxt_router_access_log_writer; + access_log->count = 1; - access_log->path.length = alcf.path.length; - access_log->path.start = (u_char *) access_log - + sizeof(nxt_router_access_log_t); + access_log->path.length = alcf.path.length; + access_log->path.start = + (u_char *)access_log + sizeof(nxt_router_access_log_t); - nxt_memcpy(access_log->path.start, alcf.path.start, alcf.path.length); - } + nxt_memcpy(access_log->path.start, alcf.path.start, alcf.path.length); + } - format = nxt_tstr_compile(rtcf->tstr_state, &alcf.format, - NXT_TSTR_LOGGING | NXT_TSTR_NEWLINE); - if (nxt_slow_path(format == NULL)) { - return NXT_ERROR; - } + format = nxt_tstr_compile(rtcf->tstr_state, &alcf.format, + NXT_TSTR_LOGGING | NXT_TSTR_NEWLINE); + if (nxt_slow_path(format == NULL)) { + return NXT_ERROR; + } - rtcf->access_log = access_log; - rtcf->log_format = format; + rtcf->access_log = access_log; + rtcf->log_format = format; - if (alcf.expr != NULL) { - nxt_conf_get_string(alcf.expr, &str); + if (alcf.expr != NULL) { + nxt_conf_get_string(alcf.expr, &str); - ret = nxt_tstr_cond_compile(rtcf->tstr_state, &str, &rtcf->log_cond); - if (nxt_slow_path(ret != NXT_OK)) { - return NXT_ERROR; - } + ret = nxt_tstr_cond_compile(rtcf->tstr_state, &str, &rtcf->log_cond); + if (nxt_slow_path(ret != NXT_OK)) { + return NXT_ERROR; } + } - return NXT_OK; + return NXT_OK; } +static void nxt_router_access_log_writer(nxt_task_t *task, + nxt_http_request_t *r, + nxt_router_access_log_t *access_log, + nxt_tstr_t *format) { + nxt_int_t ret; + nxt_router_conf_t *rtcf; + nxt_router_access_log_ctx_t *ctx; + + ctx = nxt_mp_get(r->mem_pool, sizeof(nxt_router_access_log_ctx_t)); + if (nxt_slow_path(ctx == NULL)) { + return; + } -static void -nxt_router_access_log_writer(nxt_task_t *task, nxt_http_request_t *r, - nxt_router_access_log_t *access_log, nxt_tstr_t *format) -{ - nxt_int_t ret; - nxt_router_conf_t *rtcf; - nxt_router_access_log_ctx_t *ctx; - - ctx = nxt_mp_get(r->mem_pool, sizeof(nxt_router_access_log_ctx_t)); - if (nxt_slow_path(ctx == NULL)) { - return; - } - - ctx->access_log = access_log; + ctx->access_log = access_log; - if (nxt_tstr_is_const(format)) { - nxt_tstr_str(format, &ctx->text); + if (nxt_tstr_is_const(format)) { + nxt_tstr_str(format, &ctx->text); - } else { - rtcf = r->conf->socket_conf->router_conf; + } else { + rtcf = r->conf->socket_conf->router_conf; - ret = nxt_tstr_query_init(&r->tstr_query, rtcf->tstr_state, - &r->tstr_cache, r, r->mem_pool); - if (nxt_slow_path(ret != NXT_OK)) { - return; - } + ret = nxt_tstr_query_init(&r->tstr_query, rtcf->tstr_state, &r->tstr_cache, + r, r->mem_pool); + if (nxt_slow_path(ret != NXT_OK)) { + return; + } - ret = nxt_tstr_query(task, r->tstr_query, format, &ctx->text); - if (nxt_slow_path(ret != NXT_OK)) { - return; - } + ret = nxt_tstr_query(task, r->tstr_query, format, &ctx->text); + if (nxt_slow_path(ret != NXT_OK)) { + return; } + } - nxt_router_access_log_write(task, r, ctx); + nxt_router_access_log_write(task, r, ctx); } +static void nxt_router_access_log_write(nxt_task_t *task, nxt_http_request_t *r, + nxt_router_access_log_ctx_t *ctx) { + nxt_fd_write(ctx->access_log->fd, ctx->text.start, ctx->text.length); -static void -nxt_router_access_log_write(nxt_task_t *task, nxt_http_request_t *r, - nxt_router_access_log_ctx_t *ctx) -{ - nxt_fd_write(ctx->access_log->fd, ctx->text.start, ctx->text.length); - - nxt_http_request_close_handler(task, r, r->proto.any); + nxt_http_request_close_handler(task, r, r->proto.any); } +void nxt_router_access_log_open(nxt_task_t *task, + nxt_router_temp_conf_t *tmcf) { + uint32_t stream; + nxt_int_t ret; + nxt_buf_t *b; + nxt_port_t *main_port, *router_port; + nxt_runtime_t *rt; + nxt_router_access_log_t *access_log; -void -nxt_router_access_log_open(nxt_task_t *task, nxt_router_temp_conf_t *tmcf) -{ - uint32_t stream; - nxt_int_t ret; - nxt_buf_t *b; - nxt_port_t *main_port, *router_port; - nxt_runtime_t *rt; - nxt_router_access_log_t *access_log; + access_log = tmcf->router_conf->access_log; - access_log = tmcf->router_conf->access_log; + b = nxt_buf_mem_alloc(tmcf->mem_pool, access_log->path.length + 1, 0); + if (nxt_slow_path(b == NULL)) { + goto fail; + } - b = nxt_buf_mem_alloc(tmcf->mem_pool, access_log->path.length + 1, 0); - if (nxt_slow_path(b == NULL)) { - goto fail; - } + b->completion_handler = nxt_buf_dummy_completion; - b->completion_handler = nxt_buf_dummy_completion; + nxt_buf_cpystr(b, &access_log->path); + *b->mem.free++ = '\0'; - nxt_buf_cpystr(b, &access_log->path); - *b->mem.free++ = '\0'; + rt = task->thread->runtime; + main_port = rt->port_by_type[NXT_PROCESS_MAIN]; + router_port = rt->port_by_type[NXT_PROCESS_ROUTER]; - rt = task->thread->runtime; - main_port = rt->port_by_type[NXT_PROCESS_MAIN]; - router_port = rt->port_by_type[NXT_PROCESS_ROUTER]; + stream = nxt_port_rpc_register_handler(task, router_port, + nxt_router_access_log_ready, + nxt_router_access_log_error, -1, tmcf); + if (nxt_slow_path(stream == 0)) { + goto fail; + } - stream = nxt_port_rpc_register_handler(task, router_port, - nxt_router_access_log_ready, - nxt_router_access_log_error, - -1, tmcf); - if (nxt_slow_path(stream == 0)) { - goto fail; - } + ret = nxt_port_socket_write(task, main_port, NXT_PORT_MSG_ACCESS_LOG, -1, + stream, router_port->id, b); - ret = nxt_port_socket_write(task, main_port, NXT_PORT_MSG_ACCESS_LOG, -1, - stream, router_port->id, b); + if (nxt_slow_path(ret != NXT_OK)) { + nxt_port_rpc_cancel(task, router_port, stream); + goto fail; + } - if (nxt_slow_path(ret != NXT_OK)) { - nxt_port_rpc_cancel(task, router_port, stream); - goto fail; - } - - return; + return; fail: - nxt_router_conf_error(task, tmcf); + nxt_router_conf_error(task, tmcf); } +static void nxt_router_access_log_ready(nxt_task_t *task, + nxt_port_recv_msg_t *msg, void *data) { + nxt_router_temp_conf_t *tmcf; + nxt_router_access_log_t *access_log; -static void -nxt_router_access_log_ready(nxt_task_t *task, nxt_port_recv_msg_t *msg, - void *data) -{ - nxt_router_temp_conf_t *tmcf; - nxt_router_access_log_t *access_log; - - tmcf = data; + tmcf = data; - access_log = tmcf->router_conf->access_log; + access_log = tmcf->router_conf->access_log; - access_log->fd = msg->fd[0]; + access_log->fd = msg->fd[0]; - nxt_work_queue_add(&task->thread->engine->fast_work_queue, - nxt_router_conf_apply, task, tmcf, NULL); + nxt_work_queue_add(&task->thread->engine->fast_work_queue, + nxt_router_conf_apply, task, tmcf, NULL); } +static void nxt_router_access_log_error(nxt_task_t *task, + nxt_port_recv_msg_t *msg, void *data) { + nxt_router_temp_conf_t *tmcf; -static void -nxt_router_access_log_error(nxt_task_t *task, nxt_port_recv_msg_t *msg, - void *data) -{ - nxt_router_temp_conf_t *tmcf; - - tmcf = data; + tmcf = data; - nxt_router_conf_error(task, tmcf); + nxt_router_conf_error(task, tmcf); } +void nxt_router_access_log_use(nxt_thread_spinlock_t *lock, + nxt_router_access_log_t *access_log) { + if (access_log == NULL) { + return; + } -void -nxt_router_access_log_use(nxt_thread_spinlock_t *lock, - nxt_router_access_log_t *access_log) -{ - if (access_log == NULL) { - return; - } - - nxt_thread_spin_lock(lock); + nxt_thread_spin_lock(lock); - access_log->count++; + access_log->count++; - nxt_thread_spin_unlock(lock); + nxt_thread_spin_unlock(lock); } +void nxt_router_access_log_release(nxt_task_t *task, + nxt_thread_spinlock_t *lock, + nxt_router_access_log_t *access_log) { + if (access_log == NULL) { + return; + } -void -nxt_router_access_log_release(nxt_task_t *task, nxt_thread_spinlock_t *lock, - nxt_router_access_log_t *access_log) -{ - if (access_log == NULL) { - return; - } - - nxt_thread_spin_lock(lock); - - if (--access_log->count != 0) { - access_log = NULL; - } + nxt_thread_spin_lock(lock); - nxt_thread_spin_unlock(lock); + if (--access_log->count != 0) { + access_log = NULL; + } - if (access_log != NULL) { + nxt_thread_spin_unlock(lock); - if (access_log->fd != -1) { - nxt_fd_close(access_log->fd); - } + if (access_log != NULL) { - nxt_free(access_log); + if (access_log->fd != -1) { + nxt_fd_close(access_log->fd); } -} + nxt_free(access_log); + } +} typedef struct { - nxt_mp_t *mem_pool; - nxt_router_access_log_t *access_log; + nxt_mp_t *mem_pool; + nxt_router_access_log_t *access_log; } nxt_router_access_log_reopen_t; +void nxt_router_access_log_reopen_handler(nxt_task_t *task, + nxt_port_recv_msg_t *msg) { + nxt_mp_t *mp; + uint32_t stream; + nxt_int_t ret; + nxt_buf_t *b; + nxt_port_t *main_port, *router_port; + nxt_runtime_t *rt; + nxt_router_access_log_t *access_log; + nxt_router_access_log_reopen_t *reopen; -void -nxt_router_access_log_reopen_handler(nxt_task_t *task, nxt_port_recv_msg_t *msg) -{ - nxt_mp_t *mp; - uint32_t stream; - nxt_int_t ret; - nxt_buf_t *b; - nxt_port_t *main_port, *router_port; - nxt_runtime_t *rt; - nxt_router_access_log_t *access_log; - nxt_router_access_log_reopen_t *reopen; + access_log = nxt_router->access_log; - access_log = nxt_router->access_log; - - if (access_log == NULL) { - return; - } + if (access_log == NULL) { + return; + } - mp = nxt_mp_create(1024, 128, 256, 32); - if (nxt_slow_path(mp == NULL)) { - return; - } + mp = nxt_mp_create(1024, 128, 256, 32); + if (nxt_slow_path(mp == NULL)) { + return; + } - reopen = nxt_mp_get(mp, sizeof(nxt_router_access_log_reopen_t)); - if (nxt_slow_path(reopen == NULL)) { - goto fail; - } + reopen = nxt_mp_get(mp, sizeof(nxt_router_access_log_reopen_t)); + if (nxt_slow_path(reopen == NULL)) { + goto fail; + } - reopen->mem_pool = mp; - reopen->access_log = access_log; + reopen->mem_pool = mp; + reopen->access_log = access_log; - b = nxt_buf_mem_alloc(mp, access_log->path.length + 1, 0); - if (nxt_slow_path(b == NULL)) { - goto fail; - } + b = nxt_buf_mem_alloc(mp, access_log->path.length + 1, 0); + if (nxt_slow_path(b == NULL)) { + goto fail; + } - b->completion_handler = nxt_router_access_log_reopen_completion; + b->completion_handler = nxt_router_access_log_reopen_completion; - nxt_buf_cpystr(b, &access_log->path); - *b->mem.free++ = '\0'; + nxt_buf_cpystr(b, &access_log->path); + *b->mem.free++ = '\0'; - rt = task->thread->runtime; - main_port = rt->port_by_type[NXT_PROCESS_MAIN]; - router_port = rt->port_by_type[NXT_PROCESS_ROUTER]; + rt = task->thread->runtime; + main_port = rt->port_by_type[NXT_PROCESS_MAIN]; + router_port = rt->port_by_type[NXT_PROCESS_ROUTER]; - stream = nxt_port_rpc_register_handler(task, router_port, - nxt_router_access_log_reopen_ready, - nxt_router_access_log_reopen_error, - -1, reopen); - if (nxt_slow_path(stream == 0)) { - goto fail; - } + stream = nxt_port_rpc_register_handler( + task, router_port, nxt_router_access_log_reopen_ready, + nxt_router_access_log_reopen_error, -1, reopen); + if (nxt_slow_path(stream == 0)) { + goto fail; + } - ret = nxt_port_socket_write(task, main_port, NXT_PORT_MSG_ACCESS_LOG, -1, - stream, router_port->id, b); + ret = nxt_port_socket_write(task, main_port, NXT_PORT_MSG_ACCESS_LOG, -1, + stream, router_port->id, b); - if (nxt_slow_path(ret != NXT_OK)) { - nxt_port_rpc_cancel(task, router_port, stream); - goto fail; - } + if (nxt_slow_path(ret != NXT_OK)) { + nxt_port_rpc_cancel(task, router_port, stream); + goto fail; + } - nxt_mp_retain(mp); + nxt_mp_retain(mp); - return; + return; fail: - nxt_mp_destroy(mp); + nxt_mp_destroy(mp); } +static void nxt_router_access_log_reopen_completion(nxt_task_t *task, void *obj, + void *data) { + nxt_mp_t *mp; + nxt_buf_t *b; -static void -nxt_router_access_log_reopen_completion(nxt_task_t *task, void *obj, void *data) -{ - nxt_mp_t *mp; - nxt_buf_t *b; - - b = obj; - mp = b->data; + b = obj; + mp = b->data; - nxt_mp_release(mp); + nxt_mp_release(mp); } +static void nxt_router_access_log_reopen_ready(nxt_task_t *task, + nxt_port_recv_msg_t *msg, + void *data) { + nxt_router_access_log_t *access_log; + nxt_router_access_log_reopen_t *reopen; -static void -nxt_router_access_log_reopen_ready(nxt_task_t *task, nxt_port_recv_msg_t *msg, - void *data) -{ - nxt_router_access_log_t *access_log; - nxt_router_access_log_reopen_t *reopen; - - reopen = data; + reopen = data; - access_log = reopen->access_log; + access_log = reopen->access_log; - if (access_log == nxt_router->access_log) { + if (access_log == nxt_router->access_log) { - if (nxt_slow_path(dup2(msg->fd[0], access_log->fd) == -1)) { - nxt_alert(task, "dup2(%FD, %FD) failed %E", - msg->fd[0], access_log->fd, nxt_errno); - } + if (nxt_slow_path(dup2(msg->fd[0], access_log->fd) == -1)) { + nxt_alert(task, "dup2(%FD, %FD) failed %E", msg->fd[0], access_log->fd, + nxt_errno); } + } - nxt_fd_close(msg->fd[0]); - nxt_mp_release(reopen->mem_pool); + nxt_fd_close(msg->fd[0]); + nxt_mp_release(reopen->mem_pool); } +static void nxt_router_access_log_reopen_error(nxt_task_t *task, + nxt_port_recv_msg_t *msg, + void *data) { + nxt_router_access_log_reopen_t *reopen; -static void -nxt_router_access_log_reopen_error(nxt_task_t *task, nxt_port_recv_msg_t *msg, - void *data) -{ - nxt_router_access_log_reopen_t *reopen; - - reopen = data; + reopen = data; - nxt_mp_release(reopen->mem_pool); + nxt_mp_release(reopen->mem_pool); } diff --git a/src/nxt_router_request.h b/src/nxt_router_request.h index 6e226bae8..b0c45e9e5 100644 --- a/src/nxt_router_request.h +++ b/src/nxt_router_request.h @@ -6,35 +6,31 @@ #ifndef _NXT_ROUTER_REQUEST_H_INCLUDED_ #define _NXT_ROUTER_REQUEST_H_INCLUDED_ - typedef struct { - nxt_buf_t *buf; - nxt_fd_t body_fd; - uint32_t tracking_cookie; + nxt_buf_t *buf; + nxt_fd_t body_fd; + uint32_t tracking_cookie; } nxt_msg_info_t; - typedef enum { - NXT_APR_NEW_PORT, - NXT_APR_REQUEST_FAILED, - NXT_APR_GOT_RESPONSE, - NXT_APR_UPGRADE, - NXT_APR_CLOSE, + NXT_APR_NEW_PORT, + NXT_APR_REQUEST_FAILED, + NXT_APR_GOT_RESPONSE, + NXT_APR_UPGRADE, + NXT_APR_CLOSE, } nxt_apr_action_t; - typedef struct { - uint32_t stream; - nxt_app_t *app; + uint32_t stream; + nxt_app_t *app; - nxt_port_t *app_port; - nxt_apr_action_t apr_action; + nxt_port_t *app_port; + nxt_apr_action_t apr_action; - nxt_http_request_t *request; - nxt_msg_info_t msg_info; + nxt_http_request_t *request; + nxt_msg_info_t msg_info; - nxt_bool_t rpc_cancel; + nxt_bool_t rpc_cancel; } nxt_request_rpc_data_t; - #endif /* _NXT_ROUTER_REQUEST_H_INCLUDED_ */ diff --git a/src/nxt_runtime.c b/src/nxt_runtime.c index de76f19e0..9c1889bde 100644 --- a/src/nxt_runtime.c +++ b/src/nxt_runtime.c @@ -12,11 +12,10 @@ #include #include - static nxt_int_t nxt_runtime_inherited_listen_sockets(nxt_task_t *task, - nxt_runtime_t *rt); + nxt_runtime_t *rt); static nxt_int_t nxt_runtime_systemd_listen_sockets(nxt_task_t *task, - nxt_runtime_t *rt); + nxt_runtime_t *rt); static nxt_int_t nxt_runtime_event_engines(nxt_task_t *task, nxt_runtime_t *rt); static nxt_int_t nxt_runtime_thread_pools(nxt_thread_t *thr, nxt_runtime_t *rt); static void nxt_runtime_start(nxt_task_t *task, void *obj, void *data); @@ -25,1815 +24,1700 @@ static void nxt_runtime_close_idle_connections(nxt_event_engine_t *engine); static void nxt_runtime_stop_all_processes(nxt_task_t *task, nxt_runtime_t *rt); static void nxt_runtime_exit(nxt_task_t *task, void *obj, void *data); static nxt_int_t nxt_runtime_event_engine_change(nxt_task_t *task, - nxt_runtime_t *rt); + nxt_runtime_t *rt); static nxt_int_t nxt_runtime_conf_init(nxt_task_t *task, nxt_runtime_t *rt); static nxt_int_t nxt_runtime_conf_read_cmd(nxt_task_t *task, nxt_runtime_t *rt); static nxt_int_t nxt_runtime_hostname(nxt_task_t *task, nxt_runtime_t *rt); static nxt_int_t nxt_runtime_log_files_init(nxt_runtime_t *rt); static nxt_int_t nxt_runtime_log_files_create(nxt_task_t *task, - nxt_runtime_t *rt); + nxt_runtime_t *rt); static nxt_int_t nxt_runtime_pid_file_create(nxt_task_t *task, - nxt_file_name_t *pid_file); + nxt_file_name_t *pid_file); static void nxt_runtime_thread_pool_destroy(nxt_task_t *task, nxt_runtime_t *rt, - nxt_runtime_cont_t cont); + nxt_runtime_cont_t cont); static void nxt_runtime_thread_pool_init(void); static void nxt_runtime_thread_pool_exit(nxt_task_t *task, void *obj, - void *data); + void *data); static nxt_process_t *nxt_runtime_process_get(nxt_runtime_t *rt, nxt_pid_t pid); static void nxt_runtime_port_add(nxt_task_t *task, nxt_port_t *port); +nxt_int_t nxt_runtime_create(nxt_task_t *task) { + nxt_mp_t *mp; + nxt_int_t ret; + nxt_array_t *listen_sockets; + nxt_runtime_t *rt; + nxt_app_lang_module_t *lang; -nxt_int_t -nxt_runtime_create(nxt_task_t *task) -{ - nxt_mp_t *mp; - nxt_int_t ret; - nxt_array_t *listen_sockets; - nxt_runtime_t *rt; - nxt_app_lang_module_t *lang; - - mp = nxt_mp_create(1024, 128, 256, 32); - if (nxt_slow_path(mp == NULL)) { - return NXT_ERROR; - } + mp = nxt_mp_create(1024, 128, 256, 32); + if (nxt_slow_path(mp == NULL)) { + return NXT_ERROR; + } - rt = nxt_mp_zget(mp, sizeof(nxt_runtime_t)); - if (nxt_slow_path(rt == NULL)) { - goto fail; - } + rt = nxt_mp_zget(mp, sizeof(nxt_runtime_t)); + if (nxt_slow_path(rt == NULL)) { + goto fail; + } - task->thread->runtime = rt; - rt->mem_pool = mp; + task->thread->runtime = rt; + rt->mem_pool = mp; - nxt_thread_mutex_create(&rt->processes_mutex); + nxt_thread_mutex_create(&rt->processes_mutex); - rt->services = nxt_services_init(mp); - if (nxt_slow_path(rt->services == NULL)) { - goto fail; - } + rt->services = nxt_services_init(mp); + if (nxt_slow_path(rt->services == NULL)) { + goto fail; + } - rt->languages = nxt_array_create(mp, 1, sizeof(nxt_app_lang_module_t)); - if (nxt_slow_path(rt->languages == NULL)) { - goto fail; - } + rt->languages = nxt_array_create(mp, 1, sizeof(nxt_app_lang_module_t)); + if (nxt_slow_path(rt->languages == NULL)) { + goto fail; + } - /* Should not fail. */ - lang = nxt_array_add(rt->languages); - lang->type = NXT_APP_EXTERNAL; - lang->version = (u_char *) ""; - lang->file = NULL; - lang->module = &nxt_external_module; + /* Should not fail. */ + lang = nxt_array_add(rt->languages); + lang->type = NXT_APP_EXTERNAL; + lang->version = (u_char *)""; + lang->file = NULL; + lang->module = &nxt_external_module; - lang->mounts = nxt_array_create(mp, 1, sizeof(nxt_fs_mount_t)); - if (nxt_slow_path(lang->mounts == NULL)) { - goto fail; - } + lang->mounts = nxt_array_create(mp, 1, sizeof(nxt_fs_mount_t)); + if (nxt_slow_path(lang->mounts == NULL)) { + goto fail; + } - listen_sockets = nxt_array_create(mp, 1, sizeof(nxt_listen_socket_t)); - if (nxt_slow_path(listen_sockets == NULL)) { - goto fail; - } + listen_sockets = nxt_array_create(mp, 1, sizeof(nxt_listen_socket_t)); + if (nxt_slow_path(listen_sockets == NULL)) { + goto fail; + } - rt->listen_sockets = listen_sockets; + rt->listen_sockets = listen_sockets; - ret = nxt_runtime_inherited_listen_sockets(task, rt); - if (nxt_slow_path(ret != NXT_OK)) { - goto fail; - } + ret = nxt_runtime_inherited_listen_sockets(task, rt); + if (nxt_slow_path(ret != NXT_OK)) { + goto fail; + } - if (nxt_runtime_hostname(task, rt) != NXT_OK) { - goto fail; - } + if (nxt_runtime_hostname(task, rt) != NXT_OK) { + goto fail; + } - if (nxt_slow_path(nxt_runtime_log_files_init(rt) != NXT_OK)) { - goto fail; - } + if (nxt_slow_path(nxt_runtime_log_files_init(rt) != NXT_OK)) { + goto fail; + } - if (nxt_runtime_event_engines(task, rt) != NXT_OK) { - goto fail; - } + if (nxt_runtime_event_engines(task, rt) != NXT_OK) { + goto fail; + } - if (nxt_slow_path(nxt_runtime_thread_pools(task->thread, rt) != NXT_OK)) { - goto fail; - } + if (nxt_slow_path(nxt_runtime_thread_pools(task->thread, rt) != NXT_OK)) { + goto fail; + } - rt->start = nxt_runtime_initial_start; + rt->start = nxt_runtime_initial_start; - if (nxt_runtime_conf_init(task, rt) != NXT_OK) { - goto fail; - } + if (nxt_runtime_conf_init(task, rt) != NXT_OK) { + goto fail; + } - if (nxt_port_rpc_init() != NXT_OK) { - goto fail; - } + if (nxt_port_rpc_init() != NXT_OK) { + goto fail; + } - if (nxt_slow_path(nxt_http_register_variables() != NXT_OK)) { - goto fail; - } + if (nxt_slow_path(nxt_http_register_variables() != NXT_OK)) { + goto fail; + } - if (nxt_slow_path(nxt_var_index_init() != NXT_OK)) { - goto fail; - } + if (nxt_slow_path(nxt_var_index_init() != NXT_OK)) { + goto fail; + } - nxt_work_queue_add(&task->thread->engine->fast_work_queue, - nxt_runtime_start, task, rt, NULL); + nxt_work_queue_add(&task->thread->engine->fast_work_queue, nxt_runtime_start, + task, rt, NULL); - return NXT_OK; + return NXT_OK; fail: - nxt_mp_destroy(mp); + nxt_mp_destroy(mp); - return NXT_ERROR; + return NXT_ERROR; } +static nxt_int_t nxt_runtime_inherited_listen_sockets(nxt_task_t *task, + nxt_runtime_t *rt) { + u_char *v, *p; + nxt_int_t type; + nxt_array_t *inherited_sockets; + nxt_socket_t s; + nxt_listen_socket_t *ls; -static nxt_int_t -nxt_runtime_inherited_listen_sockets(nxt_task_t *task, nxt_runtime_t *rt) -{ - u_char *v, *p; - nxt_int_t type; - nxt_array_t *inherited_sockets; - nxt_socket_t s; - nxt_listen_socket_t *ls; + v = (u_char *)getenv("NGINX"); - v = (u_char *) getenv("NGINX"); + if (v == NULL) { + return nxt_runtime_systemd_listen_sockets(task, rt); + } - if (v == NULL) { - return nxt_runtime_systemd_listen_sockets(task, rt); - } + nxt_alert(task, "using inherited listen sockets: %s", v); - nxt_alert(task, "using inherited listen sockets: %s", v); - - inherited_sockets = nxt_array_create(rt->mem_pool, - 1, sizeof(nxt_listen_socket_t)); - if (inherited_sockets == NULL) { - return NXT_ERROR; - } + inherited_sockets = + nxt_array_create(rt->mem_pool, 1, sizeof(nxt_listen_socket_t)); + if (inherited_sockets == NULL) { + return NXT_ERROR; + } - rt->inherited_sockets = inherited_sockets; + rt->inherited_sockets = inherited_sockets; - for (p = v; *p != '\0'; p++) { + for (p = v; *p != '\0'; p++) { - if (*p == ';') { - s = nxt_int_parse(v, p - v); + if (*p == ';') { + s = nxt_int_parse(v, p - v); - if (nxt_slow_path(s < 0)) { - nxt_alert(task, "invalid socket number \"%s\" " - "in NGINX environment variable, " - "ignoring the rest of the variable", v); - return NXT_ERROR; - } + if (nxt_slow_path(s < 0)) { + nxt_alert(task, + "invalid socket number \"%s\" " + "in NGINX environment variable, " + "ignoring the rest of the variable", + v); + return NXT_ERROR; + } - v = p + 1; + v = p + 1; - ls = nxt_array_zero_add(inherited_sockets); - if (nxt_slow_path(ls == NULL)) { - return NXT_ERROR; - } + ls = nxt_array_zero_add(inherited_sockets); + if (nxt_slow_path(ls == NULL)) { + return NXT_ERROR; + } - ls->socket = s; + ls->socket = s; - ls->sockaddr = nxt_getsockname(task, rt->mem_pool, s); - if (nxt_slow_path(ls->sockaddr == NULL)) { - return NXT_ERROR; - } + ls->sockaddr = nxt_getsockname(task, rt->mem_pool, s); + if (nxt_slow_path(ls->sockaddr == NULL)) { + return NXT_ERROR; + } - type = nxt_socket_getsockopt(task, s, SOL_SOCKET, SO_TYPE); - if (nxt_slow_path(type == -1)) { - return NXT_ERROR; - } + type = nxt_socket_getsockopt(task, s, SOL_SOCKET, SO_TYPE); + if (nxt_slow_path(type == -1)) { + return NXT_ERROR; + } - ls->sockaddr->type = (uint16_t) type; - } + ls->sockaddr->type = (uint16_t)type; } + } - return NXT_OK; + return NXT_OK; } +static nxt_int_t nxt_runtime_systemd_listen_sockets(nxt_task_t *task, + nxt_runtime_t *rt) { + u_char *nfd, *pid; + nxt_int_t n; + nxt_array_t *inherited_sockets; + nxt_socket_t s; + nxt_listen_socket_t *ls; + + /* + * Number of listening sockets passed. The socket + * descriptors start from number 3 and are sequential. + */ + nfd = (u_char *)getenv("LISTEN_FDS"); + if (nfd == NULL) { + return NXT_OK; + } -static nxt_int_t -nxt_runtime_systemd_listen_sockets(nxt_task_t *task, nxt_runtime_t *rt) -{ - u_char *nfd, *pid; - nxt_int_t n; - nxt_array_t *inherited_sockets; - nxt_socket_t s; - nxt_listen_socket_t *ls; + /* The pid of the service process. */ + pid = (u_char *)getenv("LISTEN_PID"); + if (pid == NULL) { + return NXT_OK; + } - /* - * Number of listening sockets passed. The socket - * descriptors start from number 3 and are sequential. - */ - nfd = (u_char *) getenv("LISTEN_FDS"); - if (nfd == NULL) { - return NXT_OK; - } + n = nxt_int_parse(nfd, nxt_strlen(nfd)); + if (n < 0) { + return NXT_OK; + } - /* The pid of the service process. */ - pid = (u_char *) getenv("LISTEN_PID"); - if (pid == NULL) { - return NXT_OK; - } + if (nxt_pid != nxt_int_parse(pid, nxt_strlen(pid))) { + return NXT_OK; + } - n = nxt_int_parse(nfd, nxt_strlen(nfd)); - if (n < 0) { - return NXT_OK; - } + nxt_log(task, NXT_LOG_INFO, "using %i systemd listen sockets", n); - if (nxt_pid != nxt_int_parse(pid, nxt_strlen(pid))) { - return NXT_OK; - } + inherited_sockets = + nxt_array_create(rt->mem_pool, n, sizeof(nxt_listen_socket_t)); + if (inherited_sockets == NULL) { + return NXT_ERROR; + } - nxt_log(task, NXT_LOG_INFO, "using %i systemd listen sockets", n); + rt->inherited_sockets = inherited_sockets; - inherited_sockets = nxt_array_create(rt->mem_pool, - n, sizeof(nxt_listen_socket_t)); - if (inherited_sockets == NULL) { - return NXT_ERROR; + for (s = 3; s < n; s++) { + ls = nxt_array_zero_add(inherited_sockets); + if (nxt_slow_path(ls == NULL)) { + return NXT_ERROR; } - rt->inherited_sockets = inherited_sockets; + ls->socket = s; - for (s = 3; s < n; s++) { - ls = nxt_array_zero_add(inherited_sockets); - if (nxt_slow_path(ls == NULL)) { - return NXT_ERROR; - } - - ls->socket = s; - - ls->sockaddr = nxt_getsockname(task, rt->mem_pool, s); - if (nxt_slow_path(ls->sockaddr == NULL)) { - return NXT_ERROR; - } - - ls->sockaddr->type = SOCK_STREAM; + ls->sockaddr = nxt_getsockname(task, rt->mem_pool, s); + if (nxt_slow_path(ls->sockaddr == NULL)) { + return NXT_ERROR; } - return NXT_OK; -} + ls->sockaddr->type = SOCK_STREAM; + } + return NXT_OK; +} -static nxt_int_t -nxt_runtime_event_engines(nxt_task_t *task, nxt_runtime_t *rt) -{ - nxt_thread_t *thread; - nxt_event_engine_t *engine; - const nxt_event_interface_t *interface; +static nxt_int_t nxt_runtime_event_engines(nxt_task_t *task, + nxt_runtime_t *rt) { + nxt_thread_t *thread; + nxt_event_engine_t *engine; + const nxt_event_interface_t *interface; - interface = nxt_service_get(rt->services, "engine", NULL); + interface = nxt_service_get(rt->services, "engine", NULL); - if (nxt_slow_path(interface == NULL)) { - /* TODO: log */ - return NXT_ERROR; - } + if (nxt_slow_path(interface == NULL)) { + /* TODO: log */ + return NXT_ERROR; + } - engine = nxt_event_engine_create(task, interface, - nxt_main_process_signals, 0, 0); + engine = + nxt_event_engine_create(task, interface, nxt_main_process_signals, 0, 0); - if (nxt_slow_path(engine == NULL)) { - return NXT_ERROR; - } + if (nxt_slow_path(engine == NULL)) { + return NXT_ERROR; + } - thread = task->thread; - thread->engine = engine; + thread = task->thread; + thread->engine = engine; #if 0 thread->fiber = &engine->fibers->fiber; #endif - engine->id = rt->last_engine_id++; - engine->mem_pool = nxt_mp_create(1024, 128, 256, 32); + engine->id = rt->last_engine_id++; + engine->mem_pool = nxt_mp_create(1024, 128, 256, 32); - nxt_queue_init(&rt->engines); - nxt_queue_insert_tail(&rt->engines, &engine->link); + nxt_queue_init(&rt->engines); + nxt_queue_insert_tail(&rt->engines, &engine->link); - return NXT_OK; + return NXT_OK; } +static nxt_int_t nxt_runtime_thread_pools(nxt_thread_t *thr, + nxt_runtime_t *rt) { + nxt_int_t ret; + nxt_array_t *thread_pools; -static nxt_int_t -nxt_runtime_thread_pools(nxt_thread_t *thr, nxt_runtime_t *rt) -{ - nxt_int_t ret; - nxt_array_t *thread_pools; + thread_pools = nxt_array_create(rt->mem_pool, 1, sizeof(nxt_thread_pool_t *)); - thread_pools = nxt_array_create(rt->mem_pool, 1, - sizeof(nxt_thread_pool_t *)); - - if (nxt_slow_path(thread_pools == NULL)) { - return NXT_ERROR; - } + if (nxt_slow_path(thread_pools == NULL)) { + return NXT_ERROR; + } - rt->thread_pools = thread_pools; - ret = nxt_runtime_thread_pool_create(thr, rt, 2, 60000 * 1000000LL); + rt->thread_pools = thread_pools; + ret = nxt_runtime_thread_pool_create(thr, rt, 2, 60000 * 1000000LL); - if (nxt_slow_path(ret != NXT_OK)) { - return NXT_ERROR; - } + if (nxt_slow_path(ret != NXT_OK)) { + return NXT_ERROR; + } - return NXT_OK; + return NXT_OK; } +static void nxt_runtime_start(nxt_task_t *task, void *obj, void *data) { + nxt_runtime_t *rt; -static void -nxt_runtime_start(nxt_task_t *task, void *obj, void *data) -{ - nxt_runtime_t *rt; + rt = obj; - rt = obj; + nxt_debug(task, "rt conf done"); - nxt_debug(task, "rt conf done"); + task->thread->log->ctx_handler = NULL; + task->thread->log->ctx = NULL; - task->thread->log->ctx_handler = NULL; - task->thread->log->ctx = NULL; + if (nxt_runtime_log_files_create(task, rt) != NXT_OK) { + goto fail; + } - if (nxt_runtime_log_files_create(task, rt) != NXT_OK) { - goto fail; - } - - if (nxt_runtime_event_engine_change(task, rt) != NXT_OK) { - goto fail; - } + if (nxt_runtime_event_engine_change(task, rt) != NXT_OK) { + goto fail; + } - /* - * Thread pools should be destroyed before starting worker - * processes, because thread pool semaphores will stick in - * locked state in new processes after fork(). - */ - nxt_runtime_thread_pool_destroy(task, rt, rt->start); + /* + * Thread pools should be destroyed before starting worker + * processes, because thread pool semaphores will stick in + * locked state in new processes after fork(). + */ + nxt_runtime_thread_pool_destroy(task, rt, rt->start); - return; + return; fail: - nxt_runtime_quit(task, 1); + nxt_runtime_quit(task, 1); } +static void nxt_runtime_initial_start(nxt_task_t *task, nxt_uint_t status) { + nxt_int_t ret; + nxt_thread_t *thr; + nxt_runtime_t *rt; + const nxt_event_interface_t *interface; -static void -nxt_runtime_initial_start(nxt_task_t *task, nxt_uint_t status) -{ - nxt_int_t ret; - nxt_thread_t *thr; - nxt_runtime_t *rt; - const nxt_event_interface_t *interface; + thr = task->thread; + rt = thr->runtime; - thr = task->thread; - rt = thr->runtime; + if (rt->inherited_sockets == NULL && rt->daemon) { - if (rt->inherited_sockets == NULL && rt->daemon) { - - if (nxt_process_daemon(task) != NXT_OK) { - goto fail; - } - - /* - * An event engine should be updated after fork() - * even if an event facility was not changed because: - * 1) inherited kqueue descriptor is invalid, - * 2) the signal thread is not inherited. - */ - interface = nxt_service_get(rt->services, "engine", rt->engine); - if (interface == NULL) { - goto fail; - } + if (nxt_process_daemon(task) != NXT_OK) { + goto fail; + } - ret = nxt_event_engine_change(task->thread->engine, interface, - rt->batch); - if (ret != NXT_OK) { - goto fail; - } + /* + * An event engine should be updated after fork() + * even if an event facility was not changed because: + * 1) inherited kqueue descriptor is invalid, + * 2) the signal thread is not inherited. + */ + interface = nxt_service_get(rt->services, "engine", rt->engine); + if (interface == NULL) { + goto fail; } - ret = nxt_runtime_pid_file_create(task, rt->pid_file); + ret = nxt_event_engine_change(task->thread->engine, interface, rt->batch); if (ret != NXT_OK) { - goto fail; + goto fail; } + } - if (nxt_runtime_event_engine_change(task, rt) != NXT_OK) { - goto fail; - } + ret = nxt_runtime_pid_file_create(task, rt->pid_file); + if (ret != NXT_OK) { + goto fail; + } - thr->engine->max_connections = rt->engine_connections; + if (nxt_runtime_event_engine_change(task, rt) != NXT_OK) { + goto fail; + } - if (nxt_main_process_start(thr, task, rt) != NXT_ERROR) { - return; - } + thr->engine->max_connections = rt->engine_connections; + + if (nxt_main_process_start(thr, task, rt) != NXT_ERROR) { + return; + } fail: - nxt_runtime_quit(task, 1); + nxt_runtime_quit(task, 1); } +void nxt_runtime_quit(nxt_task_t *task, nxt_uint_t status) { + nxt_bool_t done; + nxt_runtime_t *rt; + nxt_event_engine_t *engine; -void -nxt_runtime_quit(nxt_task_t *task, nxt_uint_t status) -{ - nxt_bool_t done; - nxt_runtime_t *rt; - nxt_event_engine_t *engine; + rt = task->thread->runtime; + rt->status |= status; + engine = task->thread->engine; - rt = task->thread->runtime; - rt->status |= status; - engine = task->thread->engine; + nxt_debug(task, "exiting"); - nxt_debug(task, "exiting"); + done = 1; - done = 1; + if (!engine->shutdown) { + engine->shutdown = 1; - if (!engine->shutdown) { - engine->shutdown = 1; - - if (!nxt_array_is_empty(rt->thread_pools)) { - nxt_runtime_thread_pool_destroy(task, rt, nxt_runtime_quit); - done = 0; - } + if (!nxt_array_is_empty(rt->thread_pools)) { + nxt_runtime_thread_pool_destroy(task, rt, nxt_runtime_quit); + done = 0; + } - if (rt->type == NXT_PROCESS_MAIN) { - nxt_runtime_stop_all_processes(task, rt); - done = 0; - } + if (rt->type == NXT_PROCESS_MAIN) { + nxt_runtime_stop_all_processes(task, rt); + done = 0; } + } - nxt_runtime_close_idle_connections(engine); + nxt_runtime_close_idle_connections(engine); - if (done) { - nxt_work_queue_add(&engine->fast_work_queue, nxt_runtime_exit, - task, rt, engine); - } + if (done) { + nxt_work_queue_add(&engine->fast_work_queue, nxt_runtime_exit, task, rt, + engine); + } } +static void nxt_runtime_close_idle_connections(nxt_event_engine_t *engine) { + nxt_conn_t *c; + nxt_queue_t *idle; + nxt_queue_link_t *link, *next; -static void -nxt_runtime_close_idle_connections(nxt_event_engine_t *engine) -{ - nxt_conn_t *c; - nxt_queue_t *idle; - nxt_queue_link_t *link, *next; - - nxt_debug(&engine->task, "close idle connections"); + nxt_debug(&engine->task, "close idle connections"); - idle = &engine->idle_connections; + idle = &engine->idle_connections; - for (link = nxt_queue_first(idle); - link != nxt_queue_tail(idle); - link = next) - { - next = nxt_queue_next(link); - c = nxt_queue_link_data(link, nxt_conn_t, link); + for (link = nxt_queue_first(idle); link != nxt_queue_tail(idle); + link = next) { + next = nxt_queue_next(link); + c = nxt_queue_link_data(link, nxt_conn_t, link); - if (!c->socket.read_ready) { - nxt_queue_remove(link); - nxt_conn_close(engine, c); - } + if (!c->socket.read_ready) { + nxt_queue_remove(link); + nxt_conn_close(engine, c); } + } } +void nxt_runtime_stop_app_processes(nxt_task_t *task, nxt_runtime_t *rt) { + nxt_port_t *port; + nxt_process_t *process; + nxt_process_init_t *init; -void -nxt_runtime_stop_app_processes(nxt_task_t *task, nxt_runtime_t *rt) -{ - nxt_port_t *port; - nxt_process_t *process; - nxt_process_init_t *init; - - nxt_runtime_process_each(rt, process) { + nxt_runtime_process_each(rt, process) { - init = nxt_process_init(process); + init = nxt_process_init(process); - if (init->type == NXT_PROCESS_APP - || init->type == NXT_PROCESS_PROTOTYPE) - { + if (init->type == NXT_PROCESS_APP || init->type == NXT_PROCESS_PROTOTYPE) { - nxt_process_port_each(process, port) { - - (void) nxt_port_socket_write(task, port, NXT_PORT_MSG_QUIT, -1, - 0, 0, NULL); - - } nxt_process_port_loop; - } + nxt_process_port_each(process, port) { - } nxt_runtime_process_loop; + (void)nxt_port_socket_write(task, port, NXT_PORT_MSG_QUIT, -1, 0, 0, + NULL); + } + nxt_process_port_loop; + } + } + nxt_runtime_process_loop; } +static void nxt_runtime_stop_all_processes(nxt_task_t *task, + nxt_runtime_t *rt) { + nxt_port_t *port; + nxt_process_t *process; -static void -nxt_runtime_stop_all_processes(nxt_task_t *task, nxt_runtime_t *rt) -{ - nxt_port_t *port; - nxt_process_t *process; - - nxt_runtime_process_each(rt, process) { - - nxt_process_port_each(process, port) { + nxt_runtime_process_each(rt, process) { - nxt_debug(task, "%d sending quit to %PI", rt->type, port->pid); + nxt_process_port_each(process, port) { - (void) nxt_port_socket_write(task, port, NXT_PORT_MSG_QUIT, -1, 0, - 0, NULL); + nxt_debug(task, "%d sending quit to %PI", rt->type, port->pid); - } nxt_process_port_loop; - - } nxt_runtime_process_loop; + (void)nxt_port_socket_write(task, port, NXT_PORT_MSG_QUIT, -1, 0, 0, + NULL); + } + nxt_process_port_loop; + } + nxt_runtime_process_loop; } +static void nxt_runtime_exit(nxt_task_t *task, void *obj, void *data) { + int status, engine_count; + nxt_runtime_t *rt; + nxt_process_t *process; + nxt_event_engine_t *engine; -static void -nxt_runtime_exit(nxt_task_t *task, void *obj, void *data) -{ - int status, engine_count; - nxt_runtime_t *rt; - nxt_process_t *process; - nxt_event_engine_t *engine; + rt = obj; + engine = data; - rt = obj; - engine = data; + nxt_debug(task, "thread pools: %d", rt->thread_pools->nelts); - nxt_debug(task, "thread pools: %d", rt->thread_pools->nelts); + if (!nxt_array_is_empty(rt->thread_pools)) { + return; + } - if (!nxt_array_is_empty(rt->thread_pools)) { - return; + if (rt->type == NXT_PROCESS_MAIN) { + if (rt->pid_file != NULL) { + nxt_file_delete(rt->pid_file); } - if (rt->type == NXT_PROCESS_MAIN) { - if (rt->pid_file != NULL) { - nxt_file_delete(rt->pid_file); - } - #if (NXT_HAVE_UNIX_DOMAIN) - { - size_t i; - nxt_sockaddr_t *sa; - nxt_file_name_t *name; - - sa = rt->controller_listen; + { + size_t i; + nxt_sockaddr_t *sa; + nxt_file_name_t *name; - if (sa->u.sockaddr.sa_family == AF_UNIX) { - name = (nxt_file_name_t *) sa->u.sockaddr_un.sun_path; - (void) nxt_file_delete(name); - } + sa = rt->controller_listen; - for (i = 0; i < rt->listen_sockets->nelts; i++) { - nxt_listen_socket_t *ls; + if (sa->u.sockaddr.sa_family == AF_UNIX) { + name = (nxt_file_name_t *)sa->u.sockaddr_un.sun_path; + (void)nxt_file_delete(name); + } - ls = (nxt_listen_socket_t *) rt->listen_sockets->elts + i; - sa = ls->sockaddr; + for (i = 0; i < rt->listen_sockets->nelts; i++) { + nxt_listen_socket_t *ls; - if (sa->u.sockaddr.sa_family != AF_UNIX - || sa->u.sockaddr_un.sun_path[0] == '\0') - { - continue; - } + ls = (nxt_listen_socket_t *)rt->listen_sockets->elts + i; + sa = ls->sockaddr; - name = (nxt_file_name_t *) sa->u.sockaddr_un.sun_path; - (void) nxt_file_delete(name); - } + if (sa->u.sockaddr.sa_family != AF_UNIX || + sa->u.sockaddr_un.sun_path[0] == '\0') { + continue; } -#endif - } - if (!engine->event.signal_support) { - nxt_event_engine_signals_stop(engine); + name = (nxt_file_name_t *)sa->u.sockaddr_un.sun_path; + (void)nxt_file_delete(name); + } } +#endif + } - nxt_runtime_process_each(rt, process) { - - nxt_runtime_process_remove(rt, process); - nxt_process_close_ports(task, process); + if (!engine->event.signal_support) { + nxt_event_engine_signals_stop(engine); + } - } nxt_runtime_process_loop; + nxt_runtime_process_each(rt, process) { - status = rt->status; + nxt_runtime_process_remove(rt, process); + nxt_process_close_ports(task, process); + } + nxt_runtime_process_loop; - engine_count = 0; + status = rt->status; - nxt_queue_each(engine, &rt->engines, nxt_event_engine_t, link) { + engine_count = 0; - engine_count++; + nxt_queue_each(engine, &rt->engines, nxt_event_engine_t, link) { - } nxt_queue_loop; + engine_count++; + } + nxt_queue_loop; - if (engine_count <= 1) { - if (rt->port_by_type[rt->type] != NULL) { - nxt_port_use(task, rt->port_by_type[rt->type], -1); - } + if (engine_count <= 1) { + if (rt->port_by_type[rt->type] != NULL) { + nxt_port_use(task, rt->port_by_type[rt->type], -1); + } - nxt_thread_mutex_destroy(&rt->processes_mutex); + nxt_thread_mutex_destroy(&rt->processes_mutex); - nxt_mp_destroy(rt->mem_pool); - } + nxt_mp_destroy(rt->mem_pool); + } - nxt_debug(task, "exit: %d", status); + nxt_debug(task, "exit: %d", status); - exit(status); - nxt_unreachable(); + exit(status); + nxt_unreachable(); } +static nxt_int_t nxt_runtime_event_engine_change(nxt_task_t *task, + nxt_runtime_t *rt) { + nxt_event_engine_t *engine; + const nxt_event_interface_t *interface; -static nxt_int_t -nxt_runtime_event_engine_change(nxt_task_t *task, nxt_runtime_t *rt) -{ - nxt_event_engine_t *engine; - const nxt_event_interface_t *interface; + engine = task->thread->engine; - engine = task->thread->engine; + if (engine->batch == rt->batch && + nxt_strcmp(engine->event.name, rt->engine) == 0) { + return NXT_OK; + } - if (engine->batch == rt->batch - && nxt_strcmp(engine->event.name, rt->engine) == 0) - { - return NXT_OK; - } + interface = nxt_service_get(rt->services, "engine", rt->engine); - interface = nxt_service_get(rt->services, "engine", rt->engine); + if (interface != NULL) { + return nxt_event_engine_change(engine, interface, rt->batch); + } - if (interface != NULL) { - return nxt_event_engine_change(engine, interface, rt->batch); - } - - return NXT_ERROR; + return NXT_ERROR; } +void nxt_runtime_event_engine_free(nxt_runtime_t *rt) { + nxt_queue_link_t *link; + nxt_event_engine_t *engine; -void -nxt_runtime_event_engine_free(nxt_runtime_t *rt) -{ - nxt_queue_link_t *link; - nxt_event_engine_t *engine; + link = nxt_queue_first(&rt->engines); + nxt_queue_remove(link); - link = nxt_queue_first(&rt->engines); - nxt_queue_remove(link); - - engine = nxt_queue_link_data(link, nxt_event_engine_t, link); - nxt_event_engine_free(engine); + engine = nxt_queue_link_data(link, nxt_event_engine_t, link); + nxt_event_engine_free(engine); } +nxt_int_t nxt_runtime_thread_pool_create(nxt_thread_t *thr, nxt_runtime_t *rt, + nxt_uint_t max_threads, + nxt_nsec_t timeout) { + nxt_thread_pool_t *thread_pool, **tp; -nxt_int_t -nxt_runtime_thread_pool_create(nxt_thread_t *thr, nxt_runtime_t *rt, - nxt_uint_t max_threads, nxt_nsec_t timeout) -{ - nxt_thread_pool_t *thread_pool, **tp; - - tp = nxt_array_add(rt->thread_pools); - if (tp == NULL) { - return NXT_ERROR; - } + tp = nxt_array_add(rt->thread_pools); + if (tp == NULL) { + return NXT_ERROR; + } - thread_pool = nxt_thread_pool_create(max_threads, timeout, - nxt_runtime_thread_pool_init, - thr->engine, - nxt_runtime_thread_pool_exit); + thread_pool = + nxt_thread_pool_create(max_threads, timeout, nxt_runtime_thread_pool_init, + thr->engine, nxt_runtime_thread_pool_exit); - if (nxt_fast_path(thread_pool != NULL)) { - *tp = thread_pool; - } + if (nxt_fast_path(thread_pool != NULL)) { + *tp = thread_pool; + } - return NXT_OK; + return NXT_OK; } +static void nxt_runtime_thread_pool_destroy(nxt_task_t *task, nxt_runtime_t *rt, + nxt_runtime_cont_t cont) { + nxt_uint_t n; + nxt_thread_pool_t **tp; -static void -nxt_runtime_thread_pool_destroy(nxt_task_t *task, nxt_runtime_t *rt, - nxt_runtime_cont_t cont) -{ - nxt_uint_t n; - nxt_thread_pool_t **tp; - - rt->continuation = cont; - - n = rt->thread_pools->nelts; - - if (n == 0) { - cont(task, 0); - return; - } + rt->continuation = cont; - tp = rt->thread_pools->elts; + n = rt->thread_pools->nelts; - do { - nxt_thread_pool_destroy(*tp); + if (n == 0) { + cont(task, 0); + return; + } - tp++; - n--; - } while (n != 0); -} + tp = rt->thread_pools->elts; + do { + nxt_thread_pool_destroy(*tp); -static void -nxt_runtime_thread_pool_init(void) -{ + tp++; + n--; + } while (n != 0); } +static void nxt_runtime_thread_pool_init(void) {} -static void -nxt_runtime_thread_pool_exit(nxt_task_t *task, void *obj, void *data) -{ - nxt_uint_t i, n; - nxt_runtime_t *rt; - nxt_thread_pool_t *tp, **thread_pools; - nxt_thread_handle_t handle; +static void nxt_runtime_thread_pool_exit(nxt_task_t *task, void *obj, + void *data) { + nxt_uint_t i, n; + nxt_runtime_t *rt; + nxt_thread_pool_t *tp, **thread_pools; + nxt_thread_handle_t handle; - tp = obj; + tp = obj; - if (data != NULL) { - handle = (nxt_thread_handle_t) (uintptr_t) data; - nxt_thread_wait(handle); - } + if (data != NULL) { + handle = (nxt_thread_handle_t)(uintptr_t)data; + nxt_thread_wait(handle); + } - rt = task->thread->runtime; + rt = task->thread->runtime; - thread_pools = rt->thread_pools->elts; - n = rt->thread_pools->nelts; + thread_pools = rt->thread_pools->elts; + n = rt->thread_pools->nelts; - nxt_debug(task, "thread pools: %ui", n); + nxt_debug(task, "thread pools: %ui", n); - for (i = 0; i < n; i++) { + for (i = 0; i < n; i++) { - if (tp == thread_pools[i]) { - nxt_array_remove(rt->thread_pools, &thread_pools[i]); + if (tp == thread_pools[i]) { + nxt_array_remove(rt->thread_pools, &thread_pools[i]); - nxt_free(tp); + nxt_free(tp); - if (n == 1) { - /* The last thread pool. */ - rt->continuation(task, 0); - } + if (n == 1) { + /* The last thread pool. */ + rt->continuation(task, 0); + } - return; - } + return; } + } } +static nxt_int_t nxt_runtime_conf_init(nxt_task_t *task, nxt_runtime_t *rt) { + nxt_int_t ret; + nxt_str_t control; + nxt_uint_t n; + nxt_file_t *file; + const char *slash; + nxt_sockaddr_t *sa; + nxt_file_name_str_t file_name; + const nxt_event_interface_t *interface; + + rt->daemon = 1; + rt->engine_connections = 256; + rt->auxiliary_threads = 2; + rt->user_cred.user = NXT_USER; + rt->group = NXT_GROUP; + rt->pid = NXT_PID; + rt->log = NXT_LOG; + rt->modules = NXT_MODULESDIR; + rt->state = NXT_STATEDIR; + rt->control = NXT_CONTROL_SOCK; + rt->tmp = NXT_TMPDIR; + + nxt_memzero(&rt->capabilities, sizeof(nxt_capabilities_t)); + + if (nxt_runtime_conf_read_cmd(task, rt) != NXT_OK) { + return NXT_ERROR; + } -static nxt_int_t -nxt_runtime_conf_init(nxt_task_t *task, nxt_runtime_t *rt) -{ - nxt_int_t ret; - nxt_str_t control; - nxt_uint_t n; - nxt_file_t *file; - const char *slash; - nxt_sockaddr_t *sa; - nxt_file_name_str_t file_name; - const nxt_event_interface_t *interface; - - rt->daemon = 1; - rt->engine_connections = 256; - rt->auxiliary_threads = 2; - rt->user_cred.user = NXT_USER; - rt->group = NXT_GROUP; - rt->pid = NXT_PID; - rt->log = NXT_LOG; - rt->modules = NXT_MODULESDIR; - rt->state = NXT_STATEDIR; - rt->control = NXT_CONTROL_SOCK; - rt->tmp = NXT_TMPDIR; - - nxt_memzero(&rt->capabilities, sizeof(nxt_capabilities_t)); - - if (nxt_runtime_conf_read_cmd(task, rt) != NXT_OK) { - return NXT_ERROR; - } - - if (nxt_capability_set(task, &rt->capabilities) != NXT_OK) { - return NXT_ERROR; - } - - if (rt->capabilities.setid) { - ret = nxt_credential_get(task, rt->mem_pool, &rt->user_cred, - rt->group); + if (nxt_capability_set(task, &rt->capabilities) != NXT_OK) { + return NXT_ERROR; + } - if (nxt_slow_path(ret != NXT_OK)) { - return NXT_ERROR; - } + if (rt->capabilities.setid) { + ret = nxt_credential_get(task, rt->mem_pool, &rt->user_cred, rt->group); - } else { - nxt_log(task, NXT_LOG_WARN, "Unit is running unprivileged, then it " - "cannot use arbitrary user and group."); + if (nxt_slow_path(ret != NXT_OK)) { + return NXT_ERROR; } - /* An engine's parameters. */ + } else { + nxt_log(task, NXT_LOG_WARN, + "Unit is running unprivileged, then it " + "cannot use arbitrary user and group."); + } - interface = nxt_service_get(rt->services, "engine", rt->engine); - if (interface == NULL) { - return NXT_ERROR; - } + /* An engine's parameters. */ - rt->engine = interface->name; + interface = nxt_service_get(rt->services, "engine", rt->engine); + if (interface == NULL) { + return NXT_ERROR; + } - ret = nxt_file_name_create(rt->mem_pool, &file_name, "%s%Z", rt->pid); - if (nxt_slow_path(ret != NXT_OK)) { - return NXT_ERROR; - } + rt->engine = interface->name; - rt->pid_file = file_name.start; + ret = nxt_file_name_create(rt->mem_pool, &file_name, "%s%Z", rt->pid); + if (nxt_slow_path(ret != NXT_OK)) { + return NXT_ERROR; + } - ret = nxt_file_name_create(rt->mem_pool, &file_name, "%s%Z", rt->log); - if (nxt_slow_path(ret != NXT_OK)) { - return NXT_ERROR; - } + rt->pid_file = file_name.start; - file = nxt_list_first(rt->log_files); - file->name = file_name.start; + ret = nxt_file_name_create(rt->mem_pool, &file_name, "%s%Z", rt->log); + if (nxt_slow_path(ret != NXT_OK)) { + return NXT_ERROR; + } - slash = ""; - n = nxt_strlen(rt->modules); + file = nxt_list_first(rt->log_files); + file->name = file_name.start; - if (n > 1 && rt->modules[n - 1] != '/') { - slash = "/"; - } + slash = ""; + n = nxt_strlen(rt->modules); - ret = nxt_file_name_create(rt->mem_pool, &file_name, "%s%s*.unit.so%Z", - rt->modules, slash); - if (nxt_slow_path(ret != NXT_OK)) { - return NXT_ERROR; - } + if (n > 1 && rt->modules[n - 1] != '/') { + slash = "/"; + } - rt->modules = (char *) file_name.start; + ret = nxt_file_name_create(rt->mem_pool, &file_name, "%s%s*.unit.so%Z", + rt->modules, slash); + if (nxt_slow_path(ret != NXT_OK)) { + return NXT_ERROR; + } - slash = ""; - n = nxt_strlen(rt->state); + rt->modules = (char *)file_name.start; - if (n > 1 && rt->state[n - 1] != '/') { - slash = "/"; - } + slash = ""; + n = nxt_strlen(rt->state); - ret = nxt_file_name_create(rt->mem_pool, &file_name, "%s%sversion%Z", - rt->state, slash); - if (nxt_slow_path(ret != NXT_OK)) { - return NXT_ERROR; - } + if (n > 1 && rt->state[n - 1] != '/') { + slash = "/"; + } - rt->ver = (char *) file_name.start; + ret = nxt_file_name_create(rt->mem_pool, &file_name, "%s%sversion%Z", + rt->state, slash); + if (nxt_slow_path(ret != NXT_OK)) { + return NXT_ERROR; + } - ret = nxt_file_name_create(rt->mem_pool, &file_name, "%s.tmp%Z", rt->ver); - if (nxt_slow_path(ret != NXT_OK)) { - return NXT_ERROR; - } + rt->ver = (char *)file_name.start; - rt->ver_tmp = (char *) file_name.start; + ret = nxt_file_name_create(rt->mem_pool, &file_name, "%s.tmp%Z", rt->ver); + if (nxt_slow_path(ret != NXT_OK)) { + return NXT_ERROR; + } - ret = nxt_file_name_create(rt->mem_pool, &file_name, "%s%sconf.json%Z", - rt->state, slash); - if (nxt_slow_path(ret != NXT_OK)) { - return NXT_ERROR; - } + rt->ver_tmp = (char *)file_name.start; - rt->conf = (char *) file_name.start; + ret = nxt_file_name_create(rt->mem_pool, &file_name, "%s%sconf.json%Z", + rt->state, slash); + if (nxt_slow_path(ret != NXT_OK)) { + return NXT_ERROR; + } - ret = nxt_file_name_create(rt->mem_pool, &file_name, "%s.tmp%Z", rt->conf); - if (nxt_slow_path(ret != NXT_OK)) { - return NXT_ERROR; - } + rt->conf = (char *)file_name.start; - rt->conf_tmp = (char *) file_name.start; + ret = nxt_file_name_create(rt->mem_pool, &file_name, "%s.tmp%Z", rt->conf); + if (nxt_slow_path(ret != NXT_OK)) { + return NXT_ERROR; + } - ret = nxt_file_name_create(rt->mem_pool, &file_name, "%s%scerts/%Z", - rt->state, slash); - if (nxt_slow_path(ret != NXT_OK)) { - return NXT_ERROR; - } + rt->conf_tmp = (char *)file_name.start; - ret = mkdir((char *) file_name.start, 0700); - if (nxt_fast_path(ret == 0 || nxt_errno == EEXIST)) { - rt->certs.length = file_name.len; - rt->certs.start = file_name.start; + ret = nxt_file_name_create(rt->mem_pool, &file_name, "%s%scerts/%Z", + rt->state, slash); + if (nxt_slow_path(ret != NXT_OK)) { + return NXT_ERROR; + } + + ret = mkdir((char *)file_name.start, 0700); + if (nxt_fast_path(ret == 0 || nxt_errno == EEXIST)) { + rt->certs.length = file_name.len; + rt->certs.start = file_name.start; + + } else { + nxt_alert(task, + "Unable to create certificates storage directory: " + "mkdir(%s) failed %E", + file_name.start, nxt_errno); + } + + ret = nxt_file_name_create(rt->mem_pool, &file_name, "%s%sscripts/%Z", + rt->state, slash); + if (nxt_slow_path(ret != NXT_OK)) { + return NXT_ERROR; + } - } else { - nxt_alert(task, "Unable to create certificates storage directory: " - "mkdir(%s) failed %E", file_name.start, nxt_errno); - } + ret = mkdir((char *)file_name.start, 0700); + if (nxt_fast_path(ret == 0 || nxt_errno == EEXIST)) { + rt->scripts.length = file_name.len; + rt->scripts.start = file_name.start; - ret = nxt_file_name_create(rt->mem_pool, &file_name, "%s%sscripts/%Z", - rt->state, slash); - if (nxt_slow_path(ret != NXT_OK)) { - return NXT_ERROR; - } + } else { + nxt_alert(task, + "Unable to create scripts storage directory: " + "mkdir(%s) failed %E", + file_name.start, nxt_errno); + } - ret = mkdir((char *) file_name.start, 0700); - if (nxt_fast_path(ret == 0 || nxt_errno == EEXIST)) { - rt->scripts.length = file_name.len; - rt->scripts.start = file_name.start; + control.length = nxt_strlen(rt->control); + control.start = (u_char *)rt->control; - } else { - nxt_alert(task, "Unable to create scripts storage directory: " - "mkdir(%s) failed %E", file_name.start, nxt_errno); - } + sa = nxt_sockaddr_parse(rt->mem_pool, &control); + if (nxt_slow_path(sa == NULL)) { + return NXT_ERROR; + } - control.length = nxt_strlen(rt->control); - control.start = (u_char *) rt->control; + sa->type = SOCK_STREAM; - sa = nxt_sockaddr_parse(rt->mem_pool, &control); - if (nxt_slow_path(sa == NULL)) { - return NXT_ERROR; - } + rt->controller_listen = sa; - sa->type = SOCK_STREAM; + if (nxt_runtime_controller_socket(task, rt) != NXT_OK) { + return NXT_ERROR; + } - rt->controller_listen = sa; + return NXT_OK; +} - if (nxt_runtime_controller_socket(task, rt) != NXT_OK) { +static nxt_int_t nxt_runtime_conf_read_cmd(nxt_task_t *task, + nxt_runtime_t *rt) { + char *p, **argv; + u_char *end; + u_char buf[1024]; + + static const char version[] = + "unit version: " NXT_VERSION "\n" + "configured as ./configure" NXT_CONFIGURE_OPTIONS "\n"; + + static const char no_control[] = + "option \"--control\" requires socket address\n"; + static const char no_control_mode[] = + "option \"--control-mode\" requires a mode\n"; + static const char no_control_user[] = + "option \"--control-user\" requires a username\n"; + static const char no_control_group[] = + "option \"--control-group\" requires a group name\n"; + static const char no_user[] = "option \"--user\" requires username\n"; + static const char no_group[] = "option \"--group\" requires group name\n"; + static const char no_pid[] = "option \"--pid\" requires filename\n"; + static const char no_log[] = "option \"--log\" requires filename\n"; + static const char no_modules[] = + "option \"--modulesdir\" requires directory\n"; + static const char no_state[] = "option \"--statedir\" requires directory\n"; + static const char no_tmp[] = "option \"--tmpdir\" requires directory\n"; + + static const char modules_deprecated[] = + "option \"--modules\" is deprecated; use \"--modulesdir\" instead\n"; + static const char state_deprecated[] = + "option \"--state\" is deprecated; use \"--statedir\" instead\n"; + static const char tmp_deprecated[] = + "option \"--tmp\" is deprecated; use \"--tmpdir\" instead\n"; + + static const char help[] = + "\n" + "unit options:\n" + "\n" + " --version print unit version and configure options\n" + "\n" + " --no-daemon run unit in non-daemon mode\n" + "\n" + " --control ADDRESS set address of control API socket\n" + " default: \"" NXT_CONTROL_SOCK "\"\n" + "\n" + " --control-mode MODE set mode of the control API socket\n" + " default: 0600\n" + "\n" + " --control-user USER set the owner of the control API socket\n" + "\n" + " --control-group GROUP set the group of the control API socket\n" + "\n" + " --pid FILE set pid filename\n" + " default: \"" NXT_PID "\"\n" + "\n" + " --log FILE set log filename\n" + " default: \"" NXT_LOG "\"\n" + "\n" + " --modulesdir DIR set modules directory name\n" + " default: \"" NXT_MODULESDIR "\"\n" + "\n" + " --statedir DIR set state directory name\n" + " default: \"" NXT_STATEDIR "\"\n" + "\n" + " --tmpdir DIR set tmp directory name\n" + " default: \"" NXT_TMPDIR "\"\n" + "\n" + " --modules DIR [deprecated] synonym for --modulesdir\n" + " --state DIR [deprecated] synonym for --statedir\n" + " --tmp DIR [deprecated] synonym for --tmpdir\n" + "\n" + " --user USER set non-privileged processes to run" + " as specified user\n" + " default: \"" NXT_USER "\"\n" + "\n" + " --group GROUP set non-privileged processes to run" + " as specified group\n" + " default: "; + + static const char group[] = "\"" NXT_GROUP "\"\n\n"; + static const char primary[] = "user's primary group\n\n"; + + argv = &nxt_process_argv[1]; + + while (*argv != NULL) { + p = *argv++; + + if (nxt_strcmp(p, "--control") == 0) { + if (*argv == NULL) { + write(STDERR_FILENO, no_control, nxt_length(no_control)); return NXT_ERROR; - } + } - return NXT_OK; -} + p = *argv++; + rt->control = p; -static nxt_int_t -nxt_runtime_conf_read_cmd(nxt_task_t *task, nxt_runtime_t *rt) -{ - char *p, **argv; - u_char *end; - u_char buf[1024]; - - static const char version[] = - "unit version: " NXT_VERSION "\n" - "configured as ./configure" NXT_CONFIGURE_OPTIONS "\n"; - - static const char no_control[] = - "option \"--control\" requires socket address\n"; - static const char no_control_mode[] = - "option \"--control-mode\" requires a mode\n"; - static const char no_control_user[] = - "option \"--control-user\" requires a username\n"; - static const char no_control_group[] = - "option \"--control-group\" requires a group name\n"; - static const char no_user[] = "option \"--user\" requires username\n"; - static const char no_group[] = "option \"--group\" requires group name\n"; - static const char no_pid[] = "option \"--pid\" requires filename\n"; - static const char no_log[] = "option \"--log\" requires filename\n"; - static const char no_modules[] = - "option \"--modulesdir\" requires directory\n"; - static const char no_state[] = - "option \"--statedir\" requires directory\n"; - static const char no_tmp[] = "option \"--tmpdir\" requires directory\n"; - - static const char modules_deprecated[] = - "option \"--modules\" is deprecated; use \"--modulesdir\" instead\n"; - static const char state_deprecated[] = - "option \"--state\" is deprecated; use \"--statedir\" instead\n"; - static const char tmp_deprecated[] = - "option \"--tmp\" is deprecated; use \"--tmpdir\" instead\n"; - - static const char help[] = - "\n" - "unit options:\n" - "\n" - " --version print unit version and configure options\n" - "\n" - " --no-daemon run unit in non-daemon mode\n" - "\n" - " --control ADDRESS set address of control API socket\n" - " default: \"" NXT_CONTROL_SOCK "\"\n" - "\n" - " --control-mode MODE set mode of the control API socket\n" - " default: 0600\n" - "\n" - " --control-user USER set the owner of the control API socket\n" - "\n" - " --control-group GROUP set the group of the control API socket\n" - "\n" - " --pid FILE set pid filename\n" - " default: \"" NXT_PID "\"\n" - "\n" - " --log FILE set log filename\n" - " default: \"" NXT_LOG "\"\n" - "\n" - " --modulesdir DIR set modules directory name\n" - " default: \"" NXT_MODULESDIR "\"\n" - "\n" - " --statedir DIR set state directory name\n" - " default: \"" NXT_STATEDIR "\"\n" - "\n" - " --tmpdir DIR set tmp directory name\n" - " default: \"" NXT_TMPDIR "\"\n" - "\n" - " --modules DIR [deprecated] synonym for --modulesdir\n" - " --state DIR [deprecated] synonym for --statedir\n" - " --tmp DIR [deprecated] synonym for --tmpdir\n" - "\n" - " --user USER set non-privileged processes to run" - " as specified user\n" - " default: \"" NXT_USER "\"\n" - "\n" - " --group GROUP set non-privileged processes to run" - " as specified group\n" - " default: "; - - static const char group[] = "\"" NXT_GROUP "\"\n\n"; - static const char primary[] = "user's primary group\n\n"; - - argv = &nxt_process_argv[1]; - - while (*argv != NULL) { - p = *argv++; - - if (nxt_strcmp(p, "--control") == 0) { - if (*argv == NULL) { - write(STDERR_FILENO, no_control, nxt_length(no_control)); - return NXT_ERROR; - } - - p = *argv++; - - rt->control = p; - - continue; - } + continue; + } - if (nxt_strcmp(p, "--control-mode") == 0) { - if (*argv == NULL) { - write(STDERR_FILENO, no_control_mode, - nxt_length(no_control_mode)); - return NXT_ERROR; - } + if (nxt_strcmp(p, "--control-mode") == 0) { + if (*argv == NULL) { + write(STDERR_FILENO, no_control_mode, nxt_length(no_control_mode)); + return NXT_ERROR; + } - p = *argv++; + p = *argv++; - rt->control_mode = strtoul(p, NULL, 8); + rt->control_mode = strtoul(p, NULL, 8); - continue; - } + continue; + } - if (nxt_strcmp(p, "--control-user") == 0) { - if (*argv == NULL) { - write(STDERR_FILENO, no_control_user, - nxt_length(no_control_user)); - return NXT_ERROR; - } + if (nxt_strcmp(p, "--control-user") == 0) { + if (*argv == NULL) { + write(STDERR_FILENO, no_control_user, nxt_length(no_control_user)); + return NXT_ERROR; + } - p = *argv++; + p = *argv++; - rt->control_user = p; + rt->control_user = p; - continue; - } + continue; + } - if (nxt_strcmp(p, "--control-group") == 0) { - if (*argv == NULL) { - write(STDERR_FILENO, no_control_group, - nxt_length(no_control_group)); - return NXT_ERROR; - } + if (nxt_strcmp(p, "--control-group") == 0) { + if (*argv == NULL) { + write(STDERR_FILENO, no_control_group, nxt_length(no_control_group)); + return NXT_ERROR; + } - p = *argv++; + p = *argv++; - rt->control_group = p; + rt->control_group = p; - continue; - } + continue; + } - if (nxt_strcmp(p, "--user") == 0) { - if (*argv == NULL) { - write(STDERR_FILENO, no_user, nxt_length(no_user)); - return NXT_ERROR; - } + if (nxt_strcmp(p, "--user") == 0) { + if (*argv == NULL) { + write(STDERR_FILENO, no_user, nxt_length(no_user)); + return NXT_ERROR; + } - p = *argv++; + p = *argv++; - rt->user_cred.user = p; + rt->user_cred.user = p; - continue; - } + continue; + } - if (nxt_strcmp(p, "--group") == 0) { - if (*argv == NULL) { - write(STDERR_FILENO, no_group, nxt_length(no_group)); - return NXT_ERROR; - } + if (nxt_strcmp(p, "--group") == 0) { + if (*argv == NULL) { + write(STDERR_FILENO, no_group, nxt_length(no_group)); + return NXT_ERROR; + } - p = *argv++; + p = *argv++; - rt->group = p; + rt->group = p; - continue; - } + continue; + } - if (nxt_strcmp(p, "--pid") == 0) { - if (*argv == NULL) { - write(STDERR_FILENO, no_pid, nxt_length(no_pid)); - return NXT_ERROR; - } + if (nxt_strcmp(p, "--pid") == 0) { + if (*argv == NULL) { + write(STDERR_FILENO, no_pid, nxt_length(no_pid)); + return NXT_ERROR; + } - p = *argv++; + p = *argv++; - rt->pid = p; + rt->pid = p; - continue; - } + continue; + } - if (nxt_strcmp(p, "--log") == 0) { - if (*argv == NULL) { - write(STDERR_FILENO, no_log, nxt_length(no_log)); - return NXT_ERROR; - } + if (nxt_strcmp(p, "--log") == 0) { + if (*argv == NULL) { + write(STDERR_FILENO, no_log, nxt_length(no_log)); + return NXT_ERROR; + } - p = *argv++; + p = *argv++; - rt->log = p; + rt->log = p; - continue; - } + continue; + } - if (nxt_strcmp(p, "--modules") == 0) { - write(STDERR_FILENO, modules_deprecated, - nxt_length(modules_deprecated)); - goto modulesdir; - } + if (nxt_strcmp(p, "--modules") == 0) { + write(STDERR_FILENO, modules_deprecated, nxt_length(modules_deprecated)); + goto modulesdir; + } - if (nxt_strcmp(p, "--modulesdir") == 0) { -modulesdir: - if (*argv == NULL) { - write(STDERR_FILENO, no_modules, nxt_length(no_modules)); - return NXT_ERROR; - } + if (nxt_strcmp(p, "--modulesdir") == 0) { + modulesdir: + if (*argv == NULL) { + write(STDERR_FILENO, no_modules, nxt_length(no_modules)); + return NXT_ERROR; + } - p = *argv++; + p = *argv++; - rt->modules = p; + rt->modules = p; - continue; - } + continue; + } - if (nxt_strcmp(p, "--state") == 0) { - write(STDERR_FILENO, state_deprecated, - nxt_length(state_deprecated)); - goto statedir; - } + if (nxt_strcmp(p, "--state") == 0) { + write(STDERR_FILENO, state_deprecated, nxt_length(state_deprecated)); + goto statedir; + } - if (nxt_strcmp(p, "--statedir") == 0) { -statedir: - if (*argv == NULL) { - write(STDERR_FILENO, no_state, nxt_length(no_state)); - return NXT_ERROR; - } + if (nxt_strcmp(p, "--statedir") == 0) { + statedir: + if (*argv == NULL) { + write(STDERR_FILENO, no_state, nxt_length(no_state)); + return NXT_ERROR; + } - p = *argv++; + p = *argv++; - rt->state = p; + rt->state = p; - continue; - } + continue; + } - if (nxt_strcmp(p, "--tmp") == 0) { - write(STDERR_FILENO, tmp_deprecated, nxt_length(tmp_deprecated)); - goto tmpdir; - } + if (nxt_strcmp(p, "--tmp") == 0) { + write(STDERR_FILENO, tmp_deprecated, nxt_length(tmp_deprecated)); + goto tmpdir; + } - if (nxt_strcmp(p, "--tmpdir") == 0) { -tmpdir: - if (*argv == NULL) { - write(STDERR_FILENO, no_tmp, nxt_length(no_tmp)); - return NXT_ERROR; - } + if (nxt_strcmp(p, "--tmpdir") == 0) { + tmpdir: + if (*argv == NULL) { + write(STDERR_FILENO, no_tmp, nxt_length(no_tmp)); + return NXT_ERROR; + } - p = *argv++; + p = *argv++; - rt->tmp = p; + rt->tmp = p; - continue; - } + continue; + } - if (nxt_strcmp(p, "--no-daemon") == 0) { - rt->daemon = 0; - continue; - } + if (nxt_strcmp(p, "--no-daemon") == 0) { + rt->daemon = 0; + continue; + } - if (nxt_strcmp(p, "--version") == 0) { - write(STDERR_FILENO, version, nxt_length(version)); - exit(0); - } + if (nxt_strcmp(p, "--version") == 0) { + write(STDERR_FILENO, version, nxt_length(version)); + exit(0); + } - if (nxt_strcmp(p, "--help") == 0 || nxt_strcmp(p, "-h") == 0) { - write(STDOUT_FILENO, help, nxt_length(help)); + if (nxt_strcmp(p, "--help") == 0 || nxt_strcmp(p, "-h") == 0) { + write(STDOUT_FILENO, help, nxt_length(help)); - if (sizeof(NXT_GROUP) == 1) { - write(STDOUT_FILENO, primary, nxt_length(primary)); + if (sizeof(NXT_GROUP) == 1) { + write(STDOUT_FILENO, primary, nxt_length(primary)); - } else { - write(STDOUT_FILENO, group, nxt_length(group)); - } + } else { + write(STDOUT_FILENO, group, nxt_length(group)); + } - exit(0); - } + exit(0); + } - end = nxt_sprintf(buf, buf + sizeof(buf), "unknown option \"%s\", " - "try \"%s -h\" for available options\n", - p, nxt_process_argv[0]); + end = nxt_sprintf(buf, buf + sizeof(buf), + "unknown option \"%s\", " + "try \"%s -h\" for available options\n", + p, nxt_process_argv[0]); - write(STDERR_FILENO, buf, end - buf); + write(STDERR_FILENO, buf, end - buf); - return NXT_ERROR; - } + return NXT_ERROR; + } - return NXT_OK; + return NXT_OK; } +nxt_listen_socket_t *nxt_runtime_listen_socket_add(nxt_runtime_t *rt, + nxt_sockaddr_t *sa) { + nxt_mp_t *mp; + nxt_listen_socket_t *ls; -nxt_listen_socket_t * -nxt_runtime_listen_socket_add(nxt_runtime_t *rt, nxt_sockaddr_t *sa) -{ - nxt_mp_t *mp; - nxt_listen_socket_t *ls; - - ls = nxt_array_zero_add(rt->listen_sockets); - if (ls == NULL) { - return NULL; - } + ls = nxt_array_zero_add(rt->listen_sockets); + if (ls == NULL) { + return NULL; + } - mp = rt->mem_pool; + mp = rt->mem_pool; - ls->sockaddr = nxt_sockaddr_create(mp, &sa->u.sockaddr, sa->socklen, - sa->length); - if (ls->sockaddr == NULL) { - return NULL; - } + ls->sockaddr = + nxt_sockaddr_create(mp, &sa->u.sockaddr, sa->socklen, sa->length); + if (ls->sockaddr == NULL) { + return NULL; + } - ls->sockaddr->type = sa->type; + ls->sockaddr->type = sa->type; - nxt_sockaddr_text(ls->sockaddr); + nxt_sockaddr_text(ls->sockaddr); - ls->socket = -1; - ls->backlog = NXT_LISTEN_BACKLOG; + ls->socket = -1; + ls->backlog = NXT_LISTEN_BACKLOG; - return ls; + return ls; } +static nxt_int_t nxt_runtime_hostname(nxt_task_t *task, nxt_runtime_t *rt) { + size_t length; + char hostname[NXT_MAXHOSTNAMELEN + 1]; -static nxt_int_t -nxt_runtime_hostname(nxt_task_t *task, nxt_runtime_t *rt) -{ - size_t length; - char hostname[NXT_MAXHOSTNAMELEN + 1]; + if (gethostname(hostname, NXT_MAXHOSTNAMELEN) != 0) { + nxt_alert(task, "gethostname() failed %E", nxt_errno); + return NXT_ERROR; + } - if (gethostname(hostname, NXT_MAXHOSTNAMELEN) != 0) { - nxt_alert(task, "gethostname() failed %E", nxt_errno); - return NXT_ERROR; - } + /* + * Linux gethostname(2): + * + * If the null-terminated hostname is too large to fit, + * then the name is truncated, and no error is returned. + * + * For this reason an additional byte is reserved in the buffer. + */ + hostname[NXT_MAXHOSTNAMELEN] = '\0'; - /* - * Linux gethostname(2): - * - * If the null-terminated hostname is too large to fit, - * then the name is truncated, and no error is returned. - * - * For this reason an additional byte is reserved in the buffer. - */ - hostname[NXT_MAXHOSTNAMELEN] = '\0'; + length = nxt_strlen(hostname); + rt->hostname.length = length; - length = nxt_strlen(hostname); - rt->hostname.length = length; + rt->hostname.start = nxt_mp_nget(rt->mem_pool, length); - rt->hostname.start = nxt_mp_nget(rt->mem_pool, length); - - if (rt->hostname.start != NULL) { - nxt_memcpy_lowcase(rt->hostname.start, (u_char *) hostname, length); - return NXT_OK; - } + if (rt->hostname.start != NULL) { + nxt_memcpy_lowcase(rt->hostname.start, (u_char *)hostname, length); + return NXT_OK; + } - return NXT_ERROR; + return NXT_ERROR; } +static nxt_int_t nxt_runtime_log_files_init(nxt_runtime_t *rt) { + nxt_file_t *file; + nxt_list_t *log_files; -static nxt_int_t -nxt_runtime_log_files_init(nxt_runtime_t *rt) -{ - nxt_file_t *file; - nxt_list_t *log_files; - - log_files = nxt_list_create(rt->mem_pool, 1, sizeof(nxt_file_t)); + log_files = nxt_list_create(rt->mem_pool, 1, sizeof(nxt_file_t)); - if (nxt_fast_path(log_files != NULL)) { - rt->log_files = log_files; + if (nxt_fast_path(log_files != NULL)) { + rt->log_files = log_files; - /* Preallocate the main log. This allocation cannot fail. */ - file = nxt_list_zero_add(log_files); + /* Preallocate the main log. This allocation cannot fail. */ + file = nxt_list_zero_add(log_files); - file->fd = NXT_FILE_INVALID; - file->log_level = NXT_LOG_ALERT; + file->fd = NXT_FILE_INVALID; + file->log_level = NXT_LOG_ALERT; - return NXT_OK; - } + return NXT_OK; + } - return NXT_ERROR; + return NXT_ERROR; } +nxt_file_t *nxt_runtime_log_file_add(nxt_runtime_t *rt, nxt_str_t *name) { + nxt_int_t ret; + nxt_file_t *file; + nxt_file_name_str_t file_name; -nxt_file_t * -nxt_runtime_log_file_add(nxt_runtime_t *rt, nxt_str_t *name) -{ - nxt_int_t ret; - nxt_file_t *file; - nxt_file_name_str_t file_name; - - ret = nxt_file_name_create(rt->mem_pool, &file_name, "V%Z", name); + ret = nxt_file_name_create(rt->mem_pool, &file_name, "V%Z", name); - if (nxt_slow_path(ret != NXT_OK)) { - return NULL; - } - - nxt_list_each(file, rt->log_files) { - - /* STUB: hardecoded case sensitive/insensitive. */ - - if (file->name != NULL - && nxt_file_name_eq(file->name, file_name.start)) - { - return file; - } + if (nxt_slow_path(ret != NXT_OK)) { + return NULL; + } - } nxt_list_loop; + nxt_list_each(file, rt->log_files) { - file = nxt_list_zero_add(rt->log_files); + /* STUB: hardecoded case sensitive/insensitive. */ - if (nxt_slow_path(file == NULL)) { - return NULL; + if (file->name != NULL && nxt_file_name_eq(file->name, file_name.start)) { + return file; } + } + nxt_list_loop; - file->fd = NXT_FILE_INVALID; - file->log_level = NXT_LOG_ALERT; - file->name = file_name.start; + file = nxt_list_zero_add(rt->log_files); - return file; -} + if (nxt_slow_path(file == NULL)) { + return NULL; + } + file->fd = NXT_FILE_INVALID; + file->log_level = NXT_LOG_ALERT; + file->name = file_name.start; -static nxt_int_t -nxt_runtime_log_files_create(nxt_task_t *task, nxt_runtime_t *rt) -{ - nxt_int_t ret; - nxt_file_t *file; + return file; +} - nxt_list_each(file, rt->log_files) { +static nxt_int_t nxt_runtime_log_files_create(nxt_task_t *task, + nxt_runtime_t *rt) { + nxt_int_t ret; + nxt_file_t *file; - ret = nxt_file_open(task, file, O_WRONLY | O_APPEND, O_CREAT, - NXT_FILE_OWNER_ACCESS); + nxt_list_each(file, rt->log_files) { - if (ret != NXT_OK) { - return NXT_ERROR; - } + ret = nxt_file_open(task, file, O_WRONLY | O_APPEND, O_CREAT, + NXT_FILE_OWNER_ACCESS); - } nxt_list_loop; + if (ret != NXT_OK) { + return NXT_ERROR; + } + } + nxt_list_loop; - file = nxt_list_first(rt->log_files); + file = nxt_list_first(rt->log_files); - return nxt_file_stderr(file); + return nxt_file_stderr(file); } +nxt_int_t nxt_runtime_listen_sockets_create(nxt_task_t *task, + nxt_runtime_t *rt) { + nxt_int_t ret; + nxt_uint_t c, p, ncurr, nprev; + nxt_listen_socket_t *curr, *prev; -nxt_int_t -nxt_runtime_listen_sockets_create(nxt_task_t *task, nxt_runtime_t *rt) -{ - nxt_int_t ret; - nxt_uint_t c, p, ncurr, nprev; - nxt_listen_socket_t *curr, *prev; - - curr = rt->listen_sockets->elts; - ncurr = rt->listen_sockets->nelts; + curr = rt->listen_sockets->elts; + ncurr = rt->listen_sockets->nelts; - if (rt->inherited_sockets != NULL) { - prev = rt->inherited_sockets->elts; - nprev = rt->inherited_sockets->nelts; + if (rt->inherited_sockets != NULL) { + prev = rt->inherited_sockets->elts; + nprev = rt->inherited_sockets->nelts; - } else { - prev = NULL; - nprev = 0; - } - - for (c = 0; c < ncurr; c++) { - - for (p = 0; p < nprev; p++) { + } else { + prev = NULL; + nprev = 0; + } - if (nxt_sockaddr_cmp(curr[c].sockaddr, prev[p].sockaddr)) { + for (c = 0; c < ncurr; c++) { - ret = nxt_listen_socket_update(task, &curr[c], &prev[p]); - if (ret != NXT_OK) { - return NXT_ERROR; - } + for (p = 0; p < nprev; p++) { - goto next; - } - } + if (nxt_sockaddr_cmp(curr[c].sockaddr, prev[p].sockaddr)) { - if (nxt_listen_socket_create(task, rt->mem_pool, &curr[c]) != NXT_OK) { - return NXT_ERROR; + ret = nxt_listen_socket_update(task, &curr[c], &prev[p]); + if (ret != NXT_OK) { + return NXT_ERROR; } - next: + goto next; + } + } - continue; + if (nxt_listen_socket_create(task, rt->mem_pool, &curr[c]) != NXT_OK) { + return NXT_ERROR; } - return NXT_OK; -} + next: + + continue; + } + return NXT_OK; +} -nxt_int_t -nxt_runtime_listen_sockets_enable(nxt_task_t *task, nxt_runtime_t *rt) -{ - nxt_uint_t i, n; - nxt_listen_socket_t *ls; +nxt_int_t nxt_runtime_listen_sockets_enable(nxt_task_t *task, + nxt_runtime_t *rt) { + nxt_uint_t i, n; + nxt_listen_socket_t *ls; - ls = rt->listen_sockets->elts; - n = rt->listen_sockets->nelts; + ls = rt->listen_sockets->elts; + n = rt->listen_sockets->nelts; - for (i = 0; i < n; i++) { - if (ls[i].flags == NXT_NONBLOCK) { - if (nxt_listen_event(task, &ls[i]) == NULL) { - return NXT_ERROR; - } - } + for (i = 0; i < n; i++) { + if (ls[i].flags == NXT_NONBLOCK) { + if (nxt_listen_event(task, &ls[i]) == NULL) { + return NXT_ERROR; + } } + } - return NXT_OK; + return NXT_OK; } +nxt_str_t *nxt_current_directory(nxt_mp_t *mp) { + size_t length; + u_char *p; + nxt_str_t *name; + char buf[NXT_MAX_PATH_LEN]; -nxt_str_t * -nxt_current_directory(nxt_mp_t *mp) -{ - size_t length; - u_char *p; - nxt_str_t *name; - char buf[NXT_MAX_PATH_LEN]; - - length = nxt_dir_current(buf, NXT_MAX_PATH_LEN); + length = nxt_dir_current(buf, NXT_MAX_PATH_LEN); - if (nxt_fast_path(length != 0)) { - name = nxt_str_alloc(mp, length + 1); + if (nxt_fast_path(length != 0)) { + name = nxt_str_alloc(mp, length + 1); - if (nxt_fast_path(name != NULL)) { - p = nxt_cpymem(name->start, buf, length); - *p = '/'; + if (nxt_fast_path(name != NULL)) { + p = nxt_cpymem(name->start, buf, length); + *p = '/'; - return name; - } + return name; } + } - return NULL; + return NULL; } +static nxt_int_t nxt_runtime_pid_file_create(nxt_task_t *task, + nxt_file_name_t *pid_file) { + ssize_t length; + nxt_int_t n; + nxt_file_t file; + u_char pid[NXT_INT64_T_LEN + nxt_length("\n")]; -static nxt_int_t -nxt_runtime_pid_file_create(nxt_task_t *task, nxt_file_name_t *pid_file) -{ - ssize_t length; - nxt_int_t n; - nxt_file_t file; - u_char pid[NXT_INT64_T_LEN + nxt_length("\n")]; - - nxt_memzero(&file, sizeof(nxt_file_t)); + nxt_memzero(&file, sizeof(nxt_file_t)); - file.name = pid_file; + file.name = pid_file; - nxt_fs_mkdir_p_dirname(pid_file, 0755); + nxt_fs_mkdir_p_dirname(pid_file, 0755); - n = nxt_file_open(task, &file, O_WRONLY, O_CREAT | O_TRUNC, - NXT_FILE_DEFAULT_ACCESS); + n = nxt_file_open(task, &file, O_WRONLY, O_CREAT | O_TRUNC, + NXT_FILE_DEFAULT_ACCESS); - if (n != NXT_OK) { - return NXT_ERROR; - } + if (n != NXT_OK) { + return NXT_ERROR; + } - length = nxt_sprintf(pid, pid + sizeof(pid), "%PI%n", nxt_pid) - pid; + length = nxt_sprintf(pid, pid + sizeof(pid), "%PI%n", nxt_pid) - pid; - if (nxt_file_write(&file, pid, length, 0) != length) { - return NXT_ERROR; - } + if (nxt_file_write(&file, pid, length, 0) != length) { + return NXT_ERROR; + } - nxt_file_close(task, &file); + nxt_file_close(task, &file); - return NXT_OK; + return NXT_OK; } +void nxt_runtime_process_release(nxt_runtime_t *rt, nxt_process_t *process) { + nxt_process_t *child; -void -nxt_runtime_process_release(nxt_runtime_t *rt, nxt_process_t *process) -{ - nxt_process_t *child; + if (process->registered == 1) { + nxt_runtime_process_remove(rt, process); + } - if (process->registered == 1) { - nxt_runtime_process_remove(rt, process); - } + if (process->link.next != NULL) { + nxt_queue_remove(&process->link); + } - if (process->link.next != NULL) { - nxt_queue_remove(&process->link); - } + nxt_queue_each(child, &process->children, nxt_process_t, link) { + nxt_queue_remove(&child->link); + child->link.next = NULL; + } + nxt_queue_loop; - nxt_queue_each(child, &process->children, nxt_process_t, link) { - nxt_queue_remove(&child->link); - child->link.next = NULL; - } nxt_queue_loop; + nxt_assert(process->use_count == 0); + nxt_assert(process->registered == 0); + nxt_assert(nxt_queue_is_empty(&process->ports)); - nxt_assert(process->use_count == 0); - nxt_assert(process->registered == 0); - nxt_assert(nxt_queue_is_empty(&process->ports)); + nxt_port_mmaps_destroy(&process->incoming, 1); - nxt_port_mmaps_destroy(&process->incoming, 1); + nxt_thread_mutex_destroy(&process->incoming.mutex); - nxt_thread_mutex_destroy(&process->incoming.mutex); - - /* processes from nxt_runtime_process_get() have no memory pool */ - if (process->mem_pool != NULL) { - nxt_mp_destroy(process->mem_pool); - } + /* processes from nxt_runtime_process_get() have no memory pool */ + if (process->mem_pool != NULL) { + nxt_mp_destroy(process->mem_pool); + } - nxt_mp_free(rt->mem_pool, process); + nxt_mp_free(rt->mem_pool, process); } +static nxt_int_t nxt_runtime_lvlhsh_pid_test(nxt_lvlhsh_query_t *lhq, + void *data) { + nxt_process_t *process; -static nxt_int_t -nxt_runtime_lvlhsh_pid_test(nxt_lvlhsh_query_t *lhq, void *data) -{ - nxt_process_t *process; + process = data; - process = data; - - if (lhq->key.length == sizeof(nxt_pid_t) - && *(nxt_pid_t *) lhq->key.start == process->pid) - { - return NXT_OK; - } + if (lhq->key.length == sizeof(nxt_pid_t) && + *(nxt_pid_t *)lhq->key.start == process->pid) { + return NXT_OK; + } - return NXT_DECLINED; + return NXT_DECLINED; } -static const nxt_lvlhsh_proto_t lvlhsh_processes_proto nxt_aligned(64) = { +static const nxt_lvlhsh_proto_t lvlhsh_processes_proto nxt_aligned(64) = { NXT_LVLHSH_DEFAULT, nxt_runtime_lvlhsh_pid_test, nxt_lvlhsh_alloc, nxt_lvlhsh_free, }; - -nxt_inline void -nxt_runtime_process_lhq_pid(nxt_lvlhsh_query_t *lhq, nxt_pid_t *pid) -{ - lhq->key_hash = nxt_murmur_hash2(pid, sizeof(*pid)); - lhq->key.length = sizeof(*pid); - lhq->key.start = (u_char *) pid; - lhq->proto = &lvlhsh_processes_proto; +nxt_inline void nxt_runtime_process_lhq_pid(nxt_lvlhsh_query_t *lhq, + nxt_pid_t *pid) { + lhq->key_hash = nxt_murmur_hash2(pid, sizeof(*pid)); + lhq->key.length = sizeof(*pid); + lhq->key.start = (u_char *)pid; + lhq->proto = &lvlhsh_processes_proto; } +nxt_process_t *nxt_runtime_process_find(nxt_runtime_t *rt, nxt_pid_t pid) { + nxt_process_t *process; + nxt_lvlhsh_query_t lhq; -nxt_process_t * -nxt_runtime_process_find(nxt_runtime_t *rt, nxt_pid_t pid) -{ - nxt_process_t *process; - nxt_lvlhsh_query_t lhq; - - process = NULL; + process = NULL; - nxt_runtime_process_lhq_pid(&lhq, &pid); + nxt_runtime_process_lhq_pid(&lhq, &pid); - nxt_thread_mutex_lock(&rt->processes_mutex); + nxt_thread_mutex_lock(&rt->processes_mutex); - if (nxt_lvlhsh_find(&rt->processes, &lhq) == NXT_OK) { - process = lhq.value; + if (nxt_lvlhsh_find(&rt->processes, &lhq) == NXT_OK) { + process = lhq.value; - } else { - nxt_thread_log_debug("process %PI not found", pid); - } + } else { + nxt_thread_log_debug("process %PI not found", pid); + } - nxt_thread_mutex_unlock(&rt->processes_mutex); + nxt_thread_mutex_unlock(&rt->processes_mutex); - return process; + return process; } +static nxt_process_t *nxt_runtime_process_get(nxt_runtime_t *rt, + nxt_pid_t pid) { + nxt_process_t *process; + nxt_lvlhsh_query_t lhq; -static nxt_process_t * -nxt_runtime_process_get(nxt_runtime_t *rt, nxt_pid_t pid) -{ - nxt_process_t *process; - nxt_lvlhsh_query_t lhq; + nxt_runtime_process_lhq_pid(&lhq, &pid); - nxt_runtime_process_lhq_pid(&lhq, &pid); + nxt_thread_mutex_lock(&rt->processes_mutex); - nxt_thread_mutex_lock(&rt->processes_mutex); + if (nxt_lvlhsh_find(&rt->processes, &lhq) == NXT_OK) { + nxt_thread_log_debug("process %PI found", pid); - if (nxt_lvlhsh_find(&rt->processes, &lhq) == NXT_OK) { - nxt_thread_log_debug("process %PI found", pid); - - nxt_thread_mutex_unlock(&rt->processes_mutex); + nxt_thread_mutex_unlock(&rt->processes_mutex); - process = lhq.value; - process->use_count++; + process = lhq.value; + process->use_count++; - return process; - } + return process; + } - process = nxt_process_new(rt); - if (nxt_slow_path(process == NULL)) { + process = nxt_process_new(rt); + if (nxt_slow_path(process == NULL)) { - nxt_thread_mutex_unlock(&rt->processes_mutex); + nxt_thread_mutex_unlock(&rt->processes_mutex); - return NULL; - } + return NULL; + } - process->pid = pid; + process->pid = pid; - lhq.replace = 0; - lhq.value = process; - lhq.pool = rt->mem_pool; + lhq.replace = 0; + lhq.value = process; + lhq.pool = rt->mem_pool; - switch (nxt_lvlhsh_insert(&rt->processes, &lhq)) { + switch (nxt_lvlhsh_insert(&rt->processes, &lhq)) { - case NXT_OK: - if (rt->nprocesses == 0) { - rt->mprocess = process; - } + case NXT_OK: + if (rt->nprocesses == 0) { + rt->mprocess = process; + } - rt->nprocesses++; + rt->nprocesses++; - process->registered = 1; + process->registered = 1; - nxt_thread_log_debug("process %PI insert", pid); - break; + nxt_thread_log_debug("process %PI insert", pid); + break; - default: - nxt_thread_log_debug("process %PI insert failed", pid); - break; - } + default: + nxt_thread_log_debug("process %PI insert failed", pid); + break; + } - nxt_thread_mutex_unlock(&rt->processes_mutex); + nxt_thread_mutex_unlock(&rt->processes_mutex); - return process; + return process; } +void nxt_runtime_process_add(nxt_task_t *task, nxt_process_t *process) { + nxt_port_t *port; + nxt_runtime_t *rt; + nxt_lvlhsh_query_t lhq; -void -nxt_runtime_process_add(nxt_task_t *task, nxt_process_t *process) -{ - nxt_port_t *port; - nxt_runtime_t *rt; - nxt_lvlhsh_query_t lhq; + nxt_assert(process->registered == 0); - nxt_assert(process->registered == 0); + rt = task->thread->runtime; - rt = task->thread->runtime; + nxt_runtime_process_lhq_pid(&lhq, &process->pid); - nxt_runtime_process_lhq_pid(&lhq, &process->pid); + lhq.replace = 0; + lhq.value = process; + lhq.pool = rt->mem_pool; - lhq.replace = 0; - lhq.value = process; - lhq.pool = rt->mem_pool; + nxt_thread_mutex_lock(&rt->processes_mutex); - nxt_thread_mutex_lock(&rt->processes_mutex); - - switch (nxt_lvlhsh_insert(&rt->processes, &lhq)) { - - case NXT_OK: - if (rt->nprocesses == 0) { - rt->mprocess = process; - } + switch (nxt_lvlhsh_insert(&rt->processes, &lhq)) { - rt->nprocesses++; + case NXT_OK: + if (rt->nprocesses == 0) { + rt->mprocess = process; + } - nxt_process_port_each(process, port) { + rt->nprocesses++; - port->pid = process->pid; + nxt_process_port_each(process, port) { - nxt_runtime_port_add(task, port); + port->pid = process->pid; - } nxt_process_port_loop; + nxt_runtime_port_add(task, port); + } + nxt_process_port_loop; - process->registered = 1; + process->registered = 1; - nxt_debug(task, "process %PI added", process->pid); - break; + nxt_debug(task, "process %PI added", process->pid); + break; - default: - nxt_alert(task, "process %PI failed to add", process->pid); - break; - } + default: + nxt_alert(task, "process %PI failed to add", process->pid); + break; + } - nxt_thread_mutex_unlock(&rt->processes_mutex); + nxt_thread_mutex_unlock(&rt->processes_mutex); } +void nxt_runtime_process_remove(nxt_runtime_t *rt, nxt_process_t *process) { + nxt_pid_t pid; + nxt_lvlhsh_query_t lhq; -void -nxt_runtime_process_remove(nxt_runtime_t *rt, nxt_process_t *process) -{ - nxt_pid_t pid; - nxt_lvlhsh_query_t lhq; - - nxt_assert(process->registered != 0); + nxt_assert(process->registered != 0); - pid = process->pid; + pid = process->pid; - nxt_runtime_process_lhq_pid(&lhq, &pid); + nxt_runtime_process_lhq_pid(&lhq, &pid); - lhq.pool = rt->mem_pool; + lhq.pool = rt->mem_pool; - nxt_thread_mutex_lock(&rt->processes_mutex); + nxt_thread_mutex_lock(&rt->processes_mutex); - switch (nxt_lvlhsh_delete(&rt->processes, &lhq)) { + switch (nxt_lvlhsh_delete(&rt->processes, &lhq)) { - case NXT_OK: - nxt_assert(lhq.value == process); + case NXT_OK: + nxt_assert(lhq.value == process); - rt->nprocesses--; + rt->nprocesses--; - process->registered = 0; + process->registered = 0; - nxt_thread_log_debug("process %PI removed", pid); - break; + nxt_thread_log_debug("process %PI removed", pid); + break; - default: - nxt_thread_log_alert("process %PI remove failed", pid); - break; - } + default: + nxt_thread_log_alert("process %PI remove failed", pid); + break; + } - nxt_thread_mutex_unlock(&rt->processes_mutex); + nxt_thread_mutex_unlock(&rt->processes_mutex); } +nxt_process_t *nxt_runtime_process_first(nxt_runtime_t *rt, + nxt_lvlhsh_each_t *lhe) { + nxt_lvlhsh_each_init(lhe, &lvlhsh_processes_proto); -nxt_process_t * -nxt_runtime_process_first(nxt_runtime_t *rt, nxt_lvlhsh_each_t *lhe) -{ - nxt_lvlhsh_each_init(lhe, &lvlhsh_processes_proto); - - return nxt_runtime_process_next(rt, lhe); + return nxt_runtime_process_next(rt, lhe); } +nxt_port_t *nxt_runtime_process_port_create(nxt_task_t *task, nxt_runtime_t *rt, + nxt_pid_t pid, nxt_port_id_t id, + nxt_process_type_t type) { + nxt_port_t *port; + nxt_process_t *process; -nxt_port_t * -nxt_runtime_process_port_create(nxt_task_t *task, nxt_runtime_t *rt, - nxt_pid_t pid, nxt_port_id_t id, nxt_process_type_t type) -{ - nxt_port_t *port; - nxt_process_t *process; - - process = nxt_runtime_process_get(rt, pid); - if (nxt_slow_path(process == NULL)) { - return NULL; - } + process = nxt_runtime_process_get(rt, pid); + if (nxt_slow_path(process == NULL)) { + return NULL; + } - port = nxt_port_new(task, id, pid, type); - if (nxt_slow_path(port == NULL)) { - nxt_process_use(task, process, -1); - return NULL; - } + port = nxt_port_new(task, id, pid, type); + if (nxt_slow_path(port == NULL)) { + nxt_process_use(task, process, -1); + return NULL; + } - nxt_process_port_add(task, process, port); + nxt_process_port_add(task, process, port); - nxt_process_use(task, process, -1); + nxt_process_use(task, process, -1); - nxt_runtime_port_add(task, port); + nxt_runtime_port_add(task, port); - nxt_port_use(task, port, -1); + nxt_port_use(task, port, -1); - return port; + return port; } +static void nxt_runtime_port_add(nxt_task_t *task, nxt_port_t *port) { + nxt_int_t res; + nxt_runtime_t *rt; -static void -nxt_runtime_port_add(nxt_task_t *task, nxt_port_t *port) -{ - nxt_int_t res; - nxt_runtime_t *rt; + rt = task->thread->runtime; - rt = task->thread->runtime; + res = nxt_port_hash_add(&rt->ports, port); - res = nxt_port_hash_add(&rt->ports, port); - - if (res != NXT_OK) { - return; - } + if (res != NXT_OK) { + return; + } - rt->port_by_type[port->type] = port; + rt->port_by_type[port->type] = port; - nxt_port_use(task, port, 1); + nxt_port_use(task, port, 1); } +void nxt_runtime_port_remove(nxt_task_t *task, nxt_port_t *port) { + nxt_int_t res; + nxt_runtime_t *rt; -void -nxt_runtime_port_remove(nxt_task_t *task, nxt_port_t *port) -{ - nxt_int_t res; - nxt_runtime_t *rt; + rt = task->thread->runtime; - rt = task->thread->runtime; + res = nxt_port_hash_remove(&rt->ports, port); - res = nxt_port_hash_remove(&rt->ports, port); + if (res != NXT_OK) { + return; + } - if (res != NXT_OK) { - return; - } + if (rt->port_by_type[port->type] == port) { + rt->port_by_type[port->type] = NULL; + } - if (rt->port_by_type[port->type] == port) { - rt->port_by_type[port->type] = NULL; - } - - nxt_port_use(task, port, -1); + nxt_port_use(task, port, -1); } - -nxt_port_t * -nxt_runtime_port_find(nxt_runtime_t *rt, nxt_pid_t pid, - nxt_port_id_t port_id) -{ - return nxt_port_hash_find(&rt->ports, pid, port_id); +nxt_port_t *nxt_runtime_port_find(nxt_runtime_t *rt, nxt_pid_t pid, + nxt_port_id_t port_id) { + return nxt_port_hash_find(&rt->ports, pid, port_id); } diff --git a/src/nxt_runtime.h b/src/nxt_runtime.h index 7bd490d70..1db5edb80 100644 --- a/src/nxt_runtime.h +++ b/src/nxt_runtime.h @@ -8,97 +8,92 @@ #ifndef _NXT_RUNTIME_H_INCLUDED_ #define _NXT_RUNTIME_H_INCLUDED_ - typedef void (*nxt_runtime_cont_t)(nxt_task_t *task, nxt_uint_t status); - struct nxt_runtime_s { - nxt_mp_t *mem_pool; + nxt_mp_t *mem_pool; - nxt_array_t *inherited_sockets; /* of nxt_listen_socket_t */ - nxt_array_t *listen_sockets; /* of nxt_listen_socket_t */ + nxt_array_t *inherited_sockets; /* of nxt_listen_socket_t */ + nxt_array_t *listen_sockets; /* of nxt_listen_socket_t */ - nxt_array_t *services; /* of nxt_service_t */ - nxt_array_t *languages; /* of nxt_app_lang_module_t */ - void *data; + nxt_array_t *services; /* of nxt_service_t */ + nxt_array_t *languages; /* of nxt_app_lang_module_t */ + void *data; - nxt_runtime_cont_t start; + nxt_runtime_cont_t start; - nxt_str_t hostname; + nxt_str_t hostname; - nxt_file_name_t *pid_file; + nxt_file_name_t *pid_file; #if (NXT_TLS) - const nxt_tls_lib_t *tls; + const nxt_tls_lib_t *tls; #endif - nxt_array_t *thread_pools; /* of nxt_thread_pool_t */ - nxt_runtime_cont_t continuation; + nxt_array_t *thread_pools; /* of nxt_thread_pool_t */ + nxt_runtime_cont_t continuation; - nxt_process_t *mprocess; - size_t nprocesses; - nxt_thread_mutex_t processes_mutex; - nxt_lvlhsh_t processes; /* of nxt_process_t */ + nxt_process_t *mprocess; + size_t nprocesses; + nxt_thread_mutex_t processes_mutex; + nxt_lvlhsh_t processes; /* of nxt_process_t */ - nxt_port_t *port_by_type[NXT_PROCESS_MAX]; - nxt_lvlhsh_t ports; /* of nxt_port_t */ + nxt_port_t *port_by_type[NXT_PROCESS_MAX]; + nxt_lvlhsh_t ports; /* of nxt_port_t */ - nxt_list_t *log_files; /* of nxt_file_t */ + nxt_list_t *log_files; /* of nxt_file_t */ - uint32_t last_engine_id; + uint32_t last_engine_id; - nxt_process_type_t type; + nxt_process_type_t type; - nxt_timer_t timer; + nxt_timer_t timer; - uint8_t daemon; - uint8_t batch; - uint8_t status; - uint8_t is_pid_isolated; + uint8_t daemon; + uint8_t batch; + uint8_t status; + uint8_t is_pid_isolated; - const char *engine; - uint32_t engine_connections; - uint32_t auxiliary_threads; - nxt_credential_t user_cred; - nxt_capabilities_t capabilities; - const char *group; - const char *pid; - const char *log; - const char *modules; - const char *state; - const char *ver; - const char *ver_tmp; - const char *conf; - const char *conf_tmp; - const char *tmp; - const char *control; + const char *engine; + uint32_t engine_connections; + uint32_t auxiliary_threads; + nxt_credential_t user_cred; + nxt_capabilities_t capabilities; + const char *group; + const char *pid; + const char *log; + const char *modules; + const char *state; + const char *ver; + const char *ver_tmp; + const char *conf; + const char *conf_tmp; + const char *tmp; + const char *control; - mode_t control_mode; - const char *control_user; - const char *control_group; + mode_t control_mode; + const char *control_user; + const char *control_group; - nxt_str_t certs; - nxt_str_t scripts; + nxt_str_t certs; + nxt_str_t scripts; - nxt_queue_t engines; /* of nxt_event_engine_t */ + nxt_queue_t engines; /* of nxt_event_engine_t */ - nxt_sockaddr_t *controller_listen; - nxt_listen_socket_t *controller_socket; + nxt_sockaddr_t *controller_listen; + nxt_listen_socket_t *controller_socket; }; - - typedef nxt_int_t (*nxt_module_init_t)(nxt_thread_t *thr, nxt_runtime_t *rt); - nxt_int_t nxt_runtime_create(nxt_task_t *task); void nxt_runtime_quit(nxt_task_t *task, nxt_uint_t status); void nxt_runtime_event_engine_free(nxt_runtime_t *rt); nxt_int_t nxt_runtime_thread_pool_create(nxt_thread_t *thr, nxt_runtime_t *rt, - nxt_uint_t max_threads, nxt_nsec_t timeout); - + nxt_uint_t max_threads, + nxt_nsec_t timeout); void nxt_runtime_process_add(nxt_task_t *task, nxt_process_t *process); void nxt_runtime_process_remove(nxt_runtime_t *rt, nxt_process_t *process); @@ -106,22 +101,21 @@ void nxt_runtime_process_remove(nxt_runtime_t *rt, nxt_process_t *process); nxt_process_t *nxt_runtime_process_find(nxt_runtime_t *rt, nxt_pid_t pid); nxt_process_t *nxt_runtime_process_first(nxt_runtime_t *rt, - nxt_lvlhsh_each_t *lhe); + nxt_lvlhsh_each_t *lhe); void nxt_runtime_process_release(nxt_runtime_t *rt, nxt_process_t *process); -#define nxt_runtime_process_next(rt, lhe) \ - nxt_lvlhsh_each(&rt->processes, lhe) +#define nxt_runtime_process_next(rt, lhe) nxt_lvlhsh_each(&rt->processes, lhe) nxt_port_t *nxt_runtime_process_port_create(nxt_task_t *task, nxt_runtime_t *rt, - nxt_pid_t pid, nxt_port_id_t id, nxt_process_type_t type); + nxt_pid_t pid, nxt_port_id_t id, + nxt_process_type_t type); void nxt_runtime_port_remove(nxt_task_t *task, nxt_port_t *port); void nxt_runtime_stop_app_processes(nxt_task_t *task, nxt_runtime_t *rt); NXT_EXPORT nxt_port_t *nxt_runtime_port_find(nxt_runtime_t *rt, nxt_pid_t pid, - nxt_port_id_t port_id); - + nxt_port_id_t port_id); /* STUB */ nxt_int_t nxt_runtime_controller_socket(nxt_task_t *task, nxt_runtime_t *rt); @@ -129,16 +123,16 @@ nxt_int_t nxt_runtime_controller_socket(nxt_task_t *task, nxt_runtime_t *rt); nxt_str_t *nxt_current_directory(nxt_mp_t *mp); nxt_listen_socket_t *nxt_runtime_listen_socket_add(nxt_runtime_t *rt, - nxt_sockaddr_t *sa); + nxt_sockaddr_t *sa); nxt_int_t nxt_runtime_listen_sockets_create(nxt_task_t *task, - nxt_runtime_t *rt); + nxt_runtime_t *rt); nxt_int_t nxt_runtime_listen_sockets_enable(nxt_task_t *task, - nxt_runtime_t *rt); + nxt_runtime_t *rt); nxt_file_t *nxt_runtime_log_file_add(nxt_runtime_t *rt, nxt_str_t *name); /* STUB */ void nxt_cdecl nxt_log_time_handler(nxt_uint_t level, nxt_log_t *log, - const char *fmt, ...); + const char *fmt, ...); void nxt_stream_connection_init(nxt_task_t *task, void *obj, void *data); @@ -147,25 +141,22 @@ nxt_int_t nxt_http_register_variables(void); void nxt_http_register_js_proto(nxt_js_conf_t *jcf); #endif - -#define nxt_runtime_process_each(rt, process) \ - do { \ - nxt_lvlhsh_each_t _lhe; \ - nxt_process_t *_nxt; \ - \ - for (process = nxt_runtime_process_first(rt, &_lhe); \ - process != NULL; \ - process = _nxt) { \ - \ - _nxt = nxt_runtime_process_next(rt, &_lhe); \ - -#define nxt_runtime_process_loop \ - } \ - } while(0) - - -extern nxt_module_init_t nxt_init_modules[]; -extern nxt_uint_t nxt_init_modules_n; - +#define nxt_runtime_process_each(rt, process) \ + do { \ + nxt_lvlhsh_each_t _lhe; \ + nxt_process_t *_nxt; \ + \ + for (process = nxt_runtime_process_first(rt, &_lhe); process != NULL; \ + process = _nxt) { \ + \ + _nxt = nxt_runtime_process_next(rt, &_lhe); + +#define nxt_runtime_process_loop \ + } \ + } \ + while (0) + +extern nxt_module_init_t nxt_init_modules[]; +extern nxt_uint_t nxt_init_modules_n; #endif /* _NXT_RUNTIME_H_INCLIDED_ */ diff --git a/src/nxt_script.c b/src/nxt_script.c index 05d9561da..edfc2c649 100644 --- a/src/nxt_script.c +++ b/src/nxt_script.c @@ -9,691 +9,627 @@ #include #include - struct nxt_script_s { - nxt_str_t text; + nxt_str_t text; }; - typedef struct { - nxt_str_t name; - nxt_conf_value_t *value; - nxt_mp_t *mp; + nxt_str_t name; + nxt_conf_value_t *value; + nxt_mp_t *mp; } nxt_script_info_t; - typedef struct { - nxt_str_t name; - nxt_fd_t fd; + nxt_str_t name; + nxt_fd_t fd; } nxt_script_item_t; - static nxt_script_t *nxt_script_get(nxt_task_t *task, nxt_str_t *name, - nxt_fd_t fd); + nxt_fd_t fd); static nxt_conf_value_t *nxt_script_details(nxt_mp_t *mp, nxt_script_t *cert); static void nxt_script_buf_completion(nxt_task_t *task, void *obj, void *data); +static nxt_lvlhsh_t nxt_script_info; -static nxt_lvlhsh_t nxt_script_info; +nxt_script_t *nxt_script_new(nxt_task_t *task, nxt_str_t *name, u_char *data, + size_t size, u_char *error) { + u_char *start; + njs_vm_t *vm; + njs_str_t mod_name; + njs_mod_t *mod; + njs_vm_opt_t opts; + nxt_script_t *script; + njs_vm_opt_init(&opts); -nxt_script_t * -nxt_script_new(nxt_task_t *task, nxt_str_t *name, u_char *data, size_t size, - u_char *error) -{ - u_char *start; - njs_vm_t *vm; - njs_str_t mod_name; - njs_mod_t *mod; - njs_vm_opt_t opts; - nxt_script_t *script; + opts.backtrace = 1; - njs_vm_opt_init(&opts); + opts.file.start = (u_char *)"default"; + opts.file.length = 7; - opts.backtrace = 1; + vm = njs_vm_create(&opts); + if (nxt_slow_path(vm == NULL)) { + return NULL; + } - opts.file.start = (u_char *) "default"; - opts.file.length = 7; + mod_name.length = name->length; + mod_name.start = name->start; - vm = njs_vm_create(&opts); - if (nxt_slow_path(vm == NULL)) { - return NULL; - } + start = data; - mod_name.length = name->length; - mod_name.start = name->start; + mod = njs_vm_compile_module(vm, &mod_name, &start, start + size); - start = data; + if (nxt_slow_path(mod == NULL)) { + (void)nxt_js_error(vm, error); + nxt_alert(task, "JS compile module(%V) failed: %s", name, error); - mod = njs_vm_compile_module(vm, &mod_name, &start, start + size); + goto fail; + } - if (nxt_slow_path(mod == NULL)) { - (void) nxt_js_error(vm, error); - nxt_alert(task, "JS compile module(%V) failed: %s", name, error); + script = nxt_zalloc(sizeof(nxt_script_t) + size); + if (nxt_slow_path(script == NULL)) { + goto fail; + } - goto fail; - } + script->text.length = size; + script->text.start = (u_char *)script + sizeof(nxt_script_t); - script = nxt_zalloc(sizeof(nxt_script_t) + size); - if (nxt_slow_path(script == NULL)) { - goto fail; - } - - script->text.length = size; - script->text.start = (u_char *) script + sizeof(nxt_script_t); - - nxt_memcpy(script->text.start, data, size); + nxt_memcpy(script->text.start, data, size); - njs_vm_destroy(vm); + njs_vm_destroy(vm); - return script; + return script; fail: - njs_vm_destroy(vm); + njs_vm_destroy(vm); - return NULL; + return NULL; } +static nxt_script_t *nxt_script_get(nxt_task_t *task, nxt_str_t *name, + nxt_fd_t fd) { + nxt_int_t ret; + nxt_str_t text; + nxt_script_t *script; + u_char error[NXT_MAX_ERROR_STR]; + + ret = nxt_script_file_read(fd, &text); + if (nxt_slow_path(ret != NXT_OK)) { + return NULL; + } -static nxt_script_t * -nxt_script_get(nxt_task_t *task, nxt_str_t *name, nxt_fd_t fd) -{ - nxt_int_t ret; - nxt_str_t text; - nxt_script_t *script; - u_char error[NXT_MAX_ERROR_STR]; - - ret = nxt_script_file_read(fd, &text); - if (nxt_slow_path(ret != NXT_OK)) { - return NULL; - } - - script = nxt_script_new(task, name, text.start, text.length, error); - - nxt_free(text.start); + script = nxt_script_new(task, name, text.start, text.length, error); - return script; -} + nxt_free(text.start); - -void -nxt_script_destroy(nxt_script_t *script) -{ - nxt_free(script); + return script; } +void nxt_script_destroy(nxt_script_t *script) { nxt_free(script); } -static nxt_int_t -nxt_script_info_hash_test(nxt_lvlhsh_query_t *lhq, void *data) -{ - nxt_script_info_t *info; +static nxt_int_t nxt_script_info_hash_test(nxt_lvlhsh_query_t *lhq, + void *data) { + nxt_script_info_t *info; - info = data; + info = data; - if (nxt_strcasestr_eq(&lhq->key, &info->name)) { - return NXT_OK; - } + if (nxt_strcasestr_eq(&lhq->key, &info->name)) { + return NXT_OK; + } - return NXT_DECLINED; + return NXT_DECLINED; } - -static const nxt_lvlhsh_proto_t nxt_script_info_hash_proto - nxt_aligned(64) = -{ +static const nxt_lvlhsh_proto_t nxt_script_info_hash_proto nxt_aligned(64) = { NXT_LVLHSH_DEFAULT, nxt_script_info_hash_test, nxt_lvlhsh_alloc, nxt_lvlhsh_free, }; +void nxt_script_info_init(nxt_task_t *task, nxt_array_t *scripts) { + uint32_t i; + nxt_script_t *script; + nxt_script_item_t *item; -void -nxt_script_info_init(nxt_task_t *task, nxt_array_t *scripts) -{ - uint32_t i; - nxt_script_t *script; - nxt_script_item_t *item; - - item = scripts->elts; - - for (i = 0; i < scripts->nelts; i++) { - script = nxt_script_get(task, &item->name, item->fd); - - if (nxt_slow_path(script == NULL)) { - continue; - } - - (void) nxt_script_info_save(&item->name, script); - - nxt_script_destroy(script); - - item++; - } -} - - -nxt_int_t -nxt_script_info_save(nxt_str_t *name, nxt_script_t *script) -{ - nxt_mp_t *mp; - nxt_int_t ret; - nxt_conf_value_t *value; - nxt_script_info_t *info; - nxt_lvlhsh_query_t lhq; + item = scripts->elts; - mp = nxt_mp_create(1024, 128, 256, 32); - if (nxt_slow_path(mp == NULL)) { - return NXT_ERROR; - } + for (i = 0; i < scripts->nelts; i++) { + script = nxt_script_get(task, &item->name, item->fd); - info = nxt_mp_get(mp, sizeof(nxt_script_info_t)); - if (nxt_slow_path(info == NULL)) { - goto fail; + if (nxt_slow_path(script == NULL)) { + continue; } - name = nxt_str_dup(mp, &info->name, name); - if (nxt_slow_path(name == NULL)) { - goto fail; - } + (void)nxt_script_info_save(&item->name, script); - value = nxt_script_details(mp, script); - if (nxt_slow_path(value == NULL)) { - goto fail; - } + nxt_script_destroy(script); - info->mp = mp; - info->value = value; + item++; + } +} - lhq.key_hash = nxt_djb_hash(name->start, name->length); - lhq.replace = 1; - lhq.key = *name; - lhq.value = info; - lhq.proto = &nxt_script_info_hash_proto; +nxt_int_t nxt_script_info_save(nxt_str_t *name, nxt_script_t *script) { + nxt_mp_t *mp; + nxt_int_t ret; + nxt_conf_value_t *value; + nxt_script_info_t *info; + nxt_lvlhsh_query_t lhq; - ret = nxt_lvlhsh_insert(&nxt_script_info, &lhq); - if (nxt_slow_path(ret != NXT_OK)) { - goto fail; - } + mp = nxt_mp_create(1024, 128, 256, 32); + if (nxt_slow_path(mp == NULL)) { + return NXT_ERROR; + } + + info = nxt_mp_get(mp, sizeof(nxt_script_info_t)); + if (nxt_slow_path(info == NULL)) { + goto fail; + } + + name = nxt_str_dup(mp, &info->name, name); + if (nxt_slow_path(name == NULL)) { + goto fail; + } + + value = nxt_script_details(mp, script); + if (nxt_slow_path(value == NULL)) { + goto fail; + } + + info->mp = mp; + info->value = value; + + lhq.key_hash = nxt_djb_hash(name->start, name->length); + lhq.replace = 1; + lhq.key = *name; + lhq.value = info; + lhq.proto = &nxt_script_info_hash_proto; + + ret = nxt_lvlhsh_insert(&nxt_script_info, &lhq); + if (nxt_slow_path(ret != NXT_OK)) { + goto fail; + } + + if (lhq.value != info) { + info = lhq.value; + nxt_mp_destroy(info->mp); + } - if (lhq.value != info) { - info = lhq.value; - nxt_mp_destroy(info->mp); - } - - return NXT_OK; + return NXT_OK; fail: - nxt_mp_destroy(mp); - return NXT_ERROR; + nxt_mp_destroy(mp); + return NXT_ERROR; } +nxt_conf_value_t *nxt_script_info_get(nxt_str_t *name) { + nxt_int_t ret; + nxt_script_info_t *info; + nxt_lvlhsh_query_t lhq; -nxt_conf_value_t * -nxt_script_info_get(nxt_str_t *name) -{ - nxt_int_t ret; - nxt_script_info_t *info; - nxt_lvlhsh_query_t lhq; + lhq.key_hash = nxt_djb_hash(name->start, name->length); + lhq.key = *name; + lhq.proto = &nxt_script_info_hash_proto; - lhq.key_hash = nxt_djb_hash(name->start, name->length); - lhq.key = *name; - lhq.proto = &nxt_script_info_hash_proto; - - ret = nxt_lvlhsh_find(&nxt_script_info, &lhq); - if (ret != NXT_OK) { - return NULL; - } + ret = nxt_lvlhsh_find(&nxt_script_info, &lhq); + if (ret != NXT_OK) { + return NULL; + } - info = lhq.value; + info = lhq.value; - return info->value; + return info->value; } +nxt_conf_value_t *nxt_script_info_get_all(nxt_mp_t *mp) { + uint32_t i; + nxt_conf_value_t *all; + nxt_script_info_t *info; + nxt_lvlhsh_each_t lhe; -nxt_conf_value_t * -nxt_script_info_get_all(nxt_mp_t *mp) -{ - uint32_t i; - nxt_conf_value_t *all; - nxt_script_info_t *info; - nxt_lvlhsh_each_t lhe; - - nxt_lvlhsh_each_init(&lhe, &nxt_script_info_hash_proto); + nxt_lvlhsh_each_init(&lhe, &nxt_script_info_hash_proto); - for (i = 0; /* void */; i++) { - info = nxt_lvlhsh_each(&nxt_script_info, &lhe); - - if (info == NULL) { - break; - } - } + for (i = 0; /* void */; i++) { + info = nxt_lvlhsh_each(&nxt_script_info, &lhe); - all = nxt_conf_create_object(mp, i); - if (nxt_slow_path(all == NULL)) { - return NULL; + if (info == NULL) { + break; } + } - nxt_lvlhsh_each_init(&lhe, &nxt_script_info_hash_proto); + all = nxt_conf_create_object(mp, i); + if (nxt_slow_path(all == NULL)) { + return NULL; + } - for (i = 0; /* void */; i++) { - info = nxt_lvlhsh_each(&nxt_script_info, &lhe); + nxt_lvlhsh_each_init(&lhe, &nxt_script_info_hash_proto); - if (info == NULL) { - break; - } + for (i = 0; /* void */; i++) { + info = nxt_lvlhsh_each(&nxt_script_info, &lhe); - nxt_conf_set_member(all, &info->name, info->value, i); + if (info == NULL) { + break; } - return all; -} + nxt_conf_set_member(all, &info->name, info->value, i); + } + return all; +} -static nxt_conf_value_t * -nxt_script_details(nxt_mp_t *mp, nxt_script_t *script) -{ - nxt_conf_value_t *value; +static nxt_conf_value_t *nxt_script_details(nxt_mp_t *mp, + nxt_script_t *script) { + nxt_conf_value_t *value; - value = nxt_conf_create_object(mp, 0); - if (nxt_slow_path(value == NULL)) { - return NULL; - } + value = nxt_conf_create_object(mp, 0); + if (nxt_slow_path(value == NULL)) { + return NULL; + } - nxt_conf_set_string_dup(value, mp, &script->text); + nxt_conf_set_string_dup(value, mp, &script->text); - return value; + return value; } +nxt_int_t nxt_script_info_delete(nxt_str_t *name) { + nxt_int_t ret; + nxt_script_info_t *info; + nxt_lvlhsh_query_t lhq; -nxt_int_t -nxt_script_info_delete(nxt_str_t *name) -{ - nxt_int_t ret; - nxt_script_info_t *info; - nxt_lvlhsh_query_t lhq; - - lhq.key_hash = nxt_djb_hash(name->start, name->length); - lhq.key = *name; - lhq.proto = &nxt_script_info_hash_proto; + lhq.key_hash = nxt_djb_hash(name->start, name->length); + lhq.key = *name; + lhq.proto = &nxt_script_info_hash_proto; - ret = nxt_lvlhsh_delete(&nxt_script_info, &lhq); + ret = nxt_lvlhsh_delete(&nxt_script_info, &lhq); - if (ret == NXT_OK) { - info = lhq.value; - nxt_mp_destroy(info->mp); - } + if (ret == NXT_OK) { + info = lhq.value; + nxt_mp_destroy(info->mp); + } - return ret; + return ret; } +nxt_array_t *nxt_script_store_load(nxt_task_t *task, nxt_mp_t *mp) { + DIR *dir; + size_t size, alloc; + u_char *buf, *p; + nxt_str_t name; + nxt_int_t ret; + nxt_file_t file; + nxt_array_t *scripts; + nxt_runtime_t *rt; + struct dirent *de; + nxt_script_item_t *item; + + rt = task->thread->runtime; + + if (nxt_slow_path(rt->scripts.start == NULL)) { + nxt_alert(task, "no scripts storage directory"); + return NULL; + } -nxt_array_t * -nxt_script_store_load(nxt_task_t *task, nxt_mp_t *mp) -{ - DIR *dir; - size_t size, alloc; - u_char *buf, *p; - nxt_str_t name; - nxt_int_t ret; - nxt_file_t file; - nxt_array_t *scripts; - nxt_runtime_t *rt; - struct dirent *de; - nxt_script_item_t *item; - - rt = task->thread->runtime; - - if (nxt_slow_path(rt->scripts.start == NULL)) { - nxt_alert(task, "no scripts storage directory"); - return NULL; - } + scripts = nxt_array_create(mp, 16, sizeof(nxt_script_item_t)); + if (nxt_slow_path(scripts == NULL)) { + return NULL; + } - scripts = nxt_array_create(mp, 16, sizeof(nxt_script_item_t)); - if (nxt_slow_path(scripts == NULL)) { - return NULL; - } + buf = NULL; + alloc = 0; - buf = NULL; - alloc = 0; + dir = opendir((char *)rt->scripts.start); + if (nxt_slow_path(dir == NULL)) { + nxt_alert(task, "opendir(\"%s\") failed %E", rt->scripts.start, nxt_errno); + goto fail; + } - dir = opendir((char *) rt->scripts.start); - if (nxt_slow_path(dir == NULL)) { - nxt_alert(task, "opendir(\"%s\") failed %E", - rt->scripts.start, nxt_errno); - goto fail; + for (;;) { + de = readdir(dir); + if (de == NULL) { + break; } - for ( ;; ) { - de = readdir(dir); - if (de == NULL) { - break; - } + nxt_debug(task, "readdir(\"%s\"): \"%s\"", rt->scripts.start, de->d_name); - nxt_debug(task, "readdir(\"%s\"): \"%s\"", - rt->scripts.start, de->d_name); + name.length = nxt_strlen(de->d_name); + name.start = (u_char *)de->d_name; - name.length = nxt_strlen(de->d_name); - name.start = (u_char *) de->d_name; - - if (nxt_str_eq(&name, ".", 1) || nxt_str_eq(&name, "..", 2)) { - continue; - } + if (nxt_str_eq(&name, ".", 1) || nxt_str_eq(&name, "..", 2)) { + continue; + } - item = nxt_array_add(scripts); - if (nxt_slow_path(item == NULL)) { - goto fail; - } + item = nxt_array_add(scripts); + if (nxt_slow_path(item == NULL)) { + goto fail; + } - item->fd = -1; + item->fd = -1; - size = rt->scripts.length + name.length + 1; + size = rt->scripts.length + name.length + 1; - if (size > alloc) { - size += 32; + if (size > alloc) { + size += 32; - p = nxt_realloc(buf, size); - if (p == NULL) { - goto fail; - } + p = nxt_realloc(buf, size); + if (p == NULL) { + goto fail; + } - alloc = size; - buf = p; - } + alloc = size; + buf = p; + } - p = nxt_cpymem(buf, rt->scripts.start, rt->scripts.length); - p = nxt_cpymem(p, name.start, name.length + 1); + p = nxt_cpymem(buf, rt->scripts.start, rt->scripts.length); + p = nxt_cpymem(p, name.start, name.length + 1); - nxt_memzero(&file, sizeof(nxt_file_t)); + nxt_memzero(&file, sizeof(nxt_file_t)); - file.name = buf; + file.name = buf; - ret = nxt_file_open(task, &file, NXT_FILE_RDONLY, NXT_FILE_OPEN, - NXT_FILE_OWNER_ACCESS); + ret = nxt_file_open(task, &file, NXT_FILE_RDONLY, NXT_FILE_OPEN, + NXT_FILE_OWNER_ACCESS); - if (nxt_slow_path(ret != NXT_OK)) { - nxt_array_remove_last(scripts); - continue; - } + if (nxt_slow_path(ret != NXT_OK)) { + nxt_array_remove_last(scripts); + continue; + } - item->fd = file.fd; + item->fd = file.fd; - if (nxt_slow_path(nxt_str_dup(mp, &item->name, &name) == NULL)) { - goto fail; - } + if (nxt_slow_path(nxt_str_dup(mp, &item->name, &name) == NULL)) { + goto fail; } + } - if (buf != NULL) { - nxt_free(buf); - } + if (buf != NULL) { + nxt_free(buf); + } - (void) closedir(dir); + (void)closedir(dir); - return scripts; + return scripts; fail: - if (buf != NULL) { - nxt_free(buf); - } + if (buf != NULL) { + nxt_free(buf); + } - if (dir != NULL) { - (void) closedir(dir); - } + if (dir != NULL) { + (void)closedir(dir); + } - nxt_script_store_release(scripts); + nxt_script_store_release(scripts); - return NULL; + return NULL; } +void nxt_script_store_release(nxt_array_t *scripts) { + uint32_t i; + nxt_script_item_t *item; -void -nxt_script_store_release(nxt_array_t *scripts) -{ - uint32_t i; - nxt_script_item_t *item; + item = scripts->elts; - item = scripts->elts; - - for (i = 0; i < scripts->nelts; i++) { - nxt_fd_close(item[i].fd); - } + for (i = 0; i < scripts->nelts; i++) { + nxt_fd_close(item[i].fd); + } - nxt_array_destroy(scripts); + nxt_array_destroy(scripts); } +void nxt_script_store_get(nxt_task_t *task, nxt_str_t *name, nxt_mp_t *mp, + nxt_port_rpc_handler_t handler, void *ctx) { + uint32_t stream; + nxt_int_t ret; + nxt_buf_t *b; + nxt_port_t *main_port, *recv_port; + nxt_runtime_t *rt; -void -nxt_script_store_get(nxt_task_t *task, nxt_str_t *name, nxt_mp_t *mp, - nxt_port_rpc_handler_t handler, void *ctx) -{ - uint32_t stream; - nxt_int_t ret; - nxt_buf_t *b; - nxt_port_t *main_port, *recv_port; - nxt_runtime_t *rt; + b = nxt_buf_mem_alloc(mp, name->length + 1, 0); + if (nxt_slow_path(b == NULL)) { + goto fail; + } - b = nxt_buf_mem_alloc(mp, name->length + 1, 0); - if (nxt_slow_path(b == NULL)) { - goto fail; - } + nxt_mp_retain(mp); + b->completion_handler = nxt_script_buf_completion; - nxt_mp_retain(mp); - b->completion_handler = nxt_script_buf_completion; + nxt_buf_cpystr(b, name); + *b->mem.free++ = '\0'; - nxt_buf_cpystr(b, name); - *b->mem.free++ = '\0'; + rt = task->thread->runtime; + main_port = rt->port_by_type[NXT_PROCESS_MAIN]; + recv_port = rt->port_by_type[rt->type]; - rt = task->thread->runtime; - main_port = rt->port_by_type[NXT_PROCESS_MAIN]; - recv_port = rt->port_by_type[rt->type]; - - stream = nxt_port_rpc_register_handler(task, recv_port, handler, handler, - -1, ctx); - if (nxt_slow_path(stream == 0)) { - goto fail; - } + stream = + nxt_port_rpc_register_handler(task, recv_port, handler, handler, -1, ctx); + if (nxt_slow_path(stream == 0)) { + goto fail; + } - ret = nxt_port_socket_write(task, main_port, NXT_PORT_MSG_SCRIPT_GET, -1, - stream, recv_port->id, b); + ret = nxt_port_socket_write(task, main_port, NXT_PORT_MSG_SCRIPT_GET, -1, + stream, recv_port->id, b); - if (nxt_slow_path(ret != NXT_OK)) { - nxt_port_rpc_cancel(task, recv_port, stream); - goto fail; - } + if (nxt_slow_path(ret != NXT_OK)) { + nxt_port_rpc_cancel(task, recv_port, stream); + goto fail; + } - return; + return; fail: - handler(task, NULL, ctx); + handler(task, NULL, ctx); } +static void nxt_script_buf_completion(nxt_task_t *task, void *obj, void *data) { + nxt_mp_t *mp; + nxt_buf_t *b; -static void -nxt_script_buf_completion(nxt_task_t *task, void *obj, void *data) -{ - nxt_mp_t *mp; - nxt_buf_t *b; - - b = obj; - mp = b->data; - nxt_assert(b->next == NULL); + b = obj; + mp = b->data; + nxt_assert(b->next == NULL); - nxt_mp_free(mp, b); - nxt_mp_release(mp); + nxt_mp_free(mp, b); + nxt_mp_release(mp); } +void nxt_script_store_get_handler(nxt_task_t *task, nxt_port_recv_msg_t *msg) { + u_char *p; + nxt_int_t ret; + nxt_str_t name; + nxt_file_t file; + nxt_port_t *port; + nxt_runtime_t *rt; + nxt_port_msg_type_t type; + + port = nxt_runtime_port_find(task->thread->runtime, msg->port_msg.pid, + msg->port_msg.reply_port); + + if (nxt_slow_path(port == NULL)) { + nxt_alert(task, "process port not found (pid %PI, reply_port %d)", + msg->port_msg.pid, msg->port_msg.reply_port); + return; + } -void -nxt_script_store_get_handler(nxt_task_t *task, nxt_port_recv_msg_t *msg) -{ - u_char *p; - nxt_int_t ret; - nxt_str_t name; - nxt_file_t file; - nxt_port_t *port; - nxt_runtime_t *rt; - nxt_port_msg_type_t type; - - port = nxt_runtime_port_find(task->thread->runtime, msg->port_msg.pid, - msg->port_msg.reply_port); - - if (nxt_slow_path(port == NULL)) { - nxt_alert(task, "process port not found (pid %PI, reply_port %d)", - msg->port_msg.pid, msg->port_msg.reply_port); - return; - } - - if (nxt_slow_path(port->type != NXT_PROCESS_CONTROLLER - && port->type != NXT_PROCESS_ROUTER)) - { - nxt_alert(task, "process %PI cannot store scripts", - msg->port_msg.pid); - return; - } + if (nxt_slow_path(port->type != NXT_PROCESS_CONTROLLER && + port->type != NXT_PROCESS_ROUTER)) { + nxt_alert(task, "process %PI cannot store scripts", msg->port_msg.pid); + return; + } - nxt_memzero(&file, sizeof(nxt_file_t)); + nxt_memzero(&file, sizeof(nxt_file_t)); - file.fd = -1; - type = NXT_PORT_MSG_RPC_ERROR; + file.fd = -1; + type = NXT_PORT_MSG_RPC_ERROR; - rt = task->thread->runtime; + rt = task->thread->runtime; - if (nxt_slow_path(rt->certs.start == NULL)) { - nxt_alert(task, "no scripts storage directory"); - goto error; - } + if (nxt_slow_path(rt->certs.start == NULL)) { + nxt_alert(task, "no scripts storage directory"); + goto error; + } - name.start = msg->buf->mem.pos; - name.length = nxt_strlen(name.start); + name.start = msg->buf->mem.pos; + name.length = nxt_strlen(name.start); - file.name = nxt_malloc(rt->scripts.length + name.length + 1); - if (nxt_slow_path(file.name == NULL)) { - goto error; - } + file.name = nxt_malloc(rt->scripts.length + name.length + 1); + if (nxt_slow_path(file.name == NULL)) { + goto error; + } - p = nxt_cpymem(file.name, rt->scripts.start, rt->scripts.length); - p = nxt_cpymem(p, name.start, name.length + 1); + p = nxt_cpymem(file.name, rt->scripts.start, rt->scripts.length); + p = nxt_cpymem(p, name.start, name.length + 1); - ret = nxt_file_open(task, &file, NXT_FILE_RDWR, NXT_FILE_CREATE_OR_OPEN, - NXT_FILE_OWNER_ACCESS); + ret = nxt_file_open(task, &file, NXT_FILE_RDWR, NXT_FILE_CREATE_OR_OPEN, + NXT_FILE_OWNER_ACCESS); - nxt_free(file.name); + nxt_free(file.name); - if (nxt_fast_path(ret == NXT_OK)) { - type = NXT_PORT_MSG_RPC_READY_LAST | NXT_PORT_MSG_CLOSE_FD; - } + if (nxt_fast_path(ret == NXT_OK)) { + type = NXT_PORT_MSG_RPC_READY_LAST | NXT_PORT_MSG_CLOSE_FD; + } error: - (void) nxt_port_socket_write(task, port, type, file.fd, - msg->port_msg.stream, 0, NULL); + (void)nxt_port_socket_write(task, port, type, file.fd, msg->port_msg.stream, + 0, NULL); } +void nxt_script_store_delete(nxt_task_t *task, nxt_str_t *name, nxt_mp_t *mp) { + nxt_buf_t *b; + nxt_port_t *main_port; + nxt_runtime_t *rt; -void -nxt_script_store_delete(nxt_task_t *task, nxt_str_t *name, nxt_mp_t *mp) -{ - nxt_buf_t *b; - nxt_port_t *main_port; - nxt_runtime_t *rt; - - b = nxt_buf_mem_alloc(mp, name->length + 1, 0); + b = nxt_buf_mem_alloc(mp, name->length + 1, 0); - if (nxt_fast_path(b != NULL)) { - nxt_buf_cpystr(b, name); - *b->mem.free++ = '\0'; + if (nxt_fast_path(b != NULL)) { + nxt_buf_cpystr(b, name); + *b->mem.free++ = '\0'; - rt = task->thread->runtime; - main_port = rt->port_by_type[NXT_PROCESS_MAIN]; + rt = task->thread->runtime; + main_port = rt->port_by_type[NXT_PROCESS_MAIN]; - (void) nxt_port_socket_write(task, main_port, - NXT_PORT_MSG_SCRIPT_DELETE, -1, 0, 0, b); - } + (void)nxt_port_socket_write(task, main_port, NXT_PORT_MSG_SCRIPT_DELETE, -1, + 0, 0, b); + } } +void nxt_script_store_delete_handler(nxt_task_t *task, + nxt_port_recv_msg_t *msg) { + u_char *p; + nxt_str_t name; + nxt_port_t *ctl_port; + nxt_runtime_t *rt; + nxt_file_name_t *path; -void -nxt_script_store_delete_handler(nxt_task_t *task, nxt_port_recv_msg_t *msg) -{ - u_char *p; - nxt_str_t name; - nxt_port_t *ctl_port; - nxt_runtime_t *rt; - nxt_file_name_t *path; + rt = task->thread->runtime; + ctl_port = rt->port_by_type[NXT_PROCESS_CONTROLLER]; - rt = task->thread->runtime; - ctl_port = rt->port_by_type[NXT_PROCESS_CONTROLLER]; - - if (nxt_slow_path(ctl_port == NULL)) { - nxt_alert(task, "controller port not found"); - return; - } + if (nxt_slow_path(ctl_port == NULL)) { + nxt_alert(task, "controller port not found"); + return; + } - if (nxt_slow_path(nxt_recv_msg_cmsg_pid(msg) != ctl_port->pid)) { - nxt_alert(task, "process %PI cannot delete scripts", - nxt_recv_msg_cmsg_pid(msg)); - return; - } + if (nxt_slow_path(nxt_recv_msg_cmsg_pid(msg) != ctl_port->pid)) { + nxt_alert(task, "process %PI cannot delete scripts", + nxt_recv_msg_cmsg_pid(msg)); + return; + } - if (nxt_slow_path(rt->scripts.start == NULL)) { - nxt_alert(task, "no scripts storage directory"); - return; - } + if (nxt_slow_path(rt->scripts.start == NULL)) { + nxt_alert(task, "no scripts storage directory"); + return; + } - name.start = msg->buf->mem.pos; - name.length = nxt_strlen(name.start); + name.start = msg->buf->mem.pos; + name.length = nxt_strlen(name.start); - path = nxt_malloc(rt->scripts.length + name.length + 1); + path = nxt_malloc(rt->scripts.length + name.length + 1); - if (nxt_fast_path(path != NULL)) { - p = nxt_cpymem(path, rt->scripts.start, rt->scripts.length); - p = nxt_cpymem(p, name.start, name.length + 1); + if (nxt_fast_path(path != NULL)) { + p = nxt_cpymem(path, rt->scripts.start, rt->scripts.length); + p = nxt_cpymem(p, name.start, name.length + 1); - (void) nxt_file_delete(path); + (void)nxt_file_delete(path); - nxt_free(path); - } + nxt_free(path); + } } +nxt_int_t nxt_script_file_read(nxt_fd_t fd, nxt_str_t *str) { + ssize_t n; + nxt_int_t ret; + nxt_file_t file; + nxt_file_info_t fi; -nxt_int_t -nxt_script_file_read(nxt_fd_t fd, nxt_str_t *str) -{ - ssize_t n; - nxt_int_t ret; - nxt_file_t file; - nxt_file_info_t fi; - - nxt_memzero(&file, sizeof(nxt_file_t)); + nxt_memzero(&file, sizeof(nxt_file_t)); - file.fd = fd; + file.fd = fd; - ret = nxt_file_info(&file, &fi); - if (nxt_slow_path(ret != NXT_OK)) { - return NXT_ERROR; - } + ret = nxt_file_info(&file, &fi); + if (nxt_slow_path(ret != NXT_OK)) { + return NXT_ERROR; + } - if (nxt_slow_path(!nxt_is_file(&fi))) { - nxt_str_null(str); - return NXT_DECLINED; - } + if (nxt_slow_path(!nxt_is_file(&fi))) { + nxt_str_null(str); + return NXT_DECLINED; + } - str->length = nxt_file_size(&fi); - str->start = nxt_malloc(str->length); - if (nxt_slow_path(str->start == NULL)) { - return NXT_ERROR; - } + str->length = nxt_file_size(&fi); + str->start = nxt_malloc(str->length); + if (nxt_slow_path(str->start == NULL)) { + return NXT_ERROR; + } - n = nxt_file_read(&file, str->start, str->length, 0); + n = nxt_file_read(&file, str->start, str->length, 0); - if (nxt_slow_path(n != (ssize_t) str->length)) { - nxt_free(str->start); - return NXT_ERROR; - } + if (nxt_slow_path(n != (ssize_t)str->length)) { + nxt_free(str->start); + return NXT_ERROR; + } - return NXT_OK; + return NXT_OK; } diff --git a/src/nxt_script.h b/src/nxt_script.h index ffefc108f..0db980699 100644 --- a/src/nxt_script.h +++ b/src/nxt_script.h @@ -7,11 +7,10 @@ #ifndef _NXT_SCRIPT_INCLUDED_ #define _NXT_SCRIPT_INCLUDED_ - -typedef struct nxt_script_s nxt_script_t; +typedef struct nxt_script_s nxt_script_t; nxt_script_t *nxt_script_new(nxt_task_t *task, nxt_str_t *name, u_char *data, - size_t size, u_char *error); + size_t size, u_char *error); void nxt_script_destroy(nxt_script_t *script); void nxt_script_info_init(nxt_task_t *task, nxt_array_t *scripts); @@ -24,14 +23,13 @@ nxt_array_t *nxt_script_store_load(nxt_task_t *task, nxt_mp_t *mem_pool); void nxt_script_store_release(nxt_array_t *scripts); void nxt_script_store_get(nxt_task_t *task, nxt_str_t *name, nxt_mp_t *mp, - nxt_port_rpc_handler_t handler, void *ctx); + nxt_port_rpc_handler_t handler, void *ctx); void nxt_script_store_delete(nxt_task_t *task, nxt_str_t *name, nxt_mp_t *mp); void nxt_script_store_get_handler(nxt_task_t *task, nxt_port_recv_msg_t *msg); void nxt_script_store_delete_handler(nxt_task_t *task, - nxt_port_recv_msg_t *msg); + nxt_port_recv_msg_t *msg); nxt_int_t nxt_script_file_read(nxt_fd_t fd, nxt_str_t *str); - #endif /* _NXT_SCRIPT_INCLUDED_ */ diff --git a/src/nxt_select_engine.c b/src/nxt_select_engine.c index 6f7600125..3ba23eb6f 100644 --- a/src/nxt_select_engine.c +++ b/src/nxt_select_engine.c @@ -6,35 +6,33 @@ #include - static nxt_int_t nxt_select_create(nxt_event_engine_t *engine, - nxt_uint_t mchanges, nxt_uint_t mevents); + nxt_uint_t mchanges, nxt_uint_t mevents); static void nxt_select_free(nxt_event_engine_t *engine); static void nxt_select_enable(nxt_event_engine_t *engine, nxt_fd_event_t *ev); static void nxt_select_disable(nxt_event_engine_t *engine, nxt_fd_event_t *ev); static nxt_bool_t nxt_select_close(nxt_event_engine_t *engine, - nxt_fd_event_t *ev); + nxt_fd_event_t *ev); static void nxt_select_enable_read(nxt_event_engine_t *engine, - nxt_fd_event_t *ev); + nxt_fd_event_t *ev); static void nxt_select_enable_write(nxt_event_engine_t *engine, - nxt_fd_event_t *ev); + nxt_fd_event_t *ev); static void nxt_select_error_handler(nxt_task_t *task, void *obj, void *data); static void nxt_select_disable_read(nxt_event_engine_t *engine, - nxt_fd_event_t *ev); + nxt_fd_event_t *ev); static void nxt_select_disable_write(nxt_event_engine_t *engine, - nxt_fd_event_t *ev); + nxt_fd_event_t *ev); static void nxt_select_block_read(nxt_event_engine_t *engine, - nxt_fd_event_t *ev); + nxt_fd_event_t *ev); static void nxt_select_block_write(nxt_event_engine_t *engine, - nxt_fd_event_t *ev); + nxt_fd_event_t *ev); static void nxt_select_oneshot_read(nxt_event_engine_t *engine, - nxt_fd_event_t *ev); + nxt_fd_event_t *ev); static void nxt_select_oneshot_write(nxt_event_engine_t *engine, - nxt_fd_event_t *ev); + nxt_fd_event_t *ev); static void nxt_select_poll(nxt_event_engine_t *engine, nxt_msec_t timeout); - -const nxt_event_interface_t nxt_select_engine = { +const nxt_event_interface_t nxt_select_engine = { "select", nxt_select_create, nxt_select_free, @@ -63,308 +61,272 @@ const nxt_event_interface_t nxt_select_engine = { NXT_NO_SIGNAL_EVENTS, }; +static nxt_int_t nxt_select_create(nxt_event_engine_t *engine, + nxt_uint_t mchanges, nxt_uint_t mevents) { + engine->u.select.nfds = -1; + engine->u.select.update_nfds = 0; -static nxt_int_t -nxt_select_create(nxt_event_engine_t *engine, nxt_uint_t mchanges, - nxt_uint_t mevents) -{ - engine->u.select.nfds = -1; - engine->u.select.update_nfds = 0; - - engine->u.select.events = nxt_zalloc(FD_SETSIZE * sizeof(nxt_fd_event_t *)); + engine->u.select.events = nxt_zalloc(FD_SETSIZE * sizeof(nxt_fd_event_t *)); - if (engine->u.select.events != NULL) { - return NXT_OK; - } + if (engine->u.select.events != NULL) { + return NXT_OK; + } - nxt_select_free(engine); + nxt_select_free(engine); - return NXT_ERROR; + return NXT_ERROR; } +static void nxt_select_free(nxt_event_engine_t *engine) { + nxt_debug(&engine->task, "select free"); -static void -nxt_select_free(nxt_event_engine_t *engine) -{ - nxt_debug(&engine->task, "select free"); + nxt_free(engine->u.select.events); - nxt_free(engine->u.select.events); - - nxt_memzero(&engine->u.select, sizeof(nxt_select_engine_t)); + nxt_memzero(&engine->u.select, sizeof(nxt_select_engine_t)); } - -static void -nxt_select_enable(nxt_event_engine_t *engine, nxt_fd_event_t *ev) -{ - nxt_select_enable_read(engine, ev); - nxt_select_enable_write(engine, ev); +static void nxt_select_enable(nxt_event_engine_t *engine, nxt_fd_event_t *ev) { + nxt_select_enable_read(engine, ev); + nxt_select_enable_write(engine, ev); } +static void nxt_select_disable(nxt_event_engine_t *engine, nxt_fd_event_t *ev) { + if (ev->read != NXT_EVENT_INACTIVE) { + nxt_select_disable_read(engine, ev); + } -static void -nxt_select_disable(nxt_event_engine_t *engine, nxt_fd_event_t *ev) -{ - if (ev->read != NXT_EVENT_INACTIVE) { - nxt_select_disable_read(engine, ev); - } - - if (ev->write != NXT_EVENT_INACTIVE) { - nxt_select_disable_write(engine, ev); - } + if (ev->write != NXT_EVENT_INACTIVE) { + nxt_select_disable_write(engine, ev); + } } +static nxt_bool_t nxt_select_close(nxt_event_engine_t *engine, + nxt_fd_event_t *ev) { + nxt_select_disable(engine, ev); -static nxt_bool_t -nxt_select_close(nxt_event_engine_t *engine, nxt_fd_event_t *ev) -{ - nxt_select_disable(engine, ev); - - return 0; + return 0; } +static void nxt_select_enable_read(nxt_event_engine_t *engine, + nxt_fd_event_t *ev) { + nxt_fd_t fd; -static void -nxt_select_enable_read(nxt_event_engine_t *engine, nxt_fd_event_t *ev) -{ - nxt_fd_t fd; - - fd = ev->fd; + fd = ev->fd; - nxt_debug(ev->task, "select enable read: fd:%d", fd); + nxt_debug(ev->task, "select enable read: fd:%d", fd); - if (fd < 0 || fd >= (nxt_fd_t) FD_SETSIZE) { - nxt_work_queue_add(&engine->fast_work_queue, nxt_select_error_handler, - ev->task, ev, ev->data); - return; - } + if (fd < 0 || fd >= (nxt_fd_t)FD_SETSIZE) { + nxt_work_queue_add(&engine->fast_work_queue, nxt_select_error_handler, + ev->task, ev, ev->data); + return; + } - ev->read = NXT_EVENT_ACTIVE; + ev->read = NXT_EVENT_ACTIVE; - FD_SET(fd, &engine->u.select.main_read_fd_set); - engine->u.select.events[fd] = ev; + FD_SET(fd, &engine->u.select.main_read_fd_set); + engine->u.select.events[fd] = ev; - if (engine->u.select.nfds < fd) { - engine->u.select.nfds = fd; - engine->u.select.update_nfds = 0; - } + if (engine->u.select.nfds < fd) { + engine->u.select.nfds = fd; + engine->u.select.update_nfds = 0; + } } +static void nxt_select_enable_write(nxt_event_engine_t *engine, + nxt_fd_event_t *ev) { + nxt_fd_t fd; -static void -nxt_select_enable_write(nxt_event_engine_t *engine, nxt_fd_event_t *ev) -{ - nxt_fd_t fd; + fd = ev->fd; - fd = ev->fd; + nxt_debug(ev->task, "select enable write: fd:%d", fd); - nxt_debug(ev->task, "select enable write: fd:%d", fd); + if (fd < 0 || fd >= (nxt_fd_t)FD_SETSIZE) { + nxt_work_queue_add(&engine->fast_work_queue, nxt_select_error_handler, + ev->task, ev, ev->data); + return; + } - if (fd < 0 || fd >= (nxt_fd_t) FD_SETSIZE) { - nxt_work_queue_add(&engine->fast_work_queue, nxt_select_error_handler, - ev->task, ev, ev->data); - return; - } + ev->write = NXT_EVENT_ACTIVE; - ev->write = NXT_EVENT_ACTIVE; + FD_SET(fd, &engine->u.select.main_write_fd_set); + engine->u.select.events[fd] = ev; - FD_SET(fd, &engine->u.select.main_write_fd_set); - engine->u.select.events[fd] = ev; - - if (engine->u.select.nfds < fd) { - engine->u.select.nfds = fd; - engine->u.select.update_nfds = 0; - } + if (engine->u.select.nfds < fd) { + engine->u.select.nfds = fd; + engine->u.select.update_nfds = 0; + } } +static void nxt_select_error_handler(nxt_task_t *task, void *obj, void *data) { + nxt_fd_event_t *ev; -static void -nxt_select_error_handler(nxt_task_t *task, void *obj, void *data) -{ - nxt_fd_event_t *ev; + ev = obj; - ev = obj; + ev->read = NXT_EVENT_INACTIVE; + ev->write = NXT_EVENT_INACTIVE; - ev->read = NXT_EVENT_INACTIVE; - ev->write = NXT_EVENT_INACTIVE; - - ev->error_handler(task, ev, data); + ev->error_handler(task, ev, data); } +static void nxt_select_disable_read(nxt_event_engine_t *engine, + nxt_fd_event_t *ev) { + nxt_fd_t fd; -static void -nxt_select_disable_read(nxt_event_engine_t *engine, nxt_fd_event_t *ev) -{ - nxt_fd_t fd; - - fd = ev->fd; + fd = ev->fd; - nxt_debug(ev->task, "select disable read: fd:%d", fd); + nxt_debug(ev->task, "select disable read: fd:%d", fd); - if (fd < 0 || fd >= (nxt_fd_t) FD_SETSIZE) { - return; - } + if (fd < 0 || fd >= (nxt_fd_t)FD_SETSIZE) { + return; + } - FD_CLR(fd, &engine->u.select.main_read_fd_set); + FD_CLR(fd, &engine->u.select.main_read_fd_set); - ev->read = NXT_EVENT_INACTIVE; + ev->read = NXT_EVENT_INACTIVE; - if (ev->write == NXT_EVENT_INACTIVE) { - engine->u.select.events[fd] = NULL; - engine->u.select.update_nfds = 1; - } + if (ev->write == NXT_EVENT_INACTIVE) { + engine->u.select.events[fd] = NULL; + engine->u.select.update_nfds = 1; + } } +static void nxt_select_disable_write(nxt_event_engine_t *engine, + nxt_fd_event_t *ev) { + nxt_fd_t fd; -static void -nxt_select_disable_write(nxt_event_engine_t *engine, nxt_fd_event_t *ev) -{ - nxt_fd_t fd; - - fd = ev->fd; + fd = ev->fd; - nxt_debug(ev->task, "select disable write: fd:%d", fd); + nxt_debug(ev->task, "select disable write: fd:%d", fd); - if (fd < 0 || fd >= (nxt_fd_t) FD_SETSIZE) { - return; - } + if (fd < 0 || fd >= (nxt_fd_t)FD_SETSIZE) { + return; + } - FD_CLR(fd, &engine->u.select.main_write_fd_set); + FD_CLR(fd, &engine->u.select.main_write_fd_set); - ev->write = NXT_EVENT_INACTIVE; + ev->write = NXT_EVENT_INACTIVE; - if (ev->read == NXT_EVENT_INACTIVE) { - engine->u.select.events[fd] = NULL; - engine->u.select.update_nfds = 1; - } + if (ev->read == NXT_EVENT_INACTIVE) { + engine->u.select.events[fd] = NULL; + engine->u.select.update_nfds = 1; + } } - -static void -nxt_select_block_read(nxt_event_engine_t *engine, nxt_fd_event_t *ev) -{ - if (ev->read != NXT_EVENT_INACTIVE) { - nxt_select_disable_read(engine, ev); - } +static void nxt_select_block_read(nxt_event_engine_t *engine, + nxt_fd_event_t *ev) { + if (ev->read != NXT_EVENT_INACTIVE) { + nxt_select_disable_read(engine, ev); + } } - -static void -nxt_select_block_write(nxt_event_engine_t *engine, nxt_fd_event_t *ev) -{ - if (ev->write != NXT_EVENT_INACTIVE) { - nxt_select_disable_write(engine, ev); - } +static void nxt_select_block_write(nxt_event_engine_t *engine, + nxt_fd_event_t *ev) { + if (ev->write != NXT_EVENT_INACTIVE) { + nxt_select_disable_write(engine, ev); + } } +static void nxt_select_oneshot_read(nxt_event_engine_t *engine, + nxt_fd_event_t *ev) { + nxt_select_enable_read(engine, ev); -static void -nxt_select_oneshot_read(nxt_event_engine_t *engine, nxt_fd_event_t *ev) -{ - nxt_select_enable_read(engine, ev); - - ev->read = NXT_EVENT_ONESHOT; + ev->read = NXT_EVENT_ONESHOT; } +static void nxt_select_oneshot_write(nxt_event_engine_t *engine, + nxt_fd_event_t *ev) { + nxt_select_enable_write(engine, ev); -static void -nxt_select_oneshot_write(nxt_event_engine_t *engine, nxt_fd_event_t *ev) -{ - nxt_select_enable_write(engine, ev); - - ev->write = NXT_EVENT_ONESHOT; + ev->write = NXT_EVENT_ONESHOT; } - -static void -nxt_select_poll(nxt_event_engine_t *engine, nxt_msec_t timeout) -{ - int nevents, nfds, found; - nxt_err_t err; - nxt_int_t i; - nxt_uint_t fd, level; - nxt_fd_event_t *ev; - struct timeval tv, *tp; - - if (timeout == NXT_INFINITE_MSEC) { - tp = NULL; - - } else { - tv.tv_sec = (long) (timeout / 1000); - tv.tv_usec = (long) ((timeout % 1000) * 1000); - tp = &tv; - } - - if (engine->u.select.update_nfds) { - for (i = engine->u.select.nfds; i >= 0; i--) { - if (engine->u.select.events[i] != NULL) { - engine->u.select.nfds = i; - engine->u.select.update_nfds = 0; - break; - } - } +static void nxt_select_poll(nxt_event_engine_t *engine, nxt_msec_t timeout) { + int nevents, nfds, found; + nxt_err_t err; + nxt_int_t i; + nxt_uint_t fd, level; + nxt_fd_event_t *ev; + struct timeval tv, *tp; + + if (timeout == NXT_INFINITE_MSEC) { + tp = NULL; + + } else { + tv.tv_sec = (long)(timeout / 1000); + tv.tv_usec = (long)((timeout % 1000) * 1000); + tp = &tv; + } + + if (engine->u.select.update_nfds) { + for (i = engine->u.select.nfds; i >= 0; i--) { + if (engine->u.select.events[i] != NULL) { + engine->u.select.nfds = i; + engine->u.select.update_nfds = 0; + break; + } } + } - engine->u.select.work_read_fd_set = engine->u.select.main_read_fd_set; - engine->u.select.work_write_fd_set = engine->u.select.main_write_fd_set; - - nfds = engine->u.select.nfds + 1; + engine->u.select.work_read_fd_set = engine->u.select.main_read_fd_set; + engine->u.select.work_write_fd_set = engine->u.select.main_write_fd_set; - nxt_debug(&engine->task, "select() nfds:%d timeout:%M", nfds, timeout); + nfds = engine->u.select.nfds + 1; - nevents = select(nfds, &engine->u.select.work_read_fd_set, - &engine->u.select.work_write_fd_set, NULL, tp); + nxt_debug(&engine->task, "select() nfds:%d timeout:%M", nfds, timeout); - err = (nevents == -1) ? nxt_errno : 0; + nevents = select(nfds, &engine->u.select.work_read_fd_set, + &engine->u.select.work_write_fd_set, NULL, tp); - nxt_thread_time_update(engine->task.thread); + err = (nevents == -1) ? nxt_errno : 0; - nxt_debug(&engine->task, "select(): %d", nevents); + nxt_thread_time_update(engine->task.thread); - if (nevents == -1) { - level = (err == NXT_EINTR) ? NXT_LOG_INFO : NXT_LOG_ALERT; - nxt_log(&engine->task, level, "select() failed %E", err); - return; - } + nxt_debug(&engine->task, "select(): %d", nevents); - for (fd = 0; fd < (nxt_uint_t) nfds && nevents != 0; fd++) { + if (nevents == -1) { + level = (err == NXT_EINTR) ? NXT_LOG_INFO : NXT_LOG_ALERT; + nxt_log(&engine->task, level, "select() failed %E", err); + return; + } - found = 0; + for (fd = 0; fd < (nxt_uint_t)nfds && nevents != 0; fd++) { - if (FD_ISSET(fd, &engine->u.select.work_read_fd_set)) { - ev = engine->u.select.events[fd]; + found = 0; - nxt_debug(ev->task, "select() fd:%ui read rd:%d wr:%d", - fd, ev->read, ev->write); + if (FD_ISSET(fd, &engine->u.select.work_read_fd_set)) { + ev = engine->u.select.events[fd]; - ev->read_ready = 1; + nxt_debug(ev->task, "select() fd:%ui read rd:%d wr:%d", fd, ev->read, + ev->write); - if (ev->read == NXT_EVENT_ONESHOT) { - nxt_select_disable_read(engine, ev); - } + ev->read_ready = 1; - nxt_work_queue_add(ev->read_work_queue, ev->read_handler, - ev->task, ev, ev->data); - found = 1; - } + if (ev->read == NXT_EVENT_ONESHOT) { + nxt_select_disable_read(engine, ev); + } - if (FD_ISSET(fd, &engine->u.select.work_write_fd_set)) { - ev = engine->u.select.events[fd]; + nxt_work_queue_add(ev->read_work_queue, ev->read_handler, ev->task, ev, + ev->data); + found = 1; + } - nxt_debug(ev->task, "select() fd:%ui write rd:%d wr:%d", - fd, ev->read, ev->write); + if (FD_ISSET(fd, &engine->u.select.work_write_fd_set)) { + ev = engine->u.select.events[fd]; - ev->write_ready = 1; + nxt_debug(ev->task, "select() fd:%ui write rd:%d wr:%d", fd, ev->read, + ev->write); - if (ev->write == NXT_EVENT_ONESHOT) { - nxt_select_disable_write(engine, ev); - } + ev->write_ready = 1; - nxt_work_queue_add(ev->write_work_queue, ev->write_handler, - ev->task, ev, ev->data); - found = 1; - } + if (ev->write == NXT_EVENT_ONESHOT) { + nxt_select_disable_write(engine, ev); + } - nevents -= found; + nxt_work_queue_add(ev->write_work_queue, ev->write_handler, ev->task, ev, + ev->data); + found = 1; } + + nevents -= found; + } } diff --git a/src/nxt_semaphore.c b/src/nxt_semaphore.c index ad05d8b9a..807c1fff8 100644 --- a/src/nxt_semaphore.c +++ b/src/nxt_semaphore.c @@ -6,7 +6,6 @@ #include - #if (NXT_HAVE_SEM_TIMEDWAIT) /* @@ -31,214 +30,192 @@ * 2) no sem_timedwait(). */ -nxt_int_t -nxt_sem_init(nxt_sem_t *sem, nxt_uint_t count) -{ - if (sem_init(sem, 0, count) == 0) { - nxt_thread_log_debug("sem_init(%p)", sem); - return NXT_OK; - } +nxt_int_t nxt_sem_init(nxt_sem_t *sem, nxt_uint_t count) { + if (sem_init(sem, 0, count) == 0) { + nxt_thread_log_debug("sem_init(%p)", sem); + return NXT_OK; + } - nxt_thread_log_alert("sem_init(%p) failed %E", sem, nxt_errno); - return NXT_ERROR; + nxt_thread_log_alert("sem_init(%p) failed %E", sem, nxt_errno); + return NXT_ERROR; } +void nxt_sem_destroy(nxt_sem_t *sem) { + if (sem_destroy(sem) == 0) { + nxt_thread_log_debug("sem_destroy(%p)", sem); + return; + } -void -nxt_sem_destroy(nxt_sem_t *sem) -{ - if (sem_destroy(sem) == 0) { - nxt_thread_log_debug("sem_destroy(%p)", sem); - return; - } - - nxt_thread_log_alert("sem_destroy(%p) failed %E", sem, nxt_errno); + nxt_thread_log_alert("sem_destroy(%p) failed %E", sem, nxt_errno); } +nxt_int_t nxt_sem_post(nxt_sem_t *sem) { + nxt_thread_log_debug("sem_post(%p)", sem); -nxt_int_t -nxt_sem_post(nxt_sem_t *sem) -{ - nxt_thread_log_debug("sem_post(%p)", sem); - - if (nxt_fast_path(sem_post(sem) == 0)) { - return NXT_OK; - } + if (nxt_fast_path(sem_post(sem) == 0)) { + return NXT_OK; + } - nxt_thread_log_alert("sem_post(%p) failed %E", sem, nxt_errno); + nxt_thread_log_alert("sem_post(%p) failed %E", sem, nxt_errno); - return NXT_ERROR; + return NXT_ERROR; } +nxt_err_t nxt_sem_wait(nxt_sem_t *sem, nxt_nsec_t timeout) { + int n; + nxt_err_t err; + nxt_nsec_t ns; + nxt_thread_t *thr; + nxt_realtime_t *now; + struct timespec ts; -nxt_err_t -nxt_sem_wait(nxt_sem_t *sem, nxt_nsec_t timeout) -{ - int n; - nxt_err_t err; - nxt_nsec_t ns; - nxt_thread_t *thr; - nxt_realtime_t *now; - struct timespec ts; - - thr = nxt_thread(); + thr = nxt_thread(); - if (timeout == NXT_INFINITE_NSEC) { - nxt_log_debug(thr->log, "sem_wait(%p) enter", sem); + if (timeout == NXT_INFINITE_NSEC) { + nxt_log_debug(thr->log, "sem_wait(%p) enter", sem); - for ( ;; ) { - n = sem_wait(sem); + for (;;) { + n = sem_wait(sem); - err = nxt_errno; + err = nxt_errno; - nxt_thread_time_update(thr); + nxt_thread_time_update(thr); - if (nxt_fast_path(n == 0)) { - nxt_thread_log_debug("sem_wait(%p) exit", sem); - return 0; - } + if (nxt_fast_path(n == 0)) { + nxt_thread_log_debug("sem_wait(%p) exit", sem); + return 0; + } - switch (err) { + switch (err) { - case NXT_EINTR: - nxt_log_error(NXT_LOG_INFO, thr->log, "sem_wait(%p) failed %E", - sem, err); - continue; + case NXT_EINTR: + nxt_log_error(NXT_LOG_INFO, thr->log, "sem_wait(%p) failed %E", sem, + err); + continue; - default: - nxt_log_alert(thr->log, "sem_wait(%p) failed %E", sem, err); - return err; - } - } + default: + nxt_log_alert(thr->log, "sem_wait(%p) failed %E", sem, err); + return err; + } } + } #if (NXT_HAVE_SEM_TRYWAIT_FAST) - nxt_log_debug(thr->log, "sem_trywait(%p) enter", sem); + nxt_log_debug(thr->log, "sem_trywait(%p) enter", sem); - /* - * Fast sem_trywait() using atomic operations may eliminate - * timeout processing. - */ + /* + * Fast sem_trywait() using atomic operations may eliminate + * timeout processing. + */ - if (nxt_fast_path(sem_trywait(sem) == 0)) { - return 0; - } + if (nxt_fast_path(sem_trywait(sem) == 0)) { + return 0; + } #endif - nxt_log_debug(thr->log, "sem_timedwait(%p, %N) enter", sem, timeout); + nxt_log_debug(thr->log, "sem_timedwait(%p, %N) enter", sem, timeout); - now = nxt_thread_realtime(thr); - ns = now->nsec + timeout; - ts.tv_sec = now->sec + ns / 1000000000; - ts.tv_nsec = ns % 1000000000; + now = nxt_thread_realtime(thr); + ns = now->nsec + timeout; + ts.tv_sec = now->sec + ns / 1000000000; + ts.tv_nsec = ns % 1000000000; - for ( ;; ) { - n = sem_timedwait(sem, &ts); + for (;;) { + n = sem_timedwait(sem, &ts); - err = nxt_errno; + err = nxt_errno; - nxt_thread_time_update(thr); + nxt_thread_time_update(thr); - if (nxt_fast_path(n == 0)) { - nxt_thread_log_debug("sem_timedwait(%p) exit", sem); - return 0; - } + if (nxt_fast_path(n == 0)) { + nxt_thread_log_debug("sem_timedwait(%p) exit", sem); + return 0; + } - switch (err) { + switch (err) { - case NXT_ETIMEDOUT: - nxt_log_debug(thr->log, "sem_timedwait(%p) exit: %d", sem, err); - return err; + case NXT_ETIMEDOUT: + nxt_log_debug(thr->log, "sem_timedwait(%p) exit: %d", sem, err); + return err; - case NXT_EINTR: - nxt_log_error(NXT_LOG_INFO, thr->log, "sem_timedwait(%p) failed %E", - sem, err); - continue; + case NXT_EINTR: + nxt_log_error(NXT_LOG_INFO, thr->log, "sem_timedwait(%p) failed %E", sem, + err); + continue; - default: - nxt_log_alert(thr->log, "sem_timedwait(%p) failed %E", sem, err); - return err; - } + default: + nxt_log_alert(thr->log, "sem_timedwait(%p) failed %E", sem, err); + return err; } + } } #else /* Semaphore implementation using pthread conditional variable. */ -nxt_int_t -nxt_sem_init(nxt_sem_t *sem, nxt_uint_t count) -{ - if (nxt_thread_mutex_create(&sem->mutex) == NXT_OK) { +nxt_int_t nxt_sem_init(nxt_sem_t *sem, nxt_uint_t count) { + if (nxt_thread_mutex_create(&sem->mutex) == NXT_OK) { - if (nxt_thread_cond_create(&sem->cond) == NXT_OK) { - sem->count = count; - return NXT_OK; - } - - nxt_thread_mutex_destroy(&sem->mutex); + if (nxt_thread_cond_create(&sem->cond) == NXT_OK) { + sem->count = count; + return NXT_OK; } - return NXT_ERROR; -} - - -void -nxt_sem_destroy(nxt_sem_t *sem) -{ - nxt_thread_cond_destroy(&sem->cond); nxt_thread_mutex_destroy(&sem->mutex); + } + + return NXT_ERROR; } +void nxt_sem_destroy(nxt_sem_t *sem) { + nxt_thread_cond_destroy(&sem->cond); + nxt_thread_mutex_destroy(&sem->mutex); +} -nxt_int_t -nxt_sem_post(nxt_sem_t *sem) -{ - nxt_int_t ret; +nxt_int_t nxt_sem_post(nxt_sem_t *sem) { + nxt_int_t ret; - if (nxt_slow_path(nxt_thread_mutex_lock(&sem->mutex) != NXT_OK)) { - return NXT_ERROR; - } + if (nxt_slow_path(nxt_thread_mutex_lock(&sem->mutex) != NXT_OK)) { + return NXT_ERROR; + } - ret = nxt_thread_cond_signal(&sem->cond); + ret = nxt_thread_cond_signal(&sem->cond); - sem->count++; + sem->count++; - /* NXT_ERROR overrides NXT_OK. */ + /* NXT_ERROR overrides NXT_OK. */ - return (nxt_thread_mutex_unlock(&sem->mutex) | ret); + return (nxt_thread_mutex_unlock(&sem->mutex) | ret); } +nxt_err_t nxt_sem_wait(nxt_sem_t *sem, nxt_nsec_t timeout) { + nxt_err_t err; -nxt_err_t -nxt_sem_wait(nxt_sem_t *sem, nxt_nsec_t timeout) -{ - nxt_err_t err; + err = 0; - err = 0; - - if (nxt_slow_path(nxt_thread_mutex_lock(&sem->mutex) != NXT_OK)) { - return NXT_ERROR; - } + if (nxt_slow_path(nxt_thread_mutex_lock(&sem->mutex) != NXT_OK)) { + return NXT_ERROR; + } - while (sem->count == 0) { + while (sem->count == 0) { - err = nxt_thread_cond_wait(&sem->cond, &sem->mutex, timeout); + err = nxt_thread_cond_wait(&sem->cond, &sem->mutex, timeout); - if (err != 0) { - goto error; - } + if (err != 0) { + goto error; } + } - sem->count--; + sem->count--; error: - /* NXT_ERROR overrides NXT_OK and NXT_ETIMEDOUT. */ + /* NXT_ERROR overrides NXT_OK and NXT_ETIMEDOUT. */ - return (nxt_thread_mutex_unlock(&sem->mutex) | err); + return (nxt_thread_mutex_unlock(&sem->mutex) | err); } #endif diff --git a/src/nxt_semaphore.h b/src/nxt_semaphore.h index d1985342c..2ddb5e0e4 100644 --- a/src/nxt_semaphore.h +++ b/src/nxt_semaphore.h @@ -7,26 +7,23 @@ #ifndef _NXT_UNIX_SEMAPHORE_H_INCLUDED_ #define _NXT_UNIX_SEMAPHORE_H_INCLUDED_ - #if (NXT_HAVE_SEM_TIMEDWAIT) -typedef sem_t nxt_sem_t; +typedef sem_t nxt_sem_t; #else typedef struct { - nxt_atomic_t count; - nxt_thread_mutex_t mutex; - nxt_thread_cond_t cond; + nxt_atomic_t count; + nxt_thread_mutex_t mutex; + nxt_thread_cond_t cond; } nxt_sem_t; #endif - NXT_EXPORT nxt_int_t nxt_sem_init(nxt_sem_t *sem, nxt_uint_t count); NXT_EXPORT void nxt_sem_destroy(nxt_sem_t *sem); NXT_EXPORT nxt_int_t nxt_sem_post(nxt_sem_t *sem); NXT_EXPORT nxt_err_t nxt_sem_wait(nxt_sem_t *sem, nxt_nsec_t timeout); - #endif /* _NXT_UNIX_SEMAPHORE_H_INCLUDED_ */ diff --git a/src/nxt_sendbuf.c b/src/nxt_sendbuf.c index 94f8e9eb9..f28df83fa 100644 --- a/src/nxt_sendbuf.c +++ b/src/nxt_sendbuf.c @@ -6,440 +6,417 @@ #include - static nxt_bool_t nxt_sendbuf_copy(nxt_buf_mem_t *bm, nxt_buf_t *b, - size_t *copied); + size_t *copied); static nxt_buf_t *nxt_sendbuf_coalesce_completion(nxt_task_t *task, - nxt_work_queue_t *wq, nxt_buf_t *start); - + nxt_work_queue_t *wq, + nxt_buf_t *start); -nxt_uint_t -nxt_sendbuf_mem_coalesce0(nxt_task_t *task, nxt_sendbuf_t *sb, - struct iovec *iov, nxt_uint_t niov_max) -{ - u_char *last; - size_t size, total; - nxt_buf_t *b; - nxt_uint_t n; +nxt_uint_t nxt_sendbuf_mem_coalesce0(nxt_task_t *task, nxt_sendbuf_t *sb, + struct iovec *iov, nxt_uint_t niov_max) { + u_char *last; + size_t size, total; + nxt_buf_t *b; + nxt_uint_t n; - total = sb->size; - last = NULL; - n = (nxt_uint_t) -1; + total = sb->size; + last = NULL; + n = (nxt_uint_t)-1; - for (b = sb->buf; b != NULL && total < sb->limit; b = b->next) { + for (b = sb->buf; b != NULL && total < sb->limit; b = b->next) { - nxt_prefetch(b->next); + nxt_prefetch(b->next); - if (nxt_buf_is_file(b)) { - break; - } + if (nxt_buf_is_file(b)) { + break; + } - if (nxt_buf_is_mem(b)) { + if (nxt_buf_is_mem(b)) { - size = b->mem.free - b->mem.pos; + size = b->mem.free - b->mem.pos; - if (size != 0) { + if (size != 0) { - if (total + size > sb->limit) { - size = sb->limit - total; + if (total + size > sb->limit) { + size = sb->limit - total; - if (size == 0) { - break; - } - } + if (size == 0) { + break; + } + } - if (b->mem.pos != last) { + if (b->mem.pos != last) { - if (++n >= niov_max) { - goto done; - } + if (++n >= niov_max) { + goto done; + } - iov[n].iov_base = b->mem.pos; - iov[n].iov_len = size; + iov[n].iov_base = b->mem.pos; + iov[n].iov_len = size; - } else { - iov[n].iov_len += size; - } + } else { + iov[n].iov_len += size; + } - nxt_debug(task, "sendbuf: %ui, %p, %uz", - n, iov[n].iov_base, iov[n].iov_len); + nxt_debug(task, "sendbuf: %ui, %p, %uz", n, iov[n].iov_base, + iov[n].iov_len); - total += size; - last = b->mem.pos + size; - } + total += size; + last = b->mem.pos + size; + } - } else { - sb->sync = 1; - sb->last |= nxt_buf_is_last(b); - } + } else { + sb->sync = 1; + sb->last |= nxt_buf_is_last(b); } + } - n++; + n++; done: - sb->buf = b; + sb->buf = b; - return n; + return n; } +nxt_uint_t nxt_sendbuf_mem_coalesce(nxt_task_t *task, + nxt_sendbuf_coalesce_t *sb) { + u_char *last; + size_t size, total; + nxt_buf_t *b; + nxt_uint_t n; -nxt_uint_t -nxt_sendbuf_mem_coalesce(nxt_task_t *task, nxt_sendbuf_coalesce_t *sb) -{ - u_char *last; - size_t size, total; - nxt_buf_t *b; - nxt_uint_t n; + total = sb->size; + last = NULL; + n = (nxt_uint_t)-1; - total = sb->size; - last = NULL; - n = (nxt_uint_t) -1; + for (b = sb->buf; b != NULL && total < sb->limit; b = b->next) { - for (b = sb->buf; b != NULL && total < sb->limit; b = b->next) { + nxt_prefetch(b->next); - nxt_prefetch(b->next); - - if (nxt_buf_is_file(b)) { - break; - } + if (nxt_buf_is_file(b)) { + break; + } - if (nxt_buf_is_mem(b)) { + if (nxt_buf_is_mem(b)) { - size = b->mem.free - b->mem.pos; + size = b->mem.free - b->mem.pos; - if (size != 0) { + if (size != 0) { - if (total + size > sb->limit) { - size = sb->limit - total; + if (total + size > sb->limit) { + size = sb->limit - total; - sb->limit_reached = 1; + sb->limit_reached = 1; - if (nxt_slow_path(size == 0)) { - break; - } - } + if (nxt_slow_path(size == 0)) { + break; + } + } - if (b->mem.pos != last) { + if (b->mem.pos != last) { - if (++n >= sb->nmax) { - sb->nmax_reached = 1; + if (++n >= sb->nmax) { + sb->nmax_reached = 1; - goto done; - } + goto done; + } - sb->iobuf[n].iov_base = b->mem.pos; - sb->iobuf[n].iov_len = size; + sb->iobuf[n].iov_base = b->mem.pos; + sb->iobuf[n].iov_len = size; - } else { - sb->iobuf[n].iov_len += size; - } + } else { + sb->iobuf[n].iov_len += size; + } - nxt_debug(task, "sendbuf: %ui, %p, %uz", - n, sb->iobuf[n].iov_base, sb->iobuf[n].iov_len); + nxt_debug(task, "sendbuf: %ui, %p, %uz", n, sb->iobuf[n].iov_base, + sb->iobuf[n].iov_len); - total += size; - last = b->mem.pos + size; - } + total += size; + last = b->mem.pos + size; + } - } else { - sb->sync = 1; - sb->last |= nxt_buf_is_last(b); - } + } else { + sb->sync = 1; + sb->last |= nxt_buf_is_last(b); } + } - n++; + n++; done: - sb->buf = b; - sb->size = total; - sb->niov = n; + sb->buf = b; + sb->size = total; + sb->niov = n; - return n; + return n; } +size_t nxt_sendbuf_file_coalesce(nxt_sendbuf_coalesce_t *sb) { + size_t file_start, total; + nxt_fd_t fd; + nxt_off_t size, last; + nxt_buf_t *b; -size_t -nxt_sendbuf_file_coalesce(nxt_sendbuf_coalesce_t *sb) -{ - size_t file_start, total; - nxt_fd_t fd; - nxt_off_t size, last; - nxt_buf_t *b; - - b = sb->buf; - fd = b->file->fd; + b = sb->buf; + fd = b->file->fd; - total = sb->size; + total = sb->size; - for ( ;; ) { + for (;;) { - nxt_prefetch(b->next); + nxt_prefetch(b->next); - size = b->file_end - b->file_pos; + size = b->file_end - b->file_pos; - if (total + size >= sb->limit) { - total = sb->limit; - break; - } + if (total + size >= sb->limit) { + total = sb->limit; + break; + } - total += size; - last = b->file_pos + size; + total += size; + last = b->file_pos + size; - b = b->next; + b = b->next; - if (b == NULL || !nxt_buf_is_file(b)) { - break; - } + if (b == NULL || !nxt_buf_is_file(b)) { + break; + } - if (b->file_pos != last || b->file->fd != fd) { - break; - } + if (b->file_pos != last || b->file->fd != fd) { + break; } + } - sb->buf = b; + sb->buf = b; - file_start = sb->size; - sb->size = total; + file_start = sb->size; + sb->size = total; - return total - file_start; + return total - file_start; } +ssize_t nxt_sendbuf_copy_coalesce(nxt_conn_t *c, nxt_buf_mem_t *bm, + nxt_buf_t *b, size_t limit) { + size_t size, bsize, copied; + ssize_t n; + nxt_bool_t flush; -ssize_t -nxt_sendbuf_copy_coalesce(nxt_conn_t *c, nxt_buf_mem_t *bm, nxt_buf_t *b, - size_t limit) -{ - size_t size, bsize, copied; - ssize_t n; - nxt_bool_t flush; - - size = nxt_buf_mem_used_size(&b->mem); - bsize = nxt_buf_mem_size(bm); + size = nxt_buf_mem_used_size(&b->mem); + bsize = nxt_buf_mem_size(bm); - if (bsize != 0) { + if (bsize != 0) { - if (size > bsize && bm->pos == bm->free) { - /* - * A data buffer size is larger than the internal - * buffer size and the internal buffer is empty. - */ - goto no_buffer; - } - - if (bm->pos == NULL) { - bm->pos = nxt_malloc(bsize); - if (nxt_slow_path(bm->pos == NULL)) { - return NXT_ERROR; - } + if (size > bsize && bm->pos == bm->free) { + /* + * A data buffer size is larger than the internal + * buffer size and the internal buffer is empty. + */ + goto no_buffer; + } - bm->start = bm->pos; - bm->free = bm->pos; - bm->end += (uintptr_t) bm->pos; - } + if (bm->pos == NULL) { + bm->pos = nxt_malloc(bsize); + if (nxt_slow_path(bm->pos == NULL)) { + return NXT_ERROR; + } - copied = 0; + bm->start = bm->pos; + bm->free = bm->pos; + bm->end += (uintptr_t)bm->pos; + } - flush = nxt_sendbuf_copy(bm, b, &copied); + copied = 0; - nxt_log_debug(c->socket.log, "sendbuf copy:%uz fl:%b", copied, flush); + flush = nxt_sendbuf_copy(bm, b, &copied); - if (flush == 0) { - return copied; - } + nxt_log_debug(c->socket.log, "sendbuf copy:%uz fl:%b", copied, flush); - size = nxt_buf_mem_used_size(bm); + if (flush == 0) { + return copied; + } - if (size == 0 && nxt_buf_is_sync(b)) { - goto done; - } + size = nxt_buf_mem_used_size(bm); - n = c->io->send(c, bm->pos, nxt_min(size, limit)); + if (size == 0 && nxt_buf_is_sync(b)) { + goto done; + } - nxt_log_debug(c->socket.log, "sendbuf sent:%z", n); + n = c->io->send(c, bm->pos, nxt_min(size, limit)); - if (n > 0) { - bm->pos += n; + nxt_log_debug(c->socket.log, "sendbuf sent:%z", n); - if (bm->pos == bm->free) { - bm->pos = bm->start; - bm->free = bm->start; - } + if (n > 0) { + bm->pos += n; - n = 0; - } + if (bm->pos == bm->free) { + bm->pos = bm->start; + bm->free = bm->start; + } - return (copied != 0) ? (ssize_t) copied : n; + n = 0; } - /* No internal buffering. */ + return (copied != 0) ? (ssize_t)copied : n; + } - if (size == 0 && nxt_buf_is_sync(b)) { - goto done; - } + /* No internal buffering. */ + + if (size == 0 && nxt_buf_is_sync(b)) { + goto done; + } no_buffer: - return c->io->send(c, b->mem.pos, nxt_min(size, limit)); + return c->io->send(c, b->mem.pos, nxt_min(size, limit)); done: - nxt_log_debug(c->socket.log, "sendbuf done"); + nxt_log_debug(c->socket.log, "sendbuf done"); - return 0; + return 0; } +static nxt_bool_t nxt_sendbuf_copy(nxt_buf_mem_t *bm, nxt_buf_t *b, + size_t *copied) { + size_t size, bsize; + nxt_bool_t flush; -static nxt_bool_t -nxt_sendbuf_copy(nxt_buf_mem_t *bm, nxt_buf_t *b, size_t *copied) -{ - size_t size, bsize; - nxt_bool_t flush; - - flush = 0; + flush = 0; - do { - nxt_prefetch(b->next); + do { + nxt_prefetch(b->next); - if (nxt_buf_is_mem(b)) { - bsize = bm->end - bm->free; - size = b->mem.free - b->mem.pos; - size = nxt_min(size, bsize); + if (nxt_buf_is_mem(b)) { + bsize = bm->end - bm->free; + size = b->mem.free - b->mem.pos; + size = nxt_min(size, bsize); - nxt_memcpy(bm->free, b->mem.pos, size); + nxt_memcpy(bm->free, b->mem.pos, size); - *copied += size; - bm->free += size; + *copied += size; + bm->free += size; - if (bm->free == bm->end) { - return 1; - } - } + if (bm->free == bm->end) { + return 1; + } + } - flush |= nxt_buf_is_flush(b) || nxt_buf_is_last(b); + flush |= nxt_buf_is_flush(b) || nxt_buf_is_last(b); - b = b->next; + b = b->next; - } while (b != NULL); + } while (b != NULL); - return flush; + return flush; } +nxt_buf_t *nxt_sendbuf_update(nxt_buf_t *b, size_t sent) { + size_t size; -nxt_buf_t * -nxt_sendbuf_update(nxt_buf_t *b, size_t sent) -{ - size_t size; + while (b != NULL) { - while (b != NULL) { + nxt_prefetch(b->next); - nxt_prefetch(b->next); + if (!nxt_buf_is_sync(b)) { - if (!nxt_buf_is_sync(b)) { + size = nxt_buf_used_size(b); - size = nxt_buf_used_size(b); + if (size != 0) { - if (size != 0) { - - if (sent == 0) { - break; - } - - if (sent < size) { - - if (nxt_buf_is_mem(b)) { - b->mem.pos += sent; - } - - if (nxt_buf_is_file(b)) { - b->file_pos += sent; - } + if (sent == 0) { + break; + } - break; - } + if (sent < size) { - /* b->mem.free is NULL in file-only buffer. */ - b->mem.pos = b->mem.free; + if (nxt_buf_is_mem(b)) { + b->mem.pos += sent; + } - if (nxt_buf_is_file(b)) { - b->file_pos = b->file_end; - } + if (nxt_buf_is_file(b)) { + b->file_pos += sent; + } - sent -= size; - } + break; } - b = b->next; - } - - return b; -} - - -nxt_buf_t * -nxt_sendbuf_completion(nxt_task_t *task, nxt_work_queue_t *wq, nxt_buf_t *b) -{ - while (b != NULL) { + /* b->mem.free is NULL in file-only buffer. */ + b->mem.pos = b->mem.free; - if (!nxt_buf_is_sync(b) && nxt_buf_used_size(b) != 0) { - break; + if (nxt_buf_is_file(b)) { + b->file_pos = b->file_end; } - b = nxt_sendbuf_coalesce_completion(task, wq, b); + sent -= size; + } } - return b; + b = b->next; + } + + return b; } +nxt_buf_t *nxt_sendbuf_completion(nxt_task_t *task, nxt_work_queue_t *wq, + nxt_buf_t *b) { + while (b != NULL) { -void -nxt_sendbuf_drain(nxt_task_t *task, nxt_work_queue_t *wq, nxt_buf_t *b) -{ - while (b != NULL) { - b = nxt_sendbuf_coalesce_completion(task, wq, b); + if (!nxt_buf_is_sync(b) && nxt_buf_used_size(b) != 0) { + break; } -} + b = nxt_sendbuf_coalesce_completion(task, wq, b); + } -static nxt_buf_t * -nxt_sendbuf_coalesce_completion(nxt_task_t *task, nxt_work_queue_t *wq, - nxt_buf_t *start) -{ - nxt_buf_t *b, *next, **last, *rest, **last_rest; - nxt_work_handler_t handler; + return b; +} - rest = NULL; - last_rest = &rest; - last = &start->next; - b = start; - handler = b->completion_handler; +void nxt_sendbuf_drain(nxt_task_t *task, nxt_work_queue_t *wq, nxt_buf_t *b) { + while (b != NULL) { + b = nxt_sendbuf_coalesce_completion(task, wq, b); + } +} - for ( ;; ) { - next = b->next; - if (next == NULL) { - break; - } +static nxt_buf_t *nxt_sendbuf_coalesce_completion(nxt_task_t *task, + nxt_work_queue_t *wq, + nxt_buf_t *start) { + nxt_buf_t *b, *next, **last, *rest, **last_rest; + nxt_work_handler_t handler; + + rest = NULL; + last_rest = &rest; + last = &start->next; + b = start; + handler = b->completion_handler; + + for (;;) { + next = b->next; + if (next == NULL) { + break; + } - b->next = NULL; - b = next; + b->next = NULL; + b = next; - if (!nxt_buf_is_sync(b) && nxt_buf_used_size(b) != 0) { - *last_rest = b; - break; - } + if (!nxt_buf_is_sync(b) && nxt_buf_used_size(b) != 0) { + *last_rest = b; + break; + } - if (handler == b->completion_handler) { - *last = b; - last = &b->next; + if (handler == b->completion_handler) { + *last = b; + last = &b->next; - } else { - *last_rest = b; - last_rest = &b->next; - } + } else { + *last_rest = b; + last_rest = &b->next; } + } - nxt_work_queue_add(wq, handler, task, start, start->parent); + nxt_work_queue_add(wq, handler, task, start, start->parent); - return rest; + return rest; } diff --git a/src/nxt_sendbuf.h b/src/nxt_sendbuf.h index fcbe1a25b..28d6e4ae1 100644 --- a/src/nxt_sendbuf.h +++ b/src/nxt_sendbuf.h @@ -7,7 +7,6 @@ #ifndef _NXT_SENDBUF_H_INCLUDED_ #define _NXT_SENDBUF_H_INCLUDED_ - /* * The sendbuf interface is intended to send a buffer chain to a connection. * It uses sendfile interface if available. Otherwise it can send only @@ -34,83 +33,78 @@ * an additional limited chain must be created on each sendbuf call. */ - typedef struct { - nxt_buf_t *buf; - void *tls; - nxt_socket_t socket; - nxt_err_t error; - nxt_off_t sent; - size_t size; - size_t limit; - - uint8_t ready; /* 1 bit */ - uint8_t once; /* 1 bit */ - uint8_t sync; /* 1 bit */ - uint8_t last; /* 1 bit */ + nxt_buf_t *buf; + void *tls; + nxt_socket_t socket; + nxt_err_t error; + nxt_off_t sent; + size_t size; + size_t limit; + + uint8_t ready; /* 1 bit */ + uint8_t once; /* 1 bit */ + uint8_t sync; /* 1 bit */ + uint8_t last; /* 1 bit */ } nxt_sendbuf_t; - typedef struct { - nxt_buf_t *buf; - nxt_iobuf_t *iobuf; - nxt_uint_t niov; - - uint32_t nmax; - uint8_t sync; /* 1 bit */ - uint8_t last; /* 1 bit */ - uint8_t limit_reached; - uint8_t nmax_reached; - - size_t size; - size_t limit; + nxt_buf_t *buf; + nxt_iobuf_t *iobuf; + nxt_uint_t niov; + + uint32_t nmax; + uint8_t sync; /* 1 bit */ + uint8_t last; /* 1 bit */ + uint8_t limit_reached; + uint8_t nmax_reached; + + size_t size; + size_t limit; } nxt_sendbuf_coalesce_t; - #if (NXT_HAVE_LINUX_SENDFILE) -#define NXT_HAVE_SENDFILE 1 +#define NXT_HAVE_SENDFILE 1 ssize_t nxt_linux_event_conn_io_sendfile(nxt_conn_t *c, nxt_buf_t *b, - size_t limit); + size_t limit); #endif #if (NXT_HAVE_FREEBSD_SENDFILE) -#define NXT_HAVE_SENDFILE 1 +#define NXT_HAVE_SENDFILE 1 ssize_t nxt_freebsd_event_conn_io_sendfile(nxt_conn_t *c, nxt_buf_t *b, - size_t limit); + size_t limit); #endif #if (NXT_HAVE_SOLARIS_SENDFILEV) -#define NXT_HAVE_SENDFILE 1 +#define NXT_HAVE_SENDFILE 1 ssize_t nxt_solaris_event_conn_io_sendfilev(nxt_conn_t *c, nxt_buf_t *b, - size_t limit); + size_t limit); #endif #if (NXT_HAVE_MACOSX_SENDFILE) -#define NXT_HAVE_SENDFILE 1 +#define NXT_HAVE_SENDFILE 1 ssize_t nxt_macosx_event_conn_io_sendfile(nxt_conn_t *c, nxt_buf_t *b, - size_t limit); + size_t limit); #endif #if (NXT_HAVE_AIX_SEND_FILE) -#define NXT_HAVE_SENDFILE 1 +#define NXT_HAVE_SENDFILE 1 ssize_t nxt_aix_event_conn_io_send_file(nxt_conn_t *c, nxt_buf_t *b, - size_t limit); + size_t limit); #endif #if (NXT_HAVE_HPUX_SENDFILE) -#define NXT_HAVE_SENDFILE 1 +#define NXT_HAVE_SENDFILE 1 ssize_t nxt_hpux_event_conn_io_sendfile(nxt_conn_t *c, nxt_buf_t *b, - size_t limit); + size_t limit); #endif -ssize_t nxt_event_conn_io_sendbuf(nxt_conn_t *c, nxt_buf_t *b, - size_t limit); - +ssize_t nxt_event_conn_io_sendbuf(nxt_conn_t *c, nxt_buf_t *b, size_t limit); nxt_uint_t nxt_sendbuf_mem_coalesce0(nxt_task_t *task, nxt_sendbuf_t *sb, - struct iovec *iov, nxt_uint_t niov_max); + struct iovec *iov, nxt_uint_t niov_max); nxt_uint_t nxt_sendbuf_mem_coalesce(nxt_task_t *task, - nxt_sendbuf_coalesce_t *sb); + nxt_sendbuf_coalesce_t *sb); size_t nxt_sendbuf_file_coalesce(nxt_sendbuf_coalesce_t *sb); /* @@ -120,12 +114,11 @@ size_t nxt_sendbuf_file_coalesce(nxt_sendbuf_coalesce_t *sb); * overhead to each SSL/TLS record. */ ssize_t nxt_sendbuf_copy_coalesce(nxt_conn_t *c, nxt_buf_mem_t *bm, - nxt_buf_t *b, size_t limit); + nxt_buf_t *b, size_t limit); nxt_buf_t *nxt_sendbuf_update(nxt_buf_t *b, size_t sent); nxt_buf_t *nxt_sendbuf_completion(nxt_task_t *task, nxt_work_queue_t *wq, - nxt_buf_t *b); + nxt_buf_t *b); void nxt_sendbuf_drain(nxt_task_t *task, nxt_work_queue_t *wq, nxt_buf_t *b); - #endif /* _NXT_SENDBUF_H_INCLUDED_ */ diff --git a/src/nxt_service.c b/src/nxt_service.c index cc9f8d894..1d4f979b8 100644 --- a/src/nxt_service.c +++ b/src/nxt_service.c @@ -6,160 +6,151 @@ #include - -static const nxt_service_t nxt_services[] = { +static const nxt_service_t nxt_services[] = { #if (NXT_HAVE_KQUEUE) - { "engine", "kqueue", &nxt_kqueue_engine }, + {"engine", "kqueue", &nxt_kqueue_engine}, #endif #if (NXT_HAVE_EPOLL_EDGE) - { "engine", "epoll", &nxt_epoll_edge_engine }, - { "engine", "epoll_edge", &nxt_epoll_edge_engine }, - { "engine", "epoll_level", &nxt_epoll_level_engine }, + {"engine", "epoll", &nxt_epoll_edge_engine}, + {"engine", "epoll_edge", &nxt_epoll_edge_engine}, + {"engine", "epoll_level", &nxt_epoll_level_engine}, #elif (NXT_HAVE_EPOLL) - { "engine", "epoll", &nxt_epoll_level_engine }, - { "engine", "epoll_level", &nxt_epoll_level_engine }, + {"engine", "epoll", &nxt_epoll_level_engine}, + {"engine", "epoll_level", &nxt_epoll_level_engine}, #endif #if (NXT_HAVE_EVENTPORT) - { "engine", "eventport", &nxt_eventport_engine }, + {"engine", "eventport", &nxt_eventport_engine}, #endif #if (NXT_HAVE_DEVPOLL) - { "engine", "devpoll", &nxt_devpoll_engine }, - { "engine", "/dev/poll", &nxt_devpoll_engine }, + {"engine", "devpoll", &nxt_devpoll_engine}, + {"engine", "/dev/poll", &nxt_devpoll_engine}, #endif #if (NXT_HAVE_POLLSET) - { "engine", "pollset", &nxt_pollset_engine }, + {"engine", "pollset", &nxt_pollset_engine}, #endif - { "engine", "poll", &nxt_poll_engine }, - { "engine", "select", &nxt_select_engine }, + {"engine", "poll", &nxt_poll_engine}, + {"engine", "select", &nxt_select_engine}, #if (NXT_HAVE_OPENSSL) - { "SSL/TLS", "OpenSSL", &nxt_openssl_lib }, - { "SSL/TLS", "openssl", &nxt_openssl_lib }, + {"SSL/TLS", "OpenSSL", &nxt_openssl_lib}, + {"SSL/TLS", "openssl", &nxt_openssl_lib}, #endif #if (NXT_HAVE_GNUTLS) - { "SSL/TLS", "GnuTLS", &nxt_gnutls_lib }, - { "SSL/TLS", "gnutls", &nxt_gnutls_lib }, + {"SSL/TLS", "GnuTLS", &nxt_gnutls_lib}, + {"SSL/TLS", "gnutls", &nxt_gnutls_lib}, #endif #if (NXT_HAVE_CYASSL) - { "SSL/TLS", "CyaSSL", &nxt_cyassl_lib }, - { "SSL/TLS", "cyassl", &nxt_cyassl_lib }, + {"SSL/TLS", "CyaSSL", &nxt_cyassl_lib}, + {"SSL/TLS", "cyassl", &nxt_cyassl_lib}, #endif }; +nxt_array_t *nxt_services_init(nxt_mp_t *mp) { + nxt_uint_t n; + nxt_array_t *services; + nxt_service_t *s; + const nxt_service_t *service; -nxt_array_t * -nxt_services_init(nxt_mp_t *mp) -{ - nxt_uint_t n; - nxt_array_t *services; - nxt_service_t *s; - const nxt_service_t *service; - - services = nxt_array_create(mp, 32, sizeof(nxt_service_t)); + services = nxt_array_create(mp, 32, sizeof(nxt_service_t)); - if (nxt_fast_path(services != NULL)) { + if (nxt_fast_path(services != NULL)) { - service = nxt_services; - n = nxt_nitems(nxt_services); + service = nxt_services; + n = nxt_nitems(nxt_services); - while (n != 0) { - s = nxt_array_add(services); - if (nxt_slow_path(s == NULL)) { - return NULL; - } + while (n != 0) { + s = nxt_array_add(services); + if (nxt_slow_path(s == NULL)) { + return NULL; + } - *s = *service; + *s = *service; - service++; - n--; - } + service++; + n--; } + } - return services; + return services; } +nxt_int_t nxt_service_add(nxt_array_t *services, const nxt_service_t *service) { + nxt_uint_t n; + nxt_service_t *s; -nxt_int_t -nxt_service_add(nxt_array_t *services, const nxt_service_t *service) -{ - nxt_uint_t n; - nxt_service_t *s; - - s = services->elts; - n = services->nelts; - - while (n != 0) { - if (nxt_strcmp(s->type, service->type) != 0) { - goto next; - } - - if (nxt_strcmp(s->name, service->name) != 0) { - goto next; - } - - nxt_thread_log_alert("service \"%s:%s\" is duplicate", - service->type, service->name); - return NXT_ERROR; + s = services->elts; + n = services->nelts; - next: - - s++; - n--; + while (n != 0) { + if (nxt_strcmp(s->type, service->type) != 0) { + goto next; } - s = nxt_array_add(services); - if (nxt_fast_path(s != NULL)) { - *s = *service; - return NXT_OK; + if (nxt_strcmp(s->name, service->name) != 0) { + goto next; } + nxt_thread_log_alert("service \"%s:%s\" is duplicate", service->type, + service->name); return NXT_ERROR; -} + next: -const void * -nxt_service_get(nxt_array_t *services, const char *type, const char *name) -{ - nxt_uint_t n; - const nxt_service_t *s; + s++; + n--; + } - if (services != NULL) { - s = services->elts; - n = services->nelts; + s = nxt_array_add(services); + if (nxt_fast_path(s != NULL)) { + *s = *service; + return NXT_OK; + } - } else { - s = nxt_services; - n = nxt_nitems(nxt_services); - } + return NXT_ERROR; +} - while (n != 0) { - if (nxt_strcmp(s->type, type) == 0) { +const void *nxt_service_get(nxt_array_t *services, const char *type, + const char *name) { + nxt_uint_t n; + const nxt_service_t *s; - if (name == NULL) { - return s->service; - } + if (services != NULL) { + s = services->elts; + n = services->nelts; + + } else { + s = nxt_services; + n = nxt_nitems(nxt_services); + } - if (nxt_strcmp(s->name, name) == 0) { - return s->service; - } - } + while (n != 0) { + if (nxt_strcmp(s->type, type) == 0) { - s++; - n--; + if (name == NULL) { + return s->service; + } + + if (nxt_strcmp(s->name, name) == 0) { + return s->service; + } } - nxt_thread_log_alert("service \"%s%s%s\" not found", - type, (name != NULL) ? ":" : "", name); + s++; + n--; + } + + nxt_thread_log_alert("service \"%s%s%s\" not found", type, + (name != NULL) ? ":" : "", name); - return NULL; + return NULL; } diff --git a/src/nxt_service.h b/src/nxt_service.h index c43d5394f..0a2a4314b 100644 --- a/src/nxt_service.h +++ b/src/nxt_service.h @@ -7,23 +7,18 @@ #ifndef _NXT_SERVICE_H_INCLUDED_ #define _NXT_SERVICE_H_INCLUDED_ - typedef struct { - const char *type; - const char *name; - const void *service; + const char *type; + const char *name; + const void *service; } nxt_service_t; - -#define nxt_service_is_module(s) \ - ((s)->type == NULL) - +#define nxt_service_is_module(s) ((s)->type == NULL) NXT_EXPORT nxt_array_t *nxt_services_init(nxt_mp_t *mp); NXT_EXPORT nxt_int_t nxt_service_add(nxt_array_t *services, - const nxt_service_t *service); + const nxt_service_t *service); NXT_EXPORT const void *nxt_service_get(nxt_array_t *services, const char *type, - const char *name); - + const char *name); #endif /* _NXT_SERVICE_H_INCLUDED_ */ diff --git a/src/nxt_sha1.c b/src/nxt_sha1.c index 407c5933c..8439e8d35 100644 --- a/src/nxt_sha1.c +++ b/src/nxt_sha1.c @@ -6,290 +6,271 @@ * An internal SHA1 implementation. */ - #include #include - static const u_char *nxt_sha1_body(nxt_sha1_t *ctx, const u_char *data, - size_t size); - + size_t size); -void -nxt_sha1_init(nxt_sha1_t *ctx) -{ - ctx->a = 0x67452301; - ctx->b = 0xefcdab89; - ctx->c = 0x98badcfe; - ctx->d = 0x10325476; - ctx->e = 0xc3d2e1f0; +void nxt_sha1_init(nxt_sha1_t *ctx) { + ctx->a = 0x67452301; + ctx->b = 0xefcdab89; + ctx->c = 0x98badcfe; + ctx->d = 0x10325476; + ctx->e = 0xc3d2e1f0; - ctx->bytes = 0; + ctx->bytes = 0; } +void nxt_sha1_update(nxt_sha1_t *ctx, const void *data, size_t size) { + size_t used, free; -void -nxt_sha1_update(nxt_sha1_t *ctx, const void *data, size_t size) -{ - size_t used, free; - - used = (size_t) (ctx->bytes & 0x3f); - ctx->bytes += size; - - if (used) { - free = 64 - used; - - if (size < free) { - memcpy(&ctx->buffer[used], data, size); - return; - } + used = (size_t)(ctx->bytes & 0x3f); + ctx->bytes += size; - memcpy(&ctx->buffer[used], data, free); - data = (u_char *) data + free; - size -= free; - (void) nxt_sha1_body(ctx, ctx->buffer, 64); - } + if (used) { + free = 64 - used; - if (size >= 64) { - data = nxt_sha1_body(ctx, data, size & ~(size_t) 0x3f); - size &= 0x3f; + if (size < free) { + memcpy(&ctx->buffer[used], data, size); + return; } - memcpy(ctx->buffer, data, size); -} - - -void -nxt_sha1_final(u_char result[20], nxt_sha1_t *ctx) -{ - size_t used, free; - - used = (size_t) (ctx->bytes & 0x3f); + memcpy(&ctx->buffer[used], data, free); + data = (u_char *)data + free; + size -= free; + (void)nxt_sha1_body(ctx, ctx->buffer, 64); + } - ctx->buffer[used++] = 0x80; + if (size >= 64) { + data = nxt_sha1_body(ctx, data, size & ~(size_t)0x3f); + size &= 0x3f; + } - free = 64 - used; - - if (free < 8) { - nxt_memzero(&ctx->buffer[used], free); - (void) nxt_sha1_body(ctx, ctx->buffer, 64); - used = 0; - free = 64; - } - - nxt_memzero(&ctx->buffer[used], free - 8); - - ctx->bytes <<= 3; - ctx->buffer[56] = (u_char) (ctx->bytes >> 56); - ctx->buffer[57] = (u_char) (ctx->bytes >> 48); - ctx->buffer[58] = (u_char) (ctx->bytes >> 40); - ctx->buffer[59] = (u_char) (ctx->bytes >> 32); - ctx->buffer[60] = (u_char) (ctx->bytes >> 24); - ctx->buffer[61] = (u_char) (ctx->bytes >> 16); - ctx->buffer[62] = (u_char) (ctx->bytes >> 8); - ctx->buffer[63] = (u_char) ctx->bytes; - - (void) nxt_sha1_body(ctx, ctx->buffer, 64); - - result[0] = (u_char) (ctx->a >> 24); - result[1] = (u_char) (ctx->a >> 16); - result[2] = (u_char) (ctx->a >> 8); - result[3] = (u_char) ctx->a; - result[4] = (u_char) (ctx->b >> 24); - result[5] = (u_char) (ctx->b >> 16); - result[6] = (u_char) (ctx->b >> 8); - result[7] = (u_char) ctx->b; - result[8] = (u_char) (ctx->c >> 24); - result[9] = (u_char) (ctx->c >> 16); - result[10] = (u_char) (ctx->c >> 8); - result[11] = (u_char) ctx->c; - result[12] = (u_char) (ctx->d >> 24); - result[13] = (u_char) (ctx->d >> 16); - result[14] = (u_char) (ctx->d >> 8); - result[15] = (u_char) ctx->d; - result[16] = (u_char) (ctx->e >> 24); - result[17] = (u_char) (ctx->e >> 16); - result[18] = (u_char) (ctx->e >> 8); - result[19] = (u_char) ctx->e; - - nxt_memzero(ctx, sizeof(*ctx)); + memcpy(ctx->buffer, data, size); } +void nxt_sha1_final(u_char result[20], nxt_sha1_t *ctx) { + size_t used, free; + + used = (size_t)(ctx->bytes & 0x3f); + + ctx->buffer[used++] = 0x80; + + free = 64 - used; + + if (free < 8) { + nxt_memzero(&ctx->buffer[used], free); + (void)nxt_sha1_body(ctx, ctx->buffer, 64); + used = 0; + free = 64; + } + + nxt_memzero(&ctx->buffer[used], free - 8); + + ctx->bytes <<= 3; + ctx->buffer[56] = (u_char)(ctx->bytes >> 56); + ctx->buffer[57] = (u_char)(ctx->bytes >> 48); + ctx->buffer[58] = (u_char)(ctx->bytes >> 40); + ctx->buffer[59] = (u_char)(ctx->bytes >> 32); + ctx->buffer[60] = (u_char)(ctx->bytes >> 24); + ctx->buffer[61] = (u_char)(ctx->bytes >> 16); + ctx->buffer[62] = (u_char)(ctx->bytes >> 8); + ctx->buffer[63] = (u_char)ctx->bytes; + + (void)nxt_sha1_body(ctx, ctx->buffer, 64); + + result[0] = (u_char)(ctx->a >> 24); + result[1] = (u_char)(ctx->a >> 16); + result[2] = (u_char)(ctx->a >> 8); + result[3] = (u_char)ctx->a; + result[4] = (u_char)(ctx->b >> 24); + result[5] = (u_char)(ctx->b >> 16); + result[6] = (u_char)(ctx->b >> 8); + result[7] = (u_char)ctx->b; + result[8] = (u_char)(ctx->c >> 24); + result[9] = (u_char)(ctx->c >> 16); + result[10] = (u_char)(ctx->c >> 8); + result[11] = (u_char)ctx->c; + result[12] = (u_char)(ctx->d >> 24); + result[13] = (u_char)(ctx->d >> 16); + result[14] = (u_char)(ctx->d >> 8); + result[15] = (u_char)ctx->d; + result[16] = (u_char)(ctx->e >> 24); + result[17] = (u_char)(ctx->e >> 16); + result[18] = (u_char)(ctx->e >> 8); + result[19] = (u_char)ctx->e; + + nxt_memzero(ctx, sizeof(*ctx)); +} /* * Helper functions. */ -#define ROTATE(bits, word) (((word) << (bits)) | ((word) >> (32 - (bits)))) - -#define F1(b, c, d) (((b) & (c)) | ((~(b)) & (d))) -#define F2(b, c, d) ((b) ^ (c) ^ (d)) -#define F3(b, c, d) (((b) & (c)) | ((b) & (d)) | ((c) & (d))) +#define ROTATE(bits, word) (((word) << (bits)) | ((word) >> (32 - (bits)))) -#define STEP(f, a, b, c, d, e, w, t) \ - temp = ROTATE(5, (a)) + f((b), (c), (d)) + (e) + (w) + (t); \ - (e) = (d); \ - (d) = (c); \ - (c) = ROTATE(30, (b)); \ - (b) = (a); \ - (a) = temp; +#define F1(b, c, d) (((b) & (c)) | ((~(b)) & (d))) +#define F2(b, c, d) ((b) ^ (c) ^ (d)) +#define F3(b, c, d) (((b) & (c)) | ((b) & (d)) | ((c) & (d))) +#define STEP(f, a, b, c, d, e, w, t) \ + temp = ROTATE(5, (a)) + f((b), (c), (d)) + (e) + (w) + (t); \ + (e) = (d); \ + (d) = (c); \ + (c) = ROTATE(30, (b)); \ + (b) = (a); \ + (a) = temp; /* * GET() reads 4 input bytes in big-endian byte order and returns * them as uint32_t. */ -#define GET(n) \ - ( ((uint32_t) p[n * 4 + 3]) \ - | ((uint32_t) p[n * 4 + 2] << 8) \ - | ((uint32_t) p[n * 4 + 1] << 16) \ - | ((uint32_t) p[n * 4] << 24)) - +#define GET(n) \ + (((uint32_t)p[n * 4 + 3]) | ((uint32_t)p[n * 4 + 2] << 8) | \ + ((uint32_t)p[n * 4 + 1] << 16) | ((uint32_t)p[n * 4] << 24)) /* * This processes one or more 64-byte data blocks, but does not update * the bit counters. There are no alignment requirements. */ -static const u_char * -nxt_sha1_body(nxt_sha1_t *ctx, const u_char *data, size_t size) -{ - uint32_t a, b, c, d, e, temp; - uint32_t saved_a, saved_b, saved_c, saved_d, saved_e; - uint32_t words[80]; - nxt_uint_t i; - const u_char *p; - - p = data; - - a = ctx->a; - b = ctx->b; - c = ctx->c; - d = ctx->d; - e = ctx->e; - - do { - saved_a = a; - saved_b = b; - saved_c = c; - saved_d = d; - saved_e = e; - - /* Load data block into the words array */ - - for (i = 0; i < 16; i++) { - words[i] = GET(i); - } - - for (i = 16; i < 80; i++) { - words[i] = ROTATE(1, words[i - 3] - ^ words[i - 8] - ^ words[i - 14] - ^ words[i - 16]); - } - - /* Transformations */ - - STEP(F1, a, b, c, d, e, words[0], 0x5a827999); - STEP(F1, a, b, c, d, e, words[1], 0x5a827999); - STEP(F1, a, b, c, d, e, words[2], 0x5a827999); - STEP(F1, a, b, c, d, e, words[3], 0x5a827999); - STEP(F1, a, b, c, d, e, words[4], 0x5a827999); - STEP(F1, a, b, c, d, e, words[5], 0x5a827999); - STEP(F1, a, b, c, d, e, words[6], 0x5a827999); - STEP(F1, a, b, c, d, e, words[7], 0x5a827999); - STEP(F1, a, b, c, d, e, words[8], 0x5a827999); - STEP(F1, a, b, c, d, e, words[9], 0x5a827999); - STEP(F1, a, b, c, d, e, words[10], 0x5a827999); - STEP(F1, a, b, c, d, e, words[11], 0x5a827999); - STEP(F1, a, b, c, d, e, words[12], 0x5a827999); - STEP(F1, a, b, c, d, e, words[13], 0x5a827999); - STEP(F1, a, b, c, d, e, words[14], 0x5a827999); - STEP(F1, a, b, c, d, e, words[15], 0x5a827999); - STEP(F1, a, b, c, d, e, words[16], 0x5a827999); - STEP(F1, a, b, c, d, e, words[17], 0x5a827999); - STEP(F1, a, b, c, d, e, words[18], 0x5a827999); - STEP(F1, a, b, c, d, e, words[19], 0x5a827999); - - STEP(F2, a, b, c, d, e, words[20], 0x6ed9eba1); - STEP(F2, a, b, c, d, e, words[21], 0x6ed9eba1); - STEP(F2, a, b, c, d, e, words[22], 0x6ed9eba1); - STEP(F2, a, b, c, d, e, words[23], 0x6ed9eba1); - STEP(F2, a, b, c, d, e, words[24], 0x6ed9eba1); - STEP(F2, a, b, c, d, e, words[25], 0x6ed9eba1); - STEP(F2, a, b, c, d, e, words[26], 0x6ed9eba1); - STEP(F2, a, b, c, d, e, words[27], 0x6ed9eba1); - STEP(F2, a, b, c, d, e, words[28], 0x6ed9eba1); - STEP(F2, a, b, c, d, e, words[29], 0x6ed9eba1); - STEP(F2, a, b, c, d, e, words[30], 0x6ed9eba1); - STEP(F2, a, b, c, d, e, words[31], 0x6ed9eba1); - STEP(F2, a, b, c, d, e, words[32], 0x6ed9eba1); - STEP(F2, a, b, c, d, e, words[33], 0x6ed9eba1); - STEP(F2, a, b, c, d, e, words[34], 0x6ed9eba1); - STEP(F2, a, b, c, d, e, words[35], 0x6ed9eba1); - STEP(F2, a, b, c, d, e, words[36], 0x6ed9eba1); - STEP(F2, a, b, c, d, e, words[37], 0x6ed9eba1); - STEP(F2, a, b, c, d, e, words[38], 0x6ed9eba1); - STEP(F2, a, b, c, d, e, words[39], 0x6ed9eba1); - - STEP(F3, a, b, c, d, e, words[40], 0x8f1bbcdc); - STEP(F3, a, b, c, d, e, words[41], 0x8f1bbcdc); - STEP(F3, a, b, c, d, e, words[42], 0x8f1bbcdc); - STEP(F3, a, b, c, d, e, words[43], 0x8f1bbcdc); - STEP(F3, a, b, c, d, e, words[44], 0x8f1bbcdc); - STEP(F3, a, b, c, d, e, words[45], 0x8f1bbcdc); - STEP(F3, a, b, c, d, e, words[46], 0x8f1bbcdc); - STEP(F3, a, b, c, d, e, words[47], 0x8f1bbcdc); - STEP(F3, a, b, c, d, e, words[48], 0x8f1bbcdc); - STEP(F3, a, b, c, d, e, words[49], 0x8f1bbcdc); - STEP(F3, a, b, c, d, e, words[50], 0x8f1bbcdc); - STEP(F3, a, b, c, d, e, words[51], 0x8f1bbcdc); - STEP(F3, a, b, c, d, e, words[52], 0x8f1bbcdc); - STEP(F3, a, b, c, d, e, words[53], 0x8f1bbcdc); - STEP(F3, a, b, c, d, e, words[54], 0x8f1bbcdc); - STEP(F3, a, b, c, d, e, words[55], 0x8f1bbcdc); - STEP(F3, a, b, c, d, e, words[56], 0x8f1bbcdc); - STEP(F3, a, b, c, d, e, words[57], 0x8f1bbcdc); - STEP(F3, a, b, c, d, e, words[58], 0x8f1bbcdc); - STEP(F3, a, b, c, d, e, words[59], 0x8f1bbcdc); - - STEP(F2, a, b, c, d, e, words[60], 0xca62c1d6); - STEP(F2, a, b, c, d, e, words[61], 0xca62c1d6); - STEP(F2, a, b, c, d, e, words[62], 0xca62c1d6); - STEP(F2, a, b, c, d, e, words[63], 0xca62c1d6); - STEP(F2, a, b, c, d, e, words[64], 0xca62c1d6); - STEP(F2, a, b, c, d, e, words[65], 0xca62c1d6); - STEP(F2, a, b, c, d, e, words[66], 0xca62c1d6); - STEP(F2, a, b, c, d, e, words[67], 0xca62c1d6); - STEP(F2, a, b, c, d, e, words[68], 0xca62c1d6); - STEP(F2, a, b, c, d, e, words[69], 0xca62c1d6); - STEP(F2, a, b, c, d, e, words[70], 0xca62c1d6); - STEP(F2, a, b, c, d, e, words[71], 0xca62c1d6); - STEP(F2, a, b, c, d, e, words[72], 0xca62c1d6); - STEP(F2, a, b, c, d, e, words[73], 0xca62c1d6); - STEP(F2, a, b, c, d, e, words[74], 0xca62c1d6); - STEP(F2, a, b, c, d, e, words[75], 0xca62c1d6); - STEP(F2, a, b, c, d, e, words[76], 0xca62c1d6); - STEP(F2, a, b, c, d, e, words[77], 0xca62c1d6); - STEP(F2, a, b, c, d, e, words[78], 0xca62c1d6); - STEP(F2, a, b, c, d, e, words[79], 0xca62c1d6); - - a += saved_a; - b += saved_b; - c += saved_c; - d += saved_d; - e += saved_e; - - p += 64; - - } while (size -= 64); - - ctx->a = a; - ctx->b = b; - ctx->c = c; - ctx->d = d; - ctx->e = e; - - return p; +static const u_char *nxt_sha1_body(nxt_sha1_t *ctx, const u_char *data, + size_t size) { + uint32_t a, b, c, d, e, temp; + uint32_t saved_a, saved_b, saved_c, saved_d, saved_e; + uint32_t words[80]; + nxt_uint_t i; + const u_char *p; + + p = data; + + a = ctx->a; + b = ctx->b; + c = ctx->c; + d = ctx->d; + e = ctx->e; + + do { + saved_a = a; + saved_b = b; + saved_c = c; + saved_d = d; + saved_e = e; + + /* Load data block into the words array */ + + for (i = 0; i < 16; i++) { + words[i] = GET(i); + } + + for (i = 16; i < 80; i++) { + words[i] = ROTATE(1, words[i - 3] ^ words[i - 8] ^ words[i - 14] ^ + words[i - 16]); + } + + /* Transformations */ + + STEP(F1, a, b, c, d, e, words[0], 0x5a827999); + STEP(F1, a, b, c, d, e, words[1], 0x5a827999); + STEP(F1, a, b, c, d, e, words[2], 0x5a827999); + STEP(F1, a, b, c, d, e, words[3], 0x5a827999); + STEP(F1, a, b, c, d, e, words[4], 0x5a827999); + STEP(F1, a, b, c, d, e, words[5], 0x5a827999); + STEP(F1, a, b, c, d, e, words[6], 0x5a827999); + STEP(F1, a, b, c, d, e, words[7], 0x5a827999); + STEP(F1, a, b, c, d, e, words[8], 0x5a827999); + STEP(F1, a, b, c, d, e, words[9], 0x5a827999); + STEP(F1, a, b, c, d, e, words[10], 0x5a827999); + STEP(F1, a, b, c, d, e, words[11], 0x5a827999); + STEP(F1, a, b, c, d, e, words[12], 0x5a827999); + STEP(F1, a, b, c, d, e, words[13], 0x5a827999); + STEP(F1, a, b, c, d, e, words[14], 0x5a827999); + STEP(F1, a, b, c, d, e, words[15], 0x5a827999); + STEP(F1, a, b, c, d, e, words[16], 0x5a827999); + STEP(F1, a, b, c, d, e, words[17], 0x5a827999); + STEP(F1, a, b, c, d, e, words[18], 0x5a827999); + STEP(F1, a, b, c, d, e, words[19], 0x5a827999); + + STEP(F2, a, b, c, d, e, words[20], 0x6ed9eba1); + STEP(F2, a, b, c, d, e, words[21], 0x6ed9eba1); + STEP(F2, a, b, c, d, e, words[22], 0x6ed9eba1); + STEP(F2, a, b, c, d, e, words[23], 0x6ed9eba1); + STEP(F2, a, b, c, d, e, words[24], 0x6ed9eba1); + STEP(F2, a, b, c, d, e, words[25], 0x6ed9eba1); + STEP(F2, a, b, c, d, e, words[26], 0x6ed9eba1); + STEP(F2, a, b, c, d, e, words[27], 0x6ed9eba1); + STEP(F2, a, b, c, d, e, words[28], 0x6ed9eba1); + STEP(F2, a, b, c, d, e, words[29], 0x6ed9eba1); + STEP(F2, a, b, c, d, e, words[30], 0x6ed9eba1); + STEP(F2, a, b, c, d, e, words[31], 0x6ed9eba1); + STEP(F2, a, b, c, d, e, words[32], 0x6ed9eba1); + STEP(F2, a, b, c, d, e, words[33], 0x6ed9eba1); + STEP(F2, a, b, c, d, e, words[34], 0x6ed9eba1); + STEP(F2, a, b, c, d, e, words[35], 0x6ed9eba1); + STEP(F2, a, b, c, d, e, words[36], 0x6ed9eba1); + STEP(F2, a, b, c, d, e, words[37], 0x6ed9eba1); + STEP(F2, a, b, c, d, e, words[38], 0x6ed9eba1); + STEP(F2, a, b, c, d, e, words[39], 0x6ed9eba1); + + STEP(F3, a, b, c, d, e, words[40], 0x8f1bbcdc); + STEP(F3, a, b, c, d, e, words[41], 0x8f1bbcdc); + STEP(F3, a, b, c, d, e, words[42], 0x8f1bbcdc); + STEP(F3, a, b, c, d, e, words[43], 0x8f1bbcdc); + STEP(F3, a, b, c, d, e, words[44], 0x8f1bbcdc); + STEP(F3, a, b, c, d, e, words[45], 0x8f1bbcdc); + STEP(F3, a, b, c, d, e, words[46], 0x8f1bbcdc); + STEP(F3, a, b, c, d, e, words[47], 0x8f1bbcdc); + STEP(F3, a, b, c, d, e, words[48], 0x8f1bbcdc); + STEP(F3, a, b, c, d, e, words[49], 0x8f1bbcdc); + STEP(F3, a, b, c, d, e, words[50], 0x8f1bbcdc); + STEP(F3, a, b, c, d, e, words[51], 0x8f1bbcdc); + STEP(F3, a, b, c, d, e, words[52], 0x8f1bbcdc); + STEP(F3, a, b, c, d, e, words[53], 0x8f1bbcdc); + STEP(F3, a, b, c, d, e, words[54], 0x8f1bbcdc); + STEP(F3, a, b, c, d, e, words[55], 0x8f1bbcdc); + STEP(F3, a, b, c, d, e, words[56], 0x8f1bbcdc); + STEP(F3, a, b, c, d, e, words[57], 0x8f1bbcdc); + STEP(F3, a, b, c, d, e, words[58], 0x8f1bbcdc); + STEP(F3, a, b, c, d, e, words[59], 0x8f1bbcdc); + + STEP(F2, a, b, c, d, e, words[60], 0xca62c1d6); + STEP(F2, a, b, c, d, e, words[61], 0xca62c1d6); + STEP(F2, a, b, c, d, e, words[62], 0xca62c1d6); + STEP(F2, a, b, c, d, e, words[63], 0xca62c1d6); + STEP(F2, a, b, c, d, e, words[64], 0xca62c1d6); + STEP(F2, a, b, c, d, e, words[65], 0xca62c1d6); + STEP(F2, a, b, c, d, e, words[66], 0xca62c1d6); + STEP(F2, a, b, c, d, e, words[67], 0xca62c1d6); + STEP(F2, a, b, c, d, e, words[68], 0xca62c1d6); + STEP(F2, a, b, c, d, e, words[69], 0xca62c1d6); + STEP(F2, a, b, c, d, e, words[70], 0xca62c1d6); + STEP(F2, a, b, c, d, e, words[71], 0xca62c1d6); + STEP(F2, a, b, c, d, e, words[72], 0xca62c1d6); + STEP(F2, a, b, c, d, e, words[73], 0xca62c1d6); + STEP(F2, a, b, c, d, e, words[74], 0xca62c1d6); + STEP(F2, a, b, c, d, e, words[75], 0xca62c1d6); + STEP(F2, a, b, c, d, e, words[76], 0xca62c1d6); + STEP(F2, a, b, c, d, e, words[77], 0xca62c1d6); + STEP(F2, a, b, c, d, e, words[78], 0xca62c1d6); + STEP(F2, a, b, c, d, e, words[79], 0xca62c1d6); + + a += saved_a; + b += saved_b; + c += saved_c; + d += saved_d; + e += saved_e; + + p += 64; + + } while (size -= 64); + + ctx->a = a; + ctx->b = b; + ctx->c = c; + ctx->d = d; + ctx->e = e; + + return p; } diff --git a/src/nxt_sha1.h b/src/nxt_sha1.h index 2816982b6..71d0df383 100644 --- a/src/nxt_sha1.h +++ b/src/nxt_sha1.h @@ -4,21 +4,17 @@ * Copyright (C) NGINX, Inc. */ - #ifndef _NXT_SHA1_H_INCLUDED_ #define _NXT_SHA1_H_INCLUDED_ - typedef struct { - uint64_t bytes; - uint32_t a, b, c, d, e; - u_char buffer[64]; + uint64_t bytes; + uint32_t a, b, c, d, e; + u_char buffer[64]; } nxt_sha1_t; - NXT_EXPORT void nxt_sha1_init(nxt_sha1_t *ctx); NXT_EXPORT void nxt_sha1_update(nxt_sha1_t *ctx, const void *data, size_t size); NXT_EXPORT void nxt_sha1_final(u_char result[20], nxt_sha1_t *ctx); - #endif /* _NXT_SHA1_H_INCLUDED_ */ diff --git a/src/nxt_signal.c b/src/nxt_signal.c index 0ab1ba996..77a40b24e 100644 --- a/src/nxt_signal.c +++ b/src/nxt_signal.c @@ -6,7 +6,6 @@ #include - /* * Signals are handled only via a main thread event engine work queue. * There are three ways to route signals to the work queue: @@ -21,172 +20,153 @@ * to the event engine. */ - static nxt_int_t nxt_signal_action(int signo, void (*handler)(int)); static void nxt_signal_thread(void *data); +nxt_event_signals_t *nxt_event_engine_signals(const nxt_sig_event_t *sigev) { + nxt_event_signals_t *signals; -nxt_event_signals_t * -nxt_event_engine_signals(const nxt_sig_event_t *sigev) -{ - nxt_event_signals_t *signals; - - signals = nxt_zalloc(sizeof(nxt_event_signals_t)); - if (signals == NULL) { - return NULL; - } + signals = nxt_zalloc(sizeof(nxt_event_signals_t)); + if (signals == NULL) { + return NULL; + } - signals->sigev = sigev; + signals->sigev = sigev; - if (nxt_signal_action(SIGSYS, SIG_IGN) != NXT_OK) { - goto fail; - } + if (nxt_signal_action(SIGSYS, SIG_IGN) != NXT_OK) { + goto fail; + } - if (nxt_signal_action(SIGPIPE, SIG_IGN) != NXT_OK) { - goto fail; - } + if (nxt_signal_action(SIGPIPE, SIG_IGN) != NXT_OK) { + goto fail; + } - sigemptyset(&signals->sigmask); + sigemptyset(&signals->sigmask); - while (sigev->signo != 0) { - sigaddset(&signals->sigmask, sigev->signo); - sigev++; - } + while (sigev->signo != 0) { + sigaddset(&signals->sigmask, sigev->signo); + sigev++; + } - if (sigprocmask(SIG_BLOCK, &signals->sigmask, NULL) != 0) { - nxt_main_log_alert("sigprocmask(SIG_BLOCK) failed %E", nxt_errno); - goto fail; - } + if (sigprocmask(SIG_BLOCK, &signals->sigmask, NULL) != 0) { + nxt_main_log_alert("sigprocmask(SIG_BLOCK) failed %E", nxt_errno); + goto fail; + } - return signals; + return signals; fail: - nxt_free(signals); + nxt_free(signals); - return NULL; + return NULL; } +static nxt_int_t nxt_signal_action(int signo, void (*handler)(int)) { + struct sigaction sa; -static nxt_int_t -nxt_signal_action(int signo, void (*handler)(int)) -{ - struct sigaction sa; - - nxt_memzero(&sa, sizeof(struct sigaction)); - sigemptyset(&sa.sa_mask); - sa.sa_handler = handler; + nxt_memzero(&sa, sizeof(struct sigaction)); + sigemptyset(&sa.sa_mask); + sa.sa_handler = handler; - if (sigaction(signo, &sa, NULL) == 0) { - return NXT_OK; - } + if (sigaction(signo, &sa, NULL) == 0) { + return NXT_OK; + } - nxt_main_log_alert("sigaction(%d) failed %E", signo, nxt_errno); + nxt_main_log_alert("sigaction(%d) failed %E", signo, nxt_errno); - return NXT_ERROR; + return NXT_ERROR; } +static void nxt_signal_handler(int signo) { + nxt_thread_t *thr; -static void -nxt_signal_handler(int signo) -{ - nxt_thread_t *thr; - - thr = nxt_thread(); + thr = nxt_thread(); - /* Thread is running in a single context now. */ - thr->time.signal++; + /* Thread is running in a single context now. */ + thr->time.signal++; - nxt_thread_time_update(thr); + nxt_thread_time_update(thr); - nxt_main_log_error(NXT_LOG_INFO, "signal handler: %d", signo); + nxt_main_log_error(NXT_LOG_INFO, "signal handler: %d", signo); - nxt_event_engine_signal(thr->engine, signo); + nxt_event_engine_signal(thr->engine, signo); - thr->time.signal--; + thr->time.signal--; } +nxt_int_t nxt_signal_thread_start(nxt_event_engine_t *engine) { + nxt_thread_link_t *link; + const nxt_sig_event_t *sigev; -nxt_int_t -nxt_signal_thread_start(nxt_event_engine_t *engine) -{ - nxt_thread_link_t *link; - const nxt_sig_event_t *sigev; + if (engine->signals->process == nxt_pid) { + return NXT_OK; + } - if (engine->signals->process == nxt_pid) { - return NXT_OK; - } - - if (sigprocmask(SIG_BLOCK, &engine->signals->sigmask, NULL) != 0) { - nxt_main_log_alert("sigprocmask(SIG_BLOCK) failed %E", nxt_errno); - return NXT_ERROR; - } + if (sigprocmask(SIG_BLOCK, &engine->signals->sigmask, NULL) != 0) { + nxt_main_log_alert("sigprocmask(SIG_BLOCK) failed %E", nxt_errno); + return NXT_ERROR; + } - /* - * kqueue sets signal handlers to SIG_IGN and sigwait() ignores - * them after the switch of event facility from "kqueue" to "select". - */ + /* + * kqueue sets signal handlers to SIG_IGN and sigwait() ignores + * them after the switch of event facility from "kqueue" to "select". + */ - for (sigev = engine->signals->sigev; sigev->signo != 0; sigev++) { - if (nxt_signal_action(sigev->signo, nxt_signal_handler) != NXT_OK) { - return NXT_ERROR; - } + for (sigev = engine->signals->sigev; sigev->signo != 0; sigev++) { + if (nxt_signal_action(sigev->signo, nxt_signal_handler) != NXT_OK) { + return NXT_ERROR; } + } - link = nxt_zalloc(sizeof(nxt_thread_link_t)); + link = nxt_zalloc(sizeof(nxt_thread_link_t)); - if (nxt_fast_path(link != NULL)) { - link->start = nxt_signal_thread; - link->work.data = engine; + if (nxt_fast_path(link != NULL)) { + link->start = nxt_signal_thread; + link->work.data = engine; - if (nxt_thread_create(&engine->signals->thread, link) == NXT_OK) { - engine->signals->process = nxt_pid; - return NXT_OK; - } + if (nxt_thread_create(&engine->signals->thread, link) == NXT_OK) { + engine->signals->process = nxt_pid; + return NXT_OK; } + } - return NXT_ERROR; + return NXT_ERROR; } +static void nxt_signal_thread(void *data) { + int signo; + nxt_err_t err; + nxt_thread_t *thr; + nxt_event_engine_t *engine; -static void -nxt_signal_thread(void *data) -{ - int signo; - nxt_err_t err; - nxt_thread_t *thr; - nxt_event_engine_t *engine; - - engine = data; + engine = data; - thr = nxt_thread(); + thr = nxt_thread(); - nxt_main_log_debug("signal thread"); + nxt_main_log_debug("signal thread"); - for ( ;; ) { - err = sigwait(&engine->signals->sigmask, &signo); + for (;;) { + err = sigwait(&engine->signals->sigmask, &signo); - nxt_thread_time_update(thr); + nxt_thread_time_update(thr); - if (nxt_fast_path(err == 0)) { - nxt_main_log_error(NXT_LOG_INFO, "signo: %d", signo); + if (nxt_fast_path(err == 0)) { + nxt_main_log_error(NXT_LOG_INFO, "signo: %d", signo); - nxt_event_engine_signal(engine, signo); + nxt_event_engine_signal(engine, signo); - } else { - nxt_main_log_alert("sigwait() failed %E", err); - } + } else { + nxt_main_log_alert("sigwait() failed %E", err); } + } } +void nxt_signal_thread_stop(nxt_event_engine_t *engine) { + nxt_thread_handle_t thread; -void -nxt_signal_thread_stop(nxt_event_engine_t *engine) -{ - nxt_thread_handle_t thread; - - thread = engine->signals->thread; + thread = engine->signals->thread; - nxt_thread_cancel(thread); - nxt_thread_wait(thread); + nxt_thread_cancel(thread); + nxt_thread_wait(thread); } diff --git a/src/nxt_signal.h b/src/nxt_signal.h index bc61eb2f1..1a22447e0 100644 --- a/src/nxt_signal.h +++ b/src/nxt_signal.h @@ -7,44 +7,35 @@ #ifndef _NXT_SIGNAL_H_INCLUDED_ #define _NXT_SIGNAL_H_INCLUDED_ - struct nxt_sig_event_s { - int signo; - nxt_work_handler_t handler; - const char *name; + int signo; + nxt_work_handler_t handler; + const char *name; }; -#define nxt_event_signal(sig, handler) \ - { sig, handler, #sig } - -#define nxt_event_signal_end \ - { 0, NULL, NULL } +#define nxt_event_signal(sig, handler) {sig, handler, #sig} +#define nxt_event_signal_end {0, NULL, NULL} typedef struct { - /* Used by epoll and eventport. */ - nxt_work_handler_t handler; + /* Used by epoll and eventport. */ + nxt_work_handler_t handler; - const nxt_sig_event_t *sigev; - sigset_t sigmask; + const nxt_sig_event_t *sigev; + sigset_t sigmask; - /* Used by the signal thread. */ - nxt_pid_t process; - nxt_thread_handle_t thread; + /* Used by the signal thread. */ + nxt_pid_t process; + nxt_thread_handle_t thread; } nxt_event_signals_t; - nxt_event_signals_t *nxt_event_engine_signals(const nxt_sig_event_t *sigev); -#define nxt_event_engine_signals_start(engine) \ - nxt_signal_thread_start(engine) - -#define nxt_event_engine_signals_stop(engine) \ - nxt_signal_thread_stop(engine) +#define nxt_event_engine_signals_start(engine) nxt_signal_thread_start(engine) +#define nxt_event_engine_signals_stop(engine) nxt_signal_thread_stop(engine) NXT_EXPORT nxt_int_t nxt_signal_thread_start(nxt_event_engine_t *engine); NXT_EXPORT void nxt_signal_thread_stop(nxt_event_engine_t *engine); - #endif /* _NXT_SIGNAL_H_INCLUDED_ */ diff --git a/src/nxt_signal_handlers.c b/src/nxt_signal_handlers.c index 63b38fab8..a6a39420a 100644 --- a/src/nxt_signal_handlers.c +++ b/src/nxt_signal_handlers.c @@ -10,15 +10,13 @@ #include #include - static void nxt_signal_handler(nxt_task_t *task, void *obj, void *data); static void nxt_signal_sigterm_handler(nxt_task_t *task, void *obj, void *data); static void nxt_signal_sigquit_handler(nxt_task_t *task, void *obj, void *data); - -const nxt_sig_event_t nxt_process_signals[] = { - nxt_event_signal(SIGHUP, nxt_signal_handler), - nxt_event_signal(SIGINT, nxt_signal_sigterm_handler), +const nxt_sig_event_t nxt_process_signals[] = { + nxt_event_signal(SIGHUP, nxt_signal_handler), + nxt_event_signal(SIGINT, nxt_signal_sigterm_handler), nxt_event_signal(SIGQUIT, nxt_signal_sigquit_handler), nxt_event_signal(SIGTERM, nxt_signal_sigterm_handler), nxt_event_signal(SIGCHLD, nxt_signal_handler), @@ -27,41 +25,29 @@ const nxt_sig_event_t nxt_process_signals[] = { nxt_event_signal_end, }; - -static void -nxt_signal_handler(nxt_task_t *task, void *obj, void *data) -{ - nxt_trace(task, "signal signo:%d (%s) received, ignored", - (int) (uintptr_t) obj, data); +static void nxt_signal_handler(nxt_task_t *task, void *obj, void *data) { + nxt_trace(task, "signal signo:%d (%s) received, ignored", (int)(uintptr_t)obj, + data); } - -void -nxt_signal_quit_handler(nxt_task_t *task, nxt_port_recv_msg_t *msg) -{ - nxt_process_quit(task, 0); +void nxt_signal_quit_handler(nxt_task_t *task, nxt_port_recv_msg_t *msg) { + nxt_process_quit(task, 0); } +static void nxt_signal_sigterm_handler(nxt_task_t *task, void *obj, + void *data) { + nxt_debug(task, "sigterm handler signo:%d (%s)", (int)(uintptr_t)obj, data); -static void -nxt_signal_sigterm_handler(nxt_task_t *task, void *obj, void *data) -{ - nxt_debug(task, "sigterm handler signo:%d (%s)", - (int) (uintptr_t) obj, data); - - /* A fast exit. */ + /* A fast exit. */ - nxt_runtime_quit(task, 0); + nxt_runtime_quit(task, 0); } +static void nxt_signal_sigquit_handler(nxt_task_t *task, void *obj, + void *data) { + nxt_debug(task, "sigquit handler signo:%d (%s)", (int)(uintptr_t)obj, data); -static void -nxt_signal_sigquit_handler(nxt_task_t *task, void *obj, void *data) -{ - nxt_debug(task, "sigquit handler signo:%d (%s)", - (int) (uintptr_t) obj, data); - - /* A graceful exit. */ + /* A graceful exit. */ - nxt_process_quit(task, 0); + nxt_process_quit(task, 0); } diff --git a/src/nxt_sockaddr.c b/src/nxt_sockaddr.c index 4d1e723b7..08b657f37 100644 --- a/src/nxt_sockaddr.c +++ b/src/nxt_sockaddr.c @@ -6,7 +6,6 @@ #include - #if (NXT_INET6) static u_char *nxt_inet6_ntop(u_char *addr, u_char *buf, u_char *end); #endif @@ -15,966 +14,904 @@ static nxt_sockaddr_t *nxt_sockaddr_unix_parse(nxt_mp_t *mp, nxt_str_t *addr); static nxt_sockaddr_t *nxt_sockaddr_inet6_parse(nxt_mp_t *mp, nxt_str_t *addr); static nxt_sockaddr_t *nxt_sockaddr_inet_parse(nxt_mp_t *mp, nxt_str_t *addr); +nxt_sockaddr_t *nxt_sockaddr_cache_alloc(nxt_event_engine_t *engine, + nxt_listen_socket_t *ls) { + size_t size; + uint8_t hint; + nxt_sockaddr_t *sa; -nxt_sockaddr_t * -nxt_sockaddr_cache_alloc(nxt_event_engine_t *engine, nxt_listen_socket_t *ls) -{ - size_t size; - uint8_t hint; - nxt_sockaddr_t *sa; - - hint = NXT_EVENT_ENGINE_NO_MEM_HINT; - size = offsetof(nxt_sockaddr_t, u) + ls->socklen + ls->address_length; + hint = NXT_EVENT_ENGINE_NO_MEM_HINT; + size = offsetof(nxt_sockaddr_t, u) + ls->socklen + ls->address_length; - sa = nxt_event_engine_mem_alloc(engine, &hint, size); + sa = nxt_event_engine_mem_alloc(engine, &hint, size); - if (nxt_fast_path(sa != NULL)) { - /* Zero only beginning of structure up to sockaddr_un.sun_path[1]. */ - nxt_memzero(sa, offsetof(nxt_sockaddr_t, u.sockaddr.sa_data[1])); + if (nxt_fast_path(sa != NULL)) { + /* Zero only beginning of structure up to sockaddr_un.sun_path[1]. */ + nxt_memzero(sa, offsetof(nxt_sockaddr_t, u.sockaddr.sa_data[1])); - sa->cache_hint = hint; - sa->socklen = ls->socklen; - sa->length = ls->address_length; + sa->cache_hint = hint; + sa->socklen = ls->socklen; + sa->length = ls->address_length; - sa->type = ls->sockaddr->type; - /* - * Set address family for unspecified Unix domain socket, - * because these sockaddr's are not updated by old BSD systems, - * see comment in nxt_conn_io_accept(). - */ - sa->u.sockaddr.sa_family = ls->sockaddr->u.sockaddr.sa_family; - } + sa->type = ls->sockaddr->type; + /* + * Set address family for unspecified Unix domain socket, + * because these sockaddr's are not updated by old BSD systems, + * see comment in nxt_conn_io_accept(). + */ + sa->u.sockaddr.sa_family = ls->sockaddr->u.sockaddr.sa_family; + } - return sa; + return sa; } +void nxt_sockaddr_cache_free(nxt_event_engine_t *engine, nxt_conn_t *c) { + nxt_sockaddr_t *sa; -void -nxt_sockaddr_cache_free(nxt_event_engine_t *engine, nxt_conn_t *c) -{ - nxt_sockaddr_t *sa; - - sa = c->remote; + sa = c->remote; - nxt_event_engine_mem_free(engine, sa->cache_hint, sa, 0); + nxt_event_engine_mem_free(engine, sa->cache_hint, sa, 0); } +nxt_sockaddr_t *nxt_sockaddr_alloc(nxt_mp_t *mp, socklen_t socklen, + size_t address_length) { + size_t size; + nxt_sockaddr_t *sa; -nxt_sockaddr_t * -nxt_sockaddr_alloc(nxt_mp_t *mp, socklen_t socklen, size_t address_length) -{ - size_t size; - nxt_sockaddr_t *sa; + size = offsetof(nxt_sockaddr_t, u) + socklen + address_length; - size = offsetof(nxt_sockaddr_t, u) + socklen + address_length; + /* + * The current struct sockaddr's define 32-bit fields at maximum + * and may define 64-bit AF_INET6 fields in the future. Alignment + * of memory allocated by nxt_mp_zalloc() is enough for these fields. + * If 128-bit alignment will be required then nxt_mem_malloc() and + * nxt_memzero() should be used instead. + */ - /* - * The current struct sockaddr's define 32-bit fields at maximum - * and may define 64-bit AF_INET6 fields in the future. Alignment - * of memory allocated by nxt_mp_zalloc() is enough for these fields. - * If 128-bit alignment will be required then nxt_mem_malloc() and - * nxt_memzero() should be used instead. - */ - - sa = nxt_mp_zalloc(mp, size); + sa = nxt_mp_zalloc(mp, size); - if (nxt_fast_path(sa != NULL)) { - sa->socklen = socklen; - sa->length = address_length; - } + if (nxt_fast_path(sa != NULL)) { + sa->socklen = socklen; + sa->length = address_length; + } - return sa; + return sa; } +nxt_sockaddr_t *nxt_sockaddr_create(nxt_mp_t *mp, struct sockaddr *sockaddr, + socklen_t length, size_t address_length) { + size_t size, copy; + nxt_sockaddr_t *sa; -nxt_sockaddr_t * -nxt_sockaddr_create(nxt_mp_t *mp, struct sockaddr *sockaddr, socklen_t length, - size_t address_length) -{ - size_t size, copy; - nxt_sockaddr_t *sa; - - size = length; - copy = length; + size = length; + copy = length; #if (NXT_HAVE_UNIX_DOMAIN) + /* + * Unspecified Unix domain sockaddr_un form and length are very + * platform depended (see comment in nxt_socket.h). Here they are + * normalized to the sockaddr_un with single zero byte sun_path[]. + */ + + if (size <= offsetof(struct sockaddr_un, sun_path)) { /* - * Unspecified Unix domain sockaddr_un form and length are very - * platform depended (see comment in nxt_socket.h). Here they are - * normalized to the sockaddr_un with single zero byte sun_path[]. + * Small socket length means a short unspecified Unix domain + * socket address: + * + * getsockname() and getpeername() on OpenBSD prior to 5.3 + * return zero length and does not update a passed sockaddr + * buffer at all. + * + * Linux returns length equal to 2, i.e. sockaddr_un without + * sun_path[], unix(7): + * + * unnamed: A stream socket that has not been bound + * to a pathname using bind(2) has no name. Likewise, + * the two sockets created by socketpair(2) are unnamed. + * When the address of an unnamed socket is returned by + * getsockname(2), getpeername(2), and accept(2), its + * length is sizeof(sa_family_t), and sun_path should + * not be inspected. */ - - if (size <= offsetof(struct sockaddr_un, sun_path)) { - /* - * Small socket length means a short unspecified Unix domain - * socket address: - * - * getsockname() and getpeername() on OpenBSD prior to 5.3 - * return zero length and does not update a passed sockaddr - * buffer at all. - * - * Linux returns length equal to 2, i.e. sockaddr_un without - * sun_path[], unix(7): - * - * unnamed: A stream socket that has not been bound - * to a pathname using bind(2) has no name. Likewise, - * the two sockets created by socketpair(2) are unnamed. - * When the address of an unnamed socket is returned by - * getsockname(2), getpeername(2), and accept(2), its - * length is sizeof(sa_family_t), and sun_path should - * not be inspected. - */ - size = offsetof(struct sockaddr_un, sun_path) + 1; + size = offsetof(struct sockaddr_un, sun_path) + 1; #if !(NXT_LINUX) - } else if (sockaddr->sa_family == AF_UNIX && sockaddr->sa_data[0] == '\0') { - /* - * Omit nonsignificant zeros of the unspecified Unix domain socket - * address. This test is disabled for Linux since Linux abstract - * socket address also starts with zero. However Linux unspecified - * Unix domain socket address is short and is handled above. - */ - size = offsetof(struct sockaddr_un, sun_path) + 1; - copy = size; + } else if (sockaddr->sa_family == AF_UNIX && sockaddr->sa_data[0] == '\0') { + /* + * Omit nonsignificant zeros of the unspecified Unix domain socket + * address. This test is disabled for Linux since Linux abstract + * socket address also starts with zero. However Linux unspecified + * Unix domain socket address is short and is handled above. + */ + size = offsetof(struct sockaddr_un, sun_path) + 1; + copy = size; #endif - } + } -#endif /* NXT_HAVE_UNIX_DOMAIN */ +#endif /* NXT_HAVE_UNIX_DOMAIN */ - sa = nxt_sockaddr_alloc(mp, size, address_length); + sa = nxt_sockaddr_alloc(mp, size, address_length); - if (nxt_fast_path(sa != NULL)) { - nxt_memcpy(&sa->u.sockaddr, sockaddr, copy); + if (nxt_fast_path(sa != NULL)) { + nxt_memcpy(&sa->u.sockaddr, sockaddr, copy); #if (NXT_HAVE_UNIX_DOMAIN && NXT_OPENBSD) - if (length == 0) { - sa->u.sockaddr.sa_family = AF_UNIX; - } + if (length == 0) { + sa->u.sockaddr.sa_family = AF_UNIX; + } #endif - } + } - return sa; + return sa; } +nxt_sockaddr_t *nxt_sockaddr_copy(nxt_mp_t *mp, nxt_sockaddr_t *src) { + size_t length; + nxt_sockaddr_t *dst; -nxt_sockaddr_t * -nxt_sockaddr_copy(nxt_mp_t *mp, nxt_sockaddr_t *src) -{ - size_t length; - nxt_sockaddr_t *dst; + length = offsetof(nxt_sockaddr_t, u) + src->socklen; - length = offsetof(nxt_sockaddr_t, u) + src->socklen; + dst = nxt_mp_alloc(mp, length); - dst = nxt_mp_alloc(mp, length); + if (nxt_fast_path(dst != NULL)) { + nxt_memcpy(dst, src, length); + } - if (nxt_fast_path(dst != NULL)) { - nxt_memcpy(dst, src, length); - } - - return dst; + return dst; } +nxt_sockaddr_t *nxt_getsockname(nxt_task_t *task, nxt_mp_t *mp, + nxt_socket_t s) { + int ret; + size_t length; + socklen_t socklen; + nxt_sockaddr_buf_t sockaddr; -nxt_sockaddr_t * -nxt_getsockname(nxt_task_t *task, nxt_mp_t *mp, nxt_socket_t s) -{ - int ret; - size_t length; - socklen_t socklen; - nxt_sockaddr_buf_t sockaddr; - - socklen = NXT_SOCKADDR_LEN; + socklen = NXT_SOCKADDR_LEN; - ret = getsockname(s, &sockaddr.buf, &socklen); + ret = getsockname(s, &sockaddr.buf, &socklen); - if (nxt_fast_path(ret == 0)) { + if (nxt_fast_path(ret == 0)) { - switch (sockaddr.buf.sa_family) { + switch (sockaddr.buf.sa_family) { #if (NXT_INET6) - case AF_INET6: - length = NXT_INET6_ADDR_STR_LEN; - break; + case AF_INET6: + length = NXT_INET6_ADDR_STR_LEN; + break; #endif #if (NXT_HAVE_UNIX_DOMAIN) - case AF_UNIX: - length = nxt_length("unix:") + socklen; - break; + case AF_UNIX: + length = nxt_length("unix:") + socklen; + break; #endif - case AF_INET: - length = NXT_INET_ADDR_STR_LEN; - break; - - default: - length = 0; - break; - } + case AF_INET: + length = NXT_INET_ADDR_STR_LEN; + break; - return nxt_sockaddr_create(mp, &sockaddr.buf, socklen, length); + default: + length = 0; + break; } - nxt_log(task, NXT_LOG_ERR, "getsockname(%d) failed %E", s, nxt_errno); + return nxt_sockaddr_create(mp, &sockaddr.buf, socklen, length); + } - return NULL; -} + nxt_log(task, NXT_LOG_ERR, "getsockname(%d) failed %E", s, nxt_errno); + return NULL; +} -void -nxt_sockaddr_text(nxt_sockaddr_t *sa) -{ - size_t offset; - u_char *p, *start, *end, *octet; - uint32_t port; +void nxt_sockaddr_text(nxt_sockaddr_t *sa) { + size_t offset; + u_char *p, *start, *end, *octet; + uint32_t port; - offset = offsetof(nxt_sockaddr_t, u) + sa->socklen; - sa->start = offset; - sa->port_start = offset; + offset = offsetof(nxt_sockaddr_t, u) + sa->socklen; + sa->start = offset; + sa->port_start = offset; - start = nxt_pointer_to(sa, offset); - end = start + sa->length; + start = nxt_pointer_to(sa, offset); + end = start + sa->length; - switch (sa->u.sockaddr.sa_family) { + switch (sa->u.sockaddr.sa_family) { - case AF_INET: - sa->address_start = offset; + case AF_INET: + sa->address_start = offset; - octet = (u_char *) &sa->u.sockaddr_in.sin_addr; + octet = (u_char *)&sa->u.sockaddr_in.sin_addr; - p = nxt_sprintf(start, end, "%ud.%ud.%ud.%ud", - octet[0], octet[1], octet[2], octet[3]); + p = nxt_sprintf(start, end, "%ud.%ud.%ud.%ud", octet[0], octet[1], octet[2], + octet[3]); - sa->address_length = p - start; - sa->port_start += sa->address_length + 1; + sa->address_length = p - start; + sa->port_start += sa->address_length + 1; - port = sa->u.sockaddr_in.sin_port; + port = sa->u.sockaddr_in.sin_port; - break; + break; #if (NXT_INET6) - case AF_INET6: - sa->address_start = offset + 1; + case AF_INET6: + sa->address_start = offset + 1; - p = start; - *p++ = '['; + p = start; + *p++ = '['; - p = nxt_inet6_ntop(sa->u.sockaddr_in6.sin6_addr.s6_addr, p, end); + p = nxt_inet6_ntop(sa->u.sockaddr_in6.sin6_addr.s6_addr, p, end); - sa->address_length = p - (start + 1); - sa->port_start += sa->address_length + 3; + sa->address_length = p - (start + 1); + sa->port_start += sa->address_length + 3; - *p++ = ']'; + *p++ = ']'; - port = sa->u.sockaddr_in6.sin6_port; + port = sa->u.sockaddr_in6.sin6_port; - break; + break; #endif #if (NXT_HAVE_UNIX_DOMAIN) - case AF_UNIX: - sa->address_start = offset; + case AF_UNIX: + sa->address_start = offset; - p = (u_char *) sa->u.sockaddr_un.sun_path; + p = (u_char *)sa->u.sockaddr_un.sun_path; #if (NXT_LINUX) - if (p[0] == '\0') { - size_t length; + if (p[0] == '\0') { + size_t length; - /* Linux abstract socket address has no trailing zero. */ - length = sa->socklen - offsetof(struct sockaddr_un, sun_path); + /* Linux abstract socket address has no trailing zero. */ + length = sa->socklen - offsetof(struct sockaddr_un, sun_path); - p = nxt_sprintf(start, end, "unix:@%*s", length - 1, p + 1); + p = nxt_sprintf(start, end, "unix:@%*s", length - 1, p + 1); - } else { - p = nxt_sprintf(start, end, "unix:%s", p); - } + } else { + p = nxt_sprintf(start, end, "unix:%s", p); + } -#else /* !(NXT_LINUX) */ +#else /* !(NXT_LINUX) */ - p = nxt_sprintf(start, end, "unix:%s", p); + p = nxt_sprintf(start, end, "unix:%s", p); #endif - sa->address_length = p - start; - sa->port_start += sa->address_length; - sa->length = p - start; + sa->address_length = p - start; + sa->port_start += sa->address_length; + sa->length = p - start; - return; + return; -#endif /* NXT_HAVE_UNIX_DOMAIN */ +#endif /* NXT_HAVE_UNIX_DOMAIN */ - default: - return; - } + default: + return; + } - p = nxt_sprintf(p, end, ":%d", ntohs(port)); + p = nxt_sprintf(p, end, ":%d", ntohs(port)); - sa->length = p - start; + sa->length = p - start; } +uint32_t nxt_sockaddr_port_number(nxt_sockaddr_t *sa) { + uint32_t port; -uint32_t -nxt_sockaddr_port_number(nxt_sockaddr_t *sa) -{ - uint32_t port; - - switch (sa->u.sockaddr.sa_family) { + switch (sa->u.sockaddr.sa_family) { #if (NXT_INET6) - case AF_INET6: - port = sa->u.sockaddr_in6.sin6_port; - break; + case AF_INET6: + port = sa->u.sockaddr_in6.sin6_port; + break; #endif #if (NXT_HAVE_UNIX_DOMAIN) - case AF_UNIX: - return 0; + case AF_UNIX: + return 0; #endif - default: - port = sa->u.sockaddr_in.sin_port; - break; - } + default: + port = sa->u.sockaddr_in.sin_port; + break; + } - return ntohs((uint16_t) port); + return ntohs((uint16_t)port); } +nxt_bool_t nxt_sockaddr_cmp(nxt_sockaddr_t *sa1, nxt_sockaddr_t *sa2) { + if (sa1->socklen != sa2->socklen) { + return 0; + } -nxt_bool_t -nxt_sockaddr_cmp(nxt_sockaddr_t *sa1, nxt_sockaddr_t *sa2) -{ - if (sa1->socklen != sa2->socklen) { - return 0; - } - - if (sa1->type != sa2->type) { - return 0; - } + if (sa1->type != sa2->type) { + return 0; + } - if (sa1->u.sockaddr.sa_family != sa2->u.sockaddr.sa_family) { - return 0; - } + if (sa1->u.sockaddr.sa_family != sa2->u.sockaddr.sa_family) { + return 0; + } - /* - * sockaddr struct's cannot be compared in whole since kernel - * may fill some fields in inherited sockaddr struct's. - */ + /* + * sockaddr struct's cannot be compared in whole since kernel + * may fill some fields in inherited sockaddr struct's. + */ - switch (sa1->u.sockaddr.sa_family) { + switch (sa1->u.sockaddr.sa_family) { #if (NXT_INET6) - case AF_INET6: - if (sa1->u.sockaddr_in6.sin6_port != sa2->u.sockaddr_in6.sin6_port) { - return 0; - } + case AF_INET6: + if (sa1->u.sockaddr_in6.sin6_port != sa2->u.sockaddr_in6.sin6_port) { + return 0; + } - if (memcmp(&sa1->u.sockaddr_in6.sin6_addr, - &sa2->u.sockaddr_in6.sin6_addr, 16) - != 0) - { - return 0; - } + if (memcmp(&sa1->u.sockaddr_in6.sin6_addr, &sa2->u.sockaddr_in6.sin6_addr, + 16) != 0) { + return 0; + } - return 1; + return 1; #endif #if (NXT_HAVE_UNIX_DOMAIN) - case AF_UNIX: - { - size_t length; + case AF_UNIX: { + size_t length; - length = sa1->socklen - offsetof(struct sockaddr_un, sun_path); + length = sa1->socklen - offsetof(struct sockaddr_un, sun_path); - if (memcmp(&sa1->u.sockaddr_un.sun_path, - &sa2->u.sockaddr_un.sun_path, length) - != 0) - { - return 0; - } + if (memcmp(&sa1->u.sockaddr_un.sun_path, &sa2->u.sockaddr_un.sun_path, + length) != 0) { + return 0; + } - return 1; - } + return 1; + } #endif - default: /* AF_INET */ - if (sa1->u.sockaddr_in.sin_port != sa2->u.sockaddr_in.sin_port) { - return 0; - } - - if (sa1->u.sockaddr_in.sin_addr.s_addr - != sa2->u.sockaddr_in.sin_addr.s_addr) - { - return 0; - } + default: /* AF_INET */ + if (sa1->u.sockaddr_in.sin_port != sa2->u.sockaddr_in.sin_port) { + return 0; + } - return 1; + if (sa1->u.sockaddr_in.sin_addr.s_addr != + sa2->u.sockaddr_in.sin_addr.s_addr) { + return 0; } -} + return 1; + } +} #if (NXT_INET6) -static u_char * -nxt_inet6_ntop(u_char *addr, u_char *buf, u_char *end) -{ - u_char *p; - size_t zero_groups, last_zero_groups, ipv6_bytes; - nxt_uint_t i, zero_start, last_zero_start; - - const size_t max_inet6_length = - nxt_length("ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff"); +static u_char *nxt_inet6_ntop(u_char *addr, u_char *buf, u_char *end) { + u_char *p; + size_t zero_groups, last_zero_groups, ipv6_bytes; + nxt_uint_t i, zero_start, last_zero_start; - if (buf + max_inet6_length > end) { - return buf; - } + const size_t max_inet6_length = + nxt_length("ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff"); - zero_start = 16; - zero_groups = 0; - last_zero_start = 16; - last_zero_groups = 0; + if (buf + max_inet6_length > end) { + return buf; + } - for (i = 0; i < 16; i += 2) { + zero_start = 16; + zero_groups = 0; + last_zero_start = 16; + last_zero_groups = 0; - if (addr[i] == 0 && addr[i + 1] == 0) { + for (i = 0; i < 16; i += 2) { - if (last_zero_groups == 0) { - last_zero_start = i; - } + if (addr[i] == 0 && addr[i + 1] == 0) { - last_zero_groups++; + if (last_zero_groups == 0) { + last_zero_start = i; + } - } else { - if (zero_groups < last_zero_groups) { - zero_groups = last_zero_groups; - zero_start = last_zero_start; - } + last_zero_groups++; - last_zero_groups = 0; - } - } - - if (zero_groups < last_zero_groups) { + } else { + if (zero_groups < last_zero_groups) { zero_groups = last_zero_groups; zero_start = last_zero_start; + } + + last_zero_groups = 0; } + } - ipv6_bytes = 16; - p = buf; + if (zero_groups < last_zero_groups) { + zero_groups = last_zero_groups; + zero_start = last_zero_start; + } - if (zero_start == 0) { + ipv6_bytes = 16; + p = buf; - /* IPv4-mapped address */ - if ((zero_groups == 5 && addr[10] == 0xFF && addr[11] == 0xFF) - /* IPv4-compatible address */ - || (zero_groups == 6) - /* not IPv6 loopback address */ - || (zero_groups == 7 && addr[14] != 0 && addr[15] != 1)) - { - ipv6_bytes = 12; - } + if (zero_start == 0) { - *p++ = ':'; + /* IPv4-mapped address */ + if ((zero_groups == 5 && addr[10] == 0xFF && addr[11] == 0xFF) + /* IPv4-compatible address */ + || (zero_groups == 6) + /* not IPv6 loopback address */ + || (zero_groups == 7 && addr[14] != 0 && addr[15] != 1)) { + ipv6_bytes = 12; } - for (i = 0; i < ipv6_bytes; i += 2) { - - if (i == zero_start) { - /* Output maximum number of consecutive zero groups as "::". */ - i += (zero_groups - 1) * 2; - *p++ = ':'; - continue; - } + *p++ = ':'; + } - p = nxt_sprintf(p, end, "%uxd", (addr[i] << 8) + addr[i + 1]); + for (i = 0; i < ipv6_bytes; i += 2) { - if (i < 14) { - *p++ = ':'; - } + if (i == zero_start) { + /* Output maximum number of consecutive zero groups as "::". */ + i += (zero_groups - 1) * 2; + *p++ = ':'; + continue; } - if (ipv6_bytes == 12) { - p = nxt_sprintf(p, end, "%ud.%ud.%ud.%ud", - addr[12], addr[13], addr[14], addr[15]); + p = nxt_sprintf(p, end, "%uxd", (addr[i] << 8) + addr[i + 1]); + + if (i < 14) { + *p++ = ':'; } + } - return p; + if (ipv6_bytes == 12) { + p = nxt_sprintf(p, end, "%ud.%ud.%ud.%ud", addr[12], addr[13], addr[14], + addr[15]); + } + + return p; } #endif +nxt_sockaddr_t *nxt_sockaddr_parse(nxt_mp_t *mp, nxt_str_t *addr) { + nxt_sockaddr_t *sa; -nxt_sockaddr_t * -nxt_sockaddr_parse(nxt_mp_t *mp, nxt_str_t *addr) -{ - nxt_sockaddr_t *sa; - - sa = nxt_sockaddr_parse_optport(mp, addr); + sa = nxt_sockaddr_parse_optport(mp, addr); - if (sa != NULL - && sa->u.sockaddr.sa_family != AF_UNIX - && nxt_sockaddr_port_number(sa) == 0) - { - nxt_thread_log_error(NXT_LOG_ERR, - "The address \"%V\" must specify a port.", addr); - return NULL; - } + if (sa != NULL && sa->u.sockaddr.sa_family != AF_UNIX && + nxt_sockaddr_port_number(sa) == 0) { + nxt_thread_log_error(NXT_LOG_ERR, "The address \"%V\" must specify a port.", + addr); + return NULL; + } - return sa; + return sa; } +nxt_sockaddr_t *nxt_sockaddr_parse_optport(nxt_mp_t *mp, nxt_str_t *addr) { + nxt_sockaddr_t *sa; -nxt_sockaddr_t * -nxt_sockaddr_parse_optport(nxt_mp_t *mp, nxt_str_t *addr) -{ - nxt_sockaddr_t *sa; + if (addr->length == 0) { + nxt_thread_log_error(NXT_LOG_ERR, "socket address cannot be empty"); + return NULL; + } - if (addr->length == 0) { - nxt_thread_log_error(NXT_LOG_ERR, "socket address cannot be empty"); - return NULL; - } + if (addr->length > 6 && memcmp(addr->start, "unix:", 5) == 0) { + sa = nxt_sockaddr_unix_parse(mp, addr); - if (addr->length > 6 && memcmp(addr->start, "unix:", 5) == 0) { - sa = nxt_sockaddr_unix_parse(mp, addr); + } else if (addr->start[0] == '[' || nxt_inet6_probe(addr)) { + sa = nxt_sockaddr_inet6_parse(mp, addr); - } else if (addr->start[0] == '[' || nxt_inet6_probe(addr)) { - sa = nxt_sockaddr_inet6_parse(mp, addr); + } else { + sa = nxt_sockaddr_inet_parse(mp, addr); + } - } else { - sa = nxt_sockaddr_inet_parse(mp, addr); - } - - if (nxt_fast_path(sa != NULL)) { - nxt_sockaddr_text(sa); - } + if (nxt_fast_path(sa != NULL)) { + nxt_sockaddr_text(sa); + } - return sa; + return sa; } - -static nxt_sockaddr_t * -nxt_sockaddr_unix_parse(nxt_mp_t *mp, nxt_str_t *addr) -{ +static nxt_sockaddr_t *nxt_sockaddr_unix_parse(nxt_mp_t *mp, nxt_str_t *addr) { #if (NXT_HAVE_UNIX_DOMAIN) - size_t length, socklen; - u_char *path; - nxt_sockaddr_t *sa; - - /* - * Actual sockaddr_un length can be lesser or even larger than defined - * struct sockaddr_un length (see comment in nxt_socket.h). So - * limit maximum Unix domain socket address length by defined sun_path[] - * length because some OSes accept addresses twice larger than defined - * struct sockaddr_un. Also reserve space for a trailing zero to avoid - * ambiguity, since many OSes accept Unix domain socket addresses - * without a trailing zero. - */ - const size_t max_len = sizeof(struct sockaddr_un) - - offsetof(struct sockaddr_un, sun_path) - 1; - - /* Cutting "unix:". */ - length = addr->length - 5; - path = addr->start + 5; - - if (length > max_len) { - nxt_thread_log_error(NXT_LOG_ERR, - "unix domain socket \"%V\" name is too long", - addr); - return NULL; - } - - socklen = offsetof(struct sockaddr_un, sun_path) + length + 1; - - /* - * Linux unix(7): - * - * abstract: an abstract socket address is distinguished by the fact - * that sun_path[0] is a null byte ('\0'). The socket's address in - * this namespace is given by the additional bytes in sun_path that - * are covered by the specified length of the address structure. - * (Null bytes in the name have no special significance.) - */ - if (path[0] == '@') { - path[0] = '\0'; - socklen--; + size_t length, socklen; + u_char *path; + nxt_sockaddr_t *sa; + + /* + * Actual sockaddr_un length can be lesser or even larger than defined + * struct sockaddr_un length (see comment in nxt_socket.h). So + * limit maximum Unix domain socket address length by defined sun_path[] + * length because some OSes accept addresses twice larger than defined + * struct sockaddr_un. Also reserve space for a trailing zero to avoid + * ambiguity, since many OSes accept Unix domain socket addresses + * without a trailing zero. + */ + const size_t max_len = + sizeof(struct sockaddr_un) - offsetof(struct sockaddr_un, sun_path) - 1; + + /* Cutting "unix:". */ + length = addr->length - 5; + path = addr->start + 5; + + if (length > max_len) { + nxt_thread_log_error(NXT_LOG_ERR, + "unix domain socket \"%V\" name is too long", addr); + return NULL; + } + + socklen = offsetof(struct sockaddr_un, sun_path) + length + 1; + + /* + * Linux unix(7): + * + * abstract: an abstract socket address is distinguished by the fact + * that sun_path[0] is a null byte ('\0'). The socket's address in + * this namespace is given by the additional bytes in sun_path that + * are covered by the specified length of the address structure. + * (Null bytes in the name have no special significance.) + */ + if (path[0] == '@') { + path[0] = '\0'; + socklen--; #if !(NXT_LINUX) - nxt_thread_log_error(NXT_LOG_ERR, - "abstract unix domain sockets are not supported"); - return NULL; + nxt_thread_log_error(NXT_LOG_ERR, + "abstract unix domain sockets are not supported"); + return NULL; #endif - } + } - sa = nxt_sockaddr_alloc(mp, socklen, addr->length); + sa = nxt_sockaddr_alloc(mp, socklen, addr->length); - if (nxt_fast_path(sa != NULL)) { - sa->u.sockaddr_un.sun_family = AF_UNIX; - nxt_memcpy(sa->u.sockaddr_un.sun_path, path, length); - } + if (nxt_fast_path(sa != NULL)) { + sa->u.sockaddr_un.sun_family = AF_UNIX; + nxt_memcpy(sa->u.sockaddr_un.sun_path, path, length); + } - return sa; + return sa; -#else /* !(NXT_HAVE_UNIX_DOMAIN) */ +#else /* !(NXT_HAVE_UNIX_DOMAIN) */ - nxt_thread_log_error(NXT_LOG_ERR, - "unix domain socket \"%V\" is not supported", addr); + nxt_thread_log_error(NXT_LOG_ERR, + "unix domain socket \"%V\" is not supported", addr); - return NULL; + return NULL; #endif } - -static nxt_sockaddr_t * -nxt_sockaddr_inet6_parse(nxt_mp_t *mp, nxt_str_t *addr) -{ +static nxt_sockaddr_t *nxt_sockaddr_inet6_parse(nxt_mp_t *mp, nxt_str_t *addr) { #if (NXT_INET6) - u_char *p, *start, *end; - size_t length; - nxt_int_t ret, port; - nxt_sockaddr_t *sa; - - if (addr->start[0] == '[') { - length = addr->length - 1; - start = addr->start + 1; - - end = memchr(start, ']', length); - if (nxt_slow_path(end == NULL)) { - return NULL; - } + u_char *p, *start, *end; + size_t length; + nxt_int_t ret, port; + nxt_sockaddr_t *sa; - p = end + 1; + if (addr->start[0] == '[') { + length = addr->length - 1; + start = addr->start + 1; - } else { - length = addr->length; - start = addr->start; - end = addr->start + addr->length; - p = NULL; + end = memchr(start, ']', length); + if (nxt_slow_path(end == NULL)) { + return NULL; } - port = 0; + p = end + 1; - if (p != NULL) { - length = (start + length) - p; + } else { + length = addr->length; + start = addr->start; + end = addr->start + addr->length; + p = NULL; + } - if (length < 2 || *p != ':') { - nxt_thread_log_error(NXT_LOG_ERR, "invalid IPv6 address in \"%V\"", - addr); - return NULL; - } + port = 0; - port = nxt_int_parse(p + 1, length - 1); + if (p != NULL) { + length = (start + length) - p; - if (port < 1 || port > 65535) { - nxt_thread_log_error(NXT_LOG_ERR, "invalid port in \"%V\"", addr); - return NULL; - } + if (length < 2 || *p != ':') { + nxt_thread_log_error(NXT_LOG_ERR, "invalid IPv6 address in \"%V\"", addr); + return NULL; } - sa = nxt_sockaddr_alloc(mp, sizeof(struct sockaddr_in6), - NXT_INET6_ADDR_STR_LEN); - if (nxt_slow_path(sa == NULL)) { - return NULL; - } + port = nxt_int_parse(p + 1, length - 1); - ret = nxt_inet6_addr(&sa->u.sockaddr_in6.sin6_addr, start, end - start); - if (nxt_slow_path(ret != NXT_OK)) { - nxt_thread_log_error(NXT_LOG_ERR, "invalid IPv6 address in \"%V\"", - addr); - return NULL; + if (port < 1 || port > 65535) { + nxt_thread_log_error(NXT_LOG_ERR, "invalid port in \"%V\"", addr); + return NULL; } + } - sa->u.sockaddr_in6.sin6_family = AF_INET6; - sa->u.sockaddr_in6.sin6_port = htons((in_port_t) port); + sa = nxt_sockaddr_alloc(mp, sizeof(struct sockaddr_in6), + NXT_INET6_ADDR_STR_LEN); + if (nxt_slow_path(sa == NULL)) { + return NULL; + } - return sa; + ret = nxt_inet6_addr(&sa->u.sockaddr_in6.sin6_addr, start, end - start); + if (nxt_slow_path(ret != NXT_OK)) { + nxt_thread_log_error(NXT_LOG_ERR, "invalid IPv6 address in \"%V\"", addr); + return NULL; + } -#else /* !(NXT_INET6) */ + sa->u.sockaddr_in6.sin6_family = AF_INET6; + sa->u.sockaddr_in6.sin6_port = htons((in_port_t)port); - nxt_thread_log_error(NXT_LOG_ERR, "IPv6 socket \"%V\" is not supported", - addr); - return NULL; + return sa; + +#else /* !(NXT_INET6) */ + + nxt_thread_log_error(NXT_LOG_ERR, "IPv6 socket \"%V\" is not supported", + addr); + return NULL; #endif } +static nxt_sockaddr_t *nxt_sockaddr_inet_parse(nxt_mp_t *mp, nxt_str_t *addr) { + u_char *p; + size_t length; + nxt_int_t port; + in_addr_t inaddr; + nxt_sockaddr_t *sa; -static nxt_sockaddr_t * -nxt_sockaddr_inet_parse(nxt_mp_t *mp, nxt_str_t *addr) -{ - u_char *p; - size_t length; - nxt_int_t port; - in_addr_t inaddr; - nxt_sockaddr_t *sa; - - p = memchr(addr->start, ':', addr->length); + p = memchr(addr->start, ':', addr->length); - if (p == NULL) { - length = addr->length; + if (p == NULL) { + length = addr->length; - } else { - length = p - addr->start; - } + } else { + length = p - addr->start; + } - if (length == 0) { - nxt_thread_log_error(NXT_LOG_ERR, "invalid address \"%V\"", addr); - return NULL; - } + if (length == 0) { + nxt_thread_log_error(NXT_LOG_ERR, "invalid address \"%V\"", addr); + return NULL; + } - inaddr = INADDR_ANY; + inaddr = INADDR_ANY; - if (length != 1 || addr->start[0] != '*') { - inaddr = nxt_inet_addr(addr->start, length); - if (nxt_slow_path(inaddr == INADDR_NONE)) { - nxt_thread_log_error(NXT_LOG_ERR, "invalid address \"%V\"", addr); - return NULL; - } + if (length != 1 || addr->start[0] != '*') { + inaddr = nxt_inet_addr(addr->start, length); + if (nxt_slow_path(inaddr == INADDR_NONE)) { + nxt_thread_log_error(NXT_LOG_ERR, "invalid address \"%V\"", addr); + return NULL; } + } - port = 0; + port = 0; - if (p != NULL) { - p++; - length = (addr->start + addr->length) - p; + if (p != NULL) { + p++; + length = (addr->start + addr->length) - p; - port = nxt_int_parse(p, length); + port = nxt_int_parse(p, length); - if (port < 1 || port > 65535) { - nxt_thread_log_error(NXT_LOG_ERR, "invalid port in \"%V\"", addr); - return NULL; - } + if (port < 1 || port > 65535) { + nxt_thread_log_error(NXT_LOG_ERR, "invalid port in \"%V\"", addr); + return NULL; } + } - sa = nxt_sockaddr_alloc(mp, sizeof(struct sockaddr_in), - NXT_INET_ADDR_STR_LEN); - if (nxt_slow_path(sa == NULL)) { - return NULL; - } + sa = + nxt_sockaddr_alloc(mp, sizeof(struct sockaddr_in), NXT_INET_ADDR_STR_LEN); + if (nxt_slow_path(sa == NULL)) { + return NULL; + } - sa->u.sockaddr_in.sin_family = AF_INET; - sa->u.sockaddr_in.sin_addr.s_addr = inaddr; - sa->u.sockaddr_in.sin_port = htons((in_port_t) port); + sa->u.sockaddr_in.sin_family = AF_INET; + sa->u.sockaddr_in.sin_addr.s_addr = inaddr; + sa->u.sockaddr_in.sin_port = htons((in_port_t)port); - return sa; + return sa; } +in_addr_t nxt_inet_addr(u_char *buf, size_t length) { + u_char c, *end; + in_addr_t addr; + nxt_uint_t digit, octet, dots; -in_addr_t -nxt_inet_addr(u_char *buf, size_t length) -{ - u_char c, *end; - in_addr_t addr; - nxt_uint_t digit, octet, dots; - - if (nxt_slow_path(*(buf + length - 1) == '.')) { - return INADDR_NONE; - } - - addr = 0; - octet = 0; - dots = 0; - - end = buf + length; + if (nxt_slow_path(*(buf + length - 1) == '.')) { + return INADDR_NONE; + } - while (buf < end) { + addr = 0; + octet = 0; + dots = 0; - c = *buf++; + end = buf + length; - digit = c - '0'; - /* values below '0' become large unsigned integers */ + while (buf < end) { - if (digit < 10) { - octet = octet * 10 + digit; - continue; - } + c = *buf++; - if (c == '.' && octet < 256) { - addr = (addr << 8) + octet; - octet = 0; - dots++; - continue; - } + digit = c - '0'; + /* values below '0' become large unsigned integers */ - return INADDR_NONE; + if (digit < 10) { + octet = octet * 10 + digit; + continue; } - if (dots == 3 && octet < 256) { - addr = (addr << 8) + octet; - return htonl(addr); + if (c == '.' && octet < 256) { + addr = (addr << 8) + octet; + octet = 0; + dots++; + continue; } return INADDR_NONE; -} + } + if (dots == 3 && octet < 256) { + addr = (addr << 8) + octet; + return htonl(addr); + } -#if (NXT_INET6) + return INADDR_NONE; +} -nxt_int_t -nxt_inet6_addr(struct in6_addr *in6_addr, u_char *buf, size_t length) -{ - u_char c, *addr, *zero_start, *ipv4, *dst, *src, *end; - nxt_uint_t digit, group, nibbles, groups_left; +#if (NXT_INET6) - if (length == 0) { - return NXT_ERROR; - } +nxt_int_t nxt_inet6_addr(struct in6_addr *in6_addr, u_char *buf, + size_t length) { + u_char c, *addr, *zero_start, *ipv4, *dst, *src, *end; + nxt_uint_t digit, group, nibbles, groups_left; - end = buf + length; + if (length == 0) { + return NXT_ERROR; + } - if (buf[0] == ':') { - buf++; - } + end = buf + length; - addr = in6_addr->s6_addr; - zero_start = NULL; - groups_left = 8; - nibbles = 0; - group = 0; - ipv4 = NULL; - - while (buf < end) { - c = *buf++; - - if (c == ':') { - if (nibbles != 0) { - ipv4 = buf; - - *addr++ = (u_char) (group >> 8); - *addr++ = (u_char) (group & 0xFF); - groups_left--; - - if (groups_left != 0) { - nibbles = 0; - group = 0; - continue; - } - - } else { - if (zero_start == NULL) { - ipv4 = buf; - zero_start = addr; - continue; - } - } - - return NXT_ERROR; - } + if (buf[0] == ':') { + buf++; + } - if (c == '.' && nibbles != 0) { + addr = in6_addr->s6_addr; + zero_start = NULL; + groups_left = 8; + nibbles = 0; + group = 0; + ipv4 = NULL; - if (groups_left < 2 || ipv4 == NULL) { - return NXT_ERROR; - } + while (buf < end) { + c = *buf++; - group = nxt_inet_addr(ipv4, end - ipv4); - if (group == INADDR_NONE) { - return NXT_ERROR; - } + if (c == ':') { + if (nibbles != 0) { + ipv4 = buf; - group = ntohl(group); + *addr++ = (u_char)(group >> 8); + *addr++ = (u_char)(group & 0xFF); + groups_left--; - *addr++ = (u_char) ((group >> 24) & 0xFF); - *addr++ = (u_char) ((group >> 16) & 0xFF); - groups_left--; + if (groups_left != 0) { + nibbles = 0; + group = 0; + continue; + } - /* the low 16-bit are copied below */ - break; + } else { + if (zero_start == NULL) { + ipv4 = buf; + zero_start = addr; + continue; } + } - nibbles++; + return NXT_ERROR; + } - if (nibbles > 4) { - return NXT_ERROR; - } + if (c == '.' && nibbles != 0) { - group <<= 4; + if (groups_left < 2 || ipv4 == NULL) { + return NXT_ERROR; + } - digit = c - '0'; - /* values below '0' become large unsigned integers */ + group = nxt_inet_addr(ipv4, end - ipv4); + if (group == INADDR_NONE) { + return NXT_ERROR; + } - if (digit < 10) { - group += digit; - continue; - } + group = ntohl(group); - c |= 0x20; - digit = c - 'a'; - /* values below 'a' become large unsigned integers */ + *addr++ = (u_char)((group >> 24) & 0xFF); + *addr++ = (u_char)((group >> 16) & 0xFF); + groups_left--; - if (digit < 6) { - group += 10 + digit; - continue; - } + /* the low 16-bit are copied below */ + break; + } - return NXT_ERROR; + nibbles++; + + if (nibbles > 4) { + return NXT_ERROR; } - if (nibbles == 0 && zero_start == NULL) { - return NXT_ERROR; + group <<= 4; + + digit = c - '0'; + /* values below '0' become large unsigned integers */ + + if (digit < 10) { + group += digit; + continue; } - *addr++ = (u_char) (group >> 8); - *addr++ = (u_char) (group & 0xFF); - groups_left--; + c |= 0x20; + digit = c - 'a'; + /* values below 'a' become large unsigned integers */ - if (groups_left != 0) { + if (digit < 6) { + group += 10 + digit; + continue; + } - if (zero_start != NULL) { + return NXT_ERROR; + } - /* moving part before consecutive zero groups to the end */ + if (nibbles == 0 && zero_start == NULL) { + return NXT_ERROR; + } - groups_left *= 2; - src = addr - 1; - dst = src + groups_left; + *addr++ = (u_char)(group >> 8); + *addr++ = (u_char)(group & 0xFF); + groups_left--; - while (src >= zero_start) { - *dst-- = *src--; - } + if (groups_left != 0) { - nxt_memzero(zero_start, groups_left); + if (zero_start != NULL) { - return NXT_OK; - } + /* moving part before consecutive zero groups to the end */ - } else { - if (zero_start == NULL) { - return NXT_OK; - } + groups_left *= 2; + src = addr - 1; + dst = src + groups_left; + + while (src >= zero_start) { + *dst-- = *src--; + } + + nxt_memzero(zero_start, groups_left); + + return NXT_OK; } - return NXT_ERROR; + } else { + if (zero_start == NULL) { + return NXT_OK; + } + } + + return NXT_ERROR; } #endif +nxt_bool_t nxt_inet6_probe(nxt_str_t *str) { + u_char *colon, *end; -nxt_bool_t -nxt_inet6_probe(nxt_str_t *str) -{ - u_char *colon, *end; + colon = memchr(str->start, ':', str->length); - colon = memchr(str->start, ':', str->length); - - if (colon != NULL) { - end = str->start + str->length; - colon = memchr(colon + 1, ':', end - (colon + 1)); - } + if (colon != NULL) { + end = str->start + str->length; + colon = memchr(colon + 1, ':', end - (colon + 1)); + } - return (colon != NULL); + return (colon != NULL); } diff --git a/src/nxt_sockaddr.h b/src/nxt_sockaddr.h index 0f96f6dd6..1e56ae9d4 100644 --- a/src/nxt_sockaddr.h +++ b/src/nxt_sockaddr.h @@ -7,7 +7,6 @@ #ifndef _NXT_SOCKADDR_H_INCLUDED_ #define _NXT_SOCKADDR_H_INCLUDED_ - /* * The nxt_sockaddr_t should be allocated using nxt_sockaddr_alloc() * with actual "struct sockaddr_..." size: @@ -20,89 +19,83 @@ */ struct nxt_sockaddr_s { - /* Socket type: SOCKS_STREAM, SOCK_DGRAM, etc. */ - uint8_t type; - /* Size of struct sockaddr. */ - uint8_t socklen; - /* - * Textual sockaddr representation, e.g.: "127.0.0.1:8000", - * "[::1]:8000", and "unix:/path/to/socket". - */ - uint8_t start; - uint8_t length; - /* - * Textual address representation, e.g: "127.0.0.1", "::1", - * and "unix:/path/to/socket". - */ - uint8_t address_start; - uint8_t address_length; - /* - * Textual port representation, e.g. "8000". - * Port length is (start + length) - port_start. - */ - uint8_t port_start; - - /* A cache hist used to place sockaddr into appropriate free list. */ - uint8_t cache_hint; - - union { - struct sockaddr sockaddr; - struct sockaddr_in sockaddr_in; + /* Socket type: SOCKS_STREAM, SOCK_DGRAM, etc. */ + uint8_t type; + /* Size of struct sockaddr. */ + uint8_t socklen; + /* + * Textual sockaddr representation, e.g.: "127.0.0.1:8000", + * "[::1]:8000", and "unix:/path/to/socket". + */ + uint8_t start; + uint8_t length; + /* + * Textual address representation, e.g: "127.0.0.1", "::1", + * and "unix:/path/to/socket". + */ + uint8_t address_start; + uint8_t address_length; + /* + * Textual port representation, e.g. "8000". + * Port length is (start + length) - port_start. + */ + uint8_t port_start; + + /* A cache hist used to place sockaddr into appropriate free list. */ + uint8_t cache_hint; + + union { + struct sockaddr sockaddr; + struct sockaddr_in sockaddr_in; #if (NXT_INET6) - struct sockaddr_in6 sockaddr_in6; + struct sockaddr_in6 sockaddr_in6; #endif #if (NXT_HAVE_UNIX_DOMAIN) - struct sockaddr_un sockaddr_un; + struct sockaddr_un sockaddr_un; #endif - } u; + } u; }; - nxt_sockaddr_t *nxt_sockaddr_cache_alloc(nxt_event_engine_t *engine, - nxt_listen_socket_t *ls); + nxt_listen_socket_t *ls); void nxt_sockaddr_cache_free(nxt_event_engine_t *engine, nxt_conn_t *c); -NXT_EXPORT nxt_sockaddr_t *nxt_sockaddr_alloc(nxt_mp_t *mp, socklen_t socklen, - size_t address_length) - NXT_MALLOC_LIKE; -NXT_EXPORT nxt_sockaddr_t *nxt_sockaddr_create(nxt_mp_t *mp, - struct sockaddr *sockaddr, socklen_t socklen, size_t address_length) - NXT_MALLOC_LIKE; -NXT_EXPORT nxt_sockaddr_t *nxt_sockaddr_copy(nxt_mp_t *mp, nxt_sockaddr_t *src) - NXT_MALLOC_LIKE; +NXT_EXPORT nxt_sockaddr_t * +nxt_sockaddr_alloc(nxt_mp_t *mp, socklen_t socklen, + size_t address_length) NXT_MALLOC_LIKE; +NXT_EXPORT nxt_sockaddr_t * +nxt_sockaddr_create(nxt_mp_t *mp, struct sockaddr *sockaddr, socklen_t socklen, + size_t address_length) NXT_MALLOC_LIKE; +NXT_EXPORT nxt_sockaddr_t * +nxt_sockaddr_copy(nxt_mp_t *mp, nxt_sockaddr_t *src) NXT_MALLOC_LIKE; NXT_EXPORT nxt_sockaddr_t *nxt_getsockname(nxt_task_t *task, nxt_mp_t *mp, - nxt_socket_t s) - NXT_MALLOC_LIKE; + nxt_socket_t s) NXT_MALLOC_LIKE; NXT_EXPORT void nxt_sockaddr_text(nxt_sockaddr_t *sa); - NXT_EXPORT uint32_t nxt_sockaddr_port_number(nxt_sockaddr_t *sa); NXT_EXPORT nxt_bool_t nxt_sockaddr_cmp(nxt_sockaddr_t *sa1, - nxt_sockaddr_t *sa2); + nxt_sockaddr_t *sa2); NXT_EXPORT nxt_sockaddr_t *nxt_sockaddr_parse(nxt_mp_t *mp, nxt_str_t *addr); NXT_EXPORT nxt_sockaddr_t *nxt_sockaddr_parse_optport(nxt_mp_t *mp, - nxt_str_t *addr); + nxt_str_t *addr); NXT_EXPORT in_addr_t nxt_inet_addr(u_char *buf, size_t len); #if (NXT_INET6) NXT_EXPORT nxt_int_t nxt_inet6_addr(struct in6_addr *in6_addr, u_char *buf, - size_t len); + size_t len); #endif NXT_EXPORT nxt_bool_t nxt_inet6_probe(nxt_str_t *addr); +#define NXT_INET_ADDR_STR_LEN nxt_length("255.255.255.255:65535") -#define NXT_INET_ADDR_STR_LEN nxt_length("255.255.255.255:65535") - -#define NXT_INET6_ADDR_STR_LEN \ - nxt_length("[ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff]:65535") - - -#define nxt_sockaddr_size(sa) \ - (offsetof(nxt_sockaddr_t, u) + sa->socklen + sa->length) -#define nxt_sockaddr_start(sa) nxt_pointer_to(sa, (sa)->start) -#define nxt_sockaddr_address(sa) nxt_pointer_to(sa, (sa)->address_start) -#define nxt_sockaddr_port(sa) nxt_pointer_to(sa, (sa)->port_start) -#define nxt_sockaddr_port_length(sa) \ - (((sa)->start + (sa)->length) - (sa)->port_start) +#define NXT_INET6_ADDR_STR_LEN \ + nxt_length("[ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff]:65535") +#define nxt_sockaddr_size(sa) \ + (offsetof(nxt_sockaddr_t, u) + sa->socklen + sa->length) +#define nxt_sockaddr_start(sa) nxt_pointer_to(sa, (sa)->start) +#define nxt_sockaddr_address(sa) nxt_pointer_to(sa, (sa)->address_start) +#define nxt_sockaddr_port(sa) nxt_pointer_to(sa, (sa)->port_start) +#define nxt_sockaddr_port_length(sa) \ + (((sa)->start + (sa)->length) - (sa)->port_start) #endif /* _NXT_SOCKADDR_H_INCLUDED_ */ diff --git a/src/nxt_socket.c b/src/nxt_socket.c index 9ac8ecd22..ed58fa9a4 100644 --- a/src/nxt_socket.c +++ b/src/nxt_socket.c @@ -6,355 +6,323 @@ #include - static const char *nxt_socket_sockopt_name(nxt_uint_t level, - nxt_uint_t sockopt); - + nxt_uint_t sockopt); -nxt_socket_t -nxt_socket_create(nxt_task_t *task, nxt_uint_t domain, nxt_uint_t type, - nxt_uint_t protocol, nxt_uint_t flags) -{ - nxt_socket_t s; +nxt_socket_t nxt_socket_create(nxt_task_t *task, nxt_uint_t domain, + nxt_uint_t type, nxt_uint_t protocol, + nxt_uint_t flags) { + nxt_socket_t s; #if (NXT_HAVE_SOCK_NONBLOCK) - if (flags & NXT_NONBLOCK) { - type |= SOCK_NONBLOCK; - } + if (flags & NXT_NONBLOCK) { + type |= SOCK_NONBLOCK; + } #endif - s = socket(domain, type, protocol); + s = socket(domain, type, protocol); - if (nxt_slow_path(s == -1)) { - nxt_alert(task, "socket(%ui, 0x%uXi, %ui) failed %E", - domain, type, protocol, nxt_socket_errno); - return s; - } + if (nxt_slow_path(s == -1)) { + nxt_alert(task, "socket(%ui, 0x%uXi, %ui) failed %E", domain, type, + protocol, nxt_socket_errno); + return s; + } - nxt_debug(task, "socket(): %d", s); + nxt_debug(task, "socket(): %d", s); #if !(NXT_HAVE_SOCK_NONBLOCK) - if (flags & NXT_NONBLOCK) { - if (nxt_slow_path(nxt_socket_nonblocking(task, s) != NXT_OK)) { - nxt_socket_close(task, s); - return -1; - } + if (flags & NXT_NONBLOCK) { + if (nxt_slow_path(nxt_socket_nonblocking(task, s) != NXT_OK)) { + nxt_socket_close(task, s); + return -1; } + } #endif - return s; + return s; } - -void -nxt_socket_defer_accept(nxt_task_t *task, nxt_socket_t s, nxt_sockaddr_t *sa) -{ +void nxt_socket_defer_accept(nxt_task_t *task, nxt_socket_t s, + nxt_sockaddr_t *sa) { #if (NXT_HAVE_UNIX_DOMAIN) - if (sa->u.sockaddr.sa_family == AF_UNIX) { - /* Deferred accept() is not supported on AF_UNIX sockets. */ - return; - } + if (sa->u.sockaddr.sa_family == AF_UNIX) { + /* Deferred accept() is not supported on AF_UNIX sockets. */ + return; + } #endif #ifdef TCP_DEFER_ACCEPT - /* Defer Linux accept() up to for 1 second. */ - (void) nxt_socket_setsockopt(task, s, IPPROTO_TCP, TCP_DEFER_ACCEPT, 1); + /* Defer Linux accept() up to for 1 second. */ + (void)nxt_socket_setsockopt(task, s, IPPROTO_TCP, TCP_DEFER_ACCEPT, 1); #endif } +nxt_int_t nxt_socket_getsockopt(nxt_task_t *task, nxt_socket_t s, + nxt_uint_t level, nxt_uint_t sockopt) { + int val; + socklen_t len; -nxt_int_t -nxt_socket_getsockopt(nxt_task_t *task, nxt_socket_t s, nxt_uint_t level, - nxt_uint_t sockopt) -{ - int val; - socklen_t len; - - len = sizeof(val); + len = sizeof(val); - if (nxt_fast_path(getsockopt(s, level, sockopt, &val, &len) == 0)) { - nxt_debug(task, "getsockopt(%d, %ui, %s): %d", - s, level, nxt_socket_sockopt_name(level, sockopt), val); - return val; - } + if (nxt_fast_path(getsockopt(s, level, sockopt, &val, &len) == 0)) { + nxt_debug(task, "getsockopt(%d, %ui, %s): %d", s, level, + nxt_socket_sockopt_name(level, sockopt), val); + return val; + } - nxt_alert(task, "getsockopt(%d, %ui, %s) failed %E", - s, level, nxt_socket_sockopt_name(level, sockopt), - nxt_socket_errno); + nxt_alert(task, "getsockopt(%d, %ui, %s) failed %E", s, level, + nxt_socket_sockopt_name(level, sockopt), nxt_socket_errno); - return -1; + return -1; } +nxt_int_t nxt_socket_setsockopt(nxt_task_t *task, nxt_socket_t s, + nxt_uint_t level, nxt_uint_t sockopt, int val) { + socklen_t len; -nxt_int_t -nxt_socket_setsockopt(nxt_task_t *task, nxt_socket_t s, nxt_uint_t level, - nxt_uint_t sockopt, int val) -{ - socklen_t len; - - len = sizeof(val); + len = sizeof(val); - if (nxt_fast_path(setsockopt(s, level, sockopt, &val, len) == 0)) { - nxt_debug(task, "setsockopt(%d, %ui, %s): %d", - s, level, nxt_socket_sockopt_name(level, sockopt), val); - return NXT_OK; - } + if (nxt_fast_path(setsockopt(s, level, sockopt, &val, len) == 0)) { + nxt_debug(task, "setsockopt(%d, %ui, %s): %d", s, level, + nxt_socket_sockopt_name(level, sockopt), val); + return NXT_OK; + } - nxt_alert(task, "setsockopt(%d, %ui, %s, %d) failed %E", - s, level, nxt_socket_sockopt_name(level, sockopt), val, - nxt_socket_errno); + nxt_alert(task, "setsockopt(%d, %ui, %s, %d) failed %E", s, level, + nxt_socket_sockopt_name(level, sockopt), val, nxt_socket_errno); - return NXT_ERROR; + return NXT_ERROR; } +static const char *nxt_socket_sockopt_name(nxt_uint_t level, + nxt_uint_t sockopt) { + switch (level) { -static const char * -nxt_socket_sockopt_name(nxt_uint_t level, nxt_uint_t sockopt) -{ - switch (level) { - - case SOL_SOCKET: - switch (sockopt) { + case SOL_SOCKET: + switch (sockopt) { - case SO_SNDBUF: - return "SO_SNDBUF"; + case SO_SNDBUF: + return "SO_SNDBUF"; - case SO_RCVBUF: - return "SO_RCVBUF"; + case SO_RCVBUF: + return "SO_RCVBUF"; - case SO_REUSEADDR: - return "SO_REUSEADDR"; + case SO_REUSEADDR: + return "SO_REUSEADDR"; - case SO_TYPE: - return "SO_TYPE"; - } + case SO_TYPE: + return "SO_TYPE"; + } - break; + break; - case IPPROTO_TCP: - switch (sockopt) { + case IPPROTO_TCP: + switch (sockopt) { - case TCP_NODELAY: - return "TCP_NODELAY"; + case TCP_NODELAY: + return "TCP_NODELAY"; #ifdef TCP_DEFER_ACCEPT - case TCP_DEFER_ACCEPT: - return "TCP_DEFER_ACCEPT"; + case TCP_DEFER_ACCEPT: + return "TCP_DEFER_ACCEPT"; #endif - } + } - break; + break; #if (NXT_INET6) - case IPPROTO_IPV6: + case IPPROTO_IPV6: - switch (sockopt) { + switch (sockopt) { - case IPV6_V6ONLY: - return "IPV6_V6ONLY"; - } + case IPV6_V6ONLY: + return "IPV6_V6ONLY"; + } - break; + break; #endif + } - } - - return ""; + return ""; } +nxt_int_t nxt_socket_bind(nxt_task_t *task, nxt_socket_t s, + nxt_sockaddr_t *sa) { + nxt_debug(task, "bind(%d, %*s)", s, (size_t)sa->length, + nxt_sockaddr_start(sa)); -nxt_int_t -nxt_socket_bind(nxt_task_t *task, nxt_socket_t s, nxt_sockaddr_t *sa) -{ - nxt_debug(task, "bind(%d, %*s)", s, (size_t) sa->length, - nxt_sockaddr_start(sa)); + if (nxt_fast_path(bind(s, &sa->u.sockaddr, sa->socklen) == 0)) { + return NXT_OK; + } - if (nxt_fast_path(bind(s, &sa->u.sockaddr, sa->socklen) == 0)) { - return NXT_OK; - } + nxt_alert(task, "bind(%d, %*s) failed %E", s, (size_t)sa->length, + nxt_sockaddr_start(sa), nxt_socket_errno); - nxt_alert(task, "bind(%d, %*s) failed %E", - s, (size_t) sa->length, nxt_sockaddr_start(sa), nxt_socket_errno); - - return NXT_ERROR; + return NXT_ERROR; } +nxt_int_t nxt_socket_connect(nxt_task_t *task, nxt_socket_t s, + nxt_sockaddr_t *sa) { + nxt_err_t err; + nxt_int_t ret; + nxt_uint_t level; -nxt_int_t -nxt_socket_connect(nxt_task_t *task, nxt_socket_t s, nxt_sockaddr_t *sa) -{ - nxt_err_t err; - nxt_int_t ret; - nxt_uint_t level; + nxt_debug(task, "connect(%d, %*s)", s, (size_t)sa->length, + nxt_sockaddr_start(sa)); - nxt_debug(task, "connect(%d, %*s)", - s, (size_t) sa->length, nxt_sockaddr_start(sa)); + if (connect(s, &sa->u.sockaddr, sa->socklen) == 0) { + return NXT_OK; + } - if (connect(s, &sa->u.sockaddr, sa->socklen) == 0) { - return NXT_OK; - } + err = nxt_socket_errno; - err = nxt_socket_errno; + switch (err) { - switch (err) { - - case NXT_EINPROGRESS: - nxt_debug(task, "connect(%d, %*s) in progress", - s, (size_t) sa->length, nxt_sockaddr_start(sa)); - return NXT_AGAIN; + case NXT_EINPROGRESS: + nxt_debug(task, "connect(%d, %*s) in progress", s, (size_t)sa->length, + nxt_sockaddr_start(sa)); + return NXT_AGAIN; - case NXT_ECONNREFUSED: + case NXT_ECONNREFUSED: #if (NXT_LINUX) - case NXT_EAGAIN: - /* - * Linux returns EAGAIN instead of ECONNREFUSED - * for UNIX sockets if a listen queue is full. - */ + case NXT_EAGAIN: + /* + * Linux returns EAGAIN instead of ECONNREFUSED + * for UNIX sockets if a listen queue is full. + */ #endif - level = NXT_LOG_ERR; - ret = NXT_DECLINED; - break; - - case NXT_ECONNRESET: - case NXT_ENETDOWN: - case NXT_ENETUNREACH: - case NXT_EHOSTDOWN: - case NXT_EHOSTUNREACH: - level = NXT_LOG_ERR; - ret = NXT_ERROR; - break; - - default: - level = NXT_LOG_ALERT; - ret = NXT_ERROR; - } - - nxt_log(task, level, "connect(%d, %*s) failed %E", - s, (size_t) sa->length, nxt_sockaddr_start(sa), err); - - return ret; + level = NXT_LOG_ERR; + ret = NXT_DECLINED; + break; + + case NXT_ECONNRESET: + case NXT_ENETDOWN: + case NXT_ENETUNREACH: + case NXT_EHOSTDOWN: + case NXT_EHOSTUNREACH: + level = NXT_LOG_ERR; + ret = NXT_ERROR; + break; + + default: + level = NXT_LOG_ALERT; + ret = NXT_ERROR; + } + + nxt_log(task, level, "connect(%d, %*s) failed %E", s, (size_t)sa->length, + nxt_sockaddr_start(sa), err); + + return ret; } +void nxt_socket_shutdown(nxt_task_t *task, nxt_socket_t s, nxt_uint_t how) { + nxt_err_t err; + nxt_uint_t level; -void -nxt_socket_shutdown(nxt_task_t *task, nxt_socket_t s, nxt_uint_t how) -{ - nxt_err_t err; - nxt_uint_t level; + if (nxt_fast_path(shutdown(s, how) == 0)) { + nxt_debug(task, "shutdown(%d, %ui)", s, how); + return; + } - if (nxt_fast_path(shutdown(s, how) == 0)) { - nxt_debug(task, "shutdown(%d, %ui)", s, how); - return; - } + err = nxt_socket_errno; - err = nxt_socket_errno; + switch (err) { - switch (err) { + case NXT_ENOTCONN: + level = NXT_LOG_DEBUG; + break; - case NXT_ENOTCONN: - level = NXT_LOG_DEBUG; - break; + case NXT_ECONNRESET: + case NXT_ENETDOWN: + case NXT_ENETUNREACH: + case NXT_EHOSTDOWN: + case NXT_EHOSTUNREACH: + level = NXT_LOG_ERR; + break; - case NXT_ECONNRESET: - case NXT_ENETDOWN: - case NXT_ENETUNREACH: - case NXT_EHOSTDOWN: - case NXT_EHOSTUNREACH: - level = NXT_LOG_ERR; - break; + default: + level = NXT_LOG_ALERT; + } - default: - level = NXT_LOG_ALERT; - } - - nxt_log(task, level, "shutdown(%d, %ui) failed %E", s, how, err); + nxt_log(task, level, "shutdown(%d, %ui) failed %E", s, how, err); } +void nxt_socket_close(nxt_task_t *task, nxt_socket_t s) { + nxt_err_t err; + nxt_uint_t level; -void -nxt_socket_close(nxt_task_t *task, nxt_socket_t s) -{ - nxt_err_t err; - nxt_uint_t level; - - if (nxt_fast_path(close(s) == 0)) { - nxt_debug(task, "socket close(%d)", s); - return; - } + if (nxt_fast_path(close(s) == 0)) { + nxt_debug(task, "socket close(%d)", s); + return; + } - err = nxt_socket_errno; + err = nxt_socket_errno; - switch (err) { + switch (err) { - case NXT_ENOTCONN: - level = NXT_LOG_DEBUG; - break; + case NXT_ENOTCONN: + level = NXT_LOG_DEBUG; + break; - case NXT_ECONNRESET: - case NXT_ENETDOWN: - case NXT_ENETUNREACH: - case NXT_EHOSTDOWN: - case NXT_EHOSTUNREACH: - level = NXT_LOG_ERR; - break; + case NXT_ECONNRESET: + case NXT_ENETDOWN: + case NXT_ENETUNREACH: + case NXT_EHOSTDOWN: + case NXT_EHOSTUNREACH: + level = NXT_LOG_ERR; + break; - default: - level = NXT_LOG_ALERT; - } + default: + level = NXT_LOG_ALERT; + } - nxt_log(task, level, "socket close(%d) failed %E", s, err); + nxt_log(task, level, "socket close(%d) failed %E", s, err); } +nxt_err_t nxt_socket_error(nxt_socket_t s) { + int ret, err; + socklen_t len; -nxt_err_t -nxt_socket_error(nxt_socket_t s) -{ - int ret, err; - socklen_t len; - - err = 0; - len = sizeof(int); - /* - * Linux and BSDs return 0 and store a pending error in the err argument; - * Solaris returns -1 and sets the errno. - */ - ret = getsockopt(s, SOL_SOCKET, SO_ERROR, (void *) &err, &len); + err = 0; + len = sizeof(int); + /* + * Linux and BSDs return 0 and store a pending error in the err argument; + * Solaris returns -1 and sets the errno. + */ + ret = getsockopt(s, SOL_SOCKET, SO_ERROR, (void *)&err, &len); - if (nxt_slow_path(ret == -1)) { - err = nxt_errno; - } + if (nxt_slow_path(ret == -1)) { + err = nxt_errno; + } - return err; + return err; } - -nxt_uint_t -nxt_socket_error_level(nxt_err_t err) -{ - switch (err) { - - case NXT_EPIPE: - case NXT_ECONNRESET: - case NXT_ENOTCONN: - case NXT_ETIMEDOUT: - case NXT_ENETDOWN: - case NXT_ENETUNREACH: - case NXT_EHOSTDOWN: - case NXT_EHOSTUNREACH: - return NXT_LOG_INFO; - - case NXT_ECONNREFUSED: - return NXT_LOG_ERR; - - default: - return NXT_LOG_ALERT; - } +nxt_uint_t nxt_socket_error_level(nxt_err_t err) { + switch (err) { + + case NXT_EPIPE: + case NXT_ECONNRESET: + case NXT_ENOTCONN: + case NXT_ETIMEDOUT: + case NXT_ENETDOWN: + case NXT_ENETUNREACH: + case NXT_EHOSTDOWN: + case NXT_EHOSTUNREACH: + return NXT_LOG_INFO; + + case NXT_ECONNREFUSED: + return NXT_LOG_ERR; + + default: + return NXT_LOG_ALERT; + } } diff --git a/src/nxt_socket.h b/src/nxt_socket.h index 69b09039f..eb9a3a311 100644 --- a/src/nxt_socket.h +++ b/src/nxt_socket.h @@ -7,11 +7,9 @@ #ifndef _NXT_SOCKET_H_INCLUDED_ #define _NXT_SOCKET_H_INCLUDED_ +typedef int nxt_socket_t; -typedef int nxt_socket_t; - -#define NXT_NONBLOCK 1 - +#define NXT_NONBLOCK 1 /* * struct sockaddr and struct sockaddr_in are 16 bytes. @@ -66,63 +64,59 @@ typedef int nxt_socket_t; */ #if (NXT_HAVE_UNIX_DOMAIN) -#define NXT_SOCKADDR_LEN sizeof(struct sockaddr_un) +#define NXT_SOCKADDR_LEN sizeof(struct sockaddr_un) #elif (NXT_HAVE_SOCKADDR_IN6) -#define NXT_SOCKADDR_LEN sizeof(struct sockaddr_in6) +#define NXT_SOCKADDR_LEN sizeof(struct sockaddr_in6) #else -#define NXT_SOCKADDR_LEN sizeof(struct sockaddr_in) +#define NXT_SOCKADDR_LEN sizeof(struct sockaddr_in) #endif - typedef union { - struct sockaddr buf; - uint64_t alignment; - char space[NXT_SOCKADDR_LEN]; + struct sockaddr buf; + uint64_t alignment; + char space[NXT_SOCKADDR_LEN]; } nxt_sockaddr_buf_t; - /* * MAXHOSTNAMELEN is: * 64 on Linux; * 256 on FreeBSD, Solaris, MacOSX, NetBSD, OpenBSD. */ -#define NXT_MAXHOSTNAMELEN MAXHOSTNAMELEN - +#define NXT_MAXHOSTNAMELEN MAXHOSTNAMELEN NXT_EXPORT nxt_socket_t nxt_socket_create(nxt_task_t *task, nxt_uint_t family, - nxt_uint_t type, nxt_uint_t protocol, nxt_uint_t flags); + nxt_uint_t type, nxt_uint_t protocol, + nxt_uint_t flags); NXT_EXPORT void nxt_socket_defer_accept(nxt_task_t *task, nxt_socket_t s, - nxt_sockaddr_t *sa); + nxt_sockaddr_t *sa); NXT_EXPORT nxt_int_t nxt_socket_getsockopt(nxt_task_t *task, nxt_socket_t s, - nxt_uint_t level, nxt_uint_t sockopt); + nxt_uint_t level, + nxt_uint_t sockopt); NXT_EXPORT nxt_int_t nxt_socket_setsockopt(nxt_task_t *task, nxt_socket_t s, - nxt_uint_t level, nxt_uint_t sockopt, int val); + nxt_uint_t level, nxt_uint_t sockopt, + int val); NXT_EXPORT nxt_int_t nxt_socket_bind(nxt_task_t *task, nxt_socket_t s, - nxt_sockaddr_t *sa); + nxt_sockaddr_t *sa); NXT_EXPORT nxt_int_t nxt_socket_connect(nxt_task_t *task, nxt_socket_t s, - nxt_sockaddr_t *sa); + nxt_sockaddr_t *sa); NXT_EXPORT void nxt_socket_shutdown(nxt_task_t *task, nxt_socket_t s, - nxt_uint_t how); + nxt_uint_t how); NXT_EXPORT void nxt_socket_close(nxt_task_t *task, nxt_socket_t s); nxt_err_t nxt_socket_error(nxt_socket_t s); nxt_uint_t nxt_socket_error_level(nxt_err_t err); NXT_EXPORT nxt_int_t nxt_socketpair_create(nxt_task_t *task, - nxt_socket_t *pair); + nxt_socket_t *pair); NXT_EXPORT void nxt_socketpair_close(nxt_task_t *task, nxt_socket_t *pair); NXT_EXPORT ssize_t nxt_socketpair_send(nxt_fd_event_t *ev, nxt_fd_t *fd, - nxt_iobuf_t *iob, nxt_uint_t niob); -NXT_EXPORT ssize_t nxt_socketpair_recv(nxt_fd_event_t *ev, - nxt_iobuf_t *iob, nxt_uint_t niob, void *oob); - - -#define nxt_socket_nonblocking(task, fd) \ - nxt_fd_nonblocking(task, fd) + nxt_iobuf_t *iob, nxt_uint_t niob); +NXT_EXPORT ssize_t nxt_socketpair_recv(nxt_fd_event_t *ev, nxt_iobuf_t *iob, + nxt_uint_t niob, void *oob); -#define nxt_socket_blocking(task, fd) \ - nxt_fd_blocking(task, fd) +#define nxt_socket_nonblocking(task, fd) nxt_fd_nonblocking(task, fd) +#define nxt_socket_blocking(task, fd) nxt_fd_blocking(task, fd) #endif /* _NXT_SOCKET_H_INCLUDED_ */ diff --git a/src/nxt_socket_msg.c b/src/nxt_socket_msg.c index 3b35ab292..4ad6a23f7 100644 --- a/src/nxt_socket_msg.c +++ b/src/nxt_socket_msg.c @@ -6,52 +6,46 @@ #include #include - -ssize_t -nxt_sendmsg(nxt_socket_t s, nxt_iobuf_t *iob, nxt_uint_t niob, - const nxt_send_oob_t *oob) -{ - struct msghdr msg; - - msg.msg_name = NULL; - msg.msg_namelen = 0; - msg.msg_iov = iob; - msg.msg_iovlen = niob; - /* Flags are cleared just to suppress valgrind warning. */ - msg.msg_flags = 0; - - if (oob != NULL && oob->size != 0) { - msg.msg_control = (void *) oob->buf; - msg.msg_controllen = oob->size; - - } else { - msg.msg_control = NULL; - msg.msg_controllen = 0; - } - - return sendmsg(s, &msg, 0); +ssize_t nxt_sendmsg(nxt_socket_t s, nxt_iobuf_t *iob, nxt_uint_t niob, + const nxt_send_oob_t *oob) { + struct msghdr msg; + + msg.msg_name = NULL; + msg.msg_namelen = 0; + msg.msg_iov = iob; + msg.msg_iovlen = niob; + /* Flags are cleared just to suppress valgrind warning. */ + msg.msg_flags = 0; + + if (oob != NULL && oob->size != 0) { + msg.msg_control = (void *)oob->buf; + msg.msg_controllen = oob->size; + + } else { + msg.msg_control = NULL; + msg.msg_controllen = 0; + } + + return sendmsg(s, &msg, 0); } +ssize_t nxt_recvmsg(nxt_socket_t s, nxt_iobuf_t *iob, nxt_uint_t niob, + nxt_recv_oob_t *oob) { + ssize_t n; + struct msghdr msg; -ssize_t -nxt_recvmsg(nxt_socket_t s, nxt_iobuf_t *iob, nxt_uint_t niob, - nxt_recv_oob_t *oob) -{ - ssize_t n; - struct msghdr msg; - - msg.msg_name = NULL; - msg.msg_namelen = 0; - msg.msg_iov = iob; - msg.msg_iovlen = niob; - msg.msg_control = oob->buf; - msg.msg_controllen = sizeof(oob->buf); + msg.msg_name = NULL; + msg.msg_namelen = 0; + msg.msg_iov = iob; + msg.msg_iovlen = niob; + msg.msg_control = oob->buf; + msg.msg_controllen = sizeof(oob->buf); - n = recvmsg(s, &msg, 0); + n = recvmsg(s, &msg, 0); - if (nxt_fast_path(n != -1)) { - oob->size = msg.msg_controllen; - } + if (nxt_fast_path(n != -1)) { + oob->size = msg.msg_controllen; + } - return n; + return n; } diff --git a/src/nxt_socket_msg.h b/src/nxt_socket_msg.h index 81617bd69..ea249bfdd 100644 --- a/src/nxt_socket_msg.h +++ b/src/nxt_socket_msg.h @@ -9,226 +9,205 @@ #include #endif - #if (NXT_HAVE_UCRED) -#define NXT_CRED_USECMSG 1 -#define NXT_CRED_CMSGTYPE SCM_CREDENTIALS -#define NXT_CRED_GETPID(u) (u->pid) +#define NXT_CRED_USECMSG 1 +#define NXT_CRED_CMSGTYPE SCM_CREDENTIALS +#define NXT_CRED_GETPID(u) (u->pid) -typedef struct ucred nxt_socket_cred_t; +typedef struct ucred nxt_socket_cred_t; #elif (NXT_HAVE_MSGHDR_CMSGCRED) -#define NXT_CRED_USECMSG 1 -#define NXT_CRED_CMSGTYPE SCM_CREDS -#define NXT_CRED_GETPID(u) (u->cmcred_pid) +#define NXT_CRED_USECMSG 1 +#define NXT_CRED_CMSGTYPE SCM_CREDS +#define NXT_CRED_GETPID(u) (u->cmcred_pid) -typedef struct cmsgcred nxt_socket_cred_t; +typedef struct cmsgcred nxt_socket_cred_t; #endif #if (NXT_CRED_USECMSG) -#define NXT_OOB_RECV_SIZE \ - (CMSG_SPACE(2 * sizeof(int)) + CMSG_SPACE(sizeof(nxt_socket_cred_t))) +#define NXT_OOB_RECV_SIZE \ + (CMSG_SPACE(2 * sizeof(int)) + CMSG_SPACE(sizeof(nxt_socket_cred_t))) #else -#define NXT_OOB_RECV_SIZE \ - CMSG_SPACE(2 * sizeof(int)) +#define NXT_OOB_RECV_SIZE CMSG_SPACE(2 * sizeof(int)) #endif #if (NXT_HAVE_MSGHDR_CMSGCRED) -#define NXT_OOB_SEND_SIZE \ - (CMSG_SPACE(2 * sizeof(int)) + CMSG_SPACE(sizeof(nxt_socket_cred_t))) +#define NXT_OOB_SEND_SIZE \ + (CMSG_SPACE(2 * sizeof(int)) + CMSG_SPACE(sizeof(nxt_socket_cred_t))) #else -#define NXT_OOB_SEND_SIZE \ - CMSG_SPACE(2 * sizeof(int)) +#define NXT_OOB_SEND_SIZE CMSG_SPACE(2 * sizeof(int)) #endif - typedef struct { - size_t size; - u_char buf[NXT_OOB_RECV_SIZE]; + size_t size; + u_char buf[NXT_OOB_RECV_SIZE]; } nxt_recv_oob_t; - typedef struct { - size_t size; - u_char buf[NXT_OOB_SEND_SIZE]; + size_t size; + u_char buf[NXT_OOB_SEND_SIZE]; } nxt_send_oob_t; - /** * The nxt_sendmsg is a wrapper for sendmsg. * The oob struct must be initialized using nxt_socket_msg_oob_init(). */ NXT_EXPORT ssize_t nxt_sendmsg(nxt_socket_t s, nxt_iobuf_t *iob, - nxt_uint_t niob, const nxt_send_oob_t *oob); + nxt_uint_t niob, const nxt_send_oob_t *oob); /** * The nxt_recvmsg is a wrapper for recvmsg. * The oob buffer must be consumed by using nxt_socket_msg_oob_get(). */ -NXT_EXPORT ssize_t nxt_recvmsg(nxt_socket_t s, - nxt_iobuf_t *iob, nxt_uint_t niob, nxt_recv_oob_t *oob); - +NXT_EXPORT ssize_t nxt_recvmsg(nxt_socket_t s, nxt_iobuf_t *iob, + nxt_uint_t niob, nxt_recv_oob_t *oob); -nxt_inline struct cmsghdr * -NXT_CMSG_NXTHDR(struct msghdr *msgh, struct cmsghdr *cmsg) -{ +nxt_inline struct cmsghdr *NXT_CMSG_NXTHDR(struct msghdr *msgh, + struct cmsghdr *cmsg) { #if !defined(__GLIBC__) && defined(__clang__) #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wsign-compare" #endif - return CMSG_NXTHDR(msgh, cmsg); + return CMSG_NXTHDR(msgh, cmsg); #if !defined(__GLIBC__) && defined(__clang__) #pragma clang diagnostic pop #endif } - -nxt_inline void -nxt_socket_msg_oob_init(nxt_send_oob_t *oob, int *fds) -{ - int nfds; - struct cmsghdr *cmsg; +nxt_inline void nxt_socket_msg_oob_init(nxt_send_oob_t *oob, int *fds) { + int nfds; + struct cmsghdr *cmsg; #if (NXT_HAVE_MSGHDR_CMSGCRED) - cmsg = (struct cmsghdr *) (oob->buf); - /* - * Fill all padding fields with 0. - * Code in Go 1.11 validate cmsghdr using padding field as part of len. - * See Cmsghdr definition and socketControlMessageHeaderAndData function. - */ - nxt_memzero(cmsg, sizeof(struct cmsghdr)); + cmsg = (struct cmsghdr *)(oob->buf); + /* + * Fill all padding fields with 0. + * Code in Go 1.11 validate cmsghdr using padding field as part of len. + * See Cmsghdr definition and socketControlMessageHeaderAndData function. + */ + nxt_memzero(cmsg, sizeof(struct cmsghdr)); - cmsg->cmsg_len = CMSG_LEN(sizeof(nxt_socket_cred_t)); - cmsg->cmsg_level = SOL_SOCKET; - cmsg->cmsg_type = NXT_CRED_CMSGTYPE; + cmsg->cmsg_len = CMSG_LEN(sizeof(nxt_socket_cred_t)); + cmsg->cmsg_level = SOL_SOCKET; + cmsg->cmsg_type = NXT_CRED_CMSGTYPE; - oob->size = CMSG_SPACE(sizeof(nxt_socket_cred_t)); + oob->size = CMSG_SPACE(sizeof(nxt_socket_cred_t)); #else - oob->size = 0; + oob->size = 0; #endif - nfds = (fds[0] != -1 ? 1 : 0) + (fds[1] != -1 ? 1 : 0); + nfds = (fds[0] != -1 ? 1 : 0) + (fds[1] != -1 ? 1 : 0); - if (nfds == 0) { - return; - } + if (nfds == 0) { + return; + } - cmsg = (struct cmsghdr *) (oob->buf + oob->size); + cmsg = (struct cmsghdr *)(oob->buf + oob->size); - nxt_memzero(cmsg, sizeof(struct cmsghdr)); + nxt_memzero(cmsg, sizeof(struct cmsghdr)); - cmsg->cmsg_len = CMSG_LEN(nfds * sizeof(int)); - cmsg->cmsg_level = SOL_SOCKET; - cmsg->cmsg_type = SCM_RIGHTS; + cmsg->cmsg_len = CMSG_LEN(nfds * sizeof(int)); + cmsg->cmsg_level = SOL_SOCKET; + cmsg->cmsg_type = SCM_RIGHTS; - /* - * nxt_memcpy() is used instead of simple - * *(int *) CMSG_DATA(&cmsg.cm) = fd; - * because GCC 4.4 with -O2/3/s optimization may issue a warning: - * dereferencing type-punned pointer will break strict-aliasing rules - * - * Fortunately, GCC with -O1 compiles this nxt_memcpy() - * in the same simple assignment as in the code above. - */ - nxt_memcpy(CMSG_DATA(cmsg), fds, nfds * sizeof(int)); + /* + * nxt_memcpy() is used instead of simple + * *(int *) CMSG_DATA(&cmsg.cm) = fd; + * because GCC 4.4 with -O2/3/s optimization may issue a warning: + * dereferencing type-punned pointer will break strict-aliasing rules + * + * Fortunately, GCC with -O1 compiles this nxt_memcpy() + * in the same simple assignment as in the code above. + */ + nxt_memcpy(CMSG_DATA(cmsg), fds, nfds * sizeof(int)); - oob->size += CMSG_SPACE(nfds * sizeof(int)); + oob->size += CMSG_SPACE(nfds * sizeof(int)); } +nxt_inline nxt_int_t nxt_socket_msg_oob_get_fds(nxt_recv_oob_t *oob, + nxt_fd_t *fd) { + size_t size; + struct msghdr msg; + struct cmsghdr *cmsg; -nxt_inline nxt_int_t -nxt_socket_msg_oob_get_fds(nxt_recv_oob_t *oob, nxt_fd_t *fd) -{ - size_t size; - struct msghdr msg; - struct cmsghdr *cmsg; - - msg.msg_control = oob->buf; - msg.msg_controllen = oob->size; + msg.msg_control = oob->buf; + msg.msg_controllen = oob->size; - for (cmsg = CMSG_FIRSTHDR(&msg); - cmsg != NULL; - cmsg = NXT_CMSG_NXTHDR(&msg, cmsg)) - { - size = cmsg->cmsg_len - CMSG_LEN(0); + for (cmsg = CMSG_FIRSTHDR(&msg); cmsg != NULL; + cmsg = NXT_CMSG_NXTHDR(&msg, cmsg)) { + size = cmsg->cmsg_len - CMSG_LEN(0); - if (cmsg->cmsg_level == SOL_SOCKET && cmsg->cmsg_type == SCM_RIGHTS) { - if (nxt_slow_path(size != sizeof(int) && size != 2 * sizeof(int))) { - return NXT_ERROR; - } + if (cmsg->cmsg_level == SOL_SOCKET && cmsg->cmsg_type == SCM_RIGHTS) { + if (nxt_slow_path(size != sizeof(int) && size != 2 * sizeof(int))) { + return NXT_ERROR; + } - nxt_memcpy(fd, CMSG_DATA(cmsg), size); + nxt_memcpy(fd, CMSG_DATA(cmsg), size); - return NXT_OK; - } + return NXT_OK; } + } - return NXT_OK; + return NXT_OK; } +nxt_inline nxt_int_t nxt_socket_msg_oob_get(nxt_recv_oob_t *oob, nxt_fd_t *fd, + nxt_pid_t *pid) { + size_t size; + struct msghdr msg; + struct cmsghdr *cmsg; -nxt_inline nxt_int_t -nxt_socket_msg_oob_get(nxt_recv_oob_t *oob, nxt_fd_t *fd, nxt_pid_t *pid) -{ - size_t size; - struct msghdr msg; - struct cmsghdr *cmsg; - - if (oob->size == 0) { - return NXT_OK; - } + if (oob->size == 0) { + return NXT_OK; + } #if (NXT_CRED_USECMSG) - *pid = -1; + *pid = -1; #endif - msg.msg_control = oob->buf; - msg.msg_controllen = oob->size; + msg.msg_control = oob->buf; + msg.msg_controllen = oob->size; - for (cmsg = CMSG_FIRSTHDR(&msg); - cmsg != NULL; - cmsg = NXT_CMSG_NXTHDR(&msg, cmsg)) - { - size = cmsg->cmsg_len - CMSG_LEN(0); + for (cmsg = CMSG_FIRSTHDR(&msg); cmsg != NULL; + cmsg = NXT_CMSG_NXTHDR(&msg, cmsg)) { + size = cmsg->cmsg_len - CMSG_LEN(0); - if (cmsg->cmsg_level == SOL_SOCKET && cmsg->cmsg_type == SCM_RIGHTS) { - if (nxt_slow_path(size != sizeof(int) && size != 2 * sizeof(int))) { - return NXT_ERROR; - } + if (cmsg->cmsg_level == SOL_SOCKET && cmsg->cmsg_type == SCM_RIGHTS) { + if (nxt_slow_path(size != sizeof(int) && size != 2 * sizeof(int))) { + return NXT_ERROR; + } - nxt_memcpy(fd, CMSG_DATA(cmsg), size); + nxt_memcpy(fd, CMSG_DATA(cmsg), size); #if (!NXT_CRED_USECMSG) - break; -#endif - } - -#if (NXT_CRED_USECMSG) - else if (cmsg->cmsg_level == SOL_SOCKET - && cmsg->cmsg_type == NXT_CRED_CMSGTYPE) - { - nxt_socket_cred_t *creds; - - if (nxt_slow_path(size != sizeof(nxt_socket_cred_t))) { - return NXT_ERROR; - } - - creds = (nxt_socket_cred_t *) CMSG_DATA(cmsg); - *pid = NXT_CRED_GETPID(creds); - } + break; #endif } #if (NXT_CRED_USECMSG) - /* For platforms supporting credential passing, it's enforced */ - if (nxt_slow_path(*pid == -1)) { + else if (cmsg->cmsg_level == SOL_SOCKET && + cmsg->cmsg_type == NXT_CRED_CMSGTYPE) { + nxt_socket_cred_t *creds; + + if (nxt_slow_path(size != sizeof(nxt_socket_cred_t))) { return NXT_ERROR; + } + + creds = (nxt_socket_cred_t *)CMSG_DATA(cmsg); + *pid = NXT_CRED_GETPID(creds); } #endif + } - return NXT_OK; -} +#if (NXT_CRED_USECMSG) + /* For platforms supporting credential passing, it's enforced */ + if (nxt_slow_path(*pid == -1)) { + return NXT_ERROR; + } +#endif + return NXT_OK; +} #endif /* _NXT_SOCKET_MSG_H_INCLUDED_ */ diff --git a/src/nxt_socketpair.c b/src/nxt_socketpair.c index 45274b788..bc6bbc72e 100644 --- a/src/nxt_socketpair.c +++ b/src/nxt_socketpair.c @@ -14,174 +14,159 @@ /* SOCK_SEQPACKET is disabled to test SOCK_DGRAM on all platforms. */ #if (0 || NXT_HAVE_AF_UNIX_SOCK_SEQPACKET) -#define NXT_UNIX_SOCKET SOCK_SEQPACKET +#define NXT_UNIX_SOCKET SOCK_SEQPACKET #else -#define NXT_UNIX_SOCKET SOCK_DGRAM +#define NXT_UNIX_SOCKET SOCK_DGRAM #endif +nxt_int_t nxt_socketpair_create(nxt_task_t *task, nxt_socket_t *pair) { + if (nxt_slow_path(socketpair(AF_UNIX, NXT_UNIX_SOCKET, 0, pair) != 0)) { + nxt_alert(task, "socketpair() failed %E", nxt_errno); + return NXT_ERROR; + } -nxt_int_t -nxt_socketpair_create(nxt_task_t *task, nxt_socket_t *pair) -{ - if (nxt_slow_path(socketpair(AF_UNIX, NXT_UNIX_SOCKET, 0, pair) != 0)) { - nxt_alert(task, "socketpair() failed %E", nxt_errno); - return NXT_ERROR; - } + nxt_debug(task, "socketpair(): %d:%d", pair[0], pair[1]); - nxt_debug(task, "socketpair(): %d:%d", pair[0], pair[1]); + if (nxt_slow_path(nxt_socket_nonblocking(task, pair[0]) != NXT_OK)) { + goto fail; + } - if (nxt_slow_path(nxt_socket_nonblocking(task, pair[0]) != NXT_OK)) { - goto fail; - } - - if (nxt_slow_path(fcntl(pair[0], F_SETFD, FD_CLOEXEC) == -1)) { - goto fail; - } + if (nxt_slow_path(fcntl(pair[0], F_SETFD, FD_CLOEXEC) == -1)) { + goto fail; + } - if (nxt_slow_path(nxt_socket_nonblocking(task, pair[1]) != NXT_OK)) { - goto fail; - } + if (nxt_slow_path(nxt_socket_nonblocking(task, pair[1]) != NXT_OK)) { + goto fail; + } - if (nxt_slow_path(fcntl(pair[1], F_SETFD, FD_CLOEXEC) == -1)) { - goto fail; - } + if (nxt_slow_path(fcntl(pair[1], F_SETFD, FD_CLOEXEC) == -1)) { + goto fail; + } #if NXT_HAVE_SOCKOPT_SO_PASSCRED - int enable_creds = 1; - - if (nxt_slow_path(setsockopt(pair[0], SOL_SOCKET, SO_PASSCRED, - &enable_creds, sizeof(enable_creds)) == -1)) - { - nxt_alert(task, "failed to set SO_PASSCRED %E", nxt_errno); - goto fail; - } - - if (nxt_slow_path(setsockopt(pair[1], SOL_SOCKET, SO_PASSCRED, - &enable_creds, sizeof(enable_creds)) == -1)) - { - nxt_alert(task, "failed to set SO_PASSCRED %E", nxt_errno); - goto fail; - } + int enable_creds = 1; + + if (nxt_slow_path(setsockopt(pair[0], SOL_SOCKET, SO_PASSCRED, &enable_creds, + sizeof(enable_creds)) == -1)) { + nxt_alert(task, "failed to set SO_PASSCRED %E", nxt_errno); + goto fail; + } + + if (nxt_slow_path(setsockopt(pair[1], SOL_SOCKET, SO_PASSCRED, &enable_creds, + sizeof(enable_creds)) == -1)) { + nxt_alert(task, "failed to set SO_PASSCRED %E", nxt_errno); + goto fail; + } #endif - return NXT_OK; + return NXT_OK; fail: - nxt_socketpair_close(task, pair); + nxt_socketpair_close(task, pair); - return NXT_ERROR; + return NXT_ERROR; } - -void -nxt_socketpair_close(nxt_task_t *task, nxt_socket_t *pair) -{ - nxt_socket_close(task, pair[0]); - nxt_socket_close(task, pair[1]); +void nxt_socketpair_close(nxt_task_t *task, nxt_socket_t *pair) { + nxt_socket_close(task, pair[0]); + nxt_socket_close(task, pair[1]); } +ssize_t nxt_socketpair_send(nxt_fd_event_t *ev, nxt_fd_t *fd, nxt_iobuf_t *iob, + nxt_uint_t niob) { + ssize_t n; + nxt_err_t err; + nxt_send_oob_t oob; -ssize_t -nxt_socketpair_send(nxt_fd_event_t *ev, nxt_fd_t *fd, nxt_iobuf_t *iob, - nxt_uint_t niob) -{ - ssize_t n; - nxt_err_t err; - nxt_send_oob_t oob; + nxt_socket_msg_oob_init(&oob, fd); - nxt_socket_msg_oob_init(&oob, fd); + for (;;) { + n = nxt_sendmsg(ev->fd, iob, niob, &oob); - for ( ;; ) { - n = nxt_sendmsg(ev->fd, iob, niob, &oob); + err = (n == -1) ? nxt_socket_errno : 0; - err = (n == -1) ? nxt_socket_errno : 0; + nxt_debug(ev->task, "sendmsg(%d, %FD, %FD, %ui): %z", ev->fd, fd[0], fd[1], + niob, n); - nxt_debug(ev->task, "sendmsg(%d, %FD, %FD, %ui): %z", ev->fd, fd[0], - fd[1], niob, n); - - if (n > 0) { - return n; - } + if (n > 0) { + return n; + } - /* n == -1 */ + /* n == -1 */ - switch (err) { + switch (err) { - case NXT_EAGAIN: - nxt_debug(ev->task, "sendmsg(%d) not ready", ev->fd); - break; + case NXT_EAGAIN: + nxt_debug(ev->task, "sendmsg(%d) not ready", ev->fd); + break; - /* - * Returned (at least on OSX) when trying to send many small messages. - */ - case NXT_ENOBUFS: - nxt_debug(ev->task, "sendmsg(%d) no buffers", ev->fd); - break; + /* + * Returned (at least on OSX) when trying to send many small messages. + */ + case NXT_ENOBUFS: + nxt_debug(ev->task, "sendmsg(%d) no buffers", ev->fd); + break; - case NXT_EINTR: - nxt_debug(ev->task, "sendmsg(%d) interrupted", ev->fd); - continue; + case NXT_EINTR: + nxt_debug(ev->task, "sendmsg(%d) interrupted", ev->fd); + continue; - default: - nxt_alert(ev->task, "sendmsg(%d, %FD, %FD, %ui) failed %E", - ev->fd, fd[0], fd[1], niob, err); + default: + nxt_alert(ev->task, "sendmsg(%d, %FD, %FD, %ui) failed %E", ev->fd, fd[0], + fd[1], niob, err); - return NXT_ERROR; - } + return NXT_ERROR; + } - ev->write_ready = 0; + ev->write_ready = 0; - return NXT_AGAIN; - } + return NXT_AGAIN; + } } +ssize_t nxt_socketpair_recv(nxt_fd_event_t *ev, nxt_iobuf_t *iob, + nxt_uint_t niob, void *oob) { + ssize_t n; + nxt_err_t err; -ssize_t -nxt_socketpair_recv(nxt_fd_event_t *ev, nxt_iobuf_t *iob, nxt_uint_t niob, - void *oob) -{ - ssize_t n; - nxt_err_t err; - - for ( ;; ) { - n = nxt_recvmsg(ev->fd, iob, niob, oob); + for (;;) { + n = nxt_recvmsg(ev->fd, iob, niob, oob); - err = (n == -1) ? nxt_socket_errno : 0; + err = (n == -1) ? nxt_socket_errno : 0; - nxt_debug(ev->task, "recvmsg(%d, %ui, %uz): %z", - ev->fd, niob, ((nxt_recv_oob_t *) oob)->size, n); + nxt_debug(ev->task, "recvmsg(%d, %ui, %uz): %z", ev->fd, niob, + ((nxt_recv_oob_t *)oob)->size, n); - if (n > 0) { - return n; - } + if (n > 0) { + return n; + } - if (n == 0) { - ev->closed = 1; - ev->read_ready = 0; + if (n == 0) { + ev->closed = 1; + ev->read_ready = 0; - return n; - } + return n; + } - /* n == -1 */ + /* n == -1 */ - switch (err) { + switch (err) { - case NXT_EAGAIN: - nxt_debug(ev->task, "recvmsg(%d) not ready", ev->fd); - ev->read_ready = 0; + case NXT_EAGAIN: + nxt_debug(ev->task, "recvmsg(%d) not ready", ev->fd); + ev->read_ready = 0; - return NXT_AGAIN; + return NXT_AGAIN; - case NXT_EINTR: - nxt_debug(ev->task, "recvmsg(%d) interrupted", ev->fd); - continue; + case NXT_EINTR: + nxt_debug(ev->task, "recvmsg(%d) interrupted", ev->fd); + continue; - default: - nxt_alert(ev->task, "recvmsg(%d, %ui) failed %E", - ev->fd, niob, err); + default: + nxt_alert(ev->task, "recvmsg(%d, %ui) failed %E", ev->fd, niob, err); - return NXT_ERROR; - } + return NXT_ERROR; } + } } diff --git a/src/nxt_solaris_sendfilev.c b/src/nxt_solaris_sendfilev.c index 1b46d0995..2b4b8d9a0 100644 --- a/src/nxt_solaris_sendfilev.c +++ b/src/nxt_solaris_sendfilev.c @@ -6,7 +6,6 @@ #include - /* * sendfilev() has been introduced in Solaris 8 (7/01). * According to sendfilev(3EXT) it can write to: @@ -16,154 +15,150 @@ */ ssize_t nxt_solaris_event_conn_io_sendfilev(nxt_event_conn_t *c, nxt_buf_t *b, - size_t limit); + size_t limit); static size_t nxt_solaris_buf_coalesce(nxt_buf_t *b, sendfilevec_t *sfv, - int32_t *nsfv, nxt_bool_t *sync, size_t limit); - - -ssize_t -nxt_solaris_event_conn_io_sendfilev(nxt_event_conn_t *c, nxt_buf_t *b, - size_t limit) -{ - size_t sent; - ssize_t n; - int32_t nsfv; - nxt_err_t err; - nxt_off_t size; - nxt_bool_t sync; - sendfilevec_t sfv[NXT_IOBUF_MAX]; - - if (c->sendfile == 0) { - /* AF_UNIX does not support sendfilev(). */ - return nxt_event_conn_io_sendbuf(c, b, limit); - } + int32_t *nsfv, nxt_bool_t *sync, + size_t limit); - sync = 0; +ssize_t nxt_solaris_event_conn_io_sendfilev(nxt_event_conn_t *c, nxt_buf_t *b, + size_t limit) { + size_t sent; + ssize_t n; + int32_t nsfv; + nxt_err_t err; + nxt_off_t size; + nxt_bool_t sync; + sendfilevec_t sfv[NXT_IOBUF_MAX]; - size = nxt_solaris_buf_coalesce(b, sfv, &nsfv, &sync, limit); + if (c->sendfile == 0) { + /* AF_UNIX does not support sendfilev(). */ + return nxt_event_conn_io_sendbuf(c, b, limit); + } - nxt_debug(c->socket.task, "sendfilev(%d, %D)", c->socket.fd, nsfv); + sync = 0; - if (nsfv == 0 && sync) { - return 0; - } + size = nxt_solaris_buf_coalesce(b, sfv, &nsfv, &sync, limit); - sent = 0; - n = sendfilev(c->socket.fd, sfv, nsfv, &sent); + nxt_debug(c->socket.task, "sendfilev(%d, %D)", c->socket.fd, nsfv); - err = (n == -1) ? nxt_errno : 0; + if (nsfv == 0 && sync) { + return 0; + } - nxt_debug(c->socket.task, "sendfilev(): %d sent:%uz", n, sent); + sent = 0; + n = sendfilev(c->socket.fd, sfv, nsfv, &sent); - if (n == -1) { - switch (err) { + err = (n == -1) ? nxt_errno : 0; - case NXT_EAGAIN: - c->socket.write_ready = 0; - break; + nxt_debug(c->socket.task, "sendfilev(): %d sent:%uz", n, sent); - case NXT_EINTR: - break; + if (n == -1) { + switch (err) { - default: - c->socket.error = err; - nxt_log(c->socket.task, nxt_socket_error_level(err), - "sendfilev(%d, %D) failed %E", c->socket.fd, nsfv, err); + case NXT_EAGAIN: + c->socket.write_ready = 0; + break; - return NXT_ERROR; - } + case NXT_EINTR: + break; - nxt_debug(c->socket.task, "sendfilev() %E", err); + default: + c->socket.error = err; + nxt_log(c->socket.task, nxt_socket_error_level(err), + "sendfilev(%d, %D) failed %E", c->socket.fd, nsfv, err); - return sent; + return NXT_ERROR; } - if ((nxt_off_t) sent < size) { - c->socket.write_ready = 0; - } + nxt_debug(c->socket.task, "sendfilev() %E", err); return sent; -} + } + if ((nxt_off_t)sent < size) { + c->socket.write_ready = 0; + } -static size_t -nxt_solaris_buf_coalesce(nxt_buf_t *b, sendfilevec_t *sfv, int32_t *nsfv, - nxt_bool_t *sync, size_t limit) -{ - size_t size, total; - nxt_fd_t fd, last_fd; - nxt_int_t i; - nxt_off_t pos, last_pos; + return sent; +} - i = -1; - last_fd = -1; - last_pos = 0; - total = 0; +static size_t nxt_solaris_buf_coalesce(nxt_buf_t *b, sendfilevec_t *sfv, + int32_t *nsfv, nxt_bool_t *sync, + size_t limit) { + size_t size, total; + nxt_fd_t fd, last_fd; + nxt_int_t i; + nxt_off_t pos, last_pos; - for (total = 0; b != NULL && total < limit; b = b->next) { + i = -1; + last_fd = -1; + last_pos = 0; + total = 0; - if (nxt_buf_is_file(b)) { + for (total = 0; b != NULL && total < limit; b = b->next) { - fd = b->file->fd; - pos = b->file_pos; - size = b->file_end - pos; + if (nxt_buf_is_file(b)) { - if (size == 0) { - continue; - } + fd = b->file->fd; + pos = b->file_pos; + size = b->file_end - pos; - if (total + size > limit) { - size = limit - total; - } + if (size == 0) { + continue; + } - } else if (nxt_buf_is_mem(b)) { + if (total + size > limit) { + size = limit - total; + } - fd = SFV_FD_SELF; - pos = (uintptr_t) b->mem.pos; - size = b->mem.free - b->mem.pos; + } else if (nxt_buf_is_mem(b)) { - if (size == 0) { - continue; - } + fd = SFV_FD_SELF; + pos = (uintptr_t)b->mem.pos; + size = b->mem.free - b->mem.pos; - if (total + size > limit) { - size = limit - total; - } + if (size == 0) { + continue; + } - } else { - *sync = 1; - continue; - } + if (total + size > limit) { + size = limit - total; + } - if (size == 0) { - break; - } + } else { + *sync = 1; + continue; + } - if (fd != last_fd || pos != last_pos) { + if (size == 0) { + break; + } - if (++i >= NXT_IOBUF_MAX) { - goto done; - } + if (fd != last_fd || pos != last_pos) { - sfv[i].sfv_fd = fd; - sfv[i].sfv_flag = 0; - sfv[i].sfv_off = pos; - sfv[i].sfv_len = size; + if (++i >= NXT_IOBUF_MAX) { + goto done; + } - } else { - sfv[i].sfv_len += size; - } + sfv[i].sfv_fd = fd; + sfv[i].sfv_flag = 0; + sfv[i].sfv_off = pos; + sfv[i].sfv_len = size; - total += size; - last_pos = pos + size; - last_fd = fd; + } else { + sfv[i].sfv_len += size; } - i++; + total += size; + last_pos = pos + size; + last_fd = fd; + } + + i++; done: - *nsfv = i; + *nsfv = i; - return total; + return total; } diff --git a/src/nxt_sort.h b/src/nxt_sort.h index b79d0919c..4618536d4 100644 --- a/src/nxt_sort.h +++ b/src/nxt_sort.h @@ -7,8 +7,6 @@ #ifndef _NXT_SORT_H_INCLUDED_ #define _NXT_SORT_H_INCLUDED_ - -#define nxt_qsort qsort - +#define nxt_qsort qsort #endif /* _NXT_SORT_H_INCLUDED_ */ diff --git a/src/nxt_source.h b/src/nxt_source.h index 0b4658dd7..50cf6846f 100644 --- a/src/nxt_source.h +++ b/src/nxt_source.h @@ -7,36 +7,31 @@ #ifndef _NXT_SOURCE_H_INCLUDED_ #define _NXT_SOURCE_H_INCLUDED_ - /* * A source handler should store a pointer to a passed source hook, but not * the hook's values themselves, because a source filter may change the values. */ typedef struct { - void *context; - nxt_work_handler_t filter; + void *context; + nxt_work_handler_t filter; } nxt_source_hook_t; - typedef void (*nxt_source_handler_t)(void *source_context, - nxt_source_hook_t *query); - - -#define nxt_source_filter(thr, wq, task, next, out) \ - do { \ - if (thr->engine->batch != 0) { \ - nxt_thread_work_queue_add(thr, wq, nxt_source_filter_handler, \ - task, next, out); \ - \ - } else { \ - (next)->filter(task, (next)->context, out); \ - } \ - \ - } while (0) - + nxt_source_hook_t *query); + +#define nxt_source_filter(thr, wq, task, next, out) \ + do { \ + if (thr->engine->batch != 0) { \ + nxt_thread_work_queue_add(thr, wq, nxt_source_filter_handler, task, \ + next, out); \ + \ + } else { \ + (next)->filter(task, (next)->context, out); \ + } \ + \ + } while (0) NXT_EXPORT void nxt_source_filter_handler(nxt_task_t *task, void *obj, - void *data); - + void *data); #endif /* _NXT_SOURCE_H_INCLUDED_ */ diff --git a/src/nxt_spinlock.c b/src/nxt_spinlock.c index 940be724e..b78bf7b18 100644 --- a/src/nxt_spinlock.c +++ b/src/nxt_spinlock.c @@ -6,7 +6,6 @@ #include - /* * Linux supports pthread spinlocks since glibc 2.3. Spinlock is an * atomic integer with zero initial value. On i386/amd64 however the @@ -26,87 +25,74 @@ * with depressed (the lowest) priority. */ - /* It should be adjusted with the "spinlock_count" directive. */ -static nxt_uint_t nxt_spinlock_count = 1000; - - -void -nxt_thread_spin_init(nxt_uint_t ncpu, nxt_uint_t count) -{ - switch (ncpu) { - - case 0: - /* Explicit spinlock count. */ - nxt_spinlock_count = count; - break; - - case 1: - /* Spinning is useless on UP. */ - nxt_spinlock_count = 0; - break; - - default: - /* - * SMP. - * - * TODO: The count should be 10 on a virtualized system - * since virtualized CPUs may share the same physical CPU. - */ - nxt_spinlock_count = 1000; - break; - } +static nxt_uint_t nxt_spinlock_count = 1000; + +void nxt_thread_spin_init(nxt_uint_t ncpu, nxt_uint_t count) { + switch (ncpu) { + + case 0: + /* Explicit spinlock count. */ + nxt_spinlock_count = count; + break; + + case 1: + /* Spinning is useless on UP. */ + nxt_spinlock_count = 0; + break; + + default: + /* + * SMP. + * + * TODO: The count should be 10 on a virtualized system + * since virtualized CPUs may share the same physical CPU. + */ + nxt_spinlock_count = 1000; + break; + } } +void nxt_thread_spin_lock(nxt_thread_spinlock_t *lock) { + nxt_uint_t n; -void -nxt_thread_spin_lock(nxt_thread_spinlock_t *lock) -{ - nxt_uint_t n; + nxt_thread_log_debug("spin_lock(%p) enter", lock); - nxt_thread_log_debug("spin_lock(%p) enter", lock); + for (;;) { - for ( ;; ) { + again: - again: - - if (nxt_fast_path(nxt_atomic_try_lock(lock))) { - return; - } - - for (n = nxt_spinlock_count; n != 0; n--) { + if (nxt_fast_path(nxt_atomic_try_lock(lock))) { + return; + } - nxt_cpu_pause(); + for (n = nxt_spinlock_count; n != 0; n--) { - if (*lock == 0) { - goto again; - } - } + nxt_cpu_pause(); - nxt_thread_yield(); + if (*lock == 0) { + goto again; + } } -} + nxt_thread_yield(); + } +} -nxt_bool_t -nxt_thread_spin_trylock(nxt_thread_spinlock_t *lock) -{ - nxt_thread_log_debug("spin_trylock(%p) enter", lock); +nxt_bool_t nxt_thread_spin_trylock(nxt_thread_spinlock_t *lock) { + nxt_thread_log_debug("spin_trylock(%p) enter", lock); - if (nxt_fast_path(nxt_atomic_try_lock(lock))) { - return 1; - } + if (nxt_fast_path(nxt_atomic_try_lock(lock))) { + return 1; + } - nxt_thread_log_debug("spin_trylock(%p) failed", lock); + nxt_thread_log_debug("spin_trylock(%p) failed", lock); - return 0; + return 0; } +void nxt_thread_spin_unlock(nxt_thread_spinlock_t *lock) { + nxt_atomic_release(lock); -void -nxt_thread_spin_unlock(nxt_thread_spinlock_t *lock) -{ - nxt_atomic_release(lock); - - nxt_thread_log_debug("spin_unlock(%p) exit", lock); + nxt_thread_log_debug("spin_unlock(%p) exit", lock); } diff --git a/src/nxt_spinlock.h b/src/nxt_spinlock.h index 28e054451..bb8c66ceb 100644 --- a/src/nxt_spinlock.h +++ b/src/nxt_spinlock.h @@ -7,13 +7,11 @@ #ifndef _NXT_UNIX_SPINLOCK_H_INCLUDED_ #define _NXT_UNIX_SPINLOCK_H_INCLUDED_ - -typedef nxt_atomic_t nxt_thread_spinlock_t; +typedef nxt_atomic_t nxt_thread_spinlock_t; NXT_EXPORT void nxt_thread_spin_init(nxt_uint_t ncpu, nxt_uint_t count); NXT_EXPORT void nxt_thread_spin_lock(nxt_thread_spinlock_t *lock); NXT_EXPORT nxt_bool_t nxt_thread_spin_trylock(nxt_thread_spinlock_t *lock); NXT_EXPORT void nxt_thread_spin_unlock(nxt_thread_spinlock_t *lock); - #endif /* _NXT_UNIX_SPINLOCK_H_INCLUDED_ */ diff --git a/src/nxt_sprintf.c b/src/nxt_sprintf.c index 875f43a59..af48b9334 100644 --- a/src/nxt_sprintf.c +++ b/src/nxt_sprintf.c @@ -8,7 +8,6 @@ #include #include - /* * Supported formats: * @@ -54,21 +53,17 @@ * %[0][width][u][x|X]Q int128_t/uint128_t */ +u_char *nxt_cdecl nxt_sprintf(u_char *buf, u_char *end, const char *fmt, ...) { + u_char *p; + va_list args; -u_char * nxt_cdecl -nxt_sprintf(u_char *buf, u_char *end, const char *fmt, ...) -{ - u_char *p; - va_list args; - - va_start(args, fmt); - p = nxt_vsprintf(buf, end, fmt, args); - va_end(args); + va_start(args, fmt); + p = nxt_vsprintf(buf, end, fmt, args); + va_end(args); - return p; + return p; } - /* * nxt_sprintf_t is used: * to pass several parameters of nxt_integer() via single pointer @@ -76,649 +71,635 @@ nxt_sprintf(u_char *buf, u_char *end, const char *fmt, ...) */ typedef struct { - u_char *end; - const u_char *hex; - uint32_t width; - int32_t frac_width; - uint8_t max_width; - u_char padding; + u_char *end; + const u_char *hex; + uint32_t width; + int32_t frac_width; + uint8_t max_width; + u_char padding; } nxt_sprintf_t; - static u_char *nxt_integer(nxt_sprintf_t *spf, u_char *buf, uint64_t ui64); static u_char *nxt_number(nxt_sprintf_t *spf, u_char *buf, double n); - /* A right way of "f == 0.0". */ -#define nxt_double_is_zero(f) \ - (fabs(f) <= FLT_EPSILON) - - -u_char * -nxt_vsprintf(u_char *buf, u_char *end, const char *fmt, va_list args) -{ - int d; - double f, i; - size_t length; - int64_t i64; - uint64_t ui64, frac; - nxt_str_t *v; - nxt_err_t err; - nxt_uint_t scale, n; - nxt_msec_t ms; - nxt_nsec_t ns; - nxt_bool_t sign; - const u_char *p; - nxt_sprintf_t spf; - nxt_file_name_t *fn; - - static const u_char hexadecimal[16] = "0123456789abcdef"; - static const u_char HEXADECIMAL[16] = "0123456789ABCDEF"; - static const u_char nan[] = "[nan]"; - static const u_char null[] = "[null]"; - static const u_char infinity[] = "[infinity]"; - - spf.end = end; - - while (*fmt != '\0' && buf < end) { - - /* - * "buf < end" means that we could copy at least one character: - * a plain character, "%%", "%c", or a minus without test. - */ - - if (*fmt != '%') { - *buf++ = *fmt++; - continue; - } +#define nxt_double_is_zero(f) (fabs(f) <= FLT_EPSILON) + +u_char *nxt_vsprintf(u_char *buf, u_char *end, const char *fmt, va_list args) { + int d; + double f, i; + size_t length; + int64_t i64; + uint64_t ui64, frac; + nxt_str_t *v; + nxt_err_t err; + nxt_uint_t scale, n; + nxt_msec_t ms; + nxt_nsec_t ns; + nxt_bool_t sign; + const u_char *p; + nxt_sprintf_t spf; + nxt_file_name_t *fn; + + static const u_char hexadecimal[16] = "0123456789abcdef"; + static const u_char HEXADECIMAL[16] = "0123456789ABCDEF"; + static const u_char nan[] = "[nan]"; + static const u_char null[] = "[null]"; + static const u_char infinity[] = "[infinity]"; + + spf.end = end; + + while (*fmt != '\0' && buf < end) { + + /* + * "buf < end" means that we could copy at least one character: + * a plain character, "%%", "%c", or a minus without test. + */ + + if (*fmt != '%') { + *buf++ = *fmt++; + continue; + } - fmt++; + fmt++; + + /* Test some often used text formats first. */ + + switch (*fmt) { + + case 'V': + fmt++; + v = va_arg(args, nxt_str_t *); + + if (nxt_fast_path(v != NULL)) { + length = v->length; + p = v->start; + goto copy; + } - /* Test some often used text formats first. */ + continue; - switch (*fmt) { + case 's': + fmt++; - case 'V': - fmt++; - v = va_arg(args, nxt_str_t *); + p = va_arg(args, const u_char *); - if (nxt_fast_path(v != NULL)) { - length = v->length; - p = v->start; - goto copy; - } + if (nxt_slow_path(p == NULL)) { + buf = nxt_cpymem(buf, null, nxt_length(null)); + continue; + } - continue; + while (*p != '\0' && buf < end) { + *buf++ = *p++; + } - case 's': - fmt++; + continue; - p = va_arg(args, const u_char *); + case '*': + length = va_arg(args, size_t); - if (nxt_slow_path(p == NULL)) { - buf = nxt_cpymem(buf, null, nxt_length(null)); - continue; - } + fmt++; - while (*p != '\0' && buf < end) { - *buf++ = *p++; - } + if (*fmt == 's') { + fmt++; + p = va_arg(args, const u_char *); - continue; + if (nxt_slow_path(p == NULL)) { + buf = nxt_cpymem(buf, null, nxt_length(null)); + continue; + } - case '*': - length = va_arg(args, size_t); + goto copy; + } - fmt++; + continue; - if (*fmt == 's') { - fmt++; - p = va_arg(args, const u_char *); + default: + break; + } - if (nxt_slow_path(p == NULL)) { - buf = nxt_cpymem(buf, null, nxt_length(null)); - continue; - } + spf.hex = NULL; + spf.width = 0; + spf.frac_width = -1; + spf.max_width = 0; + spf.padding = (*fmt == '0') ? '0' : ' '; - goto copy; - } + sign = 1; - continue; + i64 = 0; + ui64 = 0; - default: - break; - } + while (*fmt >= '0' && *fmt <= '9') { + spf.width = spf.width * 10 + (*fmt++ - '0'); + } - spf.hex = NULL; - spf.width = 0; - spf.frac_width = -1; - spf.max_width = 0; - spf.padding = (*fmt == '0') ? '0' : ' '; + for (;;) { + switch (*fmt) { - sign = 1; + case 'u': + sign = 0; + fmt++; + continue; - i64 = 0; - ui64 = 0; + case 'm': + spf.max_width = 1; + fmt++; + continue; + + case 'X': + spf.hex = HEXADECIMAL; + sign = 0; + fmt++; + continue; + + case 'x': + spf.hex = hexadecimal; + sign = 0; + fmt++; + continue; + + case '.': + fmt++; + spf.frac_width = 0; while (*fmt >= '0' && *fmt <= '9') { - spf.width = spf.width * 10 + (*fmt++ - '0'); + spf.frac_width = spf.frac_width * 10 + *fmt++ - '0'; } + break; - for ( ;; ) { - switch (*fmt) { + default: + break; + } - case 'u': - sign = 0; - fmt++; - continue; + break; + } - case 'm': - spf.max_width = 1; - fmt++; - continue; + switch (*fmt) { - case 'X': - spf.hex = HEXADECIMAL; - sign = 0; - fmt++; - continue; + case 'E': + err = va_arg(args, nxt_err_t); - case 'x': - spf.hex = hexadecimal; - sign = 0; - fmt++; - continue; + *buf++ = '('; + spf.hex = NULL; + spf.width = 0; + buf = nxt_integer(&spf, buf, err); - case '.': - fmt++; - spf.frac_width = 0; + if (buf < end - 1) { + *buf++ = ':'; + *buf++ = ' '; + } - while (*fmt >= '0' && *fmt <= '9') { - spf.frac_width = spf.frac_width * 10 + *fmt++ - '0'; - } + buf = nxt_strerror(err, buf, end - buf); - break; + if (buf < end) { + *buf++ = ')'; + } - default: - break; - } + fmt++; + continue; - break; - } + case 'O': + i64 = (int64_t)va_arg(args, nxt_off_t); + sign = 1; + goto number; + case 'T': + i64 = (int64_t)va_arg(args, nxt_time_t); + sign = 1; + goto number; - switch (*fmt) { + case 'M': + ms = (nxt_msec_t)va_arg(args, nxt_msec_t); + if ((nxt_msec_int_t)ms == -1 && spf.hex == NULL) { + i64 = -1; + sign = 1; + } else { + ui64 = (uint64_t)ms; + sign = 0; + } + goto number; + + case 'N': + ns = (nxt_nsec_t)va_arg(args, nxt_nsec_t); + if ((nxt_nsec_int_t)ns == -1) { + i64 = -1; + sign = 1; + } else { + ui64 = (uint64_t)ns; + sign = 0; + } + goto number; + + case 'z': + if (sign) { + i64 = (int64_t)va_arg(args, ssize_t); + } else { + ui64 = (uint64_t)va_arg(args, size_t); + } + goto number; + + case 'i': + if (sign) { + i64 = (int64_t)va_arg(args, nxt_int_t); + } else { + ui64 = (uint64_t)va_arg(args, nxt_uint_t); + } + + if (spf.max_width != 0) { + spf.width = NXT_INT_T_LEN; + } + + goto number; + + case 'd': + if (sign) { + i64 = (int64_t)va_arg(args, int); + } else { + ui64 = (uint64_t)va_arg(args, u_int); + } + goto number; + + case 'l': + if (sign) { + i64 = (int64_t)va_arg(args, long); + } else { + ui64 = (uint64_t)va_arg(args, u_long); + } + goto number; + + case 'D': + if (sign) { + i64 = (int64_t)va_arg(args, int32_t); + } else { + ui64 = (uint64_t)va_arg(args, uint32_t); + } + goto number; + + case 'L': + if (sign) { + i64 = va_arg(args, int64_t); + } else { + ui64 = va_arg(args, uint64_t); + } + goto number; + + case 'A': + if (sign) { + i64 = (int64_t)va_arg(args, nxt_atomic_int_t); + } else { + ui64 = (uint64_t)va_arg(args, nxt_atomic_uint_t); + } + + if (spf.max_width != 0) { + spf.width = NXT_ATOMIC_T_LEN; + } + + goto number; + + case 'b': + ui64 = (uint64_t)va_arg(args, nxt_bool_t); + sign = 0; + goto number; + + case 'f': + fmt++; + + f = va_arg(args, double); + + if (f < 0) { + *buf++ = '-'; + f = -f; + } + + if (nxt_slow_path(isnan(f))) { + p = nan; + length = nxt_length(nan); + + goto copy; + + } else if (nxt_slow_path(isinf(f))) { + p = infinity; + length = nxt_length(infinity); + + goto copy; + } + + (void)modf(f, &i); + frac = 0; + + if (spf.frac_width > 0) { + + scale = 1; + for (n = spf.frac_width; n != 0; n--) { + scale *= 10; + } - case 'E': - err = va_arg(args, nxt_err_t); + frac = (uint64_t)((f - i) * scale + 0.5); - *buf++ = '('; - spf.hex = NULL; - spf.width = 0; - buf = nxt_integer(&spf, buf, err); + if (frac == scale) { + i += 1; + frac = 0; + } + } - if (buf < end - 1) { - *buf++ = ':'; - *buf++ = ' '; - } + buf = nxt_number(&spf, buf, i); - buf = nxt_strerror(err, buf, end - buf); + if (spf.frac_width > 0) { - if (buf < end) { - *buf++ = ')'; - } + if (buf < end) { + *buf++ = '.'; - fmt++; - continue; + spf.hex = NULL; + spf.padding = '0'; + spf.width = spf.frac_width; + buf = nxt_integer(&spf, buf, frac); + } - case 'O': - i64 = (int64_t) va_arg(args, nxt_off_t); - sign = 1; - goto number; + } else if (spf.frac_width < 0) { + f = modf(f, &i); - case 'T': - i64 = (int64_t) va_arg(args, nxt_time_t); - sign = 1; - goto number; + if (!nxt_double_is_zero(f) && buf < end) { + *buf++ = '.'; - case 'M': - ms = (nxt_msec_t) va_arg(args, nxt_msec_t); - if ((nxt_msec_int_t) ms == -1 && spf.hex == NULL) { - i64 = -1; - sign = 1; - } else { - ui64 = (uint64_t) ms; - sign = 0; - } - goto number; - - case 'N': - ns = (nxt_nsec_t) va_arg(args, nxt_nsec_t); - if ((nxt_nsec_int_t) ns == -1) { - i64 = -1; - sign = 1; - } else { - ui64 = (uint64_t) ns; - sign = 0; - } - goto number; - - case 'z': - if (sign) { - i64 = (int64_t) va_arg(args, ssize_t); - } else { - ui64 = (uint64_t) va_arg(args, size_t); - } - goto number; - - case 'i': - if (sign) { - i64 = (int64_t) va_arg(args, nxt_int_t); - } else { - ui64 = (uint64_t) va_arg(args, nxt_uint_t); - } - - if (spf.max_width != 0) { - spf.width = NXT_INT_T_LEN; - } - - goto number; - - case 'd': - if (sign) { - i64 = (int64_t) va_arg(args, int); - } else { - ui64 = (uint64_t) va_arg(args, u_int); - } - goto number; - - case 'l': - if (sign) { - i64 = (int64_t) va_arg(args, long); - } else { - ui64 = (uint64_t) va_arg(args, u_long); - } - goto number; - - case 'D': - if (sign) { - i64 = (int64_t) va_arg(args, int32_t); - } else { - ui64 = (uint64_t) va_arg(args, uint32_t); - } - goto number; - - case 'L': - if (sign) { - i64 = va_arg(args, int64_t); - } else { - ui64 = va_arg(args, uint64_t); - } - goto number; - - case 'A': - if (sign) { - i64 = (int64_t) va_arg(args, nxt_atomic_int_t); - } else { - ui64 = (uint64_t) va_arg(args, nxt_atomic_uint_t); - } - - if (spf.max_width != 0) { - spf.width = NXT_ATOMIC_T_LEN; - } - - goto number; - - case 'b': - ui64 = (uint64_t) va_arg(args, nxt_bool_t); - sign = 0; - goto number; - - case 'f': - fmt++; - - f = va_arg(args, double); - - if (f < 0) { - *buf++ = '-'; - f = -f; - } - - if (nxt_slow_path(isnan(f))) { - p = nan; - length = nxt_length(nan); - - goto copy; - - } else if (nxt_slow_path(isinf(f))) { - p = infinity; - length = nxt_length(infinity); - - goto copy; - } - - (void) modf(f, &i); - frac = 0; - - if (spf.frac_width > 0) { - - scale = 1; - for (n = spf.frac_width; n != 0; n--) { - scale *= 10; - } - - frac = (uint64_t) ((f - i) * scale + 0.5); - - if (frac == scale) { - i += 1; - frac = 0; - } - } - - buf = nxt_number(&spf, buf, i); - - if (spf.frac_width > 0) { - - if (buf < end) { - *buf++ = '.'; - - spf.hex = NULL; - spf.padding = '0'; - spf.width = spf.frac_width; - buf = nxt_integer(&spf, buf, frac); - } - - } else if (spf.frac_width < 0) { - f = modf(f, &i); - - if (!nxt_double_is_zero(f) && buf < end) { - *buf++ = '.'; - - while (!nxt_double_is_zero(f) && buf < end) { - f *= 10; - f = modf(f, &i); - *buf++ = (u_char) i + '0'; - } - } - } + while (!nxt_double_is_zero(f) && buf < end) { + f *= 10; + f = modf(f, &i); + *buf++ = (u_char)i + '0'; + } + } + } - continue; + continue; - case 'r': - i64 = (int64_t) va_arg(args, rlim_t); - sign = 1; - break; + case 'r': + i64 = (int64_t)va_arg(args, rlim_t); + sign = 1; + break; - case 'p': - ui64 = (uintptr_t) va_arg(args, void *); - sign = 0; - spf.hex = HEXADECIMAL; - /* - * spf.width = NXT_PTR_SIZE * 2; - * spf.padding = '0'; - */ - goto number; + case 'p': + ui64 = (uintptr_t)va_arg(args, void *); + sign = 0; + spf.hex = HEXADECIMAL; + /* + * spf.width = NXT_PTR_SIZE * 2; + * spf.padding = '0'; + */ + goto number; - case 'c': - d = va_arg(args, int); - *buf++ = (u_char) (d & 0xFF); - fmt++; + case 'c': + d = va_arg(args, int); + *buf++ = (u_char)(d & 0xFF); + fmt++; - continue; + continue; - case 'F': - fmt++; + case 'F': + fmt++; - switch (*fmt) { + switch (*fmt) { - case 'D': - i64 = (int64_t) va_arg(args, nxt_fd_t); - sign = 1; + case 'D': + i64 = (int64_t)va_arg(args, nxt_fd_t); + sign = 1; - goto number; + goto number; - case 'N': - fn = va_arg(args, nxt_file_name_t *); - p = fn; + case 'N': + fn = va_arg(args, nxt_file_name_t *); + p = fn; - while (*p != '\0' && buf < end) { - *buf++ = *p++; - } + while (*p != '\0' && buf < end) { + *buf++ = *p++; + } - fmt++; - continue; + fmt++; + continue; - default: - continue; - } + default: + continue; + } - case 'P': - fmt++; + case 'P': + fmt++; - switch (*fmt) { + switch (*fmt) { - case 'I': - i64 = (int64_t) va_arg(args, nxt_pid_t); - sign = 1; - goto number; + case 'I': + i64 = (int64_t)va_arg(args, nxt_pid_t); + sign = 1; + goto number; - case 'T': - ui64 = (uint64_t) (uintptr_t) va_arg(args, nxt_tid_t); - sign = 0; - goto number; + case 'T': + ui64 = (uint64_t)(uintptr_t)va_arg(args, nxt_tid_t); + sign = 0; + goto number; #if 0 case 'F': ui64 = (uint64_t) va_arg(args, nxt_fid_t); sign = 0; goto number; #endif - case 'H': - ui64 = (uint64_t) (uintptr_t) va_arg(args, pthread_t); - spf.hex = HEXADECIMAL; - sign = 0; - goto number; - - default: - continue; - } - - case 'Z': - *buf++ = '\0'; - fmt++; - continue; + case 'H': + ui64 = (uint64_t)(uintptr_t)va_arg(args, pthread_t); + spf.hex = HEXADECIMAL; + sign = 0; + goto number; - case 'n': - *buf++ = '\n'; - fmt++; - continue; - - case '%': - *buf++ = '%'; - fmt++; - continue; - - default: - *buf++ = *fmt++; - continue; - } + default: + continue; + } + + case 'Z': + *buf++ = '\0'; + fmt++; + continue; + + case 'n': + *buf++ = '\n'; + fmt++; + continue; + + case '%': + *buf++ = '%'; + fmt++; + continue; + + default: + *buf++ = *fmt++; + continue; + } - number: + number: - if (sign) { - if (i64 < 0) { - *buf++ = '-'; - ui64 = (uint64_t) -i64; + if (sign) { + if (i64 < 0) { + *buf++ = '-'; + ui64 = (uint64_t)-i64; - } else { - ui64 = (uint64_t) i64; - } - } + } else { + ui64 = (uint64_t)i64; + } + } - buf = nxt_integer(&spf, buf, ui64); + buf = nxt_integer(&spf, buf, ui64); - fmt++; - continue; + fmt++; + continue; - copy: + copy: - length = nxt_min((size_t) (end - buf), length); - buf = nxt_cpymem(buf, p, length); - continue; - } + length = nxt_min((size_t)(end - buf), length); + buf = nxt_cpymem(buf, p, length); + continue; + } - return buf; + return buf; } +static u_char *nxt_integer(nxt_sprintf_t *spf, u_char *buf, uint64_t ui64) { + u_char *p, *end; + size_t length; + u_char temp[NXT_INT64_T_LEN]; -static u_char * -nxt_integer(nxt_sprintf_t *spf, u_char *buf, uint64_t ui64) -{ - u_char *p, *end; - size_t length; - u_char temp[NXT_INT64_T_LEN]; - - p = temp + NXT_INT64_T_LEN; + p = temp + NXT_INT64_T_LEN; - if (spf->hex == NULL) { + if (spf->hex == NULL) { #if (NXT_32BIT) - for ( ;; ) { - u_char *start; - uint32_t ui32; - - /* - * 32-bit platforms usually lack hardware support of 64-bit - * division and remainder operations. For this reason C compiler - * adds calls to the runtime library functions which provides - * these operations. These functions usually have about hundred - * lines of code. - * - * For 32-bit numbers and some constant divisors GCC, Clang and - * other compilers can use inlined multiplications and shifts - * which are faster than division or remainder operations. - * For example, unsigned "ui32 / 10" is compiled to - * - * ((uint64_t) ui32 * 0xCCCCCCCD) >> 35 - * - * So a 64-bit number is split to parts by 10^9. The parts fit - * to 32 bits and are processed separately as 32-bit numbers. A - * number of 64-bit division/remainder operations is significantly - * decreased depending on the 64-bit number's value, it is - * 0 if the 64-bit value is less than 4294967296, - * 1 if the 64-bit value is greater than 4294967295 - * and less than 4294967296000000000, - * 2 otherwise. - */ - - if (ui64 <= 0xFFFFFFFF) { - ui32 = (uint32_t) ui64; - start = NULL; - - } else { - ui32 = (uint32_t) (ui64 % 1000000000); - start = p - 9; - } - - do { - *(--p) = (u_char) (ui32 % 10 + '0'); - ui32 /= 10; - } while (ui32 != 0); - - if (start == NULL) { - break; - } - - /* Add leading zeros of part. */ - - while (p > start) { - *(--p) = '0'; - } - - ui64 /= 1000000000; - } + for (;;) { + u_char *start; + uint32_t ui32; + + /* + * 32-bit platforms usually lack hardware support of 64-bit + * division and remainder operations. For this reason C compiler + * adds calls to the runtime library functions which provides + * these operations. These functions usually have about hundred + * lines of code. + * + * For 32-bit numbers and some constant divisors GCC, Clang and + * other compilers can use inlined multiplications and shifts + * which are faster than division or remainder operations. + * For example, unsigned "ui32 / 10" is compiled to + * + * ((uint64_t) ui32 * 0xCCCCCCCD) >> 35 + * + * So a 64-bit number is split to parts by 10^9. The parts fit + * to 32 bits and are processed separately as 32-bit numbers. A + * number of 64-bit division/remainder operations is significantly + * decreased depending on the 64-bit number's value, it is + * 0 if the 64-bit value is less than 4294967296, + * 1 if the 64-bit value is greater than 4294967295 + * and less than 4294967296000000000, + * 2 otherwise. + */ + + if (ui64 <= 0xFFFFFFFF) { + ui32 = (uint32_t)ui64; + start = NULL; + + } else { + ui32 = (uint32_t)(ui64 % 1000000000); + start = p - 9; + } + + do { + *(--p) = (u_char)(ui32 % 10 + '0'); + ui32 /= 10; + } while (ui32 != 0); + + if (start == NULL) { + break; + } + + /* Add leading zeros of part. */ + + while (p > start) { + *(--p) = '0'; + } + + ui64 /= 1000000000; + } -#else /* NXT_64BIT */ +#else /* NXT_64BIT */ - do { - *(--p) = (u_char) (ui64 % 10 + '0'); - ui64 /= 10; - } while (ui64 != 0); + do { + *(--p) = (u_char)(ui64 % 10 + '0'); + ui64 /= 10; + } while (ui64 != 0); #endif - } else { - - do { - *(--p) = spf->hex[ui64 & 0xF]; - ui64 >>= 4; - } while (ui64 != 0); - } - - /* Zero or space padding. */ + } else { - if (spf->width != 0) { - - length = (temp + NXT_INT64_T_LEN) - p; - end = buf + (spf->width - length); - end = nxt_min(end, spf->end); + do { + *(--p) = spf->hex[ui64 & 0xF]; + ui64 >>= 4; + } while (ui64 != 0); + } - while (buf < end) { - *buf++ = spf->padding; - } - } + /* Zero or space padding. */ - /* Number copying. */ + if (spf->width != 0) { length = (temp + NXT_INT64_T_LEN) - p; - end = buf + length; + end = buf + (spf->width - length); end = nxt_min(end, spf->end); while (buf < end) { - *buf++ = *p++; + *buf++ = spf->padding; } + } - return buf; -} + /* Number copying. */ + length = (temp + NXT_INT64_T_LEN) - p; + end = buf + length; + end = nxt_min(end, spf->end); -static u_char * -nxt_number(nxt_sprintf_t *spf, u_char *buf, double n) -{ - u_char *p, *end; - size_t length; - u_char temp[NXT_DOUBLE_LEN]; + while (buf < end) { + *buf++ = *p++; + } - p = temp + NXT_DOUBLE_LEN; - - do { - *(--p) = (u_char) (fmod(n, 10) + '0'); - n = trunc(n / 10); - } while (!nxt_double_is_zero(n)); + return buf; +} - /* Zero or space padding. */ +static u_char *nxt_number(nxt_sprintf_t *spf, u_char *buf, double n) { + u_char *p, *end; + size_t length; + u_char temp[NXT_DOUBLE_LEN]; - if (spf->width != 0) { - length = (temp + NXT_DOUBLE_LEN) - p; - end = buf + (spf->width - length); - end = nxt_min(end, spf->end); + p = temp + NXT_DOUBLE_LEN; - while (buf < end) { - *buf++ = spf->padding; - } - } + do { + *(--p) = (u_char)(fmod(n, 10) + '0'); + n = trunc(n / 10); + } while (!nxt_double_is_zero(n)); - /* Number copying. */ + /* Zero or space padding. */ + if (spf->width != 0) { length = (temp + NXT_DOUBLE_LEN) - p; - - end = buf + length; + end = buf + (spf->width - length); end = nxt_min(end, spf->end); while (buf < end) { - *buf++ = *p++; + *buf++ = spf->padding; } + } + + /* Number copying. */ + + length = (temp + NXT_DOUBLE_LEN) - p; + + end = buf + length; + end = nxt_min(end, spf->end); + + while (buf < end) { + *buf++ = *p++; + } - return buf; + return buf; } diff --git a/src/nxt_sprintf.h b/src/nxt_sprintf.h index 0a927f710..cb5c76cf9 100644 --- a/src/nxt_sprintf.h +++ b/src/nxt_sprintf.h @@ -7,15 +7,12 @@ #ifndef _NXT_SPRINTF_H_INCLUDED_ #define _NXT_SPRINTF_H_INCLUDED_ - /* STUB */ -#define NXT_DOUBLE_LEN (1 + DBL_MAX_10_EXP) - +#define NXT_DOUBLE_LEN (1 + DBL_MAX_10_EXP) NXT_EXPORT u_char *nxt_cdecl nxt_sprintf(u_char *buf, u_char *end, - const char *fmt, ...); -NXT_EXPORT u_char *nxt_vsprintf(u_char *buf, u_char *end, - const char *fmt, va_list args); - + const char *fmt, ...); +NXT_EXPORT u_char *nxt_vsprintf(u_char *buf, u_char *end, const char *fmt, + va_list args); #endif /* _NXT_SPRINTF_H_INCLUDED_ */ diff --git a/src/nxt_status.c b/src/nxt_status.c index 92cbf2e65..ddafb186f 100644 --- a/src/nxt_status.c +++ b/src/nxt_status.c @@ -8,189 +8,185 @@ #include #include - -nxt_conf_value_t * -nxt_status_get(nxt_status_report_t *report, nxt_mp_t *mp) -{ - size_t i, nr_langs; - uint16_t lang_cnts[NXT_APP_UNKNOWN] = { 1 }; - uint32_t idx = 0; - nxt_str_t name; - nxt_int_t ret; - nxt_array_t *langs; - nxt_thread_t *thr; - nxt_app_type_t type, prev_type; - nxt_status_app_t *app; - nxt_conf_value_t *status, *obj, *mods, *apps, *app_obj, *mod_obj; - nxt_app_lang_module_t *modules; - - static const nxt_str_t modules_str = nxt_string("modules"); - static const nxt_str_t version_str = nxt_string("version"); - static const nxt_str_t lib_str = nxt_string("lib"); - static const nxt_str_t conns_str = nxt_string("connections"); - static const nxt_str_t acc_str = nxt_string("accepted"); - static const nxt_str_t active_str = nxt_string("active"); - static const nxt_str_t idle_str = nxt_string("idle"); - static const nxt_str_t closed_str = nxt_string("closed"); - static const nxt_str_t reqs_str = nxt_string("requests"); - static const nxt_str_t total_str = nxt_string("total"); - static const nxt_str_t apps_str = nxt_string("applications"); - static const nxt_str_t procs_str = nxt_string("processes"); - static const nxt_str_t run_str = nxt_string("running"); - static const nxt_str_t start_str = nxt_string("starting"); - - status = nxt_conf_create_object(mp, 4); - if (nxt_slow_path(status == NULL)) { - return NULL; +nxt_conf_value_t *nxt_status_get(nxt_status_report_t *report, nxt_mp_t *mp) { + size_t i, nr_langs; + uint16_t lang_cnts[NXT_APP_UNKNOWN] = {1}; + uint32_t idx = 0; + nxt_str_t name; + nxt_int_t ret; + nxt_array_t *langs; + nxt_thread_t *thr; + nxt_app_type_t type, prev_type; + nxt_status_app_t *app; + nxt_conf_value_t *status, *obj, *mods, *apps, *app_obj, *mod_obj; + nxt_app_lang_module_t *modules; + + static const nxt_str_t modules_str = nxt_string("modules"); + static const nxt_str_t version_str = nxt_string("version"); + static const nxt_str_t lib_str = nxt_string("lib"); + static const nxt_str_t conns_str = nxt_string("connections"); + static const nxt_str_t acc_str = nxt_string("accepted"); + static const nxt_str_t active_str = nxt_string("active"); + static const nxt_str_t idle_str = nxt_string("idle"); + static const nxt_str_t closed_str = nxt_string("closed"); + static const nxt_str_t reqs_str = nxt_string("requests"); + static const nxt_str_t total_str = nxt_string("total"); + static const nxt_str_t apps_str = nxt_string("applications"); + static const nxt_str_t procs_str = nxt_string("processes"); + static const nxt_str_t run_str = nxt_string("running"); + static const nxt_str_t start_str = nxt_string("starting"); + + status = nxt_conf_create_object(mp, 4); + if (nxt_slow_path(status == NULL)) { + return NULL; + } + + thr = nxt_thread(); + langs = thr->runtime->languages; + + modules = langs->elts; + /* + * We need to count the number of unique languages to correctly + * allocate the below mods object. + * + * We also need to count how many of each language. + * + * Start by skipping past NXT_APP_EXTERNAL which is always the + * first entry. + */ + for (i = 1, nr_langs = 0, prev_type = NXT_APP_UNKNOWN; i < langs->nelts; + i++) { + type = modules[i].type; + + lang_cnts[type]++; + + if (type == prev_type) { + continue; } - thr = nxt_thread(); - langs = thr->runtime->languages; - - modules = langs->elts; - /* - * We need to count the number of unique languages to correctly - * allocate the below mods object. - * - * We also need to count how many of each language. - * - * Start by skipping past NXT_APP_EXTERNAL which is always the - * first entry. - */ - for (i = 1, nr_langs = 0, prev_type = NXT_APP_UNKNOWN; i < langs->nelts; - i++) - { - type = modules[i].type; - - lang_cnts[type]++; - - if (type == prev_type) { - continue; - } - - nr_langs++; - prev_type = type; - } + nr_langs++; + prev_type = type; + } - mods = nxt_conf_create_object(mp, nr_langs); - if (nxt_slow_path(mods == NULL)) { - return NULL; - } + mods = nxt_conf_create_object(mp, nr_langs); + if (nxt_slow_path(mods == NULL)) { + return NULL; + } - nxt_conf_set_member(status, &modules_str, mods, idx++); + nxt_conf_set_member(status, &modules_str, mods, idx++); - i = 1; - obj = mod_obj = NULL; - prev_type = NXT_APP_UNKNOWN; - for (size_t l = 0, a = 0; i < langs->nelts; i++) { - nxt_str_t item, mod_name; + i = 1; + obj = mod_obj = NULL; + prev_type = NXT_APP_UNKNOWN; + for (size_t l = 0, a = 0; i < langs->nelts; i++) { + nxt_str_t item, mod_name; - type = modules[i].type; - if (type != prev_type) { - a = 0; + type = modules[i].type; + if (type != prev_type) { + a = 0; - if (lang_cnts[type] == 1) { - mod_obj = nxt_conf_create_object(mp, 2); - obj = mod_obj; - } else { - mod_obj = nxt_conf_create_array(mp, lang_cnts[type]); - } + if (lang_cnts[type] == 1) { + mod_obj = nxt_conf_create_object(mp, 2); + obj = mod_obj; + } else { + mod_obj = nxt_conf_create_array(mp, lang_cnts[type]); + } - if (nxt_slow_path(mod_obj == NULL)) { - return NULL; - } + if (nxt_slow_path(mod_obj == NULL)) { + return NULL; + } - mod_name.start = (u_char *)modules[i].name; - mod_name.length = strlen(modules[i].name); - nxt_conf_set_member(mods, &mod_name, mod_obj, l++); - } + mod_name.start = (u_char *)modules[i].name; + mod_name.length = strlen(modules[i].name); + nxt_conf_set_member(mods, &mod_name, mod_obj, l++); + } - if (lang_cnts[type] > 1) { - obj = nxt_conf_create_object(mp, 2); - if (nxt_slow_path(obj == NULL)) { - return NULL; - } + if (lang_cnts[type] > 1) { + obj = nxt_conf_create_object(mp, 2); + if (nxt_slow_path(obj == NULL)) { + return NULL; + } - nxt_conf_set_element(mod_obj, a++, obj); - } + nxt_conf_set_element(mod_obj, a++, obj); + } - item.start = modules[i].version; - item.length = nxt_strlen(modules[i].version); - nxt_conf_set_member_string(obj, &version_str, &item, 0); + item.start = modules[i].version; + item.length = nxt_strlen(modules[i].version); + nxt_conf_set_member_string(obj, &version_str, &item, 0); - item.start = (u_char *)modules[i].file; - item.length = strlen(modules[i].file); - nxt_conf_set_member_string(obj, &lib_str, &item, 1); + item.start = (u_char *)modules[i].file; + item.length = strlen(modules[i].file); + nxt_conf_set_member_string(obj, &lib_str, &item, 1); - prev_type = type; - } + prev_type = type; + } - obj = nxt_conf_create_object(mp, 4); - if (nxt_slow_path(obj == NULL)) { - return NULL; - } + obj = nxt_conf_create_object(mp, 4); + if (nxt_slow_path(obj == NULL)) { + return NULL; + } - nxt_conf_set_member(status, &conns_str, obj, idx++); + nxt_conf_set_member(status, &conns_str, obj, idx++); - nxt_conf_set_member_integer(obj, &acc_str, report->accepted_conns, 0); - nxt_conf_set_member_integer(obj, &active_str, report->accepted_conns - - report->closed_conns - - report->idle_conns, 1); - nxt_conf_set_member_integer(obj, &idle_str, report->idle_conns, 2); - nxt_conf_set_member_integer(obj, &closed_str, report->closed_conns, 3); + nxt_conf_set_member_integer(obj, &acc_str, report->accepted_conns, 0); + nxt_conf_set_member_integer( + obj, &active_str, + report->accepted_conns - report->closed_conns - report->idle_conns, 1); + nxt_conf_set_member_integer(obj, &idle_str, report->idle_conns, 2); + nxt_conf_set_member_integer(obj, &closed_str, report->closed_conns, 3); - obj = nxt_conf_create_object(mp, 1); - if (nxt_slow_path(obj == NULL)) { - return NULL; - } + obj = nxt_conf_create_object(mp, 1); + if (nxt_slow_path(obj == NULL)) { + return NULL; + } - nxt_conf_set_member(status, &reqs_str, obj, idx++); + nxt_conf_set_member(status, &reqs_str, obj, idx++); - nxt_conf_set_member_integer(obj, &total_str, report->requests, 0); + nxt_conf_set_member_integer(obj, &total_str, report->requests, 0); - apps = nxt_conf_create_object(mp, report->apps_count); - if (nxt_slow_path(apps == NULL)) { - return NULL; - } + apps = nxt_conf_create_object(mp, report->apps_count); + if (nxt_slow_path(apps == NULL)) { + return NULL; + } - nxt_conf_set_member(status, &apps_str, apps, idx++); + nxt_conf_set_member(status, &apps_str, apps, idx++); - for (i = 0; i < report->apps_count; i++) { - app = &report->apps[i]; + for (i = 0; i < report->apps_count; i++) { + app = &report->apps[i]; - app_obj = nxt_conf_create_object(mp, 2); - if (nxt_slow_path(app_obj == NULL)) { - return NULL; - } + app_obj = nxt_conf_create_object(mp, 2); + if (nxt_slow_path(app_obj == NULL)) { + return NULL; + } - name.length = app->name.length; - name.start = nxt_pointer_to(report, (uintptr_t) app->name.start); + name.length = app->name.length; + name.start = nxt_pointer_to(report, (uintptr_t)app->name.start); - ret = nxt_conf_set_member_dup(apps, mp, &name, app_obj, i); - if (nxt_slow_path(ret != NXT_OK)) { - return NULL; - } + ret = nxt_conf_set_member_dup(apps, mp, &name, app_obj, i); + if (nxt_slow_path(ret != NXT_OK)) { + return NULL; + } - obj = nxt_conf_create_object(mp, 3); - if (nxt_slow_path(obj == NULL)) { - return NULL; - } + obj = nxt_conf_create_object(mp, 3); + if (nxt_slow_path(obj == NULL)) { + return NULL; + } - nxt_conf_set_member(app_obj, &procs_str, obj, 0); + nxt_conf_set_member(app_obj, &procs_str, obj, 0); - nxt_conf_set_member_integer(obj, &run_str, app->processes, 0); - nxt_conf_set_member_integer(obj, &start_str, app->pending_processes, 1); - nxt_conf_set_member_integer(obj, &idle_str, app->idle_processes, 2); + nxt_conf_set_member_integer(obj, &run_str, app->processes, 0); + nxt_conf_set_member_integer(obj, &start_str, app->pending_processes, 1); + nxt_conf_set_member_integer(obj, &idle_str, app->idle_processes, 2); - obj = nxt_conf_create_object(mp, 1); - if (nxt_slow_path(obj == NULL)) { - return NULL; - } + obj = nxt_conf_create_object(mp, 1); + if (nxt_slow_path(obj == NULL)) { + return NULL; + } - nxt_conf_set_member(app_obj, &reqs_str, obj, 1); + nxt_conf_set_member(app_obj, &reqs_str, obj, 1); - nxt_conf_set_member_integer(obj, &active_str, app->active_requests, 0); - } + nxt_conf_set_member_integer(obj, &active_str, app->active_requests, 0); + } - return status; + return status; } diff --git a/src/nxt_status.h b/src/nxt_status.h index a99ac7d0e..2f9218253 100644 --- a/src/nxt_status.h +++ b/src/nxt_status.h @@ -6,28 +6,24 @@ #ifndef _NXT_STATUS_H_INCLUDED_ #define _NXT_STATUS_H_INCLUDED_ - typedef struct { - nxt_str_t name; - uint32_t active_requests; - uint32_t pending_processes; - uint32_t processes; - uint32_t idle_processes; + nxt_str_t name; + uint32_t active_requests; + uint32_t pending_processes; + uint32_t processes; + uint32_t idle_processes; } nxt_status_app_t; - typedef struct { - uint64_t accepted_conns; - uint64_t idle_conns; - uint64_t closed_conns; - uint64_t requests; + uint64_t accepted_conns; + uint64_t idle_conns; + uint64_t closed_conns; + uint64_t requests; - size_t apps_count; - nxt_status_app_t apps[]; + size_t apps_count; + nxt_status_app_t apps[]; } nxt_status_report_t; - nxt_conf_value_t *nxt_status_get(nxt_status_report_t *report, nxt_mp_t *mp); - #endif /* _NXT_STATUS_H_INCLUDED_ */ diff --git a/src/nxt_string.c b/src/nxt_string.c index 1ca595a1c..e591c9da2 100644 --- a/src/nxt_string.c +++ b/src/nxt_string.c @@ -6,60 +6,53 @@ #include +nxt_str_t *nxt_str_alloc(nxt_mp_t *mp, size_t length) { + nxt_str_t *s; -nxt_str_t * -nxt_str_alloc(nxt_mp_t *mp, size_t length) -{ - nxt_str_t *s; + /* The string start is allocated aligned to be close to nxt_str_t. */ + s = nxt_mp_get(mp, sizeof(nxt_str_t) + length); - /* The string start is allocated aligned to be close to nxt_str_t. */ - s = nxt_mp_get(mp, sizeof(nxt_str_t) + length); - - if (nxt_fast_path(s != NULL)) { - s->length = length; - s->start = nxt_pointer_to(s, sizeof(nxt_str_t)); - } + if (nxt_fast_path(s != NULL)) { + s->length = length; + s->start = nxt_pointer_to(s, sizeof(nxt_str_t)); + } - return s; + return s; } - /* * nxt_str_dup() creates a new string with a copy of a source string. * If length of the source string is zero, then the new string anyway * gets a pointer somewhere in mem_pool. */ -nxt_str_t * -nxt_str_dup(nxt_mp_t *mp, nxt_str_t *dst, const nxt_str_t *src) -{ - u_char *p; +nxt_str_t *nxt_str_dup(nxt_mp_t *mp, nxt_str_t *dst, const nxt_str_t *src) { + u_char *p; - if (dst == NULL) { - /* The string start is allocated aligned to be close to nxt_str_t. */ - dst = nxt_mp_get(mp, sizeof(nxt_str_t) + src->length); - if (nxt_slow_path(dst == NULL)) { - return NULL; - } + if (dst == NULL) { + /* The string start is allocated aligned to be close to nxt_str_t. */ + dst = nxt_mp_get(mp, sizeof(nxt_str_t) + src->length); + if (nxt_slow_path(dst == NULL)) { + return NULL; + } - p = (u_char *) dst; - p += sizeof(nxt_str_t); - dst->start = p; + p = (u_char *)dst; + p += sizeof(nxt_str_t); + dst->start = p; - } else { - dst->start = nxt_mp_nget(mp, src->length); - if (nxt_slow_path(dst->start == NULL)) { - return NULL; - } + } else { + dst->start = nxt_mp_nget(mp, src->length); + if (nxt_slow_path(dst->start == NULL)) { + return NULL; } + } - nxt_memcpy(dst->start, src->start, src->length); - dst->length = src->length; + nxt_memcpy(dst->start, src->start, src->length); + dst->length = src->length; - return dst; + return dst; } - /* * nxt_str_cstrz() creates a C style zero-terminated copy of a source * nxt_str_t. The function is intended to create strings suitable @@ -67,446 +60,401 @@ nxt_str_dup(nxt_mp_t *mp, nxt_str_t *dst, const nxt_str_t *src) * of u_char to minimize casts. */ -char * -nxt_str_cstrz(nxt_mp_t *mp, const nxt_str_t *src) -{ - char *p, *dst; +char *nxt_str_cstrz(nxt_mp_t *mp, const nxt_str_t *src) { + char *p, *dst; - dst = nxt_mp_alloc(mp, src->length + 1); + dst = nxt_mp_alloc(mp, src->length + 1); - if (nxt_fast_path(dst != NULL)) { - p = nxt_cpymem(dst, src->start, src->length); - *p = '\0'; - } + if (nxt_fast_path(dst != NULL)) { + p = nxt_cpymem(dst, src->start, src->length); + *p = '\0'; + } - return dst; + return dst; } +void nxt_memcpy_lowcase(u_char *dst, const u_char *src, size_t length) { + u_char c; -void -nxt_memcpy_lowcase(u_char *dst, const u_char *src, size_t length) -{ - u_char c; - - while (length != 0) { - c = *src++; - *dst++ = nxt_lowcase(c); - length--; - } + while (length != 0) { + c = *src++; + *dst++ = nxt_lowcase(c); + length--; + } } +void nxt_memcpy_upcase(u_char *dst, const u_char *src, size_t length) { + u_char c; -void -nxt_memcpy_upcase(u_char *dst, const u_char *src, size_t length) -{ - u_char c; - - while (length != 0) { - c = *src++; - *dst++ = nxt_upcase(c); - length--; - } + while (length != 0) { + c = *src++; + *dst++ = nxt_upcase(c); + length--; + } } +u_char *nxt_cpystr(u_char *dst, const u_char *src) { + for (;;) { + *dst = *src; -u_char * -nxt_cpystr(u_char *dst, const u_char *src) -{ - for ( ;; ) { - *dst = *src; + if (*dst == '\0') { + break; + } - if (*dst == '\0') { - break; - } + dst++; + src++; + } - dst++; - src++; - } + return dst; +} +u_char *nxt_cpystrn(u_char *dst, const u_char *src, size_t length) { + if (length == 0) { return dst; -} + } + while (--length != 0) { + *dst = *src; -u_char * -nxt_cpystrn(u_char *dst, const u_char *src, size_t length) -{ - if (length == 0) { - return dst; + if (*dst == '\0') { + return dst; } - while (--length != 0) { - *dst = *src; - - if (*dst == '\0') { - return dst; - } - - dst++; - src++; - } + dst++; + src++; + } - *dst = '\0'; + *dst = '\0'; - return dst; + return dst; } +nxt_int_t nxt_strcasecmp(const u_char *s1, const u_char *s2) { + u_char c1, c2; + nxt_int_t n; -nxt_int_t -nxt_strcasecmp(const u_char *s1, const u_char *s2) -{ - u_char c1, c2; - nxt_int_t n; - - for ( ;; ) { - c1 = *s1++; - c2 = *s2++; + for (;;) { + c1 = *s1++; + c2 = *s2++; - c1 = nxt_lowcase(c1); - c2 = nxt_lowcase(c2); + c1 = nxt_lowcase(c1); + c2 = nxt_lowcase(c2); - n = c1 - c2; + n = c1 - c2; - if (n != 0) { - return n; - } + if (n != 0) { + return n; + } - if (c1 == 0) { - return 0; - } + if (c1 == 0) { + return 0; } + } } +nxt_int_t nxt_strncasecmp(const u_char *s1, const u_char *s2, size_t length) { + u_char c1, c2; + nxt_int_t n; -nxt_int_t -nxt_strncasecmp(const u_char *s1, const u_char *s2, size_t length) -{ - u_char c1, c2; - nxt_int_t n; - - while (length-- != 0) { - c1 = *s1++; - c2 = *s2++; + while (length-- != 0) { + c1 = *s1++; + c2 = *s2++; - c1 = nxt_lowcase(c1); - c2 = nxt_lowcase(c2); + c1 = nxt_lowcase(c1); + c2 = nxt_lowcase(c2); - n = c1 - c2; + n = c1 - c2; - if (n != 0) { - return n; - } + if (n != 0) { + return n; + } - if (c1 == 0) { - return 0; - } + if (c1 == 0) { + return 0; } + } - return 0; + return 0; } +nxt_int_t nxt_memcasecmp(const void *p1, const void *p2, size_t length) { + u_char c1, c2; + nxt_int_t n; + const u_char *s1, *s2; -nxt_int_t -nxt_memcasecmp(const void *p1, const void *p2, size_t length) -{ - u_char c1, c2; - nxt_int_t n; - const u_char *s1, *s2; + s1 = p1; + s2 = p2; - s1 = p1; - s2 = p2; - - while (length-- != 0) { - c1 = *s1++; - c2 = *s2++; + while (length-- != 0) { + c1 = *s1++; + c2 = *s2++; - c1 = nxt_lowcase(c1); - c2 = nxt_lowcase(c2); + c1 = nxt_lowcase(c1); + c2 = nxt_lowcase(c2); - n = c1 - c2; + n = c1 - c2; - if (n != 0) { - return n; - } + if (n != 0) { + return n; } + } - return 0; + return 0; } - /* * nxt_memstrn() is intended for search of static substring "ss" * with known length "length" in string "s" limited by parameter "end". * Zeros are ignored in both strings. */ -u_char * -nxt_memstrn(const u_char *s, const u_char *end, const char *ss, size_t length) -{ - u_char c1, c2, *s2; +u_char *nxt_memstrn(const u_char *s, const u_char *end, const char *ss, + size_t length) { + u_char c1, c2, *s2; - s2 = (u_char *) ss; - c2 = *s2++; - length--; + s2 = (u_char *)ss; + c2 = *s2++; + length--; - while (s < end) { - c1 = *s++; + while (s < end) { + c1 = *s++; - if (c1 == c2) { + if (c1 == c2) { - if (s + length > end) { - return NULL; - } + if (s + length > end) { + return NULL; + } - if (memcmp(s, s2, length) == 0) { - return (u_char *) s - 1; - } - } + if (memcmp(s, s2, length) == 0) { + return (u_char *)s - 1; + } } + } - return NULL; + return NULL; } - /* * nxt_strcasestrn() is intended for caseless search of static substring * "ss" with known length "length" in string "s" limited by parameter "end". * Zeros are ignored in both strings. */ -u_char * -nxt_memcasestrn(const u_char *s, const u_char *end, const char *ss, - size_t length) -{ - u_char c1, c2, *s2; +u_char *nxt_memcasestrn(const u_char *s, const u_char *end, const char *ss, + size_t length) { + u_char c1, c2, *s2; - s2 = (u_char *) ss; - c2 = *s2++; - c2 = nxt_lowcase(c2); - length--; + s2 = (u_char *)ss; + c2 = *s2++; + c2 = nxt_lowcase(c2); + length--; - while (s < end) { - c1 = *s++; - c1 = nxt_lowcase(c1); + while (s < end) { + c1 = *s++; + c1 = nxt_lowcase(c1); - if (c1 == c2) { + if (c1 == c2) { - if (s + length > end) { - return NULL; - } + if (s + length > end) { + return NULL; + } - if (nxt_memcasecmp(s, s2, length) == 0) { - return (u_char *) s - 1; - } - } + if (nxt_memcasecmp(s, s2, length) == 0) { + return (u_char *)s - 1; + } } + } - return NULL; + return NULL; } - /* * nxt_rstrstrn() is intended to search for static substring "ss" * with known length "length" in string "s" limited by parameter "end" * in reverse order. Zeros are ignored in both strings. */ -u_char * -nxt_rmemstrn(const u_char *s, const u_char *end, const char *ss, size_t length) -{ - u_char c1, c2; - const u_char *s1, *s2; +u_char *nxt_rmemstrn(const u_char *s, const u_char *end, const char *ss, + size_t length) { + u_char c1, c2; + const u_char *s1, *s2; - s1 = end - length; - s2 = (u_char *) ss; - c2 = *s2++; - length--; + s1 = end - length; + s2 = (u_char *)ss; + c2 = *s2++; + length--; - while (s < s1) { - c1 = *s1; + while (s < s1) { + c1 = *s1; - if (c1 == c2) { - if (memcmp(s1 + 1, s2, length) == 0) { - return (u_char *) s1; - } - } - - s1--; + if (c1 == c2) { + if (memcmp(s1 + 1, s2, length) == 0) { + return (u_char *)s1; + } } - return NULL; -} + s1--; + } + return NULL; +} -size_t -nxt_str_strip(const u_char *start, u_char *end) -{ - u_char *p; +size_t nxt_str_strip(const u_char *start, u_char *end) { + u_char *p; - for (p = end - 1; p >= start; p--) { - if (*p != '\r' && *p != '\n') { - break; - } + for (p = end - 1; p >= start; p--) { + if (*p != '\r' && *p != '\n') { + break; } + } - return (p + 1) - start; + return (p + 1) - start; } +nxt_int_t nxt_strverscmp(const u_char *s1, const u_char *s2) { + u_char c1, c2; + nxt_int_t diff; -nxt_int_t -nxt_strverscmp(const u_char *s1, const u_char *s2) -{ - u_char c1, c2; - nxt_int_t diff; - - enum { - st_str = 0, - st_num, - st_zero, - st_frac, - } state; + enum { + st_str = 0, + st_num, + st_zero, + st_frac, + } state; - state = st_str; + state = st_str; - for ( ;; ) { - c1 = *s1++; - c2 = *s2++; + for (;;) { + c1 = *s1++; + c2 = *s2++; - diff = c1 - c2; + diff = c1 - c2; - if (diff != 0) { - break; - } + if (diff != 0) { + break; + } - if (c1 == '\0') { - return 0; - } + if (c1 == '\0') { + return 0; + } - if (!nxt_isdigit(c1)) { - state = st_str; - continue; - } + if (!nxt_isdigit(c1)) { + state = st_str; + continue; + } - if (state == st_str) { - state = (c1 != '0') ? st_num : st_zero; - continue; - } + if (state == st_str) { + state = (c1 != '0') ? st_num : st_zero; + continue; + } - if (state == st_zero && c1 != '0') { - state = st_frac; - continue; - } + if (state == st_zero && c1 != '0') { + state = st_frac; + continue; } + } - switch (state) { + switch (state) { - case st_str: + case st_str: - if ((u_char) (c1 - '1') > 8 || (u_char) (c2 - '1') > 8) { - return diff; - } + if ((u_char)(c1 - '1') > 8 || (u_char)(c2 - '1') > 8) { + return diff; + } - c1 = *s1++; - c2 = *s2++; + c1 = *s1++; + c2 = *s2++; - /* Fall through. */ + /* Fall through. */ - case st_num: + case st_num: - while (nxt_isdigit(c1) && nxt_isdigit(c2)) { - c1 = *s1++; - c2 = *s2++; - } + while (nxt_isdigit(c1) && nxt_isdigit(c2)) { + c1 = *s1++; + c2 = *s2++; + } - if (nxt_isdigit(c1)) { - return 1; - } + if (nxt_isdigit(c1)) { + return 1; + } - if (nxt_isdigit(c2)) { - return -1; - } + if (nxt_isdigit(c2)) { + return -1; + } - return diff; + return diff; - case st_zero: + case st_zero: - if (c1 == '0' || c2 == '\0') { - return -1; - } + if (c1 == '0' || c2 == '\0') { + return -1; + } - if (c2 == '0' || c1 == '\0') { - return 1; - } + if (c2 == '0' || c1 == '\0') { + return 1; + } - /* Fall through. */ + /* Fall through. */ - case st_frac: - default: - return diff; - } + case st_frac: + default: + return diff; + } } +nxt_bool_t nxt_strvers_match(u_char *version, u_char *prefix, size_t length) { + u_char next, last; -nxt_bool_t -nxt_strvers_match(u_char *version, u_char *prefix, size_t length) -{ - u_char next, last; - - if (length == 0) { - return 1; - } + if (length == 0) { + return 1; + } - if (nxt_strncmp(version, prefix, length) == 0) { + if (nxt_strncmp(version, prefix, length) == 0) { - next = version[length]; + next = version[length]; - if (next == '\0') { - return 1; - } + if (next == '\0') { + return 1; + } - last = version[length - 1]; + last = version[length - 1]; - if (nxt_isdigit(last) != nxt_isdigit(next)) { - /* This is a version part boundary. */ - return 1; - } + if (nxt_isdigit(last) != nxt_isdigit(next)) { + /* This is a version part boundary. */ + return 1; } + } - return 0; + return 0; } - -const uint8_t nxt_hex2int[256] - nxt_aligned(32) = -{ - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 16, 16, 16, 16, 16, 16, - 16, 10, 11, 12, 13, 14, 15, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 10, 11, 12, 13, 14, 15, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, +const uint8_t nxt_hex2int[256] nxt_aligned(32) = { + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 0, 1, 2, 3, 4, 5, 6, 7, 8, + 9, 16, 16, 16, 16, 16, 16, 16, 10, 11, 12, 13, 14, 15, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 10, 11, 12, 13, 14, 15, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, }; - -static const uint32_t nxt_uri_escape[] = { +static const uint32_t nxt_uri_escape[] = { 0xffffffff, /* 1111 1111 1111 1111 1111 1111 1111 1111 */ - /* ?>=< ;:98 7654 3210 /.-, +*)( '&%$ #"! */ + /* ?>=< ;:98 7654 3210 /.-, +*)( '&%$ #"! */ 0xd000002d, /* 1101 0000 0000 0000 0000 0000 0010 1101 */ - /* _^]\ [ZYX WVUT SRQP ONML KJIH GFED CBA@ */ + /* _^]\ [ZYX WVUT SRQP ONML KJIH GFED CBA@ */ 0x50000000, /* 0101 0000 0000 0000 0000 0000 0000 0000 */ - /* ~}| {zyx wvut srqp onml kjih gfed cba` */ + /* ~}| {zyx wvut srqp onml kjih gfed cba` */ 0xb8000001, /* 1011 1000 0000 0000 0000 0000 0000 0001 */ 0xffffffff, /* 1111 1111 1111 1111 1111 1111 1111 1111 */ @@ -515,330 +463,310 @@ static const uint32_t nxt_uri_escape[] = { 0xffffffff /* 1111 1111 1111 1111 1111 1111 1111 1111 */ }; +u_char *nxt_decode_uri(u_char *dst, u_char *src, size_t length) { + u_char *end, ch; + uint8_t d0, d1; -u_char * -nxt_decode_uri(u_char *dst, u_char *src, size_t length) -{ - u_char *end, ch; - uint8_t d0, d1; - - nxt_prefetch(&nxt_hex2int['0']); + nxt_prefetch(&nxt_hex2int['0']); - end = src + length; + end = src + length; - while (src < end) { - ch = *src++; - - if (ch == '%') { - if (nxt_slow_path(end - src < 2)) { - return NULL; - } + while (src < end) { + ch = *src++; - d0 = nxt_hex2int[*src++]; - d1 = nxt_hex2int[*src++]; + if (ch == '%') { + if (nxt_slow_path(end - src < 2)) { + return NULL; + } - if (nxt_slow_path((d0 | d1) >= 16)) { - return NULL; - } + d0 = nxt_hex2int[*src++]; + d1 = nxt_hex2int[*src++]; - ch = (d0 << 4) + d1; - } + if (nxt_slow_path((d0 | d1) >= 16)) { + return NULL; + } - *dst++ = ch; + ch = (d0 << 4) + d1; } - return dst; -} + *dst++ = ch; + } + return dst; +} -u_char * -nxt_decode_uri_plus(u_char *dst, u_char *src, size_t length) -{ - u_char *end, ch; - uint8_t d0, d1; - - nxt_prefetch(&nxt_hex2int['0']); +u_char *nxt_decode_uri_plus(u_char *dst, u_char *src, size_t length) { + u_char *end, ch; + uint8_t d0, d1; - end = src + length; + nxt_prefetch(&nxt_hex2int['0']); - while (src < end) { - ch = *src++; + end = src + length; - switch (ch) { - case '%': - if (nxt_slow_path(end - src < 2)) { - return NULL; - } + while (src < end) { + ch = *src++; - d0 = nxt_hex2int[*src++]; - d1 = nxt_hex2int[*src++]; + switch (ch) { + case '%': + if (nxt_slow_path(end - src < 2)) { + return NULL; + } - if (nxt_slow_path((d0 | d1) >= 16)) { - return NULL; - } + d0 = nxt_hex2int[*src++]; + d1 = nxt_hex2int[*src++]; - ch = (d0 << 4) + d1; - break; + if (nxt_slow_path((d0 | d1) >= 16)) { + return NULL; + } - case '+': - ch = ' '; - break; - } + ch = (d0 << 4) + d1; + break; - *dst++ = ch; + case '+': + ch = ' '; + break; } - return dst; -} + *dst++ = ch; + } + return dst; +} -uintptr_t -nxt_encode_uri(u_char *dst, u_char *src, size_t length) -{ - u_char *end; - nxt_uint_t n; +uintptr_t nxt_encode_uri(u_char *dst, u_char *src, size_t length) { + u_char *end; + nxt_uint_t n; - static const u_char hex[16] = "0123456789ABCDEF"; + static const u_char hex[16] = "0123456789ABCDEF"; - end = src + length; + end = src + length; - if (dst == NULL) { + if (dst == NULL) { - /* Find the number of the characters to be escaped. */ + /* Find the number of the characters to be escaped. */ - n = 0; + n = 0; - while (src < end) { + while (src < end) { - if (nxt_uri_escape[*src >> 5] & (1U << (*src & 0x1f))) { - n++; - } + if (nxt_uri_escape[*src >> 5] & (1U << (*src & 0x1f))) { + n++; + } - src++; - } - - return (uintptr_t) n; + src++; } - while (src < end) { + return (uintptr_t)n; + } - if (nxt_uri_escape[*src >> 5] & (1U << (*src & 0x1f))) { - *dst++ = '%'; - *dst++ = hex[*src >> 4]; - *dst++ = hex[*src & 0xf]; + while (src < end) { - } else { - *dst++ = *src; - } + if (nxt_uri_escape[*src >> 5] & (1U << (*src & 0x1f))) { + *dst++ = '%'; + *dst++ = hex[*src >> 4]; + *dst++ = hex[*src & 0xf]; - src++; + } else { + *dst++ = *src; } - return (uintptr_t) dst; -} - + src++; + } -uintptr_t -nxt_encode_complex_uri(u_char *dst, u_char *src, size_t length) -{ - u_char *reserved, *end, ch; - nxt_uint_t n; + return (uintptr_t)dst; +} - static const u_char hex[16] = "0123456789ABCDEF"; +uintptr_t nxt_encode_complex_uri(u_char *dst, u_char *src, size_t length) { + u_char *reserved, *end, ch; + nxt_uint_t n; - reserved = (u_char *) "?#\0"; + static const u_char hex[16] = "0123456789ABCDEF"; - end = src + length; + reserved = (u_char *)"?#\0"; - if (dst == NULL) { + end = src + length; - /* Find the number of the characters to be escaped. */ + if (dst == NULL) { - n = 0; + /* Find the number of the characters to be escaped. */ - while (src < end) { - ch = *src++; + n = 0; - if (nxt_uri_escape[ch >> 5] & (1U << (ch & 0x1f))) { - if (ch == reserved[0]) { - reserved++; - continue; - } + while (src < end) { + ch = *src++; - if (ch == reserved[1]) { - reserved += 2; - continue; - } + if (nxt_uri_escape[ch >> 5] & (1U << (ch & 0x1f))) { + if (ch == reserved[0]) { + reserved++; + continue; + } - n++; - } + if (ch == reserved[1]) { + reserved += 2; + continue; } - return (uintptr_t) n; + n++; + } } - while (src < end) { - ch = *src++; + return (uintptr_t)n; + } - if (nxt_uri_escape[ch >> 5] & (1U << (ch & 0x1f))) { - if (ch == reserved[0]) { - reserved++; + while (src < end) { + ch = *src++; - } else if (ch == reserved[1]) { - reserved += 2; + if (nxt_uri_escape[ch >> 5] & (1U << (ch & 0x1f))) { + if (ch == reserved[0]) { + reserved++; - } else { - *dst++ = '%'; - *dst++ = hex[ch >> 4]; - *dst++ = hex[ch & 0xf]; - continue; - } - } + } else if (ch == reserved[1]) { + reserved += 2; - *dst++ = ch; + } else { + *dst++ = '%'; + *dst++ = hex[ch >> 4]; + *dst++ = hex[ch & 0xf]; + continue; + } } - return (uintptr_t) dst; -} + *dst++ = ch; + } + return (uintptr_t)dst; +} -nxt_bool_t -nxt_is_complex_uri_encoded(u_char *src, size_t length) -{ - u_char *reserved, *end, ch; - uint8_t d0, d1; +nxt_bool_t nxt_is_complex_uri_encoded(u_char *src, size_t length) { + u_char *reserved, *end, ch; + uint8_t d0, d1; - reserved = (u_char *) "?#\0"; + reserved = (u_char *)"?#\0"; - for (end = src + length; src < end; src++) { - ch = *src; + for (end = src + length; src < end; src++) { + ch = *src; - if (nxt_uri_escape[ch >> 5] & (1U << (ch & 0x1f))) { - if (ch == '%') { - if (end - src < 2) { - return 0; - } + if (nxt_uri_escape[ch >> 5] & (1U << (ch & 0x1f))) { + if (ch == '%') { + if (end - src < 2) { + return 0; + } - d0 = nxt_hex2int[*++src]; - d1 = nxt_hex2int[*++src]; + d0 = nxt_hex2int[*++src]; + d1 = nxt_hex2int[*++src]; - if ((d0 | d1) >= 16) { - return 0; - } + if ((d0 | d1) >= 16) { + return 0; + } - continue; - } + continue; + } - if (ch == reserved[0]) { - reserved++; - continue; - } + if (ch == reserved[0]) { + reserved++; + continue; + } - if (ch == reserved[1]) { - reserved += 2; - continue; - } + if (ch == reserved[1]) { + reserved += 2; + continue; + } - return 0; - } + return 0; } + } - return 1; + return 1; } +ssize_t nxt_base64_decode(u_char *dst, u_char *src, size_t length) { + u_char *end, *p; + size_t pad; + uint8_t v1, v2, v3, v4; + + static const uint8_t decode[] = { + 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, + 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, + 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 62, 77, 77, 77, 63, + 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 77, 77, 77, 77, 77, 77, + 77, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, + 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 77, 77, 77, 77, 77, + 77, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, + 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 77, 77, 77, 77, 77, + + 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, + 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, + 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, + 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, + 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, + 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, + 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, + 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77}; + + end = src + length; + pad = (4 - (length % 4)) % 4; + + if (dst == NULL) { + if (pad > 2) { + return NXT_ERROR; + } -ssize_t -nxt_base64_decode(u_char *dst, u_char *src, size_t length) -{ - u_char *end, *p; - size_t pad; - uint8_t v1, v2, v3, v4; - - static const uint8_t decode[] = { - 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, - 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, - 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 62, 77, 77, 77, 63, - 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 77, 77, 77, 77, 77, 77, - 77, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, - 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 77, 77, 77, 77, 77, - 77, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, - 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 77, 77, 77, 77, 77, - - 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, - 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, - 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, - 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, - 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, - 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, - 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, - 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77 - }; - - end = src + length; - pad = (4 - (length % 4)) % 4; - - if (dst == NULL) { - if (pad > 2) { - return NXT_ERROR; - } - - while (src < end) { - if (decode[*src] != 77) { - src++; - continue; - } - - if (pad == 0) { - pad = end - src; + while (src < end) { + if (decode[*src] != 77) { + src++; + continue; + } - if ((pad == 1 || (pad == 2 && src[1] == '=')) && src[0] == '=') - { - break; - } - } + if (pad == 0) { + pad = end - src; - return NXT_ERROR; + if ((pad == 1 || (pad == 2 && src[1] == '=')) && src[0] == '=') { + break; } + } - return (length + 3) / 4 * 3 - pad; + return NXT_ERROR; } - nxt_assert(length != 0); + return (length + 3) / 4 * 3 - pad; + } - if (pad == 0) { - pad = (end[-1] == '=') + (end[-2] == '='); - end -= (pad + 3) & 4; + nxt_assert(length != 0); - } else { - end -= 4 - pad; - } + if (pad == 0) { + pad = (end[-1] == '=') + (end[-2] == '='); + end -= (pad + 3) & 4; - p = dst; + } else { + end -= 4 - pad; + } - while (src < end) { - v1 = decode[src[0]]; - v2 = decode[src[1]]; - v3 = decode[src[2]]; - v4 = decode[src[3]]; + p = dst; - *p++ = (v1 << 2 | v2 >> 4); - *p++ = (v2 << 4 | v3 >> 2); - *p++ = (v3 << 6 | v4); + while (src < end) { + v1 = decode[src[0]]; + v2 = decode[src[1]]; + v3 = decode[src[2]]; + v4 = decode[src[3]]; - src += 4; - } + *p++ = (v1 << 2 | v2 >> 4); + *p++ = (v2 << 4 | v3 >> 2); + *p++ = (v3 << 6 | v4); - if (pad > 0) { - v1 = decode[src[0]]; - v2 = decode[src[1]]; + src += 4; + } - *p++ = (v1 << 2 | v2 >> 4); + if (pad > 0) { + v1 = decode[src[0]]; + v2 = decode[src[1]]; - if (pad == 1) { - v3 = decode[src[2]]; - *p++ = (v2 << 4 | v3 >> 2); - } + *p++ = (v1 << 2 | v2 >> 4); + + if (pad == 1) { + v3 = decode[src[2]]; + *p++ = (v2 << 4 | v3 >> 2); } + } - return (p - dst); + return (p - dst); } diff --git a/src/nxt_string.h b/src/nxt_string.h index 18ea5490d..c77d9c369 100644 --- a/src/nxt_string.h +++ b/src/nxt_string.h @@ -7,161 +7,118 @@ #ifndef _NXT_STRING_H_INCLUDED_ #define _NXT_STRING_H_INCLUDED_ +#define nxt_lowcase(c) (u_char)((c >= 'A' && c <= 'Z') ? c | 0x20 : c) -#define nxt_lowcase(c) \ - (u_char) ((c >= 'A' && c <= 'Z') ? c | 0x20 : c) +#define nxt_upcase(c) (u_char)((c >= 'a' && c <= 'z') ? c & ~0x20 : c) -#define nxt_upcase(c) \ - (u_char) ((c >= 'a' && c <= 'z') ? c & ~0x20 : c) +#define nxt_isdigit(c) ((u_char)((c) - '0') <= 9) -#define nxt_isdigit(c) \ - ((u_char) ((c) - '0') <= 9) +#define nxt_strtod(s, endptr) strtod((char *)s, (char **)endptr) -#define nxt_strtod(s, endptr) \ - strtod((char *) s, (char **) endptr) +#define nxt_strlen(s) strlen((char *)s) +#define nxt_strdup(s) strdup((char *)s) -#define nxt_strlen(s) \ - strlen((char *) s) +#define nxt_strchr(buf, delim) (u_char *)strchr((char *)buf, delim) +#define nxt_memzero(buf, length) (void)memset(buf, 0, length) -#define nxt_strdup(s) \ - strdup((char *) s) - - -#define nxt_strchr(buf, delim) \ - (u_char *) strchr((char *) buf, delim) - - -#define nxt_memzero(buf, length) \ - (void) memset(buf, 0, length) - - -#define nxt_memset(buf, c, length) \ - (void) memset(buf, c, length) - - -#define nxt_memcpy(dst, src, length) \ - (void) memcpy(dst, src, length) +#define nxt_memset(buf, c, length) (void)memset(buf, c, length) +#define nxt_memcpy(dst, src, length) (void)memcpy(dst, src, length) NXT_EXPORT void nxt_memcpy_lowcase(u_char *dst, const u_char *src, - size_t length); + size_t length); NXT_EXPORT void nxt_memcpy_upcase(u_char *dst, const u_char *src, - size_t length); - + size_t length); /* * nxt_cpymem() is an inline function but not a macro to * eliminate possible double evaluation of length "length". */ -nxt_inline void * -nxt_cpymem(void *dst, const void *src, size_t length) -{ - return ((u_char *) memcpy(dst, src, length)) + length; +nxt_inline void *nxt_cpymem(void *dst, const void *src, size_t length) { + return ((u_char *)memcpy(dst, src, length)) + length; } +#define nxt_memmove(dst, src, length) (void)memmove(dst, src, length) -#define nxt_memmove(dst, src, length) \ - (void) memmove(dst, src, length) - - -#define nxt_strcmp(s1, s2) \ - strcmp((char *) s1, (char *) s2) - - -#define nxt_strncmp(s1, s2, length) \ - strncmp((char *) s1, (char *) s2, length) +#define nxt_strcmp(s1, s2) strcmp((char *)s1, (char *)s2) +#define nxt_strncmp(s1, s2, length) strncmp((char *)s1, (char *)s2, length) NXT_EXPORT u_char *nxt_cpystr(u_char *dst, const u_char *src); NXT_EXPORT u_char *nxt_cpystrn(u_char *dst, const u_char *src, size_t length); NXT_EXPORT nxt_int_t nxt_strcasecmp(const u_char *s1, const u_char *s2); NXT_EXPORT nxt_int_t nxt_strncasecmp(const u_char *s1, const u_char *s2, - size_t length); + size_t length); NXT_EXPORT nxt_int_t nxt_memcasecmp(const void *p1, const void *p2, - size_t length); + size_t length); NXT_EXPORT u_char *nxt_memstrn(const u_char *s, const u_char *end, - const char *ss, size_t length); + const char *ss, size_t length); NXT_EXPORT u_char *nxt_memcasestrn(const u_char *s, const u_char *end, - const char *ss, size_t length); + const char *ss, size_t length); NXT_EXPORT u_char *nxt_rmemstrn(const u_char *s, const u_char *end, - const char *ss, size_t length); + const char *ss, size_t length); NXT_EXPORT size_t nxt_str_strip(const u_char *start, u_char *end); - typedef struct { - size_t length; - u_char *start; + size_t length; + u_char *start; } nxt_str_t; +#define nxt_string(str) {nxt_length(str), (u_char *)str} +#define nxt_string_zero(str) {sizeof(str), (u_char *)str} +#define nxt_null_string {0, NULL} -#define nxt_string(str) { nxt_length(str), (u_char *) str } -#define nxt_string_zero(str) { sizeof(str), (u_char *) str } -#define nxt_null_string { 0, NULL } - - -#define nxt_str_set(str, text) \ - do { \ - (str)->length = nxt_length(text); \ - (str)->start = (u_char *) text; \ - } while (0) - - -#define nxt_str_null(str) \ - do { \ - (str)->length = 0; \ - (str)->start = NULL; \ - } while (0) +#define nxt_str_set(str, text) \ + do { \ + (str)->length = nxt_length(text); \ + (str)->start = (u_char *)text; \ + } while (0) +#define nxt_str_null(str) \ + do { \ + (str)->length = 0; \ + (str)->start = NULL; \ + } while (0) NXT_EXPORT nxt_str_t *nxt_str_alloc(nxt_mp_t *mp, size_t length); NXT_EXPORT nxt_str_t *nxt_str_dup(nxt_mp_t *mp, nxt_str_t *dst, - const nxt_str_t *src); + const nxt_str_t *src); NXT_EXPORT char *nxt_str_cstrz(nxt_mp_t *mp, const nxt_str_t *src); +#define nxt_strstr_eq(s1, s2) \ + (((s1)->length == (s2)->length) && \ + (memcmp((s1)->start, (s2)->start, (s1)->length) == 0)) -#define nxt_strstr_eq(s1, s2) \ - (((s1)->length == (s2)->length) \ - && (memcmp((s1)->start, (s2)->start, (s1)->length) == 0)) - - -#define nxt_strcasestr_eq(s1, s2) \ - (((s1)->length == (s2)->length) \ - && (nxt_memcasecmp((s1)->start, (s2)->start, (s1)->length) == 0)) +#define nxt_strcasestr_eq(s1, s2) \ + (((s1)->length == (s2)->length) && \ + (nxt_memcasecmp((s1)->start, (s2)->start, (s1)->length) == 0)) +#define nxt_str_eq(s, p, _length) \ + (((s)->length == _length) && (memcmp((s)->start, p, _length) == 0)) -#define nxt_str_eq(s, p, _length) \ - (((s)->length == _length) && (memcmp((s)->start, p, _length) == 0)) +#define nxt_str_start(s, p, _length) \ + (((s)->length >= _length) && (memcmp((s)->start, p, _length) == 0)) +#define nxt_strchr_eq(s, c) (((s)->length == 1) && ((s)->start[0] == c)) -#define nxt_str_start(s, p, _length) \ - (((s)->length >= _length) && (memcmp((s)->start, p, _length) == 0)) - - -#define nxt_strchr_eq(s, c) \ - (((s)->length == 1) && ((s)->start[0] == c)) - - -#define nxt_strchr_start(s, c) \ - (((s)->length != 0) && ((s)->start[0] == c)) - +#define nxt_strchr_start(s, c) (((s)->length != 0) && ((s)->start[0] == c)) NXT_EXPORT nxt_int_t nxt_strverscmp(const u_char *s1, const u_char *s2); NXT_EXPORT nxt_bool_t nxt_strvers_match(u_char *version, u_char *prefix, - size_t length); + size_t length); NXT_EXPORT u_char *nxt_decode_uri(u_char *dst, u_char *src, size_t length); NXT_EXPORT u_char *nxt_decode_uri_plus(u_char *dst, u_char *src, size_t length); NXT_EXPORT uintptr_t nxt_encode_uri(u_char *dst, u_char *src, size_t length); NXT_EXPORT uintptr_t nxt_encode_complex_uri(u_char *dst, u_char *src, - size_t length); + size_t length); NXT_EXPORT nxt_bool_t nxt_is_complex_uri_encoded(u_char *s, size_t length); NXT_EXPORT ssize_t nxt_base64_decode(u_char *dst, u_char *src, size_t length); -extern const uint8_t nxt_hex2int[256]; - +extern const uint8_t nxt_hex2int[256]; #endif /* _NXT_STRING_H_INCLUDED_ */ diff --git a/src/nxt_test_build.c b/src/nxt_test_build.c index aefd8c13d..6ef1f675b 100644 --- a/src/nxt_test_build.c +++ b/src/nxt_test_build.c @@ -4,150 +4,83 @@ * Copyright (C) NGINX, Inc. */ - #include - #if (NXT_TEST_BUILD_EPOLL) -int -epoll_create(int size) -{ - return -1; -} - - -int -epoll_ctl(int epfd, int op, int fd, struct epoll_event *event) -{ - return -1; -} - +int epoll_create(int size) { return -1; } -int -epoll_wait(int epfd, struct epoll_event *events, int nevents, int timeout) -{ - return -1; +int epoll_ctl(int epfd, int op, int fd, struct epoll_event *event) { + return -1; } -int -eventfd(u_int initval, int flags) -{ - return -1; +int epoll_wait(int epfd, struct epoll_event *events, int nevents, int timeout) { + return -1; } +int eventfd(u_int initval, int flags) { return -1; } -int -signalfd(int fd, const sigset_t *mask, int flags) -{ - return -1; -} - +int signalfd(int fd, const sigset_t *mask, int flags) { return -1; } -int -accept4(int sockfd, struct sockaddr *addr, socklen_t *addrlen, int flags) -{ - return -1; +int accept4(int sockfd, struct sockaddr *addr, socklen_t *addrlen, int flags) { + return -1; } #endif - #if (NXT_TEST_BUILD_EVENTPORT) -int -port_create(void) -{ - return -1; -} +int port_create(void) { return -1; } - -int -port_associate(int port, int source, uintptr_t object, int events, void *user) -{ - return -1; +int port_associate(int port, int source, uintptr_t object, int events, + void *user) { + return -1; } +int port_dissociate(int port, int source, uintptr_t object) { return -1; } -int -port_dissociate(int port, int source, uintptr_t object) -{ - return -1; -} - - -int -port_send(int port, int events, void *user) -{ - return -1; -} - +int port_send(int port, int events, void *user) { return -1; } int port_getn(int port, port_event_t list[], uint_t max, uint_t *nget, - const timespec_t *timeout) -{ - return -1; + const timespec_t *timeout) { + return -1; } #endif - #if (NXT_TEST_BUILD_POLLSET) -pollset_t -pollset_create(int maxfd) -{ - return -1; -} - +pollset_t pollset_create(int maxfd) { return -1; } -int -pollset_destroy(pollset_t ps) -{ - return -1; -} +int pollset_destroy(pollset_t ps) { return -1; } +int pollset_query(pollset_t ps, struct pollfd *pollfd_query) { return -1; } -int -pollset_query(pollset_t ps, struct pollfd *pollfd_query) -{ - return -1; +int pollset_ctl(pollset_t ps, struct poll_ctl *pollctl_array, + int array_length) { + return -1; } - -int -pollset_ctl(pollset_t ps, struct poll_ctl *pollctl_array, int array_length) -{ - return -1; -} - - -int -pollset_poll(pollset_t ps, struct pollfd *polldata_array, int array_length, - int timeout) -{ - return -1; +int pollset_poll(pollset_t ps, struct pollfd *polldata_array, int array_length, + int timeout) { + return -1; } #endif - #if (NXT_TEST_BUILD_SOLARIS_SENDFILEV) -ssize_t sendfilev(int fd, const struct sendfilevec *vec, - int sfvcnt, size_t *xferred) -{ - return -1; +ssize_t sendfilev(int fd, const struct sendfilevec *vec, int sfvcnt, + size_t *xferred) { + return -1; } #endif - #if (NXT_TEST_BUILD_AIX_SEND_FILE) -ssize_t send_file(int *s, struct sf_parms *sf_iobuf, uint_t flags) -{ - return -1; +ssize_t send_file(int *s, struct sf_parms *sf_iobuf, uint_t flags) { + return -1; } #endif diff --git a/src/nxt_test_build.h b/src/nxt_test_build.h index 6513e748f..1537baeff 100644 --- a/src/nxt_test_build.h +++ b/src/nxt_test_build.h @@ -4,81 +4,75 @@ * Copyright (C) NGINX, Inc. */ - #ifndef _NXT_UNIX_TEST_BUILD_H_INCLUDED_ #define _NXT_UNIX_TEST_BUILD_H_INCLUDED_ - #if (NXT_TEST_BUILD_EPOLL) -#define NXT_HAVE_EPOLL 1 -#define NXT_HAVE_EPOLL_EDGE 1 -#define NXT_HAVE_EVENTFD 1 -#define NXT_HAVE_SIGNALFD 1 -#define NXT_HAVE_ACCEPT4 1 +#define NXT_HAVE_EPOLL 1 +#define NXT_HAVE_EPOLL_EDGE 1 +#define NXT_HAVE_EVENTFD 1 +#define NXT_HAVE_SIGNALFD 1 +#define NXT_HAVE_ACCEPT4 1 /* Linux epoll declarations */ -#define EPOLLIN 0x00000001 -#define EPOLLPRI 0x00000002 -#define EPOLLOUT 0x00000004 -#define EPOLLERR 0x00000008 -#define EPOLLHUP 0x00000010 -#define EPOLLRDNORM 0x00000040 -#define EPOLLRDBAND 0x00000080 -#define EPOLLWRNORM 00000x0100 -#define EPOLLWRBAND 0x00000200 -#define EPOLLMSG 0x00000400 -#define EPOLLRDHUP 0x00002000 - -#define EPOLLET 0x80000000 -#define EPOLLONESHOT 0x40000000 +#define EPOLLIN 0x00000001 +#define EPOLLPRI 0x00000002 +#define EPOLLOUT 0x00000004 +#define EPOLLERR 0x00000008 +#define EPOLLHUP 0x00000010 +#define EPOLLRDNORM 0x00000040 +#define EPOLLRDBAND 0x00000080 +#define EPOLLWRNORM 00000x0100 +#define EPOLLWRBAND 0x00000200 +#define EPOLLMSG 0x00000400 +#define EPOLLRDHUP 0x00002000 -#define EPOLL_CTL_ADD 1 -#define EPOLL_CTL_DEL 2 -#define EPOLL_CTL_MOD 3 +#define EPOLLET 0x80000000 +#define EPOLLONESHOT 0x40000000 -#define EFD_SEMAPHORE 1 -#define EFD_NONBLOCK 04000 +#define EPOLL_CTL_ADD 1 +#define EPOLL_CTL_DEL 2 +#define EPOLL_CTL_MOD 3 +#define EFD_SEMAPHORE 1 +#define EFD_NONBLOCK 04000 typedef union epoll_data { - void *ptr; - int fd; - uint32_t u32; - uint64_t u64; + void *ptr; + int fd; + uint32_t u32; + uint64_t u64; } epoll_data_t; - struct epoll_event { - uint32_t events; - epoll_data_t data; + uint32_t events; + epoll_data_t data; }; - struct signalfd_siginfo { - uint32_t ssi_signo; /* Signal number */ - int32_t ssi_errno; /* Error number (unused) */ - int32_t ssi_code; /* Signal code */ - uint32_t ssi_pid; /* PID of sender */ - uint32_t ssi_uid; /* Real UID of sender */ - int32_t ssi_fd; /* File descriptor (SIGIO) */ - uint32_t ssi_tid; /* Kernel timer ID (POSIX timers) */ - uint32_t ssi_band; /* Band event (SIGIO) */ - uint32_t ssi_overrun; /* POSIX timer overrun count */ - uint32_t ssi_trapno; /* Trap number that caused signal */ - int32_t ssi_status; /* Exit status or signal (SIGCHLD) */ - int32_t ssi_int; /* Integer sent by sigqueue(2) */ - uint64_t ssi_ptr; /* Pointer sent by sigqueue(2) */ - uint64_t ssi_utime; /* User CPU time consumed (SIGCHLD) */ - uint64_t ssi_stime; /* System CPU time consumed (SIGCHLD) */ - uint64_t ssi_addr; /* Address that generated signal - (for hardware-generated signals) */ - uint8_t pad[8]; /* Pad size to 128 bytes (allow for - additional fields in the future) */ + uint32_t ssi_signo; /* Signal number */ + int32_t ssi_errno; /* Error number (unused) */ + int32_t ssi_code; /* Signal code */ + uint32_t ssi_pid; /* PID of sender */ + uint32_t ssi_uid; /* Real UID of sender */ + int32_t ssi_fd; /* File descriptor (SIGIO) */ + uint32_t ssi_tid; /* Kernel timer ID (POSIX timers) */ + uint32_t ssi_band; /* Band event (SIGIO) */ + uint32_t ssi_overrun; /* POSIX timer overrun count */ + uint32_t ssi_trapno; /* Trap number that caused signal */ + int32_t ssi_status; /* Exit status or signal (SIGCHLD) */ + int32_t ssi_int; /* Integer sent by sigqueue(2) */ + uint64_t ssi_ptr; /* Pointer sent by sigqueue(2) */ + uint64_t ssi_utime; /* User CPU time consumed (SIGCHLD) */ + uint64_t ssi_stime; /* System CPU time consumed (SIGCHLD) */ + uint64_t ssi_addr; /* Address that generated signal + (for hardware-generated signals) */ + uint8_t pad[8]; /* Pad size to 128 bytes (allow for + additional fields in the future) */ }; - int epoll_create(int size); int epoll_ctl(int epfd, int op, int fd, struct epoll_event *event); int epoll_wait(int epfd, struct epoll_event *events, int nevents, int timeout); @@ -86,189 +80,175 @@ int epoll_wait(int epfd, struct epoll_event *events, int nevents, int timeout); int eventfd(u_int initval, int flags); int signalfd(int fd, const sigset_t *mask, int flags); -#define SOCK_NONBLOCK 04000 +#define SOCK_NONBLOCK 04000 int accept4(int sockfd, struct sockaddr *addr, socklen_t *addrlen, int flags); #endif - #if (NXT_TEST_BUILD_EVENTPORT) #include -#define NXT_HAVE_EVENTPORT 1 +#define NXT_HAVE_EVENTPORT 1 -#define ushort_t u_short -#define uint_t u_int +#define ushort_t u_short +#define uint_t u_int /* Solaris eventport declarations */ -#define PORT_SOURCE_AIO 1 -#define PORT_SOURCE_TIMER 2 -#define PORT_SOURCE_USER 3 -#define PORT_SOURCE_FD 4 -#define PORT_SOURCE_ALERT 5 -#define PORT_SOURCE_MQ 6 -#define PORT_SOURCE_FILE 7 +#define PORT_SOURCE_AIO 1 +#define PORT_SOURCE_TIMER 2 +#define PORT_SOURCE_USER 3 +#define PORT_SOURCE_FD 4 +#define PORT_SOURCE_ALERT 5 +#define PORT_SOURCE_MQ 6 +#define PORT_SOURCE_FILE 7 #ifndef ETIME -#define ETIME 62 +#define ETIME 62 #endif - typedef struct { - int portev_events; /* event data is source specific */ - ushort_t portev_source; /* event source */ - ushort_t portev_pad; /* port internal use */ - uintptr_t portev_object; /* source specific object */ - void *portev_user; /* user cookie */ + int portev_events; /* event data is source specific */ + ushort_t portev_source; /* event source */ + ushort_t portev_pad; /* port internal use */ + uintptr_t portev_object; /* source specific object */ + void *portev_user; /* user cookie */ } port_event_t; - -typedef struct timespec timespec_t; -typedef struct timespec timestruc_t; - +typedef struct timespec timespec_t; +typedef struct timespec timestruc_t; typedef struct file_obj { - timestruc_t fo_atime; /* Access time from stat(2) */ - timestruc_t fo_mtime; /* Modification time from stat(2) */ - timestruc_t fo_ctime; /* Change time from stat(2) */ - uintptr_t fo_pad[3]; /* For future expansion */ - char *fo_name; /* Null terminated file name */ + timestruc_t fo_atime; /* Access time from stat(2) */ + timestruc_t fo_mtime; /* Modification time from stat(2) */ + timestruc_t fo_ctime; /* Change time from stat(2) */ + uintptr_t fo_pad[3]; /* For future expansion */ + char *fo_name; /* Null terminated file name */ } file_obj_t; - int port_create(void); int port_associate(int port, int source, uintptr_t object, int events, - void *user); + void *user); int port_dissociate(int port, int source, uintptr_t object); int port_send(int port, int events, void *user); int port_getn(int port, port_event_t list[], uint_t max, uint_t *nget, - const timespec_t *timeout); + const timespec_t *timeout); #endif - #if (NXT_TEST_BUILD_DEVPOLL) -#define NXT_HAVE_DEVPOLL 1 +#define NXT_HAVE_DEVPOLL 1 #include #include /* Solaris /dev/poll declarations */ -#define POLLREMOVE 0x0800 -#define DP_POLL 0xD001 -#define DP_ISPOLLED 0xD002 - +#define POLLREMOVE 0x0800 +#define DP_POLL 0xD001 +#define DP_ISPOLLED 0xD002 struct dvpoll { - struct pollfd *dp_fds; - int dp_nfds; - int dp_timeout; + struct pollfd *dp_fds; + int dp_nfds; + int dp_timeout; }; #endif - #if (NXT_TEST_BUILD_POLLSET) -#define NXT_HAVE_POLLSET 1 +#define NXT_HAVE_POLLSET 1 #include /* AIX pollset declarations */ -#define PS_ADD 0x0 -#define PS_MOD 0x1 -#define PS_DELETE 0x2 - +#define PS_ADD 0x0 +#define PS_MOD 0x1 +#define PS_DELETE 0x2 -typedef int pollset_t; +typedef int pollset_t; struct poll_ctl { - short cmd; - short events; - int fd; + short cmd; + short events; + int fd; }; - pollset_t pollset_create(int maxfd); int pollset_destroy(pollset_t ps); int pollset_query(pollset_t ps, struct pollfd *pollfd_query); int pollset_ctl(pollset_t ps, struct poll_ctl *pollctl_array, int array_length); int pollset_poll(pollset_t ps, struct pollfd *polldata_array, int array_length, - int timeout); + int timeout); #endif - #if (NXT_TEST_BUILD_FREEBSD_SENDFILE || NXT_TEST_BUILD_MACOSX_SENDFILE) #if !(NXT_FREEBSD) && !(NXT_MACOSX) struct sf_hdtr { - struct iovec *headers; - int hdr_cnt; - struct iovec *trailers; - int trl_cnt; + struct iovec *headers; + int hdr_cnt; + struct iovec *trailers; + int trl_cnt; }; #endif #endif - #if (NXT_TEST_BUILD_SOLARIS_SENDFILEV) /* Solaris declarations */ typedef struct sendfilevec { - int sfv_fd; - u_int sfv_flag; - off_t sfv_off; - size_t sfv_len; + int sfv_fd; + u_int sfv_flag; + off_t sfv_off; + size_t sfv_len; } sendfilevec_t; -#define SFV_FD_SELF -2 +#define SFV_FD_SELF -2 ssize_t sendfilev(int fd, const struct sendfilevec *vec, int sfvcnt, - size_t *xferred); + size_t *xferred); #endif - #if (NXT_TEST_BUILD_AIX_SEND_FILE) #ifndef uint_t -#define uint_t u_int +#define uint_t u_int #endif struct sf_parms { - void *header_data; - uint_t header_length; + void *header_data; + uint_t header_length; - int file_descriptor; - uint64_t file_size; - uint64_t file_offset; - int64_t file_bytes; + int file_descriptor; + uint64_t file_size; + uint64_t file_offset; + int64_t file_bytes; - void *trailer_data; - uint_t trailer_length; + void *trailer_data; + uint_t trailer_length; - uint64_t bytes_sent; + uint64_t bytes_sent; }; -#define SF_CLOSE 0x00000001 /* close the socket after completion */ -#define SF_REUSE 0x00000002 /* reuse socket. not supported */ -#define SF_DONT_CACHE 0x00000004 /* don't apply network buffer cache */ -#define SF_SYNC_CACHE 0x00000008 /* sync/update network buffer cache */ +#define SF_CLOSE 0x00000001 /* close the socket after completion */ +#define SF_REUSE 0x00000002 /* reuse socket. not supported */ +#define SF_DONT_CACHE 0x00000004 /* don't apply network buffer cache */ +#define SF_SYNC_CACHE 0x00000008 /* sync/update network buffer cache */ ssize_t send_file(int *s, struct sf_parms *sf_iobuf, uint_t flags); #endif - #endif /* _NXT_UNIX_TEST_BUILD_H_INCLUDED_ */ diff --git a/src/nxt_thread.c b/src/nxt_thread.c index f38047198..3c523fa10 100644 --- a/src/nxt_thread.c +++ b/src/nxt_thread.c @@ -6,262 +6,231 @@ #include - static void *nxt_thread_trampoline(void *data); static void nxt_thread_time_cleanup(void *data); - #if (NXT_HAVE_PTHREAD_SPECIFIC_DATA) static void nxt_thread_key_dtor(void *data); +void nxt_thread_init_data(nxt_thread_specific_data_t tsd) { + void *p; + nxt_err_t err; + pthread_key_t key; -void -nxt_thread_init_data(nxt_thread_specific_data_t tsd) -{ - void *p; - nxt_err_t err; - pthread_key_t key; - - while ((nxt_atomic_int_t) tsd->key < 0) { - /* - * Atomic allocation of a key number. - * -1 means an uninitialized key, - * -2 is the initializing lock to assure the single value for the key. - */ - if (nxt_atomic_cmp_set(&tsd->key, -1, -2)) { + while ((nxt_atomic_int_t)tsd->key < 0) { + /* + * Atomic allocation of a key number. + * -1 means an uninitialized key, + * -2 is the initializing lock to assure the single value for the key. + */ + if (nxt_atomic_cmp_set(&tsd->key, -1, -2)) { - err = pthread_key_create(&key, nxt_thread_key_dtor); - if (err != 0) { - nxt_main_log_alert("pthread_key_create() failed %E", err); - goto fail; - } + err = pthread_key_create(&key, nxt_thread_key_dtor); + if (err != 0) { + nxt_main_log_alert("pthread_key_create() failed %E", err); + goto fail; + } - tsd->key = (nxt_atomic_t) key; + tsd->key = (nxt_atomic_t)key; - nxt_main_log_debug("pthread_key_create(): %A", tsd->key); - } + nxt_main_log_debug("pthread_key_create(): %A", tsd->key); } + } - if (pthread_getspecific((pthread_key_t) tsd->key) != NULL) { - return; - } + if (pthread_getspecific((pthread_key_t)tsd->key) != NULL) { + return; + } - p = nxt_zalloc(tsd->size); - if (p == NULL) { - goto fail; - } + p = nxt_zalloc(tsd->size); + if (p == NULL) { + goto fail; + } - err = pthread_setspecific((pthread_key_t) tsd->key, p); - if (err == 0) { - return; - } + err = pthread_setspecific((pthread_key_t)tsd->key, p); + if (err == 0) { + return; + } - nxt_main_log_alert("pthread_setspecific(%A) failed %E", tsd->key, err); + nxt_main_log_alert("pthread_setspecific(%A) failed %E", tsd->key, err); fail: - pthread_exit(NULL); - nxt_unreachable(); + pthread_exit(NULL); + nxt_unreachable(); } +static void nxt_thread_key_dtor(void *data) { + nxt_main_log_debug("pthread key dtor: %p", data); -static void -nxt_thread_key_dtor(void *data) -{ - nxt_main_log_debug("pthread key dtor: %p", data); - - nxt_free(data); + nxt_free(data); } #endif +nxt_int_t nxt_thread_create(nxt_thread_handle_t *handle, + nxt_thread_link_t *link) { + nxt_err_t err; -nxt_int_t -nxt_thread_create(nxt_thread_handle_t *handle, nxt_thread_link_t *link) -{ - nxt_err_t err; + err = pthread_create(handle, NULL, nxt_thread_trampoline, link); - err = pthread_create(handle, NULL, nxt_thread_trampoline, link); + if (nxt_fast_path(err == 0)) { + nxt_thread_log_debug("pthread_create(): %PH", *handle); - if (nxt_fast_path(err == 0)) { - nxt_thread_log_debug("pthread_create(): %PH", *handle); + return NXT_OK; + } - return NXT_OK; - } + nxt_thread_log_alert("pthread_create() failed %E", err); - nxt_thread_log_alert("pthread_create() failed %E", err); + nxt_free(link); - nxt_free(link); - - return NXT_ERROR; + return NXT_ERROR; } +static void *nxt_thread_trampoline(void *data) { + nxt_thread_t *thr; + nxt_thread_link_t *link; + nxt_thread_start_t start; -static void * -nxt_thread_trampoline(void *data) -{ - nxt_thread_t *thr; - nxt_thread_link_t *link; - nxt_thread_start_t start; - - link = data; + link = data; - thr = nxt_thread_init(); + thr = nxt_thread_init(); - nxt_log_debug(thr->log, "thread trampoline: %PH", thr->handle); + nxt_log_debug(thr->log, "thread trampoline: %PH", thr->handle); - pthread_cleanup_push(nxt_thread_time_cleanup, thr); + pthread_cleanup_push(nxt_thread_time_cleanup, thr); - start = link->start; - data = link->work.data; + start = link->start; + data = link->work.data; - if (link->work.handler != NULL) { - thr->link = link; + if (link->work.handler != NULL) { + thr->link = link; - } else { - nxt_free(link); - } + } else { + nxt_free(link); + } - start(data); + start(data); - /* - * nxt_thread_time_cleanup() should be called only if a thread - * would be canceled, so ignore it here because nxt_thread_exit() - * calls nxt_thread_time_free() as well. - */ - pthread_cleanup_pop(0); + /* + * nxt_thread_time_cleanup() should be called only if a thread + * would be canceled, so ignore it here because nxt_thread_exit() + * calls nxt_thread_time_free() as well. + */ + pthread_cleanup_pop(0); - nxt_thread_exit(thr); - nxt_unreachable(); - return NULL; + nxt_thread_exit(thr); + nxt_unreachable(); + return NULL; } +nxt_thread_t *nxt_thread_init(void) { + nxt_thread_t *thr; -nxt_thread_t * -nxt_thread_init(void) -{ - nxt_thread_t *thr; - - nxt_thread_init_data(nxt_thread_context); + nxt_thread_init_data(nxt_thread_context); - thr = nxt_thread(); + thr = nxt_thread(); - if (thr->log == NULL) { - thr->log = &nxt_main_log; - thr->handle = nxt_thread_handle(); + if (thr->log == NULL) { + thr->log = &nxt_main_log; + thr->handle = nxt_thread_handle(); - /* - * Threads are never preempted by asynchronous signals, since - * the signals are processed synchronously by dedicated thread. - */ - thr->time.signal = -1; + /* + * Threads are never preempted by asynchronous signals, since + * the signals are processed synchronously by dedicated thread. + */ + thr->time.signal = -1; - nxt_thread_time_update(thr); - } + nxt_thread_time_update(thr); + } - nxt_random_init(&thr->random); + nxt_random_init(&thr->random); - return thr; + return thr; } +static void nxt_thread_time_cleanup(void *data) { + nxt_thread_t *thr; -static void -nxt_thread_time_cleanup(void *data) -{ - nxt_thread_t *thr; + thr = data; - thr = data; + nxt_log_debug(thr->log, "thread time cleanup"); - nxt_log_debug(thr->log, "thread time cleanup"); - - nxt_thread_time_free(thr); + nxt_thread_time_free(thr); } +void nxt_thread_exit(nxt_thread_t *thr) { + nxt_thread_link_t *link; + nxt_event_engine_t *engine; -void -nxt_thread_exit(nxt_thread_t *thr) -{ - nxt_thread_link_t *link; - nxt_event_engine_t *engine; - - nxt_log_debug(thr->log, "thread exit"); + nxt_log_debug(thr->log, "thread exit"); - link = thr->link; - thr->link = NULL; + link = thr->link; + thr->link = NULL; - if (link != NULL) { - /* - * link->work.handler is already set to an exit handler, - * and link->work.task is already set to the correct engine->task. - * The link should be freed by the exit handler. - */ - link->work.obj = (void *) (uintptr_t) thr->handle; - engine = nxt_container_of(link->work.task, nxt_event_engine_t, task); + if (link != NULL) { + /* + * link->work.handler is already set to an exit handler, + * and link->work.task is already set to the correct engine->task. + * The link should be freed by the exit handler. + */ + link->work.obj = (void *)(uintptr_t)thr->handle; + engine = nxt_container_of(link->work.task, nxt_event_engine_t, task); - nxt_event_engine_post(engine, &link->work); - } + nxt_event_engine_post(engine, &link->work); + } - nxt_thread_time_free(thr); + nxt_thread_time_free(thr); - pthread_exit(NULL); - nxt_unreachable(); + pthread_exit(NULL); + nxt_unreachable(); } +void nxt_thread_cancel(nxt_thread_handle_t handle) { + nxt_err_t err; -void -nxt_thread_cancel(nxt_thread_handle_t handle) -{ - nxt_err_t err; + nxt_thread_log_debug("thread cancel: %PH", handle); - nxt_thread_log_debug("thread cancel: %PH", handle); + err = pthread_cancel(handle); - err = pthread_cancel(handle); - - if (err != 0) { - nxt_main_log_alert("pthread_cancel(%PH) failed %E", handle, err); - } + if (err != 0) { + nxt_main_log_alert("pthread_cancel(%PH) failed %E", handle, err); + } } +void nxt_thread_wait(nxt_thread_handle_t handle) { + nxt_err_t err; -void -nxt_thread_wait(nxt_thread_handle_t handle) -{ - nxt_err_t err; + nxt_thread_log_debug("thread wait: %PH", handle); - nxt_thread_log_debug("thread wait: %PH", handle); + err = pthread_join(handle, NULL); - err = pthread_join(handle, NULL); - - if (err != 0) { - nxt_main_log_alert("pthread_join(%PH) failed %E", handle, err); - } + if (err != 0) { + nxt_main_log_alert("pthread_join(%PH) failed %E", handle, err); + } } - -nxt_tid_t -nxt_thread_tid(nxt_thread_t *thr) -{ +nxt_tid_t nxt_thread_tid(nxt_thread_t *thr) { #if (NXT_HAVE_THREAD_STORAGE_CLASS) - if (nxt_slow_path(thr->tid == 0)) { - thr->tid = nxt_thread_get_tid(); - } + if (nxt_slow_path(thr->tid == 0)) { + thr->tid = nxt_thread_get_tid(); + } - return thr->tid; + return thr->tid; #else - if (nxt_fast_path(thr != NULL)) { - - if (nxt_slow_path(thr->tid == 0)) { - thr->tid = nxt_thread_get_tid(); - } + if (nxt_fast_path(thr != NULL)) { - return thr->tid; + if (nxt_slow_path(thr->tid == 0)) { + thr->tid = nxt_thread_get_tid(); } - return nxt_thread_get_tid(); + return thr->tid; + } + + return nxt_thread_get_tid(); #endif } diff --git a/src/nxt_thread.h b/src/nxt_thread.h index 53b2d8c0f..63c449577 100644 --- a/src/nxt_thread.h +++ b/src/nxt_thread.h @@ -7,7 +7,6 @@ #ifndef _NXT_UNIX_THREAD_H_INCLUDED_ #define _NXT_UNIX_THREAD_H_INCLUDED_ - /* * Thread Specific Data * @@ -30,17 +29,13 @@ #if (NXT_HAVE_THREAD_STORAGE_CLASS) -#define nxt_thread_extern_data(type, tsd) \ - NXT_EXPORT extern __thread type tsd +#define nxt_thread_extern_data(type, tsd) NXT_EXPORT extern __thread type tsd -#define nxt_thread_declare_data(type, tsd) \ - __thread type tsd +#define nxt_thread_declare_data(type, tsd) __thread type tsd #define nxt_thread_init_data(tsd) -#define nxt_thread_get_data(tsd) \ - &tsd - +#define nxt_thread_get_data(tsd) &tsd #else /* NXT_HAVE_PTHREAD_SPECIFIC_DATA */ @@ -58,47 +53,40 @@ */ typedef struct { - nxt_atomic_t key; - size_t size; + nxt_atomic_t key; + size_t size; } nxt_thread_specific_data_t[1]; +#define nxt_thread_extern_data(type, tsd) \ + NXT_EXPORT extern nxt_thread_specific_data_t tsd -#define nxt_thread_extern_data(type, tsd) \ - NXT_EXPORT extern nxt_thread_specific_data_t tsd - -#define nxt_thread_declare_data(type, tsd) \ - nxt_thread_specific_data_t tsd = { { (nxt_atomic_int_t) -1, sizeof(type) } } +#define nxt_thread_declare_data(type, tsd) \ + nxt_thread_specific_data_t tsd = {{(nxt_atomic_int_t) - 1, sizeof(type)}} NXT_EXPORT void nxt_thread_init_data(nxt_thread_specific_data_t tsd); -#define nxt_thread_get_data(tsd) \ - pthread_getspecific((pthread_key_t) tsd->key) +#define nxt_thread_get_data(tsd) pthread_getspecific((pthread_key_t)tsd->key) #endif - typedef void (*nxt_thread_start_t)(void *data); typedef struct { - nxt_thread_start_t start; - nxt_event_engine_t *engine; - nxt_work_t work; + nxt_thread_start_t start; + nxt_event_engine_t *engine; + nxt_work_t work; } nxt_thread_link_t; - NXT_EXPORT nxt_int_t nxt_thread_create(nxt_thread_handle_t *handle, - nxt_thread_link_t *link); + nxt_thread_link_t *link); NXT_EXPORT nxt_thread_t *nxt_thread_init(void); NXT_EXPORT void nxt_thread_exit(nxt_thread_t *thr); NXT_EXPORT void nxt_thread_cancel(nxt_thread_handle_t handle); NXT_EXPORT void nxt_thread_wait(nxt_thread_handle_t handle); +#define nxt_thread_handle() pthread_self() -#define nxt_thread_handle() \ - pthread_self() - - -typedef pthread_mutex_t nxt_thread_mutex_t; +typedef pthread_mutex_t nxt_thread_mutex_t; NXT_EXPORT nxt_int_t nxt_thread_mutex_create(nxt_thread_mutex_t *mtx); NXT_EXPORT void nxt_thread_mutex_destroy(nxt_thread_mutex_t *mtx); @@ -106,47 +94,42 @@ NXT_EXPORT nxt_int_t nxt_thread_mutex_lock(nxt_thread_mutex_t *mtx); NXT_EXPORT nxt_bool_t nxt_thread_mutex_trylock(nxt_thread_mutex_t *mtx); NXT_EXPORT nxt_int_t nxt_thread_mutex_unlock(nxt_thread_mutex_t *mtx); - -typedef pthread_cond_t nxt_thread_cond_t; +typedef pthread_cond_t nxt_thread_cond_t; NXT_EXPORT nxt_int_t nxt_thread_cond_create(nxt_thread_cond_t *cond); NXT_EXPORT void nxt_thread_cond_destroy(nxt_thread_cond_t *cond); NXT_EXPORT nxt_int_t nxt_thread_cond_signal(nxt_thread_cond_t *cond); NXT_EXPORT nxt_err_t nxt_thread_cond_wait(nxt_thread_cond_t *cond, - nxt_thread_mutex_t *mtx, nxt_nsec_t timeout); - + nxt_thread_mutex_t *mtx, + nxt_nsec_t timeout); #if (NXT_HAVE_PTHREAD_YIELD) -#define nxt_thread_yield() \ - pthread_yield() +#define nxt_thread_yield() pthread_yield() #elif (NXT_HAVE_PTHREAD_YIELD_NP) -#define nxt_thread_yield() \ - pthread_yield_np() +#define nxt_thread_yield() pthread_yield_np() #else -#define nxt_thread_yield() \ - nxt_sched_yield() +#define nxt_thread_yield() nxt_sched_yield() #endif - struct nxt_thread_s { - nxt_log_t *log; - nxt_log_t main_log; + nxt_log_t *log; + nxt_log_t main_log; - nxt_task_t *task; + nxt_task_t *task; - nxt_tid_t tid; - nxt_thread_handle_t handle; - nxt_thread_link_t *link; - nxt_thread_pool_t *thread_pool; + nxt_tid_t tid; + nxt_thread_handle_t handle; + nxt_thread_link_t *link; + nxt_thread_pool_t *thread_pool; - nxt_thread_time_t time; + nxt_thread_time_t time; - nxt_runtime_t *runtime; - nxt_event_engine_t *engine; - void *data; + nxt_runtime_t *runtime; + nxt_event_engine_t *engine; + void *data; #if 0 /* @@ -156,8 +139,7 @@ struct nxt_thread_s { nxt_fiber_t *fiber; #endif - nxt_random_t random; + nxt_random_t random; }; - #endif /* _NXT_UNIX_THREAD_H_INCLUDED_ */ diff --git a/src/nxt_thread_cond.c b/src/nxt_thread_cond.c index fcd108e4a..e3b6d6e96 100644 --- a/src/nxt_thread_cond.c +++ b/src/nxt_thread_cond.c @@ -6,102 +6,89 @@ #include +nxt_int_t nxt_thread_cond_create(nxt_thread_cond_t *cond) { + nxt_err_t err; -nxt_int_t -nxt_thread_cond_create(nxt_thread_cond_t *cond) -{ - nxt_err_t err; + err = pthread_cond_init(cond, NULL); + if (err == 0) { + nxt_thread_log_debug("pthread_cond_init(%p)", cond); + return NXT_OK; + } - err = pthread_cond_init(cond, NULL); - if (err == 0) { - nxt_thread_log_debug("pthread_cond_init(%p)", cond); - return NXT_OK; - } - - nxt_thread_log_alert("pthread_cond_init() failed %E", err); - return NXT_ERROR; + nxt_thread_log_alert("pthread_cond_init() failed %E", err); + return NXT_ERROR; } +void nxt_thread_cond_destroy(nxt_thread_cond_t *cond) { + nxt_err_t err; -void -nxt_thread_cond_destroy(nxt_thread_cond_t *cond) -{ - nxt_err_t err; - - err = pthread_cond_destroy(cond); - if (err != 0) { - nxt_thread_log_alert("pthread_cond_destroy() failed %E", err); - } + err = pthread_cond_destroy(cond); + if (err != 0) { + nxt_thread_log_alert("pthread_cond_destroy() failed %E", err); + } - nxt_thread_log_debug("pthread_cond_destroy(%p)", cond); + nxt_thread_log_debug("pthread_cond_destroy(%p)", cond); } +nxt_int_t nxt_thread_cond_signal(nxt_thread_cond_t *cond) { + nxt_err_t err; -nxt_int_t -nxt_thread_cond_signal(nxt_thread_cond_t *cond) -{ - nxt_err_t err; - - err = pthread_cond_signal(cond); - if (nxt_fast_path(err == 0)) { - nxt_thread_log_debug("pthread_cond_signal(%p)", cond); - return NXT_OK; - } + err = pthread_cond_signal(cond); + if (nxt_fast_path(err == 0)) { + nxt_thread_log_debug("pthread_cond_signal(%p)", cond); + return NXT_OK; + } - nxt_thread_log_alert("pthread_cond_signal() failed %E", err); + nxt_thread_log_alert("pthread_cond_signal() failed %E", err); - return NXT_ERROR; + return NXT_ERROR; } +nxt_err_t nxt_thread_cond_wait(nxt_thread_cond_t *cond, nxt_thread_mutex_t *mtx, + nxt_nsec_t timeout) { + nxt_err_t err; + nxt_nsec_t ns; + nxt_thread_t *thr; + nxt_realtime_t *now; + struct timespec ts; -nxt_err_t -nxt_thread_cond_wait(nxt_thread_cond_t *cond, nxt_thread_mutex_t *mtx, - nxt_nsec_t timeout) -{ - nxt_err_t err; - nxt_nsec_t ns; - nxt_thread_t *thr; - nxt_realtime_t *now; - struct timespec ts; - - thr = nxt_thread(); - - if (timeout == NXT_INFINITE_NSEC) { - nxt_log_debug(thr->log, "pthread_cond_wait(%p) enter", cond); + thr = nxt_thread(); - err = pthread_cond_wait(cond, mtx); + if (timeout == NXT_INFINITE_NSEC) { + nxt_log_debug(thr->log, "pthread_cond_wait(%p) enter", cond); - nxt_thread_time_update(thr); + err = pthread_cond_wait(cond, mtx); - if (nxt_fast_path(err == 0)) { - nxt_log_debug(thr->log, "pthread_cond_wait(%p) exit", cond); - return 0; - } + nxt_thread_time_update(thr); - nxt_log_alert(thr->log, "pthread_cond_wait() failed %E", err); + if (nxt_fast_path(err == 0)) { + nxt_log_debug(thr->log, "pthread_cond_wait(%p) exit", cond); + return 0; + } - } else { - nxt_log_debug(thr->log, "pthread_cond_timedwait(%p, %N) enter", - cond, timeout); + nxt_log_alert(thr->log, "pthread_cond_wait() failed %E", err); - now = nxt_thread_realtime(thr); + } else { + nxt_log_debug(thr->log, "pthread_cond_timedwait(%p, %N) enter", cond, + timeout); - ns = now->nsec + timeout; - ts.tv_sec = now->sec + ns / 1000000000; - ts.tv_nsec = ns % 1000000000; + now = nxt_thread_realtime(thr); - err = pthread_cond_timedwait(cond, mtx, &ts); + ns = now->nsec + timeout; + ts.tv_sec = now->sec + ns / 1000000000; + ts.tv_nsec = ns % 1000000000; - nxt_thread_time_update(thr); + err = pthread_cond_timedwait(cond, mtx, &ts); - if (nxt_fast_path(err == 0 || err == NXT_ETIMEDOUT)) { - nxt_log_debug(thr->log, "pthread_cond_timedwait(%p) exit: %d", - cond, err); - return err; - } + nxt_thread_time_update(thr); - nxt_log_alert(thr->log, "pthread_cond_timedwait() failed %E", err); + if (nxt_fast_path(err == 0 || err == NXT_ETIMEDOUT)) { + nxt_log_debug(thr->log, "pthread_cond_timedwait(%p) exit: %d", cond, err); + return err; } - return NXT_ERROR; + nxt_log_alert(thr->log, "pthread_cond_timedwait() failed %E", err); + } + + return NXT_ERROR; } diff --git a/src/nxt_thread_id.h b/src/nxt_thread_id.h index 764c99344..a01a95a7c 100644 --- a/src/nxt_thread_id.h +++ b/src/nxt_thread_id.h @@ -7,7 +7,6 @@ #ifndef _NXT_UNIX_THREAD_ID_H_INCLUDED_ #define _NXT_UNIX_THREAD_ID_H_INCLUDED_ - #if (NXT_LINUX) /* @@ -15,13 +14,9 @@ * glibc does not provide a wrapper for gettid(). */ -typedef pid_t nxt_tid_t; +typedef pid_t nxt_tid_t; -nxt_inline nxt_tid_t -nxt_thread_get_tid(void) -{ - return syscall(SYS_gettid); -} +nxt_inline nxt_tid_t nxt_thread_get_tid(void) { return syscall(SYS_gettid); } #elif (NXT_FREEBSD) @@ -32,25 +27,19 @@ nxt_thread_get_tid(void) * Thread id is a number above 100,000. */ -typedef uint32_t nxt_tid_t; +typedef uint32_t nxt_tid_t; -nxt_inline nxt_tid_t -nxt_thread_get_tid(void) -{ - return (uint32_t) (*(long *) pthread_self()); +nxt_inline nxt_tid_t nxt_thread_get_tid(void) { + return (uint32_t)(*(long *)pthread_self()); } #elif (NXT_SOLARIS) /* Solaris pthread_t are numbers starting with 1. */ -typedef pthread_t nxt_tid_t; +typedef pthread_t nxt_tid_t; -nxt_inline nxt_tid_t -nxt_thread_get_tid(void) -{ - return pthread_self(); -} +nxt_inline nxt_tid_t nxt_thread_get_tid(void) { return pthread_self(); } #elif (NXT_MACOSX) @@ -62,15 +51,13 @@ nxt_thread_get_tid(void) * syscall. It is a number above 300,000. */ -typedef uint64_t nxt_tid_t; +typedef uint64_t nxt_tid_t; -nxt_inline nxt_tid_t -nxt_thread_get_tid(void) -{ - uint64_t tid; +nxt_inline nxt_tid_t nxt_thread_get_tid(void) { + uint64_t tid; - (void) pthread_threadid_np(NULL, &tid); - return tid; + (void)pthread_threadid_np(NULL, &tid); + return tid; } /* @@ -82,15 +69,11 @@ nxt_thread_get_tid(void) #elif (NXT_OPENBSD) -typedef pid_t nxt_tid_t; +typedef pid_t nxt_tid_t; /* OpenBSD 3.9 getthrid(). */ -nxt_inline nxt_tid_t -nxt_thread_get_tid(void) -{ - return getthrid(); -} +nxt_inline nxt_tid_t nxt_thread_get_tid(void) { return getthrid(); } #elif (NXT_AIX) @@ -102,28 +85,26 @@ nxt_thread_get_tid(void) * shown in "ps -ef -m -o THREAD" output. */ -typedef tid_t nxt_tid_t; +typedef tid_t nxt_tid_t; -nxt_inline nxt_tid_t -nxt_thread_get_tid(void) -{ - int err, size; - pthread_t pt; - struct __pthrdsinfo ti; +nxt_inline nxt_tid_t nxt_thread_get_tid(void) { + int err, size; + pthread_t pt; + struct __pthrdsinfo ti; - size = 0; - pt = pthread_self(); + size = 0; + pt = pthread_self(); - err = pthread_getthrds_np(&pt, PTHRDSINFO_QUERY_TID, &ti, + err = pthread_getthrds_np(&pt, PTHRDSINFO_QUERY_TID, &ti, sizeof(struct __pthrdsinfo), NULL, size); - if (nxt_fast_path(err == 0)) { - return ti.__pi_tid; - } + if (nxt_fast_path(err == 0)) { + return ti.__pi_tid; + } - nxt_main_log_alert("pthread_getthrds_np(PTHRDSINFO_QUERY_TID) failed %E", - err); - return 0; + nxt_main_log_alert("pthread_getthrds_np(PTHRDSINFO_QUERY_TID) failed %E", + err); + return 0; } /* @@ -144,30 +125,20 @@ nxt_thread_get_tid(void) /* HP-UX pthread_t are numbers starting with 1. */ -typedef pthread_t nxt_tid_t; +typedef pthread_t nxt_tid_t; -nxt_inline nxt_tid_t -nxt_thread_get_tid(void) -{ - return pthread_self(); -} +nxt_inline nxt_tid_t nxt_thread_get_tid(void) { return pthread_self(); } #else -typedef pthread_t nxt_tid_t; +typedef pthread_t nxt_tid_t; -nxt_inline nxt_tid_t -nxt_thread_get_tid(void) -{ - return pthread_self(); -} +nxt_inline nxt_tid_t nxt_thread_get_tid(void) { return pthread_self(); } #endif - NXT_EXPORT nxt_tid_t nxt_thread_tid(nxt_thread_t *thr); - /* * On Linux pthread_t is unsigned long integer. * On FreeBSD, MacOSX, NetBSD, and OpenBSD pthread_t is pointer to a struct. @@ -176,14 +147,10 @@ NXT_EXPORT nxt_tid_t nxt_thread_tid(nxt_thread_t *thr); * On Cygwin pthread_t is pointer to void. * On z/OS pthread_t is "struct { char __[0x08]; }". */ -typedef pthread_t nxt_thread_handle_t; - - -#define nxt_thread_handle_clear(th) \ - th = (pthread_t) 0 +typedef pthread_t nxt_thread_handle_t; -#define nxt_thread_handle_equal(th0, th1) \ - pthread_equal(th0, th1) +#define nxt_thread_handle_clear(th) th = (pthread_t)0 +#define nxt_thread_handle_equal(th0, th1) pthread_equal(th0, th1) #endif /* _NXT_UNIX_THREAD_ID_H_INCLUDED_ */ diff --git a/src/nxt_thread_log.h b/src/nxt_thread_log.h index 214098ffa..b2879b0a3 100644 --- a/src/nxt_thread_log.h +++ b/src/nxt_thread_log.h @@ -7,38 +7,33 @@ #ifndef _NXT_THREAD_LOG_H_INCLUDED_ #define _NXT_THREAD_LOG_H_INCLUDED_ - -#define nxt_thread_log_alert(...) \ - do { \ - nxt_thread_t *_thr = nxt_thread(); \ - \ - nxt_log_alert(_thr->log, __VA_ARGS__); \ - \ - } while (0) - - -#define nxt_thread_log_error(_level, ...) \ - do { \ - nxt_thread_t *_thr = nxt_thread(); \ - \ - nxt_log_error(_level, _thr->log, __VA_ARGS__); \ - \ - } while (0) - +#define nxt_thread_log_alert(...) \ + do { \ + nxt_thread_t *_thr = nxt_thread(); \ + \ + nxt_log_alert(_thr->log, __VA_ARGS__); \ + \ + } while (0) + +#define nxt_thread_log_error(_level, ...) \ + do { \ + nxt_thread_t *_thr = nxt_thread(); \ + \ + nxt_log_error(_level, _thr->log, __VA_ARGS__); \ + \ + } while (0) #if (NXT_DEBUG) -#define nxt_thread_log_debug(...) \ - do { \ - nxt_thread_t *_thr = nxt_thread(); \ - \ - nxt_log_debug(_thr->log, __VA_ARGS__); \ - \ - } while (0) +#define nxt_thread_log_debug(...) \ + do { \ + nxt_thread_t *_thr = nxt_thread(); \ + \ + nxt_log_debug(_thr->log, __VA_ARGS__); \ + \ + } while (0) - -#define nxt_thread_debug(thr) \ - nxt_thread_t *thr = nxt_thread() +#define nxt_thread_debug(thr) nxt_thread_t *thr = nxt_thread() #else @@ -47,15 +42,11 @@ #endif +nxt_inline nxt_log_t *nxt_thread_log(void) { + nxt_thread_t *thr; -nxt_inline nxt_log_t * -nxt_thread_log(void) -{ - nxt_thread_t *thr; - - thr = nxt_thread(); - return thr->log; + thr = nxt_thread(); + return thr->log; } - #endif /* _NXT_THREAD_LOG_H_INCLUDED_ */ diff --git a/src/nxt_thread_mutex.c b/src/nxt_thread_mutex.c index 472a69f05..f35e1bb3f 100644 --- a/src/nxt_thread_mutex.c +++ b/src/nxt_thread_mutex.c @@ -6,7 +6,6 @@ #include - /* * All modern pthread mutex implementations try to acquire a lock atomically * in userland before going to sleep in kernel. Some spins on SMP systems @@ -76,117 +75,103 @@ * MacOSX: PTHREAD_MUTEX_NORMAL. */ +nxt_int_t nxt_thread_mutex_create(nxt_thread_mutex_t *mtx) { + nxt_err_t err; + pthread_mutexattr_t attr; -nxt_int_t -nxt_thread_mutex_create(nxt_thread_mutex_t *mtx) -{ - nxt_err_t err; - pthread_mutexattr_t attr; - - err = pthread_mutexattr_init(&attr); - if (err != 0) { - nxt_thread_log_alert("pthread_mutexattr_init() failed %E", err); - return NXT_ERROR; - } + err = pthread_mutexattr_init(&attr); + if (err != 0) { + nxt_thread_log_alert("pthread_mutexattr_init() failed %E", err); + return NXT_ERROR; + } - err = pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_ERRORCHECK); - if (err != 0) { - nxt_thread_log_alert("pthread_mutexattr_settype" - "(PTHREAD_MUTEX_ERRORCHECK) failed %E", err); - return NXT_ERROR; - } + err = pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_ERRORCHECK); + if (err != 0) { + nxt_thread_log_alert("pthread_mutexattr_settype" + "(PTHREAD_MUTEX_ERRORCHECK) failed %E", + err); + return NXT_ERROR; + } - err = pthread_mutex_init(mtx, &attr); - if (err != 0) { - nxt_thread_log_alert("pthread_mutex_init() failed %E", err); - return NXT_ERROR; - } + err = pthread_mutex_init(mtx, &attr); + if (err != 0) { + nxt_thread_log_alert("pthread_mutex_init() failed %E", err); + return NXT_ERROR; + } - err = pthread_mutexattr_destroy(&attr); - if (err != 0) { - nxt_thread_log_alert("pthread_mutexattr_destroy() failed %E", err); - } + err = pthread_mutexattr_destroy(&attr); + if (err != 0) { + nxt_thread_log_alert("pthread_mutexattr_destroy() failed %E", err); + } - nxt_thread_log_debug("pthread_mutex_init(%p)", mtx); + nxt_thread_log_debug("pthread_mutex_init(%p)", mtx); - return NXT_OK; + return NXT_OK; } +void nxt_thread_mutex_destroy(nxt_thread_mutex_t *mtx) { + nxt_err_t err; -void -nxt_thread_mutex_destroy(nxt_thread_mutex_t *mtx) -{ - nxt_err_t err; - - err = pthread_mutex_destroy(mtx); - if (nxt_slow_path(err != 0)) { - nxt_thread_log_alert("pthread_mutex_destroy() failed %E", err); - } + err = pthread_mutex_destroy(mtx); + if (nxt_slow_path(err != 0)) { + nxt_thread_log_alert("pthread_mutex_destroy() failed %E", err); + } - nxt_thread_log_debug("pthread_mutex_destroy(%p)", mtx); + nxt_thread_log_debug("pthread_mutex_destroy(%p)", mtx); } +nxt_int_t nxt_thread_mutex_lock(nxt_thread_mutex_t *mtx) { + nxt_err_t err; -nxt_int_t -nxt_thread_mutex_lock(nxt_thread_mutex_t *mtx) -{ - nxt_err_t err; + nxt_thread_log_debug("pthread_mutex_lock(%p) enter", mtx); - nxt_thread_log_debug("pthread_mutex_lock(%p) enter", mtx); - - err = pthread_mutex_lock(mtx); - if (nxt_fast_path(err == 0)) { - return NXT_OK; - } + err = pthread_mutex_lock(mtx); + if (nxt_fast_path(err == 0)) { + return NXT_OK; + } - nxt_thread_log_alert("pthread_mutex_lock() failed %E", err); + nxt_thread_log_alert("pthread_mutex_lock() failed %E", err); - return NXT_ERROR; + return NXT_ERROR; } +nxt_bool_t nxt_thread_mutex_trylock(nxt_thread_mutex_t *mtx) { + nxt_err_t err; -nxt_bool_t -nxt_thread_mutex_trylock(nxt_thread_mutex_t *mtx) -{ - nxt_err_t err; - - nxt_thread_debug(thr); + nxt_thread_debug(thr); - nxt_log_debug(thr->log, "pthread_mutex_trylock(%p) enter", mtx); + nxt_log_debug(thr->log, "pthread_mutex_trylock(%p) enter", mtx); - err = pthread_mutex_trylock(mtx); - if (nxt_fast_path(err == 0)) { - return 1; - } + err = pthread_mutex_trylock(mtx); + if (nxt_fast_path(err == 0)) { + return 1; + } - if (err == NXT_EBUSY) { - nxt_log_debug(thr->log, "pthread_mutex_trylock(%p) failed", mtx); + if (err == NXT_EBUSY) { + nxt_log_debug(thr->log, "pthread_mutex_trylock(%p) failed", mtx); - } else { - nxt_thread_log_alert("pthread_mutex_trylock() failed %E", err); - } + } else { + nxt_thread_log_alert("pthread_mutex_trylock() failed %E", err); + } - return 0; + return 0; } +nxt_int_t nxt_thread_mutex_unlock(nxt_thread_mutex_t *mtx) { + nxt_err_t err; + nxt_thread_t *thr; -nxt_int_t -nxt_thread_mutex_unlock(nxt_thread_mutex_t *mtx) -{ - nxt_err_t err; - nxt_thread_t *thr; + err = pthread_mutex_unlock(mtx); - err = pthread_mutex_unlock(mtx); + thr = nxt_thread(); + nxt_thread_time_update(thr); - thr = nxt_thread(); - nxt_thread_time_update(thr); - - if (nxt_fast_path(err == 0)) { - nxt_log_debug(thr->log, "pthread_mutex_unlock(%p) exit", mtx); - return NXT_OK; - } + if (nxt_fast_path(err == 0)) { + nxt_log_debug(thr->log, "pthread_mutex_unlock(%p) exit", mtx); + return NXT_OK; + } - nxt_log_alert(thr->log, "pthread_mutex_unlock() failed %E", err); + nxt_log_alert(thr->log, "pthread_mutex_unlock() failed %E", err); - return NXT_ERROR; + return NXT_ERROR; } diff --git a/src/nxt_thread_pool.c b/src/nxt_thread_pool.c index 0be2ddc06..bebddd9f6 100644 --- a/src/nxt_thread_pool.c +++ b/src/nxt_thread_pool.c @@ -6,252 +6,230 @@ #include - static nxt_int_t nxt_thread_pool_init(nxt_thread_pool_t *tp); static void nxt_thread_pool_exit(nxt_task_t *task, void *obj, void *data); static void nxt_thread_pool_start(void *ctx); static void nxt_thread_pool_loop(void *ctx); static void nxt_thread_pool_wait(nxt_thread_pool_t *tp); - -nxt_thread_pool_t * -nxt_thread_pool_create(nxt_uint_t max_threads, nxt_nsec_t timeout, - nxt_thread_pool_init_t init, nxt_event_engine_t *engine, - nxt_work_handler_t exit) -{ - nxt_thread_pool_t *tp; - - tp = nxt_zalloc(sizeof(nxt_thread_pool_t)); - if (tp == NULL) { - return NULL; - } - - tp->max_threads = max_threads; - tp->timeout = timeout; - tp->engine = engine; - tp->task.thread = engine->task.thread; - tp->task.log = engine->task.log; - tp->init = init; - tp->exit = exit; - - return tp; +nxt_thread_pool_t *nxt_thread_pool_create(nxt_uint_t max_threads, + nxt_nsec_t timeout, + nxt_thread_pool_init_t init, + nxt_event_engine_t *engine, + nxt_work_handler_t exit) { + nxt_thread_pool_t *tp; + + tp = nxt_zalloc(sizeof(nxt_thread_pool_t)); + if (tp == NULL) { + return NULL; + } + + tp->max_threads = max_threads; + tp->timeout = timeout; + tp->engine = engine; + tp->task.thread = engine->task.thread; + tp->task.log = engine->task.log; + tp->init = init; + tp->exit = exit; + + return tp; } +nxt_int_t nxt_thread_pool_post(nxt_thread_pool_t *tp, nxt_work_t *work) { + nxt_thread_log_debug("thread pool post"); -nxt_int_t -nxt_thread_pool_post(nxt_thread_pool_t *tp, nxt_work_t *work) -{ - nxt_thread_log_debug("thread pool post"); + if (nxt_slow_path(nxt_thread_pool_init(tp) != NXT_OK)) { + return NXT_ERROR; + } - if (nxt_slow_path(nxt_thread_pool_init(tp) != NXT_OK)) { - return NXT_ERROR; - } - - nxt_locked_work_queue_add(&tp->work_queue, work); + nxt_locked_work_queue_add(&tp->work_queue, work); - (void) nxt_sem_post(&tp->sem); + (void)nxt_sem_post(&tp->sem); - return NXT_OK; + return NXT_OK; } +static nxt_int_t nxt_thread_pool_init(nxt_thread_pool_t *tp) { + nxt_int_t ret; + nxt_thread_link_t *link; + nxt_thread_handle_t handle; -static nxt_int_t -nxt_thread_pool_init(nxt_thread_pool_t *tp) -{ - nxt_int_t ret; - nxt_thread_link_t *link; - nxt_thread_handle_t handle; - - if (nxt_fast_path(tp->ready)) { - return NXT_OK; - } - - if (tp->max_threads == 0) { - /* The pool is being destroyed. */ - return NXT_ERROR; - } + if (nxt_fast_path(tp->ready)) { + return NXT_OK; + } - nxt_thread_spin_lock(&tp->work_queue.lock); + if (tp->max_threads == 0) { + /* The pool is being destroyed. */ + return NXT_ERROR; + } - ret = NXT_OK; + nxt_thread_spin_lock(&tp->work_queue.lock); - if (!tp->ready) { + ret = NXT_OK; - nxt_thread_log_debug("thread pool init"); + if (!tp->ready) { - (void) nxt_atomic_fetch_add(&tp->threads, 1); + nxt_thread_log_debug("thread pool init"); - if (nxt_fast_path(nxt_sem_init(&tp->sem, 0) == NXT_OK)) { + (void)nxt_atomic_fetch_add(&tp->threads, 1); - link = nxt_zalloc(sizeof(nxt_thread_link_t)); + if (nxt_fast_path(nxt_sem_init(&tp->sem, 0) == NXT_OK)) { - if (nxt_fast_path(link != NULL)) { - link->start = nxt_thread_pool_start; - link->work.data = tp; + link = nxt_zalloc(sizeof(nxt_thread_link_t)); - if (nxt_thread_create(&handle, link) == NXT_OK) { - tp->ready = 1; - goto done; - } - } + if (nxt_fast_path(link != NULL)) { + link->start = nxt_thread_pool_start; + link->work.data = tp; - nxt_sem_destroy(&tp->sem); + if (nxt_thread_create(&handle, link) == NXT_OK) { + tp->ready = 1; + goto done; } + } - (void) nxt_atomic_fetch_add(&tp->threads, -1); - - ret = NXT_ERROR; + nxt_sem_destroy(&tp->sem); } + (void)nxt_atomic_fetch_add(&tp->threads, -1); + + ret = NXT_ERROR; + } + done: - nxt_thread_spin_unlock(&tp->work_queue.lock); + nxt_thread_spin_unlock(&tp->work_queue.lock); - return ret; + return ret; } +static void nxt_thread_pool_start(void *ctx) { + nxt_thread_t *thr; + nxt_thread_pool_t *tp; -static void -nxt_thread_pool_start(void *ctx) -{ - nxt_thread_t *thr; - nxt_thread_pool_t *tp; - - tp = ctx; - thr = nxt_thread(); + tp = ctx; + thr = nxt_thread(); - tp->main = thr->handle; - tp->task.thread = thr; + tp->main = thr->handle; + tp->task.thread = thr; - nxt_thread_pool_loop(ctx); + nxt_thread_pool_loop(ctx); } +static void nxt_thread_pool_loop(void *ctx) { + void *obj, *data; + nxt_task_t *task; + nxt_thread_t *thr; + nxt_thread_pool_t *tp; + nxt_work_handler_t handler; -static void -nxt_thread_pool_loop(void *ctx) -{ - void *obj, *data; - nxt_task_t *task; - nxt_thread_t *thr; - nxt_thread_pool_t *tp; - nxt_work_handler_t handler; + tp = ctx; + thr = nxt_thread(); - tp = ctx; - thr = nxt_thread(); + if (tp->init != NULL) { + tp->init(); + } - if (tp->init != NULL) { - tp->init(); - } + for (;;) { + nxt_thread_pool_wait(tp); - for ( ;; ) { - nxt_thread_pool_wait(tp); + handler = nxt_locked_work_queue_pop(&tp->work_queue, &task, &obj, &data); - handler = nxt_locked_work_queue_pop(&tp->work_queue, &task, &obj, - &data); + if (nxt_fast_path(handler != NULL)) { + task->thread = thr; - if (nxt_fast_path(handler != NULL)) { - task->thread = thr; + nxt_log_debug(thr->log, "locked work queue"); - nxt_log_debug(thr->log, "locked work queue"); - - handler(task, obj, data); - } - - thr->log = &nxt_main_log; + handler(task, obj, data); } -} + thr->log = &nxt_main_log; + } +} -static void -nxt_thread_pool_wait(nxt_thread_pool_t *tp) -{ - nxt_err_t err; - nxt_thread_t *thr; - nxt_atomic_uint_t waiting, threads; - nxt_thread_link_t *link; - nxt_thread_handle_t handle; +static void nxt_thread_pool_wait(nxt_thread_pool_t *tp) { + nxt_err_t err; + nxt_thread_t *thr; + nxt_atomic_uint_t waiting, threads; + nxt_thread_link_t *link; + nxt_thread_handle_t handle; - thr = nxt_thread(); + thr = nxt_thread(); - nxt_log_debug(thr->log, "thread pool wait"); + nxt_log_debug(thr->log, "thread pool wait"); - (void) nxt_atomic_fetch_add(&tp->waiting, 1); + (void)nxt_atomic_fetch_add(&tp->waiting, 1); - for ( ;; ) { - err = nxt_sem_wait(&tp->sem, tp->timeout); + for (;;) { + err = nxt_sem_wait(&tp->sem, tp->timeout); - if (err == 0) { - waiting = nxt_atomic_fetch_add(&tp->waiting, -1); - break; - } + if (err == 0) { + waiting = nxt_atomic_fetch_add(&tp->waiting, -1); + break; + } - if (err == NXT_ETIMEDOUT) { - if (nxt_thread_handle_equal(thr->handle, tp->main)) { - continue; - } - } + if (err == NXT_ETIMEDOUT) { + if (nxt_thread_handle_equal(thr->handle, tp->main)) { + continue; + } + } - (void) nxt_atomic_fetch_add(&tp->waiting, -1); - (void) nxt_atomic_fetch_add(&tp->threads, -1); + (void)nxt_atomic_fetch_add(&tp->waiting, -1); + (void)nxt_atomic_fetch_add(&tp->threads, -1); - nxt_thread_exit(thr); - nxt_unreachable(); - } + nxt_thread_exit(thr); + nxt_unreachable(); + } - nxt_log_debug(thr->log, "thread pool awake, waiting: %A", waiting); + nxt_log_debug(thr->log, "thread pool awake, waiting: %A", waiting); - if (waiting > 1) { - return; - } + if (waiting > 1) { + return; + } - do { - threads = tp->threads; + do { + threads = tp->threads; - if (threads >= tp->max_threads) { - return; - } + if (threads >= tp->max_threads) { + return; + } - } while (!nxt_atomic_cmp_set(&tp->threads, threads, threads + 1)); + } while (!nxt_atomic_cmp_set(&tp->threads, threads, threads + 1)); - link = nxt_zalloc(sizeof(nxt_thread_link_t)); + link = nxt_zalloc(sizeof(nxt_thread_link_t)); - if (nxt_fast_path(link != NULL)) { - link->start = nxt_thread_pool_loop; - link->work.data = tp; + if (nxt_fast_path(link != NULL)) { + link->start = nxt_thread_pool_loop; + link->work.data = tp; - if (nxt_thread_create(&handle, link) != NXT_OK) { - (void) nxt_atomic_fetch_add(&tp->threads, -1); - } + if (nxt_thread_create(&handle, link) != NXT_OK) { + (void)nxt_atomic_fetch_add(&tp->threads, -1); } + } } +void nxt_thread_pool_destroy(nxt_thread_pool_t *tp) { + nxt_thread_t *thr; -void -nxt_thread_pool_destroy(nxt_thread_pool_t *tp) -{ - nxt_thread_t *thr; + thr = nxt_thread(); - thr = nxt_thread(); + nxt_log_debug(thr->log, "thread pool destroy: %A", tp->ready); - nxt_log_debug(thr->log, "thread pool destroy: %A", tp->ready); - - if (!tp->ready) { - nxt_work_queue_add(&thr->engine->fast_work_queue, tp->exit, - &tp->engine->task, tp, NULL); - return; - } + if (!tp->ready) { + nxt_work_queue_add(&thr->engine->fast_work_queue, tp->exit, + &tp->engine->task, tp, NULL); + return; + } - if (tp->max_threads != 0) { - /* Disable new threads creation and mark a pool as being destroyed. */ - tp->max_threads = 0; + if (tp->max_threads != 0) { + /* Disable new threads creation and mark a pool as being destroyed. */ + tp->max_threads = 0; - nxt_work_set(&tp->work, nxt_thread_pool_exit, &tp->task, tp, NULL); + nxt_work_set(&tp->work, nxt_thread_pool_exit, &tp->task, tp, NULL); - nxt_thread_pool_post(tp, &tp->work); - } + nxt_thread_pool_post(tp, &tp->work); + } } - /* * A thread handle (pthread_t) is either pointer or integer, so it can be * passed as work handler pointer "data" argument. To convert void pointer @@ -263,48 +241,46 @@ nxt_thread_pool_destroy(nxt_thread_pool_t *tp) * the last thread of pool will exit. */ -static void -nxt_thread_pool_exit(nxt_task_t *task, void *obj, void *data) -{ - nxt_thread_t *thread; - nxt_thread_pool_t *tp; - nxt_atomic_uint_t threads; - nxt_thread_handle_t handle; +static void nxt_thread_pool_exit(nxt_task_t *task, void *obj, void *data) { + nxt_thread_t *thread; + nxt_thread_pool_t *tp; + nxt_atomic_uint_t threads; + nxt_thread_handle_t handle; - tp = obj; - thread = task->thread; + tp = obj; + thread = task->thread; - nxt_debug(task, "thread pool exit"); + nxt_debug(task, "thread pool exit"); - if (data != NULL) { - handle = (nxt_thread_handle_t) (uintptr_t) data; - nxt_thread_wait(handle); - } + if (data != NULL) { + handle = (nxt_thread_handle_t)(uintptr_t)data; + nxt_thread_wait(handle); + } - threads = nxt_atomic_fetch_add(&tp->threads, -1); + threads = nxt_atomic_fetch_add(&tp->threads, -1); - nxt_debug(task, "thread pool threads: %A", threads); + nxt_debug(task, "thread pool threads: %A", threads); - if (threads > 1) { - nxt_work_set(&tp->work, nxt_thread_pool_exit, &tp->task, tp, - (void *) (uintptr_t) thread->handle); + if (threads > 1) { + nxt_work_set(&tp->work, nxt_thread_pool_exit, &tp->task, tp, + (void *)(uintptr_t)thread->handle); - nxt_thread_pool_post(tp, &tp->work); + nxt_thread_pool_post(tp, &tp->work); - } else { - nxt_debug(task, "thread pool destroy"); + } else { + nxt_debug(task, "thread pool destroy"); - nxt_sem_destroy(&tp->sem); + nxt_sem_destroy(&tp->sem); - nxt_work_set(&tp->work, tp->exit, &tp->engine->task, tp, - (void *) (uintptr_t) thread->handle); + nxt_work_set(&tp->work, tp->exit, &tp->engine->task, tp, + (void *)(uintptr_t)thread->handle); - nxt_event_engine_post(tp->engine, &tp->work); + nxt_event_engine_post(tp->engine, &tp->work); - /* The "tp" memory should be freed by tp->exit handler. */ - } + /* The "tp" memory should be freed by tp->exit handler. */ + } - nxt_thread_exit(thread); + nxt_thread_exit(thread); - nxt_unreachable(); + nxt_unreachable(); } diff --git a/src/nxt_thread_pool.h b/src/nxt_thread_pool.h index 750b98f82..60856a85a 100644 --- a/src/nxt_thread_pool.h +++ b/src/nxt_thread_pool.h @@ -7,38 +7,35 @@ #ifndef _NXT_UNIX_THREAD_POOL_H_INCLUDED_ #define _NXT_UNIX_THREAD_POOL_H_INCLUDED_ - typedef void (*nxt_thread_pool_init_t)(void); - struct nxt_thread_pool_s { - nxt_atomic_t ready; - nxt_atomic_t waiting; - nxt_atomic_t threads; - nxt_uint_t max_threads; + nxt_atomic_t ready; + nxt_atomic_t waiting; + nxt_atomic_t threads; + nxt_uint_t max_threads; - nxt_sem_t sem; - nxt_nsec_t timeout; + nxt_sem_t sem; + nxt_nsec_t timeout; - nxt_work_t work; - nxt_task_t task; + nxt_work_t work; + nxt_task_t task; - nxt_locked_work_queue_t work_queue; + nxt_locked_work_queue_t work_queue; - nxt_thread_handle_t main; + nxt_thread_handle_t main; - nxt_event_engine_t *engine; - nxt_thread_pool_init_t init; - nxt_work_handler_t exit; + nxt_event_engine_t *engine; + nxt_thread_pool_init_t init; + nxt_work_handler_t exit; }; - -NXT_EXPORT nxt_thread_pool_t *nxt_thread_pool_create(nxt_uint_t max_threads, - nxt_nsec_t timeout, nxt_thread_pool_init_t init, - nxt_event_engine_t *engine, nxt_work_handler_t exit); +NXT_EXPORT nxt_thread_pool_t * +nxt_thread_pool_create(nxt_uint_t max_threads, nxt_nsec_t timeout, + nxt_thread_pool_init_t init, nxt_event_engine_t *engine, + nxt_work_handler_t exit); NXT_EXPORT void nxt_thread_pool_destroy(nxt_thread_pool_t *tp); NXT_EXPORT nxt_int_t nxt_thread_pool_post(nxt_thread_pool_t *tp, - nxt_work_t *work); - + nxt_work_t *work); #endif /* _NXT_UNIX_THREAD_POOL_H_INCLUDED_ */ diff --git a/src/nxt_thread_time.c b/src/nxt_thread_time.c index d084af0af..3dd8c97b7 100644 --- a/src/nxt_thread_time.c +++ b/src/nxt_thread_time.c @@ -6,7 +6,6 @@ #include - /* * Each thread keeps several time representations in its thread local * storage: @@ -29,109 +28,96 @@ * are always updated only on demand. */ - static void nxt_time_thread(void *data); static void nxt_thread_time_shared(nxt_monotonic_time_t *now); static void nxt_thread_realtime_update(nxt_thread_t *thr, - nxt_monotonic_time_t *now); + nxt_monotonic_time_t *now); static u_char *nxt_thread_time_string_no_cache(nxt_thread_t *thr, - nxt_time_string_t *ts, u_char *buf); + nxt_time_string_t *ts, + u_char *buf); static nxt_atomic_uint_t nxt_thread_time_string_slot(nxt_time_string_t *ts); -static nxt_time_string_cache_t *nxt_thread_time_string_cache(nxt_thread_t *thr, - nxt_atomic_uint_t slot); - - -static nxt_atomic_int_t nxt_gmtoff; -static nxt_bool_t nxt_use_shared_time = 0; -static volatile nxt_monotonic_time_t nxt_shared_time; +static nxt_time_string_cache_t * +nxt_thread_time_string_cache(nxt_thread_t *thr, nxt_atomic_uint_t slot); +static nxt_atomic_int_t nxt_gmtoff; +static nxt_bool_t nxt_use_shared_time = 0; +static volatile nxt_monotonic_time_t nxt_shared_time; -void -nxt_thread_time_update(nxt_thread_t *thr) -{ - if (nxt_use_shared_time) { - nxt_thread_time_shared(&thr->time.now); +void nxt_thread_time_update(nxt_thread_t *thr) { + if (nxt_use_shared_time) { + nxt_thread_time_shared(&thr->time.now); - } else { - nxt_monotonic_time(&thr->time.now); - } + } else { + nxt_monotonic_time(&thr->time.now); + } } +void nxt_thread_time_free(nxt_thread_t *thr) { + nxt_uint_t i; + nxt_time_string_cache_t *tsc; -void -nxt_thread_time_free(nxt_thread_t *thr) -{ - nxt_uint_t i; - nxt_time_string_cache_t *tsc; - - tsc = thr->time.strings; + tsc = thr->time.strings; - if (tsc) { - thr->time.no_cache = 1; - - for (i = 0; i < thr->time.nstrings; i++) { - nxt_free(tsc[i].string.start); - } + if (tsc) { + thr->time.no_cache = 1; - nxt_free(tsc); - thr->time.strings = NULL; + for (i = 0; i < thr->time.nstrings; i++) { + nxt_free(tsc[i].string.start); } -} + nxt_free(tsc); + thr->time.strings = NULL; + } +} -void -nxt_time_thread_start(nxt_msec_t interval) -{ - nxt_thread_link_t *link; - nxt_thread_handle_t handle; +void nxt_time_thread_start(nxt_msec_t interval) { + nxt_thread_link_t *link; + nxt_thread_handle_t handle; - link = nxt_zalloc(sizeof(nxt_thread_link_t)); + link = nxt_zalloc(sizeof(nxt_thread_link_t)); - if (nxt_fast_path(link != NULL)) { - link->start = nxt_time_thread; - link->work.data = (void *) (uintptr_t) interval; + if (nxt_fast_path(link != NULL)) { + link->start = nxt_time_thread; + link->work.data = (void *)(uintptr_t)interval; - (void) nxt_thread_create(&handle, link); - } + (void)nxt_thread_create(&handle, link); + } } +static void nxt_time_thread(void *data) { + nxt_nsec_t interval, rest; + nxt_thread_t *thr; + nxt_monotonic_time_t now; -static void -nxt_time_thread(void *data) -{ - nxt_nsec_t interval, rest; - nxt_thread_t *thr; - nxt_monotonic_time_t now; - - interval = (uintptr_t) data; - interval *= 1000000; + interval = (uintptr_t)data; + interval *= 1000000; - thr = nxt_thread(); - /* - * The time thread is never preempted by asynchronous signals, since - * the signals are processed synchronously by dedicated thread. - */ - thr->time.signal = -1; + thr = nxt_thread(); + /* + * The time thread is never preempted by asynchronous signals, since + * the signals are processed synchronously by dedicated thread. + */ + thr->time.signal = -1; - nxt_log_debug(thr->log, "time thread"); + nxt_log_debug(thr->log, "time thread"); - nxt_memzero(&now, sizeof(nxt_monotonic_time_t)); + nxt_memzero(&now, sizeof(nxt_monotonic_time_t)); - nxt_monotonic_time(&now); - nxt_thread_realtime_update(thr, &now); + nxt_monotonic_time(&now); + nxt_thread_realtime_update(thr, &now); - nxt_shared_time = now; - nxt_use_shared_time = 1; + nxt_shared_time = now; + nxt_use_shared_time = 1; - for ( ;; ) { - rest = 1000000000 - now.realtime.nsec; + for (;;) { + rest = 1000000000 - now.realtime.nsec; - nxt_nanosleep(nxt_min(interval, rest)); + nxt_nanosleep(nxt_min(interval, rest)); - nxt_monotonic_time(&now); - nxt_thread_realtime_update(thr, &now); + nxt_monotonic_time(&now); + nxt_thread_realtime_update(thr, &now); - nxt_shared_time = now; + nxt_shared_time = now; #if 0 thr->time.now = now; @@ -144,289 +130,266 @@ nxt_time_thread(void *data) return; } #endif - } + } } +static void nxt_thread_time_shared(nxt_monotonic_time_t *now) { + nxt_uint_t n; + nxt_time_t t; + nxt_nsec_t m, u; -static void -nxt_thread_time_shared(nxt_monotonic_time_t *now) -{ - nxt_uint_t n; - nxt_time_t t; - nxt_nsec_t m, u; - - /* Lock-free thread time update. */ + /* Lock-free thread time update. */ - for ( ;; ) { - *now = nxt_shared_time; + for (;;) { + *now = nxt_shared_time; - t = nxt_shared_time.realtime.sec; - n = nxt_shared_time.realtime.nsec; - m = nxt_shared_time.monotonic; - u = nxt_shared_time.update; + t = nxt_shared_time.realtime.sec; + n = nxt_shared_time.realtime.nsec; + m = nxt_shared_time.monotonic; + u = nxt_shared_time.update; - if (now->realtime.sec == t && now->realtime.nsec == n - && now->monotonic == m && now->update == u) - { - return; - } + if (now->realtime.sec == t && now->realtime.nsec == n && + now->monotonic == m && now->update == u) { + return; } + } } +nxt_time_t nxt_thread_time(nxt_thread_t *thr) { + nxt_thread_realtime_update(thr, &thr->time.now); -nxt_time_t -nxt_thread_time(nxt_thread_t *thr) -{ - nxt_thread_realtime_update(thr, &thr->time.now); - - return thr->time.now.realtime.sec; + return thr->time.now.realtime.sec; } +nxt_realtime_t *nxt_thread_realtime(nxt_thread_t *thr) { + nxt_thread_realtime_update(thr, &thr->time.now); -nxt_realtime_t * -nxt_thread_realtime(nxt_thread_t *thr) -{ - nxt_thread_realtime_update(thr, &thr->time.now); - - return &thr->time.now.realtime; + return &thr->time.now.realtime; } - -static void -nxt_thread_realtime_update(nxt_thread_t *thr, nxt_monotonic_time_t *now) -{ - nxt_nsec_t delta; +static void nxt_thread_realtime_update(nxt_thread_t *thr, + nxt_monotonic_time_t *now) { + nxt_nsec_t delta; #if (NXT_DEBUG) - if (nxt_slow_path(thr->log->level == NXT_LOG_DEBUG || nxt_debug)) { + if (nxt_slow_path(thr->log->level == NXT_LOG_DEBUG || nxt_debug)) { - if (now->monotonic >= now->update) { - nxt_realtime(&now->realtime); - - delta = 1000000 - now->realtime.nsec % 1000000; - now->update = now->monotonic + delta; - } + if (now->monotonic >= now->update) { + nxt_realtime(&now->realtime); - return; + delta = 1000000 - now->realtime.nsec % 1000000; + now->update = now->monotonic + delta; } + return; + } + #endif - if (now->monotonic >= now->update) { - nxt_realtime(&now->realtime); + if (now->monotonic >= now->update) { + nxt_realtime(&now->realtime); - delta = 1000000000 - now->realtime.nsec; - now->update = now->monotonic + delta; - } + delta = 1000000000 - now->realtime.nsec; + now->update = now->monotonic + delta; + } } +u_char *nxt_thread_time_string(nxt_thread_t *thr, nxt_time_string_t *ts, + u_char *buf) { + u_char *p; + struct tm *tm; + nxt_time_t s; + nxt_bool_t update; + nxt_atomic_uint_t slot; + nxt_time_string_cache_t *tsc; -u_char * -nxt_thread_time_string(nxt_thread_t *thr, nxt_time_string_t *ts, u_char *buf) -{ - u_char *p; - struct tm *tm; - nxt_time_t s; - nxt_bool_t update; - nxt_atomic_uint_t slot; - nxt_time_string_cache_t *tsc; + if (nxt_slow_path(thr == NULL || thr->time.no_cache)) { + return nxt_thread_time_string_no_cache(thr, ts, buf); + } - if (nxt_slow_path(thr == NULL || thr->time.no_cache)) { - return nxt_thread_time_string_no_cache(thr, ts, buf); - } + slot = nxt_thread_time_string_slot(ts); - slot = nxt_thread_time_string_slot(ts); + tsc = nxt_thread_time_string_cache(thr, slot); + if (tsc == NULL) { + return buf; + } - tsc = nxt_thread_time_string_cache(thr, slot); - if (tsc == NULL) { - return buf; - } - - if (thr->time.signal < 0) { - /* - * Lazy real time update: - * signal event support or multi-threaded mode. - */ - nxt_thread_realtime_update(thr, &thr->time.now); - } + if (thr->time.signal < 0) { + /* + * Lazy real time update: + * signal event support or multi-threaded mode. + */ + nxt_thread_realtime_update(thr, &thr->time.now); + } - s = thr->time.now.realtime.sec; + s = thr->time.now.realtime.sec; - update = (s != tsc->last); + update = (s != tsc->last); #if (NXT_DEBUG) - if (ts->msec == NXT_THREAD_TIME_MSEC - && (nxt_slow_path(thr->log->level == NXT_LOG_DEBUG || nxt_debug))) - { - nxt_msec_t ms; + if (ts->msec == NXT_THREAD_TIME_MSEC && + (nxt_slow_path(thr->log->level == NXT_LOG_DEBUG || nxt_debug))) { + nxt_msec_t ms; - ms = thr->time.now.realtime.nsec / 1000000; - update |= (ms != tsc->last_msec); - tsc->last_msec = ms; - } + ms = thr->time.now.realtime.nsec / 1000000; + update |= (ms != tsc->last_msec); + tsc->last_msec = ms; + } #endif - if (nxt_slow_path(update)) { - - if (ts->timezone == NXT_THREAD_TIME_LOCAL) { - - tm = &thr->time.localtime; - - if (nxt_slow_path(s != thr->time.last_localtime)) { - - if (thr->time.signal < 0) { - /* - * Lazy local time update: - * signal event support or multi-threaded mode. - */ - nxt_localtime(s, &thr->time.localtime); - thr->time.last_localtime = s; - - } else { - /* - * "thr->time.signal >= 0" means that a thread may be - * interrupted by a signal handler. Since localtime() - * cannot be safely called in a signal context, the - * thread's thr->time.localtime must be updated regularly - * by nxt_thread_time_update() in non-signal context. - * Stale timestamp means that nxt_thread_time_string() - * is being called in a signal context, so here is - * Async-Signal-Safe localtime() emulation using the - * latest cached GMT offset. - * - * The timestamp is not set here intentionally to update - * thr->time.localtime later in non-signal context. The - * real previously cached thr->localtime is used because - * Linux and Solaris strftime() depend on tm.tm_isdst - * and tm.tm_gmtoff fields. - */ - nxt_gmtime(s + nxt_timezone(tm), tm); - } - } + if (nxt_slow_path(update)) { - } else { - tm = &thr->time.gmtime; + if (ts->timezone == NXT_THREAD_TIME_LOCAL) { - if (nxt_slow_path(s != thr->time.last_gmtime)) { - nxt_gmtime(s, tm); - thr->time.last_gmtime = s; - } + tm = &thr->time.localtime; - } + if (nxt_slow_path(s != thr->time.last_localtime)) { - p = tsc->string.start; + if (thr->time.signal < 0) { + /* + * Lazy local time update: + * signal event support or multi-threaded mode. + */ + nxt_localtime(s, &thr->time.localtime); + thr->time.last_localtime = s; - if (nxt_slow_path(p == NULL)) { + } else { + /* + * "thr->time.signal >= 0" means that a thread may be + * interrupted by a signal handler. Since localtime() + * cannot be safely called in a signal context, the + * thread's thr->time.localtime must be updated regularly + * by nxt_thread_time_update() in non-signal context. + * Stale timestamp means that nxt_thread_time_string() + * is being called in a signal context, so here is + * Async-Signal-Safe localtime() emulation using the + * latest cached GMT offset. + * + * The timestamp is not set here intentionally to update + * thr->time.localtime later in non-signal context. The + * real previously cached thr->localtime is used because + * Linux and Solaris strftime() depend on tm.tm_isdst + * and tm.tm_gmtoff fields. + */ + nxt_gmtime(s + nxt_timezone(tm), tm); + } + } - thr->time.no_cache = 1; - p = nxt_zalloc(ts->size); - thr->time.no_cache = 0; + } else { + tm = &thr->time.gmtime; - if (p == NULL) { - return buf; - } + if (nxt_slow_path(s != thr->time.last_gmtime)) { + nxt_gmtime(s, tm); + thr->time.last_gmtime = s; + } + } - tsc->string.start = p; - } + p = tsc->string.start; - p = ts->handler(p, &thr->time.now.realtime, tm, ts->size, ts->format); + if (nxt_slow_path(p == NULL)) { - tsc->string.length = p - tsc->string.start; + thr->time.no_cache = 1; + p = nxt_zalloc(ts->size); + thr->time.no_cache = 0; - if (nxt_slow_path(tsc->string.length == 0)) { - return buf; - } + if (p == NULL) { + return buf; + } - tsc->last = s; + tsc->string.start = p; } - return nxt_cpymem(buf, tsc->string.start, tsc->string.length); -} + p = ts->handler(p, &thr->time.now.realtime, tm, ts->size, ts->format); + tsc->string.length = p - tsc->string.start; -static u_char * -nxt_thread_time_string_no_cache(nxt_thread_t *thr, nxt_time_string_t *ts, - u_char *buf) -{ - struct tm tm; - nxt_realtime_t now; + if (nxt_slow_path(tsc->string.length == 0)) { + return buf; + } - nxt_realtime(&now); + tsc->last = s; + } - if (ts->timezone == NXT_THREAD_TIME_LOCAL) { + return nxt_cpymem(buf, tsc->string.start, tsc->string.length); +} - if (thr == NULL || thr->time.signal <= 0) { - /* Non-signal context */ - nxt_localtime(now.sec, &tm); +static u_char *nxt_thread_time_string_no_cache(nxt_thread_t *thr, + nxt_time_string_t *ts, + u_char *buf) { + struct tm tm; + nxt_realtime_t now; - } else { - nxt_gmtime(now.sec + nxt_gmtoff, &tm); - } + nxt_realtime(&now); + + if (ts->timezone == NXT_THREAD_TIME_LOCAL) { + + if (thr == NULL || thr->time.signal <= 0) { + /* Non-signal context */ + nxt_localtime(now.sec, &tm); } else { - nxt_gmtime(now.sec, &tm); + nxt_gmtime(now.sec + nxt_gmtoff, &tm); } - return ts->handler(buf, &now, &tm, ts->size, ts->format); -} + } else { + nxt_gmtime(now.sec, &tm); + } + return ts->handler(buf, &now, &tm, ts->size, ts->format); +} -static nxt_atomic_uint_t -nxt_thread_time_string_slot(nxt_time_string_t *ts) -{ - static nxt_atomic_t slot; +static nxt_atomic_uint_t nxt_thread_time_string_slot(nxt_time_string_t *ts) { + static nxt_atomic_t slot; - while (nxt_slow_path((nxt_atomic_int_t) ts->slot < 0)) { - /* - * Atomic allocation of a slot number. - * -1 means an uninitialized slot, - * -2 is the initializing lock to assure the single value for the slot. - */ - if (nxt_atomic_cmp_set(&ts->slot, -1, -2)) { - ts->slot = nxt_atomic_fetch_add(&slot, 1); + while (nxt_slow_path((nxt_atomic_int_t)ts->slot < 0)) { + /* + * Atomic allocation of a slot number. + * -1 means an uninitialized slot, + * -2 is the initializing lock to assure the single value for the slot. + */ + if (nxt_atomic_cmp_set(&ts->slot, -1, -2)) { + ts->slot = nxt_atomic_fetch_add(&slot, 1); - /* No "break" here since it adds only dispensable "jmp". */ - } + /* No "break" here since it adds only dispensable "jmp". */ } + } - return (nxt_atomic_uint_t) ts->slot; + return (nxt_atomic_uint_t)ts->slot; } - static nxt_time_string_cache_t * -nxt_thread_time_string_cache(nxt_thread_t *thr, nxt_atomic_uint_t slot) -{ - size_t size; - nxt_atomic_uint_t i, nstrings; - nxt_time_string_cache_t *tsc; - - if (nxt_fast_path(slot < thr->time.nstrings)) { - tsc = &thr->time.strings[slot]; - nxt_prefetch(tsc->string.start); - return tsc; - } +nxt_thread_time_string_cache(nxt_thread_t *thr, nxt_atomic_uint_t slot) { + size_t size; + nxt_atomic_uint_t i, nstrings; + nxt_time_string_cache_t *tsc; - nstrings = slot + 1; - size = nstrings * sizeof(nxt_time_string_cache_t); + if (nxt_fast_path(slot < thr->time.nstrings)) { + tsc = &thr->time.strings[slot]; + nxt_prefetch(tsc->string.start); + return tsc; + } - thr->time.no_cache = 1; - tsc = nxt_realloc(thr->time.strings, size); - thr->time.no_cache = 0; + nstrings = slot + 1; + size = nstrings * sizeof(nxt_time_string_cache_t); - if (tsc == NULL) { - return NULL; - } + thr->time.no_cache = 1; + tsc = nxt_realloc(thr->time.strings, size); + thr->time.no_cache = 0; - for (i = thr->time.nstrings; i < nstrings; i++) { - tsc[i].last = -1; - tsc[i].string.start = NULL; - } + if (tsc == NULL) { + return NULL; + } + + for (i = thr->time.nstrings; i < nstrings; i++) { + tsc[i].last = -1; + tsc[i].string.start = NULL; + } - thr->time.strings = tsc; - thr->time.nstrings = nstrings; + thr->time.strings = tsc; + thr->time.nstrings = nstrings; - return &tsc[slot]; + return &tsc[slot]; } diff --git a/src/nxt_thread_time.h b/src/nxt_thread_time.h index 77eaea493..575e4ce51 100644 --- a/src/nxt_thread_time.h +++ b/src/nxt_thread_time.h @@ -7,77 +7,67 @@ #ifndef _NXT_THREAD_TIME_H_INCLUDED_ #define _NXT_THREAD_TIME_H_INCLUDED_ +#define NXT_THREAD_TIME_LOCAL 0 +#define NXT_THREAD_TIME_GMT 1 -#define NXT_THREAD_TIME_LOCAL 0 -#define NXT_THREAD_TIME_GMT 1 - -#define NXT_THREAD_TIME_SEC 0 -#define NXT_THREAD_TIME_MSEC 1 - +#define NXT_THREAD_TIME_SEC 0 +#define NXT_THREAD_TIME_MSEC 1 typedef struct { - nxt_atomic_t slot; - u_char *(*handler)(u_char *buf, nxt_realtime_t *now, - struct tm *tm, size_t size, - const char *format); - const char *format; - size_t size; - - uint8_t timezone; /* 1 bit */ - uint8_t msec; /* 1 bit */ + nxt_atomic_t slot; + u_char *(*handler)(u_char *buf, nxt_realtime_t *now, struct tm *tm, + size_t size, const char *format); + const char *format; + size_t size; + + uint8_t timezone; /* 1 bit */ + uint8_t msec; /* 1 bit */ } nxt_time_string_t; - typedef struct { - nxt_time_t last; + nxt_time_t last; #if (NXT_DEBUG) - nxt_msec_t last_msec; + nxt_msec_t last_msec; #endif - nxt_str_t string; + nxt_str_t string; } nxt_time_string_cache_t; - typedef struct { - nxt_monotonic_time_t now; - - nxt_time_t last_gmtime; - nxt_time_t last_localtime; - struct tm gmtime; - struct tm localtime; - - uint32_t no_cache; /* 1 bit */ - - /* - * The flag indicating a signal state of a thread. - * It is used to handle local time of the thread: - * -1 means that the thread never runs in a signal context; - * 0 means that the thread may run in a signal context but not now; - * >0 means that the thread runs in a signal context right now. - */ - nxt_atomic_int_t signal; - - nxt_atomic_uint_t nstrings; - nxt_time_string_cache_t *strings; + nxt_monotonic_time_t now; + + nxt_time_t last_gmtime; + nxt_time_t last_localtime; + struct tm gmtime; + struct tm localtime; + + uint32_t no_cache; /* 1 bit */ + + /* + * The flag indicating a signal state of a thread. + * It is used to handle local time of the thread: + * -1 means that the thread never runs in a signal context; + * 0 means that the thread may run in a signal context but not now; + * >0 means that the thread runs in a signal context right now. + */ + nxt_atomic_int_t signal; + + nxt_atomic_uint_t nstrings; + nxt_time_string_cache_t *strings; } nxt_thread_time_t; - NXT_EXPORT void nxt_thread_time_update(nxt_thread_t *thr); void nxt_thread_time_free(nxt_thread_t *thr); NXT_EXPORT nxt_time_t nxt_thread_time(nxt_thread_t *thr); NXT_EXPORT nxt_realtime_t *nxt_thread_realtime(nxt_thread_t *thr); NXT_EXPORT u_char *nxt_thread_time_string(nxt_thread_t *thr, - nxt_time_string_t *ts, u_char *buf); + nxt_time_string_t *ts, u_char *buf); void nxt_time_thread_start(nxt_msec_t interval); - -#define nxt_thread_monotonic_time(thr) \ - (thr)->time.now.monotonic - +#define nxt_thread_monotonic_time(thr) (thr)->time.now.monotonic #if (NXT_DEBUG) -#define nxt_thread_time_debug_update(thr) \ - nxt_thread_time_update(thr) +#define nxt_thread_time_debug_update(thr) nxt_thread_time_update(thr) #else @@ -85,8 +75,6 @@ void nxt_time_thread_start(nxt_msec_t interval); #endif - NXT_EXPORT void nxt_gmtime(nxt_time_t s, struct tm *tm); - #endif /* _NXT_THREAD_TIME_H_INCLUDED_ */ diff --git a/src/nxt_time.c b/src/nxt_time.c index dfead51c5..aaf895551 100644 --- a/src/nxt_time.c +++ b/src/nxt_time.c @@ -6,10 +6,8 @@ #include - /* OS-specific real, monotonic, and local times and timezone update. */ - /* Real time. */ #if (NXT_HAVE_CLOCK_REALTIME_COARSE) @@ -21,18 +19,15 @@ * and it is several times faster than clock_gettime(CLOCK_REALTIME). */ -void -nxt_realtime(nxt_realtime_t *now) -{ - struct timespec ts; +void nxt_realtime(nxt_realtime_t *now) { + struct timespec ts; - (void) clock_gettime(CLOCK_REALTIME_COARSE, &ts); + (void)clock_gettime(CLOCK_REALTIME_COARSE, &ts); - now->sec = (nxt_time_t) ts.tv_sec; - now->nsec = ts.tv_nsec; + now->sec = (nxt_time_t)ts.tv_sec; + now->nsec = ts.tv_nsec; } - #elif (NXT_HAVE_CLOCK_REALTIME_FAST) /* @@ -45,18 +40,15 @@ nxt_realtime(nxt_realtime_t *now) * clock_gettime(CLOCK_REALTIME). */ -void -nxt_realtime(nxt_realtime_t *now) -{ - struct timespec ts; +void nxt_realtime(nxt_realtime_t *now) { + struct timespec ts; - (void) clock_gettime(CLOCK_REALTIME_FAST, &ts); + (void)clock_gettime(CLOCK_REALTIME_FAST, &ts); - now->sec = (nxt_time_t) ts.tv_sec; - now->nsec = ts.tv_nsec; + now->sec = (nxt_time_t)ts.tv_sec; + now->nsec = ts.tv_nsec; } - #elif (NXT_HAVE_CLOCK_REALTIME && !(NXT_HPUX)) /* @@ -68,36 +60,30 @@ nxt_realtime(nxt_realtime_t *now) * on the vDSO page and reads TSC. */ -void -nxt_realtime(nxt_realtime_t *now) -{ - struct timespec ts; +void nxt_realtime(nxt_realtime_t *now) { + struct timespec ts; - (void) clock_gettime(CLOCK_REALTIME, &ts); + (void)clock_gettime(CLOCK_REALTIME, &ts); - now->sec = (nxt_time_t) ts.tv_sec; - now->nsec = ts.tv_nsec; + now->sec = (nxt_time_t)ts.tv_sec; + now->nsec = ts.tv_nsec; } - #else /* MacOSX, HP-UX. */ -void -nxt_realtime(nxt_realtime_t *now) -{ - struct timeval tv; +void nxt_realtime(nxt_realtime_t *now) { + struct timeval tv; - (void) gettimeofday(&tv, NULL); + (void)gettimeofday(&tv, NULL); - now->sec = (nxt_time_t) tv.tv_sec; - now->nsec = tv.tv_usec * 1000; + now->sec = (nxt_time_t)tv.tv_sec; + now->nsec = tv.tv_usec * 1000; } #endif - /* Monotonic time. */ #if (NXT_HAVE_CLOCK_MONOTONIC_COARSE) @@ -109,17 +95,14 @@ nxt_realtime(nxt_realtime_t *now) * and it is several times faster than clock_gettime(CLOCK_MONOTONIC). */ -void -nxt_monotonic_time(nxt_monotonic_time_t *now) -{ - struct timespec ts; +void nxt_monotonic_time(nxt_monotonic_time_t *now) { + struct timespec ts; - (void) clock_gettime(CLOCK_MONOTONIC_COARSE, &ts); + (void)clock_gettime(CLOCK_MONOTONIC_COARSE, &ts); - now->monotonic = (nxt_nsec_t) ts.tv_sec * 1000000000 + ts.tv_nsec; + now->monotonic = (nxt_nsec_t)ts.tv_sec * 1000000000 + ts.tv_nsec; } - #elif (NXT_HAVE_CLOCK_MONOTONIC_FAST) /* @@ -132,17 +115,14 @@ nxt_monotonic_time(nxt_monotonic_time_t *now) * clock_gettime(CLOCK_MONOTONIC). */ -void -nxt_monotonic_time(nxt_monotonic_time_t *now) -{ - struct timespec ts; +void nxt_monotonic_time(nxt_monotonic_time_t *now) { + struct timespec ts; - (void) clock_gettime(CLOCK_MONOTONIC_FAST, &ts); + (void)clock_gettime(CLOCK_MONOTONIC_FAST, &ts); - now->monotonic = (nxt_nsec_t) ts.tv_sec * 1000000000 + ts.tv_nsec; + now->monotonic = (nxt_nsec_t)ts.tv_sec * 1000000000 + ts.tv_nsec; } - #elif (NXT_HAVE_HG_GETHRTIME) /* @@ -151,13 +131,10 @@ nxt_monotonic_time(nxt_monotonic_time_t *now) * by Project Mercury ("HG"). */ -void -nxt_monotonic_time(nxt_monotonic_time_t *now) -{ - now->monotonic = (nxt_nsec_t) hg_gethrtime(); +void nxt_monotonic_time(nxt_monotonic_time_t *now) { + now->monotonic = (nxt_nsec_t)hg_gethrtime(); } - #elif (NXT_SOLARIS || NXT_HPUX) /* @@ -170,13 +147,10 @@ nxt_monotonic_time(nxt_monotonic_time_t *now) * system call gethrtime(). */ -void -nxt_monotonic_time(nxt_monotonic_time_t *now) -{ - now->monotonic = (nxt_nsec_t) gethrtime(); +void nxt_monotonic_time(nxt_monotonic_time_t *now) { + now->monotonic = (nxt_nsec_t)gethrtime(); } - #elif (NXT_HAVE_CLOCK_MONOTONIC) /* @@ -186,17 +160,14 @@ nxt_monotonic_time(nxt_monotonic_time_t *now) * clock_gettime(CLOCK_MONOTONIC) resides on the vDSO page and reads TSC. */ -void -nxt_monotonic_time(nxt_monotonic_time_t *now) -{ - struct timespec ts; +void nxt_monotonic_time(nxt_monotonic_time_t *now) { + struct timespec ts; - (void) clock_gettime(CLOCK_MONOTONIC, &ts); + (void)clock_gettime(CLOCK_MONOTONIC, &ts); - now->monotonic = (nxt_nsec_t) ts.tv_sec * 1000000000 + ts.tv_nsec; + now->monotonic = (nxt_nsec_t)ts.tv_sec * 1000000000 + ts.tv_nsec; } - #elif (NXT_MACOSX) /* @@ -208,84 +179,72 @@ nxt_monotonic_time(nxt_monotonic_time_t *now) * and on iOS 3 they were 1000000000/24000000. */ -void -nxt_monotonic_time(nxt_monotonic_time_t *now) -{ - now->monotonic = mach_absolute_time(); +void nxt_monotonic_time(nxt_monotonic_time_t *now) { + now->monotonic = mach_absolute_time(); } - #else -void -nxt_monotonic_time(nxt_monotonic_time_t *now) -{ - nxt_nsec_t current; - nxt_nsec_int_t delta; - struct timeval tv; +void nxt_monotonic_time(nxt_monotonic_time_t *now) { + nxt_nsec_t current; + nxt_nsec_int_t delta; + struct timeval tv; - (void) gettimeofday(&tv, NULL); + (void)gettimeofday(&tv, NULL); - now->realtime.sec = (nxt_time_t) tv.tv_sec; - now->realtime.nsec = tv.tv_usec * 1000; + now->realtime.sec = (nxt_time_t)tv.tv_sec; + now->realtime.nsec = tv.tv_usec * 1000; - /* - * Monotonic time emulation using gettimeofday() - * for platforms which lack monotonic time. - */ + /* + * Monotonic time emulation using gettimeofday() + * for platforms which lack monotonic time. + */ - current = (nxt_nsec_t) tv.tv_sec * 1000000000 + tv.tv_usec * 1000; - delta = current - now->previous; - now->previous = current; + current = (nxt_nsec_t)tv.tv_sec * 1000000000 + tv.tv_usec * 1000; + delta = current - now->previous; + now->previous = current; - if (delta > 0) { - now->monotonic += delta; + if (delta > 0) { + now->monotonic += delta; - } else { - /* The time went backward. */ - now->monotonic++; - } + } else { + /* The time went backward. */ + now->monotonic++; + } - /* - * Eliminate subsequent gettimeofday() call - * in nxt_thread_realtime_update(). - */ - now->update = now->monotonic + 1; + /* + * Eliminate subsequent gettimeofday() call + * in nxt_thread_realtime_update(). + */ + now->update = now->monotonic + 1; } #endif - /* Local time. */ #if (NXT_HAVE_LOCALTIME_R) -void -nxt_localtime(nxt_time_t s, struct tm *tm) -{ - time_t _s; +void nxt_localtime(nxt_time_t s, struct tm *tm) { + time_t _s; - _s = (time_t) s; - (void) localtime_r(&_s, tm); + _s = (time_t)s; + (void)localtime_r(&_s, tm); } - #else -void -nxt_localtime(nxt_time_t s, struct tm *tm) -{ - time_t _s; - struct tm *_tm; +void nxt_localtime(nxt_time_t s, struct tm *tm) { + time_t _s; + struct tm *_tm; - _s = (time_t) s; - _tm = localtime(&_s); - *tm = *_tm; + _s = (time_t)s; + _tm = localtime(&_s); + *tm = *_tm; } #endif - /* Timezone update. */ #if (NXT_LINUX) @@ -295,16 +254,13 @@ nxt_localtime(nxt_time_t s, struct tm *tm) * in localtime_r(), but tests in localtime(). */ -void -nxt_timezone_update(void) -{ - time_t s; +void nxt_timezone_update(void) { + time_t s; - s = time(NULL); - (void) localtime(&s); + s = time(NULL); + (void)localtime(&s); } - #elif (NXT_FREEBSD) /* @@ -313,23 +269,20 @@ nxt_timezone_update(void) * to update timezone. This trick should work since FreeBSD 2.1.0. */ -void -nxt_timezone_update(void) -{ - if (getenv("TZ") != NULL) { - return; - } +void nxt_timezone_update(void) { + if (getenv("TZ") != NULL) { + return; + } - /* The libc uses /etc/localtime if TZ is not set. */ + /* The libc uses /etc/localtime if TZ is not set. */ - (void) putenv((char *) "TZ=UTC"); - tzset(); + (void)putenv((char *)"TZ=UTC"); + tzset(); - (void) unsetenv("TZ"); - tzset(); + (void)unsetenv("TZ"); + tzset(); } - #elif (NXT_SOLARIS) /* @@ -344,22 +297,15 @@ nxt_timezone_update(void) * the processes within the current zone. */ -void -nxt_timezone_update(void) -{ - time_t s; +void nxt_timezone_update(void) { + time_t s; - s = time(NULL); - (void) ctime(&s); + s = time(NULL); + (void)ctime(&s); } - #else -void -nxt_timezone_update(void) -{ - return; -} +void nxt_timezone_update(void) { return; } #endif diff --git a/src/nxt_time.h b/src/nxt_time.h index 9617b3d41..312cf5f49 100644 --- a/src/nxt_time.h +++ b/src/nxt_time.h @@ -7,34 +7,30 @@ #ifndef _NXT_UNIX_TIME_H_INCLUDED_ #define _NXT_UNIX_TIME_H_INCLUDED_ - -typedef uint64_t nxt_nsec_t; -typedef int64_t nxt_nsec_int_t; -#define NXT_INFINITE_NSEC ((nxt_nsec_t) -1) - +typedef uint64_t nxt_nsec_t; +typedef int64_t nxt_nsec_int_t; +#define NXT_INFINITE_NSEC ((nxt_nsec_t) - 1) typedef struct { - nxt_time_t sec; - nxt_uint_t nsec; + nxt_time_t sec; + nxt_uint_t nsec; } nxt_realtime_t; - /* * nxt_monotonic_time_t includes nxt_realtime_t to eliminate * surplus gettimeofday() call on platform without monotonic time. */ typedef struct { - nxt_realtime_t realtime; - nxt_nsec_t monotonic; - nxt_nsec_t update; + nxt_realtime_t realtime; + nxt_nsec_t monotonic; + nxt_nsec_t update; #if !(NXT_HAVE_CLOCK_MONOTONIC || NXT_SOLARIS || NXT_HPUX || NXT_MACOSX) - nxt_nsec_t previous; + nxt_nsec_t previous; #endif } nxt_monotonic_time_t; - NXT_EXPORT void nxt_realtime(nxt_realtime_t *now); NXT_EXPORT void nxt_monotonic_time(nxt_monotonic_time_t *now); NXT_EXPORT void nxt_localtime(nxt_time_t s, struct tm *tm); @@ -74,34 +70,27 @@ NXT_EXPORT void nxt_timezone_update(void); #if (NXT_HAVE_TM_GMTOFF) -#define nxt_timezone(tm) \ - ((tm)->tm_gmtoff) +#define nxt_timezone(tm) ((tm)->tm_gmtoff) #elif (NXT_HAVE_ALTZONE) -#define nxt_timezone(tm) \ - (-(((tm)->tm_isdst > 0) ? altzone : timezone)) +#define nxt_timezone(tm) (-(((tm)->tm_isdst > 0) ? altzone : timezone)) #else -#define nxt_timezone(tm) \ - (-(((tm)->tm_isdst > 0) ? timezone + 3600 : timezone)) +#define nxt_timezone(tm) (-(((tm)->tm_isdst > 0) ? timezone + 3600 : timezone)) #endif - -typedef uint32_t nxt_msec_t; -typedef int32_t nxt_msec_int_t; -#define NXT_INFINITE_MSEC ((nxt_msec_t) -1) - +typedef uint32_t nxt_msec_t; +typedef int32_t nxt_msec_int_t; +#define NXT_INFINITE_MSEC ((nxt_msec_t) - 1) /* * Since nxt_msec_t values are stored just in 32 bits, they overflow * every 49 days. This signed subtraction takes into account that overflow. * "nxt_msec_diff(m1, m2) < 0" means that m1 is lesser than m2. */ -#define nxt_msec_diff(m1, m2) \ - ((int32_t) ((m1) - (m2))) - +#define nxt_msec_diff(m1, m2) ((int32_t)((m1) - (m2))) #endif /* _NXT_UNIX_TIME_H_INCLUDED_ */ diff --git a/src/nxt_time_parse.c b/src/nxt_time_parse.c index 1ac52fe4a..5a8166add 100644 --- a/src/nxt_time_parse.c +++ b/src/nxt_time_parse.c @@ -6,300 +6,295 @@ #include - /* * nxt_time_parse() parses a time string given in RFC822, RFC850, or ISOC * formats and returns nxt_time_t value >= 0 on success or -1 on failure. */ -nxt_time_t -nxt_time_parse(const u_char *p, size_t len) -{ - size_t n; - u_char c; - uint64_t s; - nxt_int_t yr, month, day, hour, min, sec; - nxt_uint_t year, days; - const u_char *end; - - static const nxt_int_t mday[12] = { - 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 - }; - - enum { - RFC822 = 0, /* "Mon, 28 Sep 1970 12:00:00" */ - RFC850, /* "Monday, 28-Sep-70 12:00:00" */ - ISOC, /* "Mon Sep 28 12:00:00 1970" */ - } fmt; - - fmt = RFC822; - end = p + len; - - while (p < end) { - c = *p++; - - if (c == ',') { - break; - } +nxt_time_t nxt_time_parse(const u_char *p, size_t len) { + size_t n; + u_char c; + uint64_t s; + nxt_int_t yr, month, day, hour, min, sec; + nxt_uint_t year, days; + const u_char *end; - if (c == ' ') { - fmt = ISOC; - break; - } - } + static const nxt_int_t mday[12] = {31, 28, 31, 30, 31, 30, + 31, 31, 30, 31, 30, 31}; - while (p < end) { - if (*p != ' ') { - break; - } + enum { + RFC822 = 0, /* "Mon, 28 Sep 1970 12:00:00" */ + RFC850, /* "Monday, 28-Sep-70 12:00:00" */ + ISOC, /* "Mon Sep 28 12:00:00 1970" */ + } fmt; - p++; + fmt = RFC822; + end = p + len; + + while (p < end) { + c = *p++; + + if (c == ',') { + break; } - if (nxt_slow_path(p + 18 > end)) { - /* Lesser than RFC850 "28-Sep-70 12:00:00" length. */ - return -1; + if (c == ' ') { + fmt = ISOC; + break; } + } - day = 0; + while (p < end) { + if (*p != ' ') { + break; + } - if (fmt != ISOC) { - day = nxt_int_parse(p, 2); - if (nxt_slow_path(day <= 0)) { - return -1; - } - p += 2; + p++; + } - if (*p == ' ') { - if (nxt_slow_path(p + 18 > end)) { - /* Lesser than RFC822 " Sep 1970 12:00:00" length. */ - return -1; - } + if (nxt_slow_path(p + 18 > end)) { + /* Lesser than RFC850 "28-Sep-70 12:00:00" length. */ + return -1; + } - /* RFC822 */ + day = 0; - } else if (*p == '-') { - fmt = RFC850; + if (fmt != ISOC) { + day = nxt_int_parse(p, 2); + if (nxt_slow_path(day <= 0)) { + return -1; + } + p += 2; - } else { - return -1; - } + if (*p == ' ') { + if (nxt_slow_path(p + 18 > end)) { + /* Lesser than RFC822 " Sep 1970 12:00:00" length. */ + return -1; + } - p++; - } + /* RFC822 */ - switch (*p) { + } else if (*p == '-') { + fmt = RFC850; - case 'J': - month = p[1] == 'a' ? 0 : p[2] == 'n' ? 5 : 6; - break; + } else { + return -1; + } - case 'F': - month = 1; - break; + p++; + } - case 'M': - month = p[2] == 'r' ? 2 : 4; - break; + switch (*p) { - case 'A': - month = p[1] == 'p' ? 3 : 7; - break; + case 'J': + month = p[1] == 'a' ? 0 : p[2] == 'n' ? 5 : 6; + break; - case 'S': - month = 8; - break; + case 'F': + month = 1; + break; - case 'O': - month = 9; - break; + case 'M': + month = p[2] == 'r' ? 2 : 4; + break; - case 'N': - month = 10; - break; + case 'A': + month = p[1] == 'p' ? 3 : 7; + break; - case 'D': - month = 11; - break; + case 'S': + month = 8; + break; - default: - return -1; - } + case 'O': + month = 9; + break; - p += 3; - yr = 0; + case 'N': + month = 10; + break; - switch (fmt) { + case 'D': + month = 11; + break; - case RFC822: - if (nxt_slow_path(*p++ != ' ')) { - return -1; - } + default: + return -1; + } - yr = nxt_int_parse(p, 4); - if (nxt_slow_path(yr <= 0)) { - return -1; - } - p += 4; + p += 3; + yr = 0; - break; + switch (fmt) { - case RFC850: - if (nxt_slow_path(*p++ != '-')) { - return -1; - } + case RFC822: + if (nxt_slow_path(*p++ != ' ')) { + return -1; + } - yr = nxt_int_parse(p, 2); - if (nxt_slow_path(yr <= 0)) { - return -1; - } - p += 2; + yr = nxt_int_parse(p, 4); + if (nxt_slow_path(yr <= 0)) { + return -1; + } + p += 4; - yr += (yr < 70) ? 2000 : 1900; + break; - break; + case RFC850: + if (nxt_slow_path(*p++ != '-')) { + return -1; + } - default: /* ISOC */ - if (nxt_slow_path(*p++ != ' ')) { - return -1; - } + yr = nxt_int_parse(p, 2); + if (nxt_slow_path(yr <= 0)) { + return -1; + } + p += 2; - if (p[0] != ' ') { - n = 2; + yr += (yr < 70) ? 2000 : 1900; - if (p[1] == ' ') { - n = 1; - } + break; - } else { - p++; - n = 1; - } + default: /* ISOC */ + if (nxt_slow_path(*p++ != ' ')) { + return -1; + } - day = nxt_int_parse(p, n); - if (nxt_slow_path(day <= 0)) { - return -1; - } - p += n; + if (p[0] != ' ') { + n = 2; - if (nxt_slow_path(p + 14 > end)) { - /* Lesser than ISOC " 12:00:00 1970" length. */ - return -1; - } + if (p[1] == ' ') { + n = 1; + } - break; + } else { + p++; + n = 1; } - if (nxt_slow_path(*p++ != ' ')) { - return -1; + day = nxt_int_parse(p, n); + if (nxt_slow_path(day <= 0)) { + return -1; } + p += n; - hour = nxt_int_parse(p, 2); - if (nxt_slow_path(hour < 0)) { - return -1; + if (nxt_slow_path(p + 14 > end)) { + /* Lesser than ISOC " 12:00:00 1970" length. */ + return -1; } - p += 2; - if (nxt_slow_path(*p++ != ':')) { - return -1; - } + break; + } - min = nxt_int_parse(p, 2); - if (nxt_slow_path(min < 0)) { - return -1; - } - p += 2; + if (nxt_slow_path(*p++ != ' ')) { + return -1; + } - if (nxt_slow_path(*p++ != ':')) { - return -1; - } + hour = nxt_int_parse(p, 2); + if (nxt_slow_path(hour < 0)) { + return -1; + } + p += 2; - sec = nxt_int_parse(p, 2); - if (nxt_slow_path(sec < 0)) { - return -1; - } + if (nxt_slow_path(*p++ != ':')) { + return -1; + } - if (fmt == ISOC) { - p += 2; + min = nxt_int_parse(p, 2); + if (nxt_slow_path(min < 0)) { + return -1; + } + p += 2; - if (nxt_slow_path(*p++ != ' ')) { - return -1; - } + if (nxt_slow_path(*p++ != ':')) { + return -1; + } - yr = nxt_int_parse(p, 4); - if (nxt_slow_path(yr < 0)) { - return -1; - } + sec = nxt_int_parse(p, 2); + if (nxt_slow_path(sec < 0)) { + return -1; + } + + if (fmt == ISOC) { + p += 2; + + if (nxt_slow_path(*p++ != ' ')) { + return -1; } - if (nxt_slow_path(hour > 23 || min > 59 || sec > 59)) { - return -1; + yr = nxt_int_parse(p, 4); + if (nxt_slow_path(yr < 0)) { + return -1; } + } - year = yr; + if (nxt_slow_path(hour > 23 || min > 59 || sec > 59)) { + return -1; + } - if (day == 29 && month == 1) { + year = yr; - if (nxt_slow_path((year & 3) != 0)) { - /* Not a leap year. */ - return -1; - } + if (day == 29 && month == 1) { - if (nxt_slow_path((year % 100 == 0) && (year % 400) != 0)) { - /* Not a leap year. */ - return -1; - } + if (nxt_slow_path((year & 3) != 0)) { + /* Not a leap year. */ + return -1; + } - } else if (nxt_slow_path(day > mday[(nxt_uint_t) month])) { - return -1; + if (nxt_slow_path((year % 100 == 0) && (year % 400) != 0)) { + /* Not a leap year. */ + return -1; } - /* - * Shift new year to March 1 and start months - * from 1 (not 0), as required for Gauss' formula. - */ + } else if (nxt_slow_path(day > mday[(nxt_uint_t)month])) { + return -1; + } - if (--month <= 0) { - month += 12; - year -= 1; - } + /* + * Shift new year to March 1 and start months + * from 1 (not 0), as required for Gauss' formula. + */ + + if (--month <= 0) { + month += 12; + year -= 1; + } - /* Gauss' formula for Gregorian days since March 1, 1 BCE. */ + /* Gauss' formula for Gregorian days since March 1, 1 BCE. */ - /* Days in years including leap years since March 1, 1 BCE. */ - days = 365 * year + year / 4 - year / 100 + year / 400 + /* Days in years including leap years since March 1, 1 BCE. */ + days = 365 * year + year / 4 - year / 100 + + year / 400 - /* Days before the month. */ - + 367 * (nxt_uint_t) month / 12 - 30 + /* Days before the month. */ + + 367 * (nxt_uint_t)month / 12 - + 30 - /* Days before the day. */ - + (nxt_uint_t) day - 1; + /* Days before the day. */ + + (nxt_uint_t)day - 1; - /* - * 719527 days were between March 1, 1 BCE and March 1, 1970, - * 31 and 28 days were in January and February 1970. - */ - days = days - 719527 + 31 + 28; + /* + * 719527 days were between March 1, 1 BCE and March 1, 1970, + * 31 and 28 days were in January and February 1970. + */ + days = days - 719527 + 31 + 28; - s = (uint64_t) days * 86400 - + (nxt_uint_t) hour * 3600 - + (nxt_uint_t) min * 60 - + (nxt_uint_t) sec; + s = (uint64_t)days * 86400 + (nxt_uint_t)hour * 3600 + (nxt_uint_t)min * 60 + + (nxt_uint_t)sec; #if (NXT_TIME_T_SIZE <= 4) - /* Y2038 */ + /* Y2038 */ - if (nxt_slow_path(s > 0x7FFFFFFF)) { - return -1; - } + if (nxt_slow_path(s > 0x7FFFFFFF)) { + return -1; + } #endif - return (nxt_time_t) s; + return (nxt_time_t)s; } - /* * nxt_term_parse() parses term string given in format "200", "10m", * or "1d 1h" and returns nxt_int_t value >= 0 on success, -1 on failure, @@ -307,177 +302,175 @@ nxt_time_parse(const u_char *p, size_t len) * 68 years in seconds or about 24 days in milliseconds. */ -nxt_int_t -nxt_term_parse(const u_char *p, size_t len, nxt_bool_t seconds) -{ - u_char c, ch; - nxt_uint_t val, term, scale, max; - const u_char *end; - - enum { - st_first_digit = 0, - st_digit, - st_space, - } state; - - enum { - st_start = 0, - st_year, - st_month, - st_week, - st_day, - st_hour, - st_min, - st_sec, - st_msec, - st_last, - } step; +nxt_int_t nxt_term_parse(const u_char *p, size_t len, nxt_bool_t seconds) { + u_char c, ch; + nxt_uint_t val, term, scale, max; + const u_char *end; - val = 0; - term = 0; - state = st_first_digit; - step = seconds ? st_start : st_month; + enum { + st_first_digit = 0, + st_digit, + st_space, + } state; - end = p + len; + enum { + st_start = 0, + st_year, + st_month, + st_week, + st_day, + st_hour, + st_min, + st_sec, + st_msec, + st_last, + } step; - while (p < end) { + val = 0; + term = 0; + state = st_first_digit; + step = seconds ? st_start : st_month; - ch = *p++; + end = p + len; - if (state == st_space) { + while (p < end) { - if (ch == ' ') { - continue; - } + ch = *p++; - state = st_first_digit; - } + if (state == st_space) { - /* Values below '0' become >= 208. */ - c = ch - '0'; + if (ch == ' ') { + continue; + } - if (c <= 9) { - val = val * 10 + c; - state = st_digit; - continue; - } + state = st_first_digit; + } - if (state == st_first_digit) { - return -1; - } + /* Values below '0' become >= 208. */ + c = ch - '0'; - switch (ch) { - - case 'y': - if (step > st_start) { - return -1; - } - step = st_year; - max = NXT_INT32_T_MAX / (365 * 24 * 60 * 60); - scale = 365 * 24 * 60 * 60; - break; - - case 'M': - if (step >= st_month) { - return -1; - } - step = st_month; - max = NXT_INT32_T_MAX / (30 * 24 * 60 * 60); - scale = 30 * 24 * 60 * 60; - break; - - case 'w': - if (step >= st_week) { - return -1; - } - step = st_week; - max = NXT_INT32_T_MAX / (7 * 24 * 60 * 60); - scale = 7 * 24 * 60 * 60; - break; - - case 'd': - if (step >= st_day) { - return -1; - } - step = st_day; - max = NXT_INT32_T_MAX / (24 * 60 * 60); - scale = 24 * 60 * 60; - break; - - case 'h': - if (step >= st_hour) { - return -1; - } - step = st_hour; - max = NXT_INT32_T_MAX / (60 * 60); - scale = 60 * 60; - break; - - case 'm': - if (p < end && *p == 's') { - if (seconds || step >= st_msec) { - return -1; - } - p++; - step = st_msec; - max = NXT_INT32_T_MAX; - scale = 1; - break; - } - - if (step >= st_min) { - return -1; - } - step = st_min; - max = NXT_INT32_T_MAX / 60; - scale = 60; - break; - - case 's': - if (step >= st_sec) { - return -1; - } - step = st_sec; - max = NXT_INT32_T_MAX; - scale = 1; - break; - - case ' ': - if (step >= st_sec) { - return -1; - } - step = st_last; - max = NXT_INT32_T_MAX; - scale = 1; - break; - - default: - return -1; - } + if (c <= 9) { + val = val * 10 + c; + state = st_digit; + continue; + } - if (!seconds && step != st_msec) { - scale *= 1000; - max /= 1000; - } + if (state == st_first_digit) { + return -1; + } - if (val > max) { - return -2; - } + switch (ch) { - term += val * scale; + case 'y': + if (step > st_start) { + return -1; + } + step = st_year; + max = NXT_INT32_T_MAX / (365 * 24 * 60 * 60); + scale = 365 * 24 * 60 * 60; + break; - if (term > NXT_INT32_T_MAX) { - return -2; + case 'M': + if (step >= st_month) { + return -1; + } + step = st_month; + max = NXT_INT32_T_MAX / (30 * 24 * 60 * 60); + scale = 30 * 24 * 60 * 60; + break; + + case 'w': + if (step >= st_week) { + return -1; + } + step = st_week; + max = NXT_INT32_T_MAX / (7 * 24 * 60 * 60); + scale = 7 * 24 * 60 * 60; + break; + + case 'd': + if (step >= st_day) { + return -1; + } + step = st_day; + max = NXT_INT32_T_MAX / (24 * 60 * 60); + scale = 24 * 60 * 60; + break; + + case 'h': + if (step >= st_hour) { + return -1; + } + step = st_hour; + max = NXT_INT32_T_MAX / (60 * 60); + scale = 60 * 60; + break; + + case 'm': + if (p < end && *p == 's') { + if (seconds || step >= st_msec) { + return -1; } + p++; + step = st_msec; + max = NXT_INT32_T_MAX; + scale = 1; + break; + } - val = 0; + if (step >= st_min) { + return -1; + } + step = st_min; + max = NXT_INT32_T_MAX / 60; + scale = 60; + break; + + case 's': + if (step >= st_sec) { + return -1; + } + step = st_sec; + max = NXT_INT32_T_MAX; + scale = 1; + break; + + case ' ': + if (step >= st_sec) { + return -1; + } + step = st_last; + max = NXT_INT32_T_MAX; + scale = 1; + break; - state = st_space; + default: + return -1; } - if (!seconds) { - val *= 1000; + if (!seconds && step != st_msec) { + scale *= 1000; + max /= 1000; } - return term + val; + if (val > max) { + return -2; + } + + term += val * scale; + + if (term > NXT_INT32_T_MAX) { + return -2; + } + + val = 0; + + state = st_space; + } + + if (!seconds) { + val *= 1000; + } + + return term + val; } diff --git a/src/nxt_timer.c b/src/nxt_timer.c index cb94b77c8..d155926d1 100644 --- a/src/nxt_timer.c +++ b/src/nxt_timer.c @@ -6,7 +6,6 @@ #include - /* * Timer operations are batched in the changes array to improve instruction * and data cache locality of rbtree operations. @@ -20,325 +19,291 @@ */ static intptr_t nxt_timer_rbtree_compare(nxt_rbtree_node_t *node1, - nxt_rbtree_node_t *node2); + nxt_rbtree_node_t *node2); static void nxt_timer_change(nxt_event_engine_t *engine, nxt_timer_t *timer, - nxt_timer_operation_t change, nxt_msec_t time); + nxt_timer_operation_t change, nxt_msec_t time); static void nxt_timer_changes_commit(nxt_event_engine_t *engine); static void nxt_timer_handler(nxt_task_t *task, void *obj, void *data); +nxt_int_t nxt_timers_init(nxt_timers_t *timers, nxt_uint_t mchanges) { + nxt_rbtree_init(&timers->tree, nxt_timer_rbtree_compare); -nxt_int_t -nxt_timers_init(nxt_timers_t *timers, nxt_uint_t mchanges) -{ - nxt_rbtree_init(&timers->tree, nxt_timer_rbtree_compare); + if (mchanges > NXT_TIMER_MAX_CHANGES) { + mchanges = NXT_TIMER_MAX_CHANGES; + } - if (mchanges > NXT_TIMER_MAX_CHANGES) { - mchanges = NXT_TIMER_MAX_CHANGES; - } + timers->mchanges = mchanges; - timers->mchanges = mchanges; + timers->changes = nxt_malloc(sizeof(nxt_timer_change_t) * mchanges); - timers->changes = nxt_malloc(sizeof(nxt_timer_change_t) * mchanges); + if (nxt_fast_path(timers->changes != NULL)) { + return NXT_OK; + } - if (nxt_fast_path(timers->changes != NULL)) { - return NXT_OK; - } - - return NXT_ERROR; + return NXT_ERROR; } - -static intptr_t -nxt_timer_rbtree_compare(nxt_rbtree_node_t *node1, nxt_rbtree_node_t *node2) -{ - nxt_timer_t *timer1, *timer2; - - timer1 = (nxt_timer_t *) node1; - timer2 = (nxt_timer_t *) node2; - - /* - * Timer values are distributed in small range, usually several minutes - * and overflow every 49 days if nxt_msec_t is stored in 32 bits. - * This signed comparison takes into account that overflow. - */ - /* timer1->time < timer2->time */ - return nxt_msec_diff(timer1->time , timer2->time); +static intptr_t nxt_timer_rbtree_compare(nxt_rbtree_node_t *node1, + nxt_rbtree_node_t *node2) { + nxt_timer_t *timer1, *timer2; + + timer1 = (nxt_timer_t *)node1; + timer2 = (nxt_timer_t *)node2; + + /* + * Timer values are distributed in small range, usually several minutes + * and overflow every 49 days if nxt_msec_t is stored in 32 bits. + * This signed comparison takes into account that overflow. + */ + /* timer1->time < timer2->time */ + return nxt_msec_diff(timer1->time, timer2->time); } +void nxt_timer_add(nxt_event_engine_t *engine, nxt_timer_t *timer, + nxt_msec_t timeout) { + int32_t diff; + uint32_t time; -void -nxt_timer_add(nxt_event_engine_t *engine, nxt_timer_t *timer, - nxt_msec_t timeout) -{ - int32_t diff; - uint32_t time; - - time = engine->timers.now + timeout; + time = engine->timers.now + timeout; - nxt_debug(timer->task, "timer add: %M±%d %M:%M", - timer->time, timer->bias, timeout, time); + nxt_debug(timer->task, "timer add: %M±%d %M:%M", timer->time, timer->bias, + timeout, time); - timer->enabled = 1; + timer->enabled = 1; - if (nxt_timer_is_in_tree(timer)) { + if (nxt_timer_is_in_tree(timer)) { - diff = nxt_msec_diff(time, timer->time); - /* - * Use the previous timer if difference between it and the - * new timer is within bias: this decreases number of rbtree - * operations for fast connections. - */ - if (nxt_abs(diff) <= timer->bias) { - nxt_debug(timer->task, "timer previous: %M±%d", - time, timer->bias); + diff = nxt_msec_diff(time, timer->time); + /* + * Use the previous timer if difference between it and the + * new timer is within bias: this decreases number of rbtree + * operations for fast connections. + */ + if (nxt_abs(diff) <= timer->bias) { + nxt_debug(timer->task, "timer previous: %M±%d", time, timer->bias); - nxt_timer_change(engine, timer, NXT_TIMER_NOPE, 0); - return; - } + nxt_timer_change(engine, timer, NXT_TIMER_NOPE, 0); + return; } + } - nxt_timer_change(engine, timer, NXT_TIMER_ADD, time); + nxt_timer_change(engine, timer, NXT_TIMER_ADD, time); } +nxt_bool_t nxt_timer_delete(nxt_event_engine_t *engine, nxt_timer_t *timer) { + nxt_debug(timer->task, "timer delete: %M±%d", timer->time, timer->bias); -nxt_bool_t -nxt_timer_delete(nxt_event_engine_t *engine, nxt_timer_t *timer) -{ - nxt_debug(timer->task, "timer delete: %M±%d", - timer->time, timer->bias); + timer->enabled = 0; - timer->enabled = 0; + if (nxt_timer_is_in_tree(timer)) { - if (nxt_timer_is_in_tree(timer)) { + nxt_timer_change(engine, timer, NXT_TIMER_DELETE, 0); - nxt_timer_change(engine, timer, NXT_TIMER_DELETE, 0); + return 1; + } - return 1; - } - - nxt_timer_change(engine, timer, NXT_TIMER_NOPE, 0); + nxt_timer_change(engine, timer, NXT_TIMER_NOPE, 0); - return (timer->queued || timer->change != NXT_TIMER_NO_CHANGE); + return (timer->queued || timer->change != NXT_TIMER_NO_CHANGE); } +static void nxt_timer_change(nxt_event_engine_t *engine, nxt_timer_t *timer, + nxt_timer_operation_t change, nxt_msec_t time) { + nxt_timers_t *timers; + nxt_timer_change_t *ch; -static void -nxt_timer_change(nxt_event_engine_t *engine, nxt_timer_t *timer, - nxt_timer_operation_t change, nxt_msec_t time) -{ - nxt_timers_t *timers; - nxt_timer_change_t *ch; - - timers = &engine->timers; - - if (timer->change == NXT_TIMER_NO_CHANGE) { + timers = &engine->timers; - if (change == NXT_TIMER_NOPE) { - return; - } + if (timer->change == NXT_TIMER_NO_CHANGE) { - if (timers->nchanges >= timers->mchanges) { - nxt_timer_changes_commit(engine); - } + if (change == NXT_TIMER_NOPE) { + return; + } - timers->nchanges++; - timer->change = timers->nchanges; + if (timers->nchanges >= timers->mchanges) { + nxt_timer_changes_commit(engine); } - nxt_debug(timer->task, "timer change: %M±%d:%d", - time, timer->bias, change); + timers->nchanges++; + timer->change = timers->nchanges; + } + + nxt_debug(timer->task, "timer change: %M±%d:%d", time, timer->bias, change); - ch = &timers->changes[timer->change - 1]; + ch = &timers->changes[timer->change - 1]; - ch->change = change; - ch->time = time; - ch->timer = timer; + ch->change = change; + ch->time = time; + ch->timer = timer; } +static void nxt_timer_changes_commit(nxt_event_engine_t *engine) { + nxt_timer_t *timer; + nxt_timers_t *timers; + nxt_timer_change_t *ch, *end, *add, *add_end; -static void -nxt_timer_changes_commit(nxt_event_engine_t *engine) -{ - nxt_timer_t *timer; - nxt_timers_t *timers; - nxt_timer_change_t *ch, *end, *add, *add_end; + timers = &engine->timers; - timers = &engine->timers; + nxt_debug(&engine->task, "timers changes: %ui", timers->nchanges); - nxt_debug(&engine->task, "timers changes: %ui", timers->nchanges); + ch = timers->changes; + end = ch + timers->nchanges; - ch = timers->changes; - end = ch + timers->nchanges; + add = ch; + add_end = add; - add = ch; - add_end = add; + while (ch < end) { + timer = ch->timer; - while (ch < end) { - timer = ch->timer; + switch (ch->change) { - switch (ch->change) { + case NXT_TIMER_NOPE: + break; - case NXT_TIMER_NOPE: - break; + case NXT_TIMER_ADD: - case NXT_TIMER_ADD: + timer->time = ch->time; - timer->time = ch->time; + add_end->timer = timer; + add_end++; - add_end->timer = timer; - add_end++; + if (!nxt_timer_is_in_tree(timer)) { + break; + } - if (!nxt_timer_is_in_tree(timer)) { - break; - } + /* Fall through. */ - /* Fall through. */ + case NXT_TIMER_DELETE: + nxt_debug(timer->task, "timer rbtree delete: %M±%d", timer->time, + timer->bias); - case NXT_TIMER_DELETE: - nxt_debug(timer->task, "timer rbtree delete: %M±%d", - timer->time, timer->bias); + nxt_rbtree_delete(&timers->tree, &timer->node); + nxt_timer_in_tree_clear(timer); - nxt_rbtree_delete(&timers->tree, &timer->node); - nxt_timer_in_tree_clear(timer); + break; + } - break; - } + timer->change = NXT_TIMER_NO_CHANGE; - timer->change = NXT_TIMER_NO_CHANGE; + ch++; + } - ch++; - } + while (add < add_end) { + timer = add->timer; - while (add < add_end) { - timer = add->timer; + nxt_debug(timer->task, "timer rbtree insert: %M±%d", timer->time, + timer->bias); - nxt_debug(timer->task, "timer rbtree insert: %M±%d", - timer->time, timer->bias); + nxt_rbtree_insert(&timers->tree, &timer->node); + nxt_timer_in_tree_set(timer); - nxt_rbtree_insert(&timers->tree, &timer->node); - nxt_timer_in_tree_set(timer); + add++; + } - add++; - } - - timers->nchanges = 0; + timers->nchanges = 0; } +nxt_msec_t nxt_timer_find(nxt_event_engine_t *engine) { + int32_t delta; + nxt_msec_t time; + nxt_timer_t *timer; + nxt_timers_t *timers; + nxt_rbtree_t *tree; + nxt_rbtree_node_t *node, *next; -nxt_msec_t -nxt_timer_find(nxt_event_engine_t *engine) -{ - int32_t delta; - nxt_msec_t time; - nxt_timer_t *timer; - nxt_timers_t *timers; - nxt_rbtree_t *tree; - nxt_rbtree_node_t *node, *next; + timers = &engine->timers; - timers = &engine->timers; - - if (timers->nchanges != 0) { - nxt_timer_changes_commit(engine); - } + if (timers->nchanges != 0) { + nxt_timer_changes_commit(engine); + } - tree = &timers->tree; + tree = &timers->tree; - for (node = nxt_rbtree_min(tree); - nxt_rbtree_is_there_successor(tree, node); - node = next) - { - next = nxt_rbtree_node_successor(tree, node); + for (node = nxt_rbtree_min(tree); nxt_rbtree_is_there_successor(tree, node); + node = next) { + next = nxt_rbtree_node_successor(tree, node); - timer = (nxt_timer_t *) node; + timer = (nxt_timer_t *)node; - /* - * Disabled timers are not deleted here since the minimum active - * timer may be larger than a disabled timer, but event poll may - * return much earlier and the disabled timer can be reactivated. - */ + /* + * Disabled timers are not deleted here since the minimum active + * timer may be larger than a disabled timer, but event poll may + * return much earlier and the disabled timer can be reactivated. + */ - if (timer->enabled) { - time = timer->time; - timers->minimum = time - timer->bias; + if (timer->enabled) { + time = timer->time; + timers->minimum = time - timer->bias; - nxt_debug(timer->task, "timer found minimum: %M±%d:%M", - time, timer->bias, timers->now); + nxt_debug(timer->task, "timer found minimum: %M±%d:%M", time, timer->bias, + timers->now); - delta = nxt_msec_diff(time, timers->now); + delta = nxt_msec_diff(time, timers->now); - return (nxt_msec_t) nxt_max(delta, 0); - } + return (nxt_msec_t)nxt_max(delta, 0); } + } - /* Set minimum time one day ahead. */ - timers->minimum = timers->now + 24 * 60 * 60 * 1000; + /* Set minimum time one day ahead. */ + timers->minimum = timers->now + 24 * 60 * 60 * 1000; - return NXT_INFINITE_MSEC; + return NXT_INFINITE_MSEC; } +void nxt_timer_expire(nxt_event_engine_t *engine, nxt_msec_t now) { + nxt_timer_t *timer; + nxt_timers_t *timers; + nxt_rbtree_t *tree; + nxt_rbtree_node_t *node, *next; -void -nxt_timer_expire(nxt_event_engine_t *engine, nxt_msec_t now) -{ - nxt_timer_t *timer; - nxt_timers_t *timers; - nxt_rbtree_t *tree; - nxt_rbtree_node_t *node, *next; + timers = &engine->timers; + timers->now = now; - timers = &engine->timers; - timers->now = now; + nxt_debug(&engine->task, "timer expire minimum: %M:%M", timers->minimum, now); - nxt_debug(&engine->task, "timer expire minimum: %M:%M", - timers->minimum, now); - - /* timers->minimum > now */ - if (nxt_msec_diff(timers->minimum , now) > 0) { - return; - } + /* timers->minimum > now */ + if (nxt_msec_diff(timers->minimum, now) > 0) { + return; + } - tree = &timers->tree; + tree = &timers->tree; - for (node = nxt_rbtree_min(tree); - nxt_rbtree_is_there_successor(tree, node); - node = next) - { - timer = (nxt_timer_t *) node; + for (node = nxt_rbtree_min(tree); nxt_rbtree_is_there_successor(tree, node); + node = next) { + timer = (nxt_timer_t *)node; - /* timer->time > now + timer->bias */ - if (nxt_msec_diff(timer->time , now) > (int32_t) timer->bias) { - return; - } + /* timer->time > now + timer->bias */ + if (nxt_msec_diff(timer->time, now) > (int32_t)timer->bias) { + return; + } - next = nxt_rbtree_node_successor(tree, node); + next = nxt_rbtree_node_successor(tree, node); - nxt_debug(timer->task, "timer expire delete: %M±%d", - timer->time, timer->bias); + nxt_debug(timer->task, "timer expire delete: %M±%d", timer->time, + timer->bias); - nxt_rbtree_delete(tree, &timer->node); - nxt_timer_in_tree_clear(timer); + nxt_rbtree_delete(tree, &timer->node); + nxt_timer_in_tree_clear(timer); - if (timer->enabled) { - timer->queued = 1; + if (timer->enabled) { + timer->queued = 1; - nxt_work_queue_add(timer->work_queue, nxt_timer_handler, - timer->task, timer, NULL); - } + nxt_work_queue_add(timer->work_queue, nxt_timer_handler, timer->task, + timer, NULL); } + } } +static void nxt_timer_handler(nxt_task_t *task, void *obj, void *data) { + nxt_timer_t *timer; -static void -nxt_timer_handler(nxt_task_t *task, void *obj, void *data) -{ - nxt_timer_t *timer; - - timer = obj; + timer = obj; - timer->queued = 0; + timer->queued = 0; - if (timer->enabled && timer->change == NXT_TIMER_NO_CHANGE) { - timer->enabled = 0; + if (timer->enabled && timer->change == NXT_TIMER_NO_CHANGE) { + timer->enabled = 0; - timer->handler(task, timer, NULL); - } + timer->handler(task, timer, NULL); + } } diff --git a/src/nxt_timer.h b/src/nxt_timer.h index 3ccff848d..7d99aaeee 100644 --- a/src/nxt_timer.h +++ b/src/nxt_timer.h @@ -7,107 +7,101 @@ #ifndef _NXT_TIMER_H_INCLUDED_ #define _NXT_TIMER_H_INCLUDED_ - /* Valid values are between 0ms to 255ms. */ -#define NXT_TIMER_DEFAULT_BIAS 50 -//#define NXT_TIMER_DEFAULT_BIAS 0 - +#define NXT_TIMER_DEFAULT_BIAS 50 +// #define NXT_TIMER_DEFAULT_BIAS 0 /* * The nxt_timer_t structure can hold up to 14 bits of change index, * but 0 reserved for NXT_TIMER_NO_CHANGE. */ -#define NXT_TIMER_MAX_CHANGES 16383 -#define NXT_TIMER_NO_CHANGE 0 - +#define NXT_TIMER_MAX_CHANGES 16383 +#define NXT_TIMER_NO_CHANGE 0 typedef struct { - /* The rbtree node must be the first field. */ - NXT_RBTREE_NODE (node); + /* The rbtree node must be the first field. */ + NXT_RBTREE_NODE(node); - uint8_t bias; + uint8_t bias; - uint16_t change:14; - uint16_t enabled:1; - uint16_t queued:1; + uint16_t change : 14; + uint16_t enabled : 1; + uint16_t queued : 1; - nxt_msec_t time; + nxt_msec_t time; - nxt_work_queue_t *work_queue; - nxt_work_handler_t handler; + nxt_work_queue_t *work_queue; + nxt_work_handler_t handler; - nxt_task_t *task; - nxt_log_t *log; + nxt_task_t *task; + nxt_log_t *log; } nxt_timer_t; - -#define NXT_TIMER { NXT_RBTREE_NODE_INIT, 0, NXT_TIMER_NO_CHANGE, \ - 0, 0, 0, NULL, NULL, NULL, NULL } - +#define NXT_TIMER \ + {NXT_RBTREE_NODE_INIT, \ + 0, \ + NXT_TIMER_NO_CHANGE, \ + 0, \ + 0, \ + 0, \ + NULL, \ + NULL, \ + NULL, \ + NULL} typedef enum { - NXT_TIMER_NOPE = 0, - NXT_TIMER_ADD, - NXT_TIMER_DELETE, + NXT_TIMER_NOPE = 0, + NXT_TIMER_ADD, + NXT_TIMER_DELETE, } nxt_timer_operation_t; - typedef struct { - nxt_timer_operation_t change:8; - nxt_msec_t time; - nxt_timer_t *timer; + nxt_timer_operation_t change : 8; + nxt_msec_t time; + nxt_timer_t *timer; } nxt_timer_change_t; - typedef struct { - nxt_rbtree_t tree; + nxt_rbtree_t tree; - /* An overflown milliseconds counter. */ - nxt_msec_t now; - nxt_msec_t minimum; + /* An overflown milliseconds counter. */ + nxt_msec_t now; + nxt_msec_t minimum; - nxt_uint_t mchanges; - nxt_uint_t nchanges; + nxt_uint_t mchanges; + nxt_uint_t nchanges; - nxt_timer_change_t *changes; + nxt_timer_change_t *changes; } nxt_timers_t; - -#define nxt_timer_data(obj, type, timer) \ - nxt_container_of(obj, type, timer) - +#define nxt_timer_data(obj, type, timer) nxt_container_of(obj, type, timer) /* * When timer resides in rbtree all links of its node are not NULL. * A parent link is the nearst to other timer flags. */ -#define nxt_timer_is_in_tree(timer) \ - ((timer)->node.parent != NULL) +#define nxt_timer_is_in_tree(timer) ((timer)->node.parent != NULL) #define nxt_timer_in_tree_set(timer) - /* Noop, because rbtree insertion sets a node's parent link. */ - -#define nxt_timer_in_tree_clear(timer) \ - (timer)->node.parent = NULL +/* Noop, because rbtree insertion sets a node's parent link. */ +#define nxt_timer_in_tree_clear(timer) (timer)->node.parent = NULL nxt_int_t nxt_timers_init(nxt_timers_t *timers, nxt_uint_t mchanges); nxt_msec_t nxt_timer_find(nxt_event_engine_t *engine); void nxt_timer_expire(nxt_event_engine_t *engine, nxt_msec_t now); NXT_EXPORT void nxt_timer_add(nxt_event_engine_t *engine, nxt_timer_t *timer, - nxt_msec_t timeout); + nxt_msec_t timeout); NXT_EXPORT nxt_bool_t nxt_timer_delete(nxt_event_engine_t *engine, - nxt_timer_t *timer); + nxt_timer_t *timer); -nxt_inline void -nxt_timer_disable(nxt_event_engine_t *engine, nxt_timer_t *timer) -{ - nxt_debug(timer->task, "timer disable: %M", timer->time); +nxt_inline void nxt_timer_disable(nxt_event_engine_t *engine, + nxt_timer_t *timer) { + nxt_debug(timer->task, "timer disable: %M", timer->time); - timer->enabled = 0; + timer->enabled = 0; } - #endif /* _NXT_TIMER_H_INCLUDED_ */ diff --git a/src/nxt_tls.h b/src/nxt_tls.h index 0667ade3c..f1baa3d7b 100644 --- a/src/nxt_tls.h +++ b/src/nxt_tls.h @@ -7,10 +7,8 @@ #ifndef _NXT_TLS_H_INCLUDED_ #define _NXT_TLS_H_INCLUDED_ - #include - /* * The SSL/TLS libraries lack vector I/O interface yet add noticeable * overhead to each SSL/TLS record so buffering allows to decrease the @@ -23,94 +21,84 @@ * and compatible with tunnels. */ -#define NXT_TLS_BUFFER_SIZE 4096 - +#define NXT_TLS_BUFFER_SIZE 4096 -typedef struct nxt_tls_conf_s nxt_tls_conf_t; -typedef struct nxt_tls_bundle_conf_s nxt_tls_bundle_conf_t; -typedef struct nxt_tls_init_s nxt_tls_init_t; -typedef struct nxt_tls_ticket_s nxt_tls_ticket_t; -typedef struct nxt_tls_tickets_s nxt_tls_tickets_t; +typedef struct nxt_tls_conf_s nxt_tls_conf_t; +typedef struct nxt_tls_bundle_conf_s nxt_tls_bundle_conf_t; +typedef struct nxt_tls_init_s nxt_tls_init_t; +typedef struct nxt_tls_ticket_s nxt_tls_ticket_t; +typedef struct nxt_tls_tickets_s nxt_tls_tickets_t; typedef struct { - nxt_int_t (*library_init)(nxt_task_t *task); - void (*library_free)(nxt_task_t *task); - - nxt_int_t (*server_init)(nxt_task_t *task, nxt_mp_t *mp, - nxt_tls_init_t *tls_init, - nxt_bool_t last); - void (*server_free)(nxt_task_t *task, - nxt_tls_conf_t *conf); -} nxt_tls_lib_t; + nxt_int_t (*library_init)(nxt_task_t *task); + void (*library_free)(nxt_task_t *task); + nxt_int_t (*server_init)(nxt_task_t *task, nxt_mp_t *mp, + nxt_tls_init_t *tls_init, nxt_bool_t last); + void (*server_free)(nxt_task_t *task, nxt_tls_conf_t *conf); +} nxt_tls_lib_t; typedef struct { - nxt_tls_bundle_conf_t *bundle; + nxt_tls_bundle_conf_t *bundle; - nxt_str_t name; + nxt_str_t name; } nxt_tls_bundle_hash_item_t; - struct nxt_tls_bundle_conf_s { - void *ctx; + void *ctx; - nxt_fd_t chain_file; - nxt_str_t name; + nxt_fd_t chain_file; + nxt_str_t name; - nxt_tls_bundle_conf_t *next; + nxt_tls_bundle_conf_t *next; }; - struct nxt_tls_conf_s { - nxt_tls_bundle_conf_t *bundle; - nxt_lvlhsh_t bundle_hash; + nxt_tls_bundle_conf_t *bundle; + nxt_lvlhsh_t bundle_hash; - nxt_tls_tickets_t *tickets; + nxt_tls_tickets_t *tickets; - void (*conn_init)(nxt_task_t *task, - nxt_tls_conf_t *conf, nxt_conn_t *c); + void (*conn_init)(nxt_task_t *task, nxt_tls_conf_t *conf, nxt_conn_t *c); - const nxt_tls_lib_t *lib; + const nxt_tls_lib_t *lib; - char *ciphers; + char *ciphers; - char *ca_certificate; + char *ca_certificate; - size_t buffer_size; + size_t buffer_size; - uint8_t no_wait_shutdown; /* 1 bit */ + uint8_t no_wait_shutdown; /* 1 bit */ }; - struct nxt_tls_init_s { - size_t cache_size; - nxt_time_t timeout; - nxt_conf_value_t *conf_cmds; - nxt_conf_value_t *tickets_conf; + size_t cache_size; + nxt_time_t timeout; + nxt_conf_value_t *conf_cmds; + nxt_conf_value_t *tickets_conf; - nxt_tls_conf_t *conf; + nxt_tls_conf_t *conf; }; - #if (NXT_HAVE_OPENSSL) -extern const nxt_tls_lib_t nxt_openssl_lib; +extern const nxt_tls_lib_t nxt_openssl_lib; void nxt_cdecl nxt_openssl_log_error(nxt_task_t *task, nxt_uint_t level, - const char *fmt, ...); + const char *fmt, ...); u_char *nxt_openssl_copy_error(u_char *p, u_char *end); #endif #if (NXT_HAVE_GNUTLS) -extern const nxt_tls_lib_t nxt_gnutls_lib; +extern const nxt_tls_lib_t nxt_gnutls_lib; #endif #if (NXT_HAVE_CYASSL) -extern const nxt_tls_lib_t nxt_cyassl_lib; +extern const nxt_tls_lib_t nxt_cyassl_lib; #endif #if (NXT_HAVE_POLARSSL) -extern const nxt_tls_lib_t nxt_polar_lib; +extern const nxt_tls_lib_t nxt_polar_lib; #endif - #endif /* _NXT_TLS_H_INCLUDED_ */ diff --git a/src/nxt_tstr.c b/src/nxt_tstr.c index 36d77e69e..71575e363 100644 --- a/src/nxt_tstr.c +++ b/src/nxt_tstr.c @@ -5,317 +5,281 @@ #include - typedef enum { - NXT_TSTR_CONST = 0, - NXT_TSTR_VAR, + NXT_TSTR_CONST = 0, + NXT_TSTR_VAR, #if (NXT_HAVE_NJS) - NXT_TSTR_JS, + NXT_TSTR_JS, #endif } nxt_tstr_type_t; - struct nxt_tstr_s { - nxt_str_t str; + nxt_str_t str; - union { - nxt_var_t *var; + union { + nxt_var_t *var; #if (NXT_HAVE_NJS) - nxt_js_t *js; + nxt_js_t *js; #endif - } u; + } u; - nxt_tstr_flags_t flags; - nxt_tstr_type_t type; + nxt_tstr_flags_t flags; + nxt_tstr_type_t type; }; - struct nxt_tstr_query_s { - nxt_mp_t *pool; + nxt_mp_t *pool; - nxt_tstr_state_t *state; - nxt_tstr_cache_t *cache; + nxt_tstr_state_t *state; + nxt_tstr_cache_t *cache; - void *ctx; - void *data; + void *ctx; + void *data; }; +#define nxt_tstr_is_js(str) nxt_strchr_start(str, '`') -#define nxt_tstr_is_js(str) \ - nxt_strchr_start(str, '`') +nxt_tstr_state_t *nxt_tstr_state_new(nxt_mp_t *mp, nxt_bool_t test) { + nxt_tstr_state_t *state; + state = nxt_mp_get(mp, sizeof(nxt_tstr_state_t)); + if (nxt_slow_path(state == NULL)) { + return NULL; + } -nxt_tstr_state_t * -nxt_tstr_state_new(nxt_mp_t *mp, nxt_bool_t test) -{ - nxt_tstr_state_t *state; - - state = nxt_mp_get(mp, sizeof(nxt_tstr_state_t)); - if (nxt_slow_path(state == NULL)) { - return NULL; - } - - state->pool = mp; - state->test = test; + state->pool = mp; + state->test = test; - state->var_refs = nxt_array_create(mp, 4, sizeof(nxt_var_ref_t)); - if (nxt_slow_path(state->var_refs == NULL)) { - return NULL; - } + state->var_refs = nxt_array_create(mp, 4, sizeof(nxt_var_ref_t)); + if (nxt_slow_path(state->var_refs == NULL)) { + return NULL; + } #if (NXT_HAVE_NJS) - state->jcf = nxt_js_conf_new(mp, test); - if (nxt_slow_path(state->jcf == NULL)) { - return NULL; - } + state->jcf = nxt_js_conf_new(mp, test); + if (nxt_slow_path(state->jcf == NULL)) { + return NULL; + } #endif - return state; + return state; } +nxt_tstr_t *nxt_tstr_compile(nxt_tstr_state_t *state, const nxt_str_t *str, + nxt_tstr_flags_t flags) { + u_char *p; + nxt_tstr_t *tstr; + nxt_bool_t strz, newline; -nxt_tstr_t * -nxt_tstr_compile(nxt_tstr_state_t *state, const nxt_str_t *str, - nxt_tstr_flags_t flags) -{ - u_char *p; - nxt_tstr_t *tstr; - nxt_bool_t strz, newline; + strz = (flags & NXT_TSTR_STRZ) != 0; + newline = (flags & NXT_TSTR_NEWLINE) != 0; - strz = (flags & NXT_TSTR_STRZ) != 0; - newline = (flags & NXT_TSTR_NEWLINE) != 0; + tstr = nxt_mp_get(state->pool, sizeof(nxt_tstr_t)); + if (nxt_slow_path(tstr == NULL)) { + return NULL; + } - tstr = nxt_mp_get(state->pool, sizeof(nxt_tstr_t)); - if (nxt_slow_path(tstr == NULL)) { - return NULL; - } - - tstr->str.length = str->length + newline + strz; + tstr->str.length = str->length + newline + strz; - tstr->str.start = nxt_mp_nget(state->pool, tstr->str.length); - if (nxt_slow_path(tstr->str.start == NULL)) { - return NULL; - } + tstr->str.start = nxt_mp_nget(state->pool, tstr->str.length); + if (nxt_slow_path(tstr->str.start == NULL)) { + return NULL; + } - p = nxt_cpymem(tstr->str.start, str->start, str->length); + p = nxt_cpymem(tstr->str.start, str->start, str->length); - if (newline) { - *p++ = '\n'; - } + if (newline) { + *p++ = '\n'; + } - if (strz) { - *p = '\0'; - } + if (strz) { + *p = '\0'; + } - tstr->flags = flags; + tstr->flags = flags; - if (nxt_tstr_is_js(str)) { + if (nxt_tstr_is_js(str)) { #if (NXT_HAVE_NJS) - nxt_str_t tpl; + nxt_str_t tpl; - tstr->type = NXT_TSTR_JS; + tstr->type = NXT_TSTR_JS; - nxt_tstr_str(tstr, &tpl); + nxt_tstr_str(tstr, &tpl); - tstr->u.js = nxt_js_add_tpl(state->jcf, &tpl, flags); - if (nxt_slow_path(tstr->u.js == NULL)) { - return NULL; - } + tstr->u.js = nxt_js_add_tpl(state->jcf, &tpl, flags); + if (nxt_slow_path(tstr->u.js == NULL)) { + return NULL; + } #endif - } else { - p = memchr(str->start, '$', str->length); + } else { + p = memchr(str->start, '$', str->length); - if (p != NULL) { - tstr->type = NXT_TSTR_VAR; + if (p != NULL) { + tstr->type = NXT_TSTR_VAR; - tstr->u.var = nxt_var_compile(state, &tstr->str); - if (nxt_slow_path(tstr->u.var == NULL)) { - return NULL; - } + tstr->u.var = nxt_var_compile(state, &tstr->str); + if (nxt_slow_path(tstr->u.var == NULL)) { + return NULL; + } - } else { - tstr->type = NXT_TSTR_CONST; - } + } else { + tstr->type = NXT_TSTR_CONST; } + } - return tstr; + return tstr; } +nxt_int_t nxt_tstr_test(nxt_tstr_state_t *state, nxt_str_t *str, + u_char *error) { + u_char *p; -nxt_int_t -nxt_tstr_test(nxt_tstr_state_t *state, nxt_str_t *str, u_char *error) -{ - u_char *p; - - if (nxt_tstr_is_js(str)) { + if (nxt_tstr_is_js(str)) { #if (NXT_HAVE_NJS) - return nxt_js_test(state->jcf, str, error); + return nxt_js_test(state->jcf, str, error); #else - nxt_sprintf(error, error + NXT_MAX_ERROR_STR, - "Unit is built without support of njs: " - "\"--njs\" ./configure option is missing.%Z"); - return NXT_ERROR; + nxt_sprintf(error, error + NXT_MAX_ERROR_STR, + "Unit is built without support of njs: " + "\"--njs\" ./configure option is missing.%Z"); + return NXT_ERROR; #endif - } else { - p = memchr(str->start, '$', str->length); + } else { + p = memchr(str->start, '$', str->length); - if (p != NULL) { - return nxt_var_test(state, str, error); - } + if (p != NULL) { + return nxt_var_test(state, str, error); } + } - return NXT_OK; + return NXT_OK; } - -nxt_int_t -nxt_tstr_state_done(nxt_tstr_state_t *state, u_char *error) -{ +nxt_int_t nxt_tstr_state_done(nxt_tstr_state_t *state, u_char *error) { #if (NXT_HAVE_NJS) - if (!state->test) { - nxt_int_t ret; + if (!state->test) { + nxt_int_t ret; - ret = nxt_js_compile(state->jcf); - if (nxt_slow_path(ret != NXT_OK)) { - return NXT_ERROR; - } + ret = nxt_js_compile(state->jcf); + if (nxt_slow_path(ret != NXT_OK)) { + return NXT_ERROR; } + } #endif - return NXT_OK; + return NXT_OK; } - -void -nxt_tstr_state_release(nxt_tstr_state_t *state) -{ +void nxt_tstr_state_release(nxt_tstr_state_t *state) { #if (NXT_HAVE_NJS) - nxt_js_conf_release(state->jcf); + nxt_js_conf_release(state->jcf); #endif } +nxt_int_t nxt_tstr_cond_compile(nxt_tstr_state_t *state, nxt_str_t *str, + nxt_tstr_cond_t *cond) { + if (str->length > 0 && str->start[0] == '!') { + cond->negate = 1; -nxt_int_t -nxt_tstr_cond_compile(nxt_tstr_state_t *state, nxt_str_t *str, - nxt_tstr_cond_t *cond) -{ - if (str->length > 0 && str->start[0] == '!') { - cond->negate = 1; - - str->start++; - str->length--; - } + str->start++; + str->length--; + } - cond->expr = nxt_tstr_compile(state, str, 0); - if (nxt_slow_path(cond->expr == NULL)) { - return NXT_ERROR; - } + cond->expr = nxt_tstr_compile(state, str, 0); + if (nxt_slow_path(cond->expr == NULL)) { + return NXT_ERROR; + } - return NXT_OK; + return NXT_OK; } - -nxt_bool_t -nxt_tstr_is_const(nxt_tstr_t *tstr) -{ - return (tstr->type == NXT_TSTR_CONST); +nxt_bool_t nxt_tstr_is_const(nxt_tstr_t *tstr) { + return (tstr->type == NXT_TSTR_CONST); } +void nxt_tstr_str(nxt_tstr_t *tstr, nxt_str_t *str) { + *str = tstr->str; -void -nxt_tstr_str(nxt_tstr_t *tstr, nxt_str_t *str) -{ - *str = tstr->str; - - if (tstr->flags & NXT_TSTR_STRZ) { - str->length--; - } + if (tstr->flags & NXT_TSTR_STRZ) { + str->length--; + } } +nxt_int_t nxt_tstr_query_init(nxt_tstr_query_t **query_p, + nxt_tstr_state_t *state, nxt_tstr_cache_t *cache, + void *ctx, nxt_mp_t *mp) { + nxt_tstr_query_t *query; -nxt_int_t -nxt_tstr_query_init(nxt_tstr_query_t **query_p, nxt_tstr_state_t *state, - nxt_tstr_cache_t *cache, void *ctx, nxt_mp_t *mp) -{ - nxt_tstr_query_t *query; - - query = *query_p; + query = *query_p; - if (*query_p == NULL) { - query = nxt_mp_zget(mp, sizeof(nxt_tstr_query_t)); - if (nxt_slow_path(query == NULL)) { - return NXT_ERROR; - } + if (*query_p == NULL) { + query = nxt_mp_zget(mp, sizeof(nxt_tstr_query_t)); + if (nxt_slow_path(query == NULL)) { + return NXT_ERROR; } + } - query->pool = mp; - query->state = state; - query->cache = cache; - query->ctx = ctx; + query->pool = mp; + query->state = state; + query->cache = cache; + query->ctx = ctx; - *query_p = query; + *query_p = query; - return NXT_OK; + return NXT_OK; } +nxt_int_t nxt_tstr_query(nxt_task_t *task, nxt_tstr_query_t *query, + nxt_tstr_t *tstr, nxt_str_t *val) { + nxt_int_t ret; -nxt_int_t -nxt_tstr_query(nxt_task_t *task, nxt_tstr_query_t *query, nxt_tstr_t *tstr, - nxt_str_t *val) -{ - nxt_int_t ret; - - if (nxt_tstr_is_const(tstr)) { - nxt_tstr_str(tstr, val); - return NXT_OK; - } + if (nxt_tstr_is_const(tstr)) { + nxt_tstr_str(tstr, val); + return NXT_OK; + } - if (tstr->type == NXT_TSTR_VAR) { - ret = nxt_var_interpreter(task, query->state, &query->cache->var, - tstr->u.var, val, query->ctx, - tstr->flags & NXT_TSTR_LOGGING); + if (tstr->type == NXT_TSTR_VAR) { + ret = + nxt_var_interpreter(task, query->state, &query->cache->var, tstr->u.var, + val, query->ctx, tstr->flags & NXT_TSTR_LOGGING); - if (nxt_slow_path(ret != NXT_OK)) { - return NXT_ERROR; - } + if (nxt_slow_path(ret != NXT_OK)) { + return NXT_ERROR; + } - } else { + } else { #if (NXT_HAVE_NJS) - ret = nxt_js_call(task, query->state->jcf, &query->cache->js, - tstr->u.js, val, query->ctx); + ret = nxt_js_call(task, query->state->jcf, &query->cache->js, tstr->u.js, + val, query->ctx); - if (nxt_slow_path(ret != NXT_OK)) { - return NXT_ERROR; - } -#endif + if (nxt_slow_path(ret != NXT_OK)) { + return NXT_ERROR; } +#endif + } - if (tstr->flags & NXT_TSTR_STRZ) { - val->length--; - } + if (tstr->flags & NXT_TSTR_STRZ) { + val->length--; + } #if (NXT_DEBUG) - nxt_str_t str; + nxt_str_t str; - nxt_tstr_str(tstr, &str); + nxt_tstr_str(tstr, &str); - nxt_debug(task, "tstr query: \"%V\", result: \"%V\"", &str, val); + nxt_debug(task, "tstr query: \"%V\", result: \"%V\"", &str, val); #endif - return NXT_OK; + return NXT_OK; } - -void -nxt_tstr_query_release(nxt_tstr_query_t *query) -{ +void nxt_tstr_query_release(nxt_tstr_query_t *query) { #if (NXT_HAVE_NJS) - nxt_js_release(&query->cache->js); + nxt_js_release(&query->cache->js); #endif } diff --git a/src/nxt_tstr.h b/src/nxt_tstr.h index 8e3cdb93e..50113eab1 100644 --- a/src/nxt_tstr.h +++ b/src/nxt_tstr.h @@ -6,81 +6,71 @@ #ifndef _NXT_TSTR_H_INCLUDED_ #define _NXT_TSTR_H_INCLUDED_ - #include -typedef struct nxt_tstr_s nxt_tstr_t; -typedef struct nxt_tstr_query_s nxt_tstr_query_t; - +typedef struct nxt_tstr_s nxt_tstr_t; +typedef struct nxt_tstr_query_s nxt_tstr_query_t; struct nxt_tstr_state_s { - nxt_mp_t *pool; - nxt_array_t *var_refs; + nxt_mp_t *pool; + nxt_array_t *var_refs; #if (NXT_HAVE_NJS) - nxt_js_conf_t *jcf; + nxt_js_conf_t *jcf; #endif - uint8_t test; /* 1 bit */ + uint8_t test; /* 1 bit */ }; - typedef struct { - nxt_var_cache_t var; + nxt_var_cache_t var; #if (NXT_HAVE_NJS) - nxt_js_cache_t js; + nxt_js_cache_t js; #endif } nxt_tstr_cache_t; - typedef enum { - NXT_TSTR_STRZ = 1 << 0, - NXT_TSTR_LOGGING = 1 << 1, - NXT_TSTR_NEWLINE = 1 << 2, + NXT_TSTR_STRZ = 1 << 0, + NXT_TSTR_LOGGING = 1 << 1, + NXT_TSTR_NEWLINE = 1 << 2, } nxt_tstr_flags_t; - typedef struct { - nxt_tstr_t *expr; - uint8_t negate; /* 1 bit */ + nxt_tstr_t *expr; + uint8_t negate; /* 1 bit */ } nxt_tstr_cond_t; - nxt_tstr_state_t *nxt_tstr_state_new(nxt_mp_t *mp, nxt_bool_t test); nxt_tstr_t *nxt_tstr_compile(nxt_tstr_state_t *state, const nxt_str_t *str, - nxt_tstr_flags_t flags); + nxt_tstr_flags_t flags); nxt_int_t nxt_tstr_test(nxt_tstr_state_t *state, nxt_str_t *str, u_char *error); nxt_int_t nxt_tstr_state_done(nxt_tstr_state_t *state, u_char *error); void nxt_tstr_state_release(nxt_tstr_state_t *state); nxt_int_t nxt_tstr_cond_compile(nxt_tstr_state_t *state, nxt_str_t *str, - nxt_tstr_cond_t *cond); + nxt_tstr_cond_t *cond); nxt_bool_t nxt_tstr_is_const(nxt_tstr_t *tstr); void nxt_tstr_str(nxt_tstr_t *tstr, nxt_str_t *str); nxt_int_t nxt_tstr_query_init(nxt_tstr_query_t **query_p, - nxt_tstr_state_t *state, nxt_tstr_cache_t *cache, void *ctx, - nxt_mp_t *mp); + nxt_tstr_state_t *state, nxt_tstr_cache_t *cache, + void *ctx, nxt_mp_t *mp); nxt_int_t nxt_tstr_query(nxt_task_t *task, nxt_tstr_query_t *query, - nxt_tstr_t *tstr, nxt_str_t *val); + nxt_tstr_t *tstr, nxt_str_t *val); void nxt_tstr_query_release(nxt_tstr_query_t *query); +nxt_inline nxt_bool_t nxt_is_tstr(nxt_str_t *str) { + u_char *p; -nxt_inline nxt_bool_t -nxt_is_tstr(nxt_str_t *str) -{ - u_char *p; + p = memchr(str->start, '`', str->length); + if (p != NULL) { + return 1; + } - p = memchr(str->start, '`', str->length); - if (p != NULL) { - return 1; - } + p = memchr(str->start, '$', str->length); + if (p != NULL) { + return 1; + } - p = memchr(str->start, '$', str->length); - if (p != NULL) { - return 1; - } - - return 0; + return 0; } - #endif /* _NXT_TSTR_H_INCLUDED_ */ diff --git a/src/nxt_types.h b/src/nxt_types.h index 723346d9f..29243b0a1 100644 --- a/src/nxt_types.h +++ b/src/nxt_types.h @@ -7,7 +7,6 @@ #ifndef _NXT_TYPES_H_INCLUDED_ #define _NXT_TYPES_H_INCLUDED_ - /* * nxt_int_t corresponds to the most efficient integer type, * an architecture word. It is usually the long type, @@ -20,27 +19,24 @@ * AMD64 64-bit multiplication and division operations * are slower and 64-bit instructions are longer. */ -#define NXT_INT_T_SIZE 4 -typedef int nxt_int_t; -typedef u_int nxt_uint_t; +#define NXT_INT_T_SIZE 4 +typedef int nxt_int_t; +typedef u_int nxt_uint_t; #else -#define NXT_INT_T_SIZE NXT_PTR_SIZE -typedef intptr_t nxt_int_t; -typedef uintptr_t nxt_uint_t; +#define NXT_INT_T_SIZE NXT_PTR_SIZE +typedef intptr_t nxt_int_t; +typedef uintptr_t nxt_uint_t; #endif - -typedef nxt_uint_t nxt_bool_t; - +typedef nxt_uint_t nxt_bool_t; /* * nxt_off_t corresponds to OS's off_t, a file offset type. * Although Linux, Solaris, and HP-UX define both off_t and off64_t, * setting _FILE_OFFSET_BITS to 64 defines off_t as off64_t. */ -typedef off_t nxt_off_t; - +typedef off_t nxt_off_t; /* * nxt_time_t corresponds to OS's time_t, time in seconds. nxt_time_t is @@ -57,94 +53,86 @@ typedef off_t nxt_off_t; * QNX defines time_t as uint32_t. * Y2038 fix: "typedef int64_t nxt_time_t". */ -typedef int32_t nxt_time_t; +typedef int32_t nxt_time_t; #else /* Y2038, if time_t is 32-bit integer. */ -typedef time_t nxt_time_t; +typedef time_t nxt_time_t; #endif - #if (NXT_PTR_SIZE == 8) -#define NXT_64BIT 1 -#define NXT_32BIT 0 +#define NXT_64BIT 1 +#define NXT_32BIT 0 #else -#define NXT_64BIT 0 -#define NXT_32BIT 1 +#define NXT_64BIT 0 +#define NXT_32BIT 1 #endif +#define NXT_INT64_T_LEN nxt_length("-9223372036854775808") +#define NXT_INT32_T_LEN nxt_length("-2147483648") -#define NXT_INT64_T_LEN nxt_length("-9223372036854775808") -#define NXT_INT32_T_LEN nxt_length("-2147483648") - -#define NXT_INT64_T_HEXLEN nxt_length("FFFFFFFFFFFFFFFF") -#define NXT_INT32_T_HEXLEN nxt_length("FFFFFFFF") - -#define NXT_INT64_T_MAX 0x7FFFFFFFFFFFFFFFLL -#define NXT_INT32_T_MAX 0x7FFFFFFF +#define NXT_INT64_T_HEXLEN nxt_length("FFFFFFFFFFFFFFFF") +#define NXT_INT32_T_HEXLEN nxt_length("FFFFFFFF") +#define NXT_INT64_T_MAX 0x7FFFFFFFFFFFFFFFLL +#define NXT_INT32_T_MAX 0x7FFFFFFF #if (NXT_INT_T_SIZE == 8) -#define NXT_INT_T_LEN NXT_INT64_T_LEN -#define NXT_INT_T_HEXLEN NXT_INT64_T_HEXLEN -#define NXT_INT_T_MAX NXT_INT64_T_MAX +#define NXT_INT_T_LEN NXT_INT64_T_LEN +#define NXT_INT_T_HEXLEN NXT_INT64_T_HEXLEN +#define NXT_INT_T_MAX NXT_INT64_T_MAX #else -#define NXT_INT_T_LEN NXT_INT32_T_LEN -#define NXT_INT_T_HEXLEN NXT_INT32_T_HEXLEN -#define NXT_INT_T_MAX NXT_INT32_T_MAX +#define NXT_INT_T_LEN NXT_INT32_T_LEN +#define NXT_INT_T_HEXLEN NXT_INT32_T_HEXLEN +#define NXT_INT_T_MAX NXT_INT32_T_MAX #endif - #if (NXT_64BIT) -#define NXT_ATOMIC_T_LEN NXT_INT64_T_LEN -#define NXT_ATOMIC_T_HEXLEN NXT_INT64_T_HEXLEN -#define NXT_ATOMIC_T_MAX NXT_INT64_T_MAX +#define NXT_ATOMIC_T_LEN NXT_INT64_T_LEN +#define NXT_ATOMIC_T_HEXLEN NXT_INT64_T_HEXLEN +#define NXT_ATOMIC_T_MAX NXT_INT64_T_MAX #else -#define NXT_ATOMIC_T_LEN NXT_INT32_T_LEN -#define NXT_ATOMIC_T_HEXLEN NXT_INT32_T_HEXLEN -#define NXT_ATOMIC_T_MAX NXT_INT32_T_MAX +#define NXT_ATOMIC_T_LEN NXT_INT32_T_LEN +#define NXT_ATOMIC_T_HEXLEN NXT_INT32_T_HEXLEN +#define NXT_ATOMIC_T_MAX NXT_INT32_T_MAX #endif - #if (NXT_OFF_T_SIZE == 8) -typedef uint64_t nxt_uoff_t; -#define NXT_OFF_T_LEN NXT_INT64_T_LEN -#define NXT_OFF_T_HEXLEN NXT_INT64_T_HEXLEN -#define NXT_OFF_T_MAX NXT_INT64_T_MAX +typedef uint64_t nxt_uoff_t; +#define NXT_OFF_T_LEN NXT_INT64_T_LEN +#define NXT_OFF_T_HEXLEN NXT_INT64_T_HEXLEN +#define NXT_OFF_T_MAX NXT_INT64_T_MAX #else -typedef uint32_t nxt_uoff_t; -#define NXT_OFF_T_LEN NXT_INT32_T_LEN -#define NXT_OFF_T_HEXLEN NXT_INT32_T_HEXLEN -#define NXT_OFF_T_MAX NXT_INT32_T_MAX +typedef uint32_t nxt_uoff_t; +#define NXT_OFF_T_LEN NXT_INT32_T_LEN +#define NXT_OFF_T_HEXLEN NXT_INT32_T_HEXLEN +#define NXT_OFF_T_MAX NXT_INT32_T_MAX #endif - #if (NXT_SIZE_T_SIZE == 8) -#define NXT_SIZE_T_LEN NXT_INT64_T_LEN -#define NXT_SIZE_T_HEXLEN NXT_INT64_T_HEXLEN -#define NXT_SIZE_T_MAX NXT_INT64_T_MAX +#define NXT_SIZE_T_LEN NXT_INT64_T_LEN +#define NXT_SIZE_T_HEXLEN NXT_INT64_T_HEXLEN +#define NXT_SIZE_T_MAX NXT_INT64_T_MAX #else -#define NXT_SIZE_T_LEN NXT_INT32_T_LEN -#define NXT_SIZE_T_HEXLEN NXT_INT32_T_HEXLEN -#define NXT_SIZE_T_MAX NXT_INT32_T_MAX +#define NXT_SIZE_T_LEN NXT_INT32_T_LEN +#define NXT_SIZE_T_HEXLEN NXT_INT32_T_HEXLEN +#define NXT_SIZE_T_MAX NXT_INT32_T_MAX #endif - #if (NXT_TIME_T_SIZE == 8) -#define NXT_TIME_T_LEN NXT_INT64_T_LEN -#define NXT_TIME_T_HEXLEN NXT_INT64_T_HEXLEN -#define NXT_TIME_T_MAX NXT_INT64_T_MAX +#define NXT_TIME_T_LEN NXT_INT64_T_LEN +#define NXT_TIME_T_HEXLEN NXT_INT64_T_HEXLEN +#define NXT_TIME_T_MAX NXT_INT64_T_MAX #else -#define NXT_TIME_T_LEN NXT_INT32_T_LEN -#define NXT_TIME_T_HEXLEN NXT_INT32_T_HEXLEN -#define NXT_TIME_T_MAX NXT_INT32_T_MAX +#define NXT_TIME_T_LEN NXT_INT32_T_LEN +#define NXT_TIME_T_HEXLEN NXT_INT32_T_HEXLEN +#define NXT_TIME_T_MAX NXT_INT32_T_MAX #endif - #endif /* _NXT_TYPES_H_INCLUDED_ */ diff --git a/src/nxt_unicode_lowcase.h b/src/nxt_unicode_lowcase.h index 2f25ab69e..934770b04 100644 --- a/src/nxt_unicode_lowcase.h +++ b/src/nxt_unicode_lowcase.h @@ -4,12 +4,11 @@ * 14920 bytes on 32-bit platforms, 17000 bytes on 64-bit platforms. */ -#define NXT_UNICODE_MAX_LOWCASE 0x10427 +#define NXT_UNICODE_MAX_LOWCASE 0x10427 -#define NXT_UNICODE_BLOCK_SIZE 128 +#define NXT_UNICODE_BLOCK_SIZE 128 - -static const uint32_t nxt_unicode_block_000[128] nxt_aligned(64) = { +static const uint32_t nxt_unicode_block_000[128] nxt_aligned(64) = { 0x00000, 0x00001, 0x00002, 0x00003, 0x00004, 0x00005, 0x00006, 0x00007, 0x00008, 0x00009, 0x0000A, 0x0000B, 0x0000C, 0x0000D, 0x0000E, 0x0000F, 0x00010, 0x00011, 0x00012, 0x00013, 0x00014, 0x00015, 0x00016, 0x00017, @@ -28,8 +27,7 @@ static const uint32_t nxt_unicode_block_000[128] nxt_aligned(64) = { 0x00078, 0x00079, 0x0007A, 0x0007B, 0x0007C, 0x0007D, 0x0007E, 0x0007F, }; - -static const uint32_t nxt_unicode_block_001[128] nxt_aligned(64) = { +static const uint32_t nxt_unicode_block_001[128] nxt_aligned(64) = { 0x00080, 0x00081, 0x00082, 0x00083, 0x00084, 0x00085, 0x00086, 0x00087, 0x00088, 0x00089, 0x0008A, 0x0008B, 0x0008C, 0x0008D, 0x0008E, 0x0008F, 0x00090, 0x00091, 0x00092, 0x00093, 0x00094, 0x00095, 0x00096, 0x00097, @@ -48,8 +46,7 @@ static const uint32_t nxt_unicode_block_001[128] nxt_aligned(64) = { 0x000F8, 0x000F9, 0x000FA, 0x000FB, 0x000FC, 0x000FD, 0x000FE, 0x000FF, }; - -static const uint32_t nxt_unicode_block_002[128] nxt_aligned(64) = { +static const uint32_t nxt_unicode_block_002[128] nxt_aligned(64) = { 0x00101, 0x00101, 0x00103, 0x00103, 0x00105, 0x00105, 0x00107, 0x00107, 0x00109, 0x00109, 0x0010B, 0x0010B, 0x0010D, 0x0010D, 0x0010F, 0x0010F, 0x00111, 0x00111, 0x00113, 0x00113, 0x00115, 0x00115, 0x00117, 0x00117, @@ -68,8 +65,7 @@ static const uint32_t nxt_unicode_block_002[128] nxt_aligned(64) = { 0x000FF, 0x0017A, 0x0017A, 0x0017C, 0x0017C, 0x0017E, 0x0017E, 0x00073, }; - -static const uint32_t nxt_unicode_block_003[128] nxt_aligned(64) = { +static const uint32_t nxt_unicode_block_003[128] nxt_aligned(64) = { 0x00180, 0x00253, 0x00183, 0x00183, 0x00185, 0x00185, 0x00254, 0x00188, 0x00188, 0x00256, 0x00257, 0x0018C, 0x0018C, 0x0018D, 0x001DD, 0x00259, 0x0025B, 0x00192, 0x00192, 0x00260, 0x00263, 0x00195, 0x00269, 0x00268, @@ -88,8 +84,7 @@ static const uint32_t nxt_unicode_block_003[128] nxt_aligned(64) = { 0x001F9, 0x001F9, 0x001FB, 0x001FB, 0x001FD, 0x001FD, 0x001FF, 0x001FF, }; - -static const uint32_t nxt_unicode_block_004[128] nxt_aligned(64) = { +static const uint32_t nxt_unicode_block_004[128] nxt_aligned(64) = { 0x00201, 0x00201, 0x00203, 0x00203, 0x00205, 0x00205, 0x00207, 0x00207, 0x00209, 0x00209, 0x0020B, 0x0020B, 0x0020D, 0x0020D, 0x0020F, 0x0020F, 0x00211, 0x00211, 0x00213, 0x00213, 0x00215, 0x00215, 0x00217, 0x00217, @@ -108,8 +103,7 @@ static const uint32_t nxt_unicode_block_004[128] nxt_aligned(64) = { 0x00278, 0x00279, 0x0027A, 0x0027B, 0x0027C, 0x0027D, 0x0027E, 0x0027F, }; - -static const uint32_t nxt_unicode_block_006[128] nxt_aligned(64) = { +static const uint32_t nxt_unicode_block_006[128] nxt_aligned(64) = { 0x00300, 0x00301, 0x00302, 0x00303, 0x00304, 0x00305, 0x00306, 0x00307, 0x00308, 0x00309, 0x0030A, 0x0030B, 0x0030C, 0x0030D, 0x0030E, 0x0030F, 0x00310, 0x00311, 0x00312, 0x00313, 0x00314, 0x00315, 0x00316, 0x00317, @@ -128,8 +122,7 @@ static const uint32_t nxt_unicode_block_006[128] nxt_aligned(64) = { 0x00378, 0x00379, 0x0037A, 0x0037B, 0x0037C, 0x0037D, 0x0037E, 0x0037F, }; - -static const uint32_t nxt_unicode_block_007[128] nxt_aligned(64) = { +static const uint32_t nxt_unicode_block_007[128] nxt_aligned(64) = { 0x00380, 0x00381, 0x00382, 0x00383, 0x00384, 0x00385, 0x003AC, 0x00387, 0x003AD, 0x003AE, 0x003AF, 0x0038B, 0x003CC, 0x0038D, 0x003CD, 0x003CE, 0x00390, 0x003B1, 0x003B2, 0x003B3, 0x003B4, 0x003B5, 0x003B6, 0x003B7, @@ -148,8 +141,7 @@ static const uint32_t nxt_unicode_block_007[128] nxt_aligned(64) = { 0x003F8, 0x003F2, 0x003FB, 0x003FB, 0x003FC, 0x0037B, 0x0037C, 0x0037D, }; - -static const uint32_t nxt_unicode_block_008[128] nxt_aligned(64) = { +static const uint32_t nxt_unicode_block_008[128] nxt_aligned(64) = { 0x00450, 0x00451, 0x00452, 0x00453, 0x00454, 0x00455, 0x00456, 0x00457, 0x00458, 0x00459, 0x0045A, 0x0045B, 0x0045C, 0x0045D, 0x0045E, 0x0045F, 0x00430, 0x00431, 0x00432, 0x00433, 0x00434, 0x00435, 0x00436, 0x00437, @@ -168,8 +160,7 @@ static const uint32_t nxt_unicode_block_008[128] nxt_aligned(64) = { 0x00479, 0x00479, 0x0047B, 0x0047B, 0x0047D, 0x0047D, 0x0047F, 0x0047F, }; - -static const uint32_t nxt_unicode_block_009[128] nxt_aligned(64) = { +static const uint32_t nxt_unicode_block_009[128] nxt_aligned(64) = { 0x00481, 0x00481, 0x00482, 0x00483, 0x00484, 0x00485, 0x00486, 0x00487, 0x00488, 0x00489, 0x0048B, 0x0048B, 0x0048D, 0x0048D, 0x0048F, 0x0048F, 0x00491, 0x00491, 0x00493, 0x00493, 0x00495, 0x00495, 0x00497, 0x00497, @@ -188,8 +179,7 @@ static const uint32_t nxt_unicode_block_009[128] nxt_aligned(64) = { 0x004F9, 0x004F9, 0x004FB, 0x004FB, 0x004FD, 0x004FD, 0x004FF, 0x004FF, }; - -static const uint32_t nxt_unicode_block_00a[128] nxt_aligned(64) = { +static const uint32_t nxt_unicode_block_00a[128] nxt_aligned(64) = { 0x00501, 0x00501, 0x00503, 0x00503, 0x00505, 0x00505, 0x00507, 0x00507, 0x00509, 0x00509, 0x0050B, 0x0050B, 0x0050D, 0x0050D, 0x0050F, 0x0050F, 0x00511, 0x00511, 0x00513, 0x00513, 0x00515, 0x00515, 0x00517, 0x00517, @@ -208,8 +198,7 @@ static const uint32_t nxt_unicode_block_00a[128] nxt_aligned(64) = { 0x00578, 0x00579, 0x0057A, 0x0057B, 0x0057C, 0x0057D, 0x0057E, 0x0057F, }; - -static const uint32_t nxt_unicode_block_021[128] nxt_aligned(64) = { +static const uint32_t nxt_unicode_block_021[128] nxt_aligned(64) = { 0x01080, 0x01081, 0x01082, 0x01083, 0x01084, 0x01085, 0x01086, 0x01087, 0x01088, 0x01089, 0x0108A, 0x0108B, 0x0108C, 0x0108D, 0x0108E, 0x0108F, 0x01090, 0x01091, 0x01092, 0x01093, 0x01094, 0x01095, 0x01096, 0x01097, @@ -228,8 +217,7 @@ static const uint32_t nxt_unicode_block_021[128] nxt_aligned(64) = { 0x010F8, 0x010F9, 0x010FA, 0x010FB, 0x010FC, 0x010FD, 0x010FE, 0x010FF, }; - -static const uint32_t nxt_unicode_block_03c[128] nxt_aligned(64) = { +static const uint32_t nxt_unicode_block_03c[128] nxt_aligned(64) = { 0x01E01, 0x01E01, 0x01E03, 0x01E03, 0x01E05, 0x01E05, 0x01E07, 0x01E07, 0x01E09, 0x01E09, 0x01E0B, 0x01E0B, 0x01E0D, 0x01E0D, 0x01E0F, 0x01E0F, 0x01E11, 0x01E11, 0x01E13, 0x01E13, 0x01E15, 0x01E15, 0x01E17, 0x01E17, @@ -248,8 +236,7 @@ static const uint32_t nxt_unicode_block_03c[128] nxt_aligned(64) = { 0x01E79, 0x01E79, 0x01E7B, 0x01E7B, 0x01E7D, 0x01E7D, 0x01E7F, 0x01E7F, }; - -static const uint32_t nxt_unicode_block_03d[128] nxt_aligned(64) = { +static const uint32_t nxt_unicode_block_03d[128] nxt_aligned(64) = { 0x01E81, 0x01E81, 0x01E83, 0x01E83, 0x01E85, 0x01E85, 0x01E87, 0x01E87, 0x01E89, 0x01E89, 0x01E8B, 0x01E8B, 0x01E8D, 0x01E8D, 0x01E8F, 0x01E8F, 0x01E91, 0x01E91, 0x01E93, 0x01E93, 0x01E95, 0x01E95, 0x01E96, 0x01E97, @@ -268,8 +255,7 @@ static const uint32_t nxt_unicode_block_03d[128] nxt_aligned(64) = { 0x01EF9, 0x01EF9, 0x01EFB, 0x01EFB, 0x01EFD, 0x01EFD, 0x01EFF, 0x01EFF, }; - -static const uint32_t nxt_unicode_block_03e[128] nxt_aligned(64) = { +static const uint32_t nxt_unicode_block_03e[128] nxt_aligned(64) = { 0x01F00, 0x01F01, 0x01F02, 0x01F03, 0x01F04, 0x01F05, 0x01F06, 0x01F07, 0x01F00, 0x01F01, 0x01F02, 0x01F03, 0x01F04, 0x01F05, 0x01F06, 0x01F07, 0x01F10, 0x01F11, 0x01F12, 0x01F13, 0x01F14, 0x01F15, 0x01F16, 0x01F17, @@ -288,8 +274,7 @@ static const uint32_t nxt_unicode_block_03e[128] nxt_aligned(64) = { 0x01F78, 0x01F79, 0x01F7A, 0x01F7B, 0x01F7C, 0x01F7D, 0x01F7E, 0x01F7F, }; - -static const uint32_t nxt_unicode_block_03f[128] nxt_aligned(64) = { +static const uint32_t nxt_unicode_block_03f[128] nxt_aligned(64) = { 0x01F80, 0x01F81, 0x01F82, 0x01F83, 0x01F84, 0x01F85, 0x01F86, 0x01F87, 0x01F80, 0x01F81, 0x01F82, 0x01F83, 0x01F84, 0x01F85, 0x01F86, 0x01F87, 0x01F90, 0x01F91, 0x01F92, 0x01F93, 0x01F94, 0x01F95, 0x01F96, 0x01F97, @@ -308,8 +293,7 @@ static const uint32_t nxt_unicode_block_03f[128] nxt_aligned(64) = { 0x01F78, 0x01F79, 0x01F7C, 0x01F7D, 0x01FF3, 0x01FFD, 0x01FFE, 0x01FFF, }; - -static const uint32_t nxt_unicode_block_042[128] nxt_aligned(64) = { +static const uint32_t nxt_unicode_block_042[128] nxt_aligned(64) = { 0x02100, 0x02101, 0x02102, 0x02103, 0x02104, 0x02105, 0x02106, 0x02107, 0x02108, 0x02109, 0x0210A, 0x0210B, 0x0210C, 0x0210D, 0x0210E, 0x0210F, 0x02110, 0x02111, 0x02112, 0x02113, 0x02114, 0x02115, 0x02116, 0x02117, @@ -328,8 +312,7 @@ static const uint32_t nxt_unicode_block_042[128] nxt_aligned(64) = { 0x02178, 0x02179, 0x0217A, 0x0217B, 0x0217C, 0x0217D, 0x0217E, 0x0217F, }; - -static const uint32_t nxt_unicode_block_043[128] nxt_aligned(64) = { +static const uint32_t nxt_unicode_block_043[128] nxt_aligned(64) = { 0x02180, 0x02181, 0x02182, 0x02184, 0x02184, 0x02185, 0x02186, 0x02187, 0x02188, 0x02189, 0x0218A, 0x0218B, 0x0218C, 0x0218D, 0x0218E, 0x0218F, 0x02190, 0x02191, 0x02192, 0x02193, 0x02194, 0x02195, 0x02196, 0x02197, @@ -348,8 +331,7 @@ static const uint32_t nxt_unicode_block_043[128] nxt_aligned(64) = { 0x021F8, 0x021F9, 0x021FA, 0x021FB, 0x021FC, 0x021FD, 0x021FE, 0x021FF, }; - -static const uint32_t nxt_unicode_block_049[128] nxt_aligned(64) = { +static const uint32_t nxt_unicode_block_049[128] nxt_aligned(64) = { 0x02480, 0x02481, 0x02482, 0x02483, 0x02484, 0x02485, 0x02486, 0x02487, 0x02488, 0x02489, 0x0248A, 0x0248B, 0x0248C, 0x0248D, 0x0248E, 0x0248F, 0x02490, 0x02491, 0x02492, 0x02493, 0x02494, 0x02495, 0x02496, 0x02497, @@ -368,8 +350,7 @@ static const uint32_t nxt_unicode_block_049[128] nxt_aligned(64) = { 0x024F8, 0x024F9, 0x024FA, 0x024FB, 0x024FC, 0x024FD, 0x024FE, 0x024FF, }; - -static const uint32_t nxt_unicode_block_058[128] nxt_aligned(64) = { +static const uint32_t nxt_unicode_block_058[128] nxt_aligned(64) = { 0x02C30, 0x02C31, 0x02C32, 0x02C33, 0x02C34, 0x02C35, 0x02C36, 0x02C37, 0x02C38, 0x02C39, 0x02C3A, 0x02C3B, 0x02C3C, 0x02C3D, 0x02C3E, 0x02C3F, 0x02C40, 0x02C41, 0x02C42, 0x02C43, 0x02C44, 0x02C45, 0x02C46, 0x02C47, @@ -388,8 +369,7 @@ static const uint32_t nxt_unicode_block_058[128] nxt_aligned(64) = { 0x02C78, 0x02C79, 0x02C7A, 0x02C7B, 0x02C7C, 0x02C7D, 0x0023F, 0x00240, }; - -static const uint32_t nxt_unicode_block_059[128] nxt_aligned(64) = { +static const uint32_t nxt_unicode_block_059[128] nxt_aligned(64) = { 0x02C81, 0x02C81, 0x02C83, 0x02C83, 0x02C85, 0x02C85, 0x02C87, 0x02C87, 0x02C89, 0x02C89, 0x02C8B, 0x02C8B, 0x02C8D, 0x02C8D, 0x02C8F, 0x02C8F, 0x02C91, 0x02C91, 0x02C93, 0x02C93, 0x02C95, 0x02C95, 0x02C97, 0x02C97, @@ -408,8 +388,7 @@ static const uint32_t nxt_unicode_block_059[128] nxt_aligned(64) = { 0x02CF8, 0x02CF9, 0x02CFA, 0x02CFB, 0x02CFC, 0x02CFD, 0x02CFE, 0x02CFF, }; - -static const uint32_t nxt_unicode_block_14c[128] nxt_aligned(64) = { +static const uint32_t nxt_unicode_block_14c[128] nxt_aligned(64) = { 0x0A600, 0x0A601, 0x0A602, 0x0A603, 0x0A604, 0x0A605, 0x0A606, 0x0A607, 0x0A608, 0x0A609, 0x0A60A, 0x0A60B, 0x0A60C, 0x0A60D, 0x0A60E, 0x0A60F, 0x0A610, 0x0A611, 0x0A612, 0x0A613, 0x0A614, 0x0A615, 0x0A616, 0x0A617, @@ -428,8 +407,7 @@ static const uint32_t nxt_unicode_block_14c[128] nxt_aligned(64) = { 0x0A678, 0x0A679, 0x0A67A, 0x0A67B, 0x0A67C, 0x0A67D, 0x0A67E, 0x0A67F, }; - -static const uint32_t nxt_unicode_block_14d[128] nxt_aligned(64) = { +static const uint32_t nxt_unicode_block_14d[128] nxt_aligned(64) = { 0x0A681, 0x0A681, 0x0A683, 0x0A683, 0x0A685, 0x0A685, 0x0A687, 0x0A687, 0x0A689, 0x0A689, 0x0A68B, 0x0A68B, 0x0A68D, 0x0A68D, 0x0A68F, 0x0A68F, 0x0A691, 0x0A691, 0x0A693, 0x0A693, 0x0A695, 0x0A695, 0x0A697, 0x0A697, @@ -448,8 +426,7 @@ static const uint32_t nxt_unicode_block_14d[128] nxt_aligned(64) = { 0x0A6F8, 0x0A6F9, 0x0A6FA, 0x0A6FB, 0x0A6FC, 0x0A6FD, 0x0A6FE, 0x0A6FF, }; - -static const uint32_t nxt_unicode_block_14e[128] nxt_aligned(64) = { +static const uint32_t nxt_unicode_block_14e[128] nxt_aligned(64) = { 0x0A700, 0x0A701, 0x0A702, 0x0A703, 0x0A704, 0x0A705, 0x0A706, 0x0A707, 0x0A708, 0x0A709, 0x0A70A, 0x0A70B, 0x0A70C, 0x0A70D, 0x0A70E, 0x0A70F, 0x0A710, 0x0A711, 0x0A712, 0x0A713, 0x0A714, 0x0A715, 0x0A716, 0x0A717, @@ -468,8 +445,7 @@ static const uint32_t nxt_unicode_block_14e[128] nxt_aligned(64) = { 0x0A778, 0x0A77A, 0x0A77A, 0x0A77C, 0x0A77C, 0x01D79, 0x0A77F, 0x0A77F, }; - -static const uint32_t nxt_unicode_block_14f[128] nxt_aligned(64) = { +static const uint32_t nxt_unicode_block_14f[128] nxt_aligned(64) = { 0x0A781, 0x0A781, 0x0A783, 0x0A783, 0x0A785, 0x0A785, 0x0A787, 0x0A787, 0x0A788, 0x0A789, 0x0A78A, 0x0A78C, 0x0A78C, 0x00265, 0x0A78E, 0x0A78F, 0x0A791, 0x0A791, 0x0A793, 0x0A793, 0x0A794, 0x0A795, 0x0A796, 0x0A797, @@ -488,8 +464,7 @@ static const uint32_t nxt_unicode_block_14f[128] nxt_aligned(64) = { 0x0A7F8, 0x0A7F9, 0x0A7FA, 0x0A7FB, 0x0A7FC, 0x0A7FD, 0x0A7FE, 0x0A7FF, }; - -static const uint32_t nxt_unicode_block_1fe[128] nxt_aligned(64) = { +static const uint32_t nxt_unicode_block_1fe[128] nxt_aligned(64) = { 0x0FF00, 0x0FF01, 0x0FF02, 0x0FF03, 0x0FF04, 0x0FF05, 0x0FF06, 0x0FF07, 0x0FF08, 0x0FF09, 0x0FF0A, 0x0FF0B, 0x0FF0C, 0x0FF0D, 0x0FF0E, 0x0FF0F, 0x0FF10, 0x0FF11, 0x0FF12, 0x0FF13, 0x0FF14, 0x0FF15, 0x0FF16, 0x0FF17, @@ -508,8 +483,7 @@ static const uint32_t nxt_unicode_block_1fe[128] nxt_aligned(64) = { 0x0FF78, 0x0FF79, 0x0FF7A, 0x0FF7B, 0x0FF7C, 0x0FF7D, 0x0FF7E, 0x0FF7F, }; - -static const uint32_t nxt_unicode_block_208[40] nxt_aligned(64) = { +static const uint32_t nxt_unicode_block_208[40] nxt_aligned(64) = { 0x10428, 0x10429, 0x1042A, 0x1042B, 0x1042C, 0x1042D, 0x1042E, 0x1042F, 0x10430, 0x10431, 0x10432, 0x10433, 0x10434, 0x10435, 0x10436, 0x10437, 0x10438, 0x10439, 0x1043A, 0x1043B, 0x1043C, 0x1043D, 0x1043E, 0x1043F, @@ -517,8 +491,7 @@ static const uint32_t nxt_unicode_block_208[40] nxt_aligned(64) = { 0x10448, 0x10449, 0x1044A, 0x1044B, 0x1044C, 0x1044D, 0x1044E, 0x1044F, }; - -static const uint32_t *nxt_unicode_blocks[] nxt_aligned(64) = { +static const uint32_t *nxt_unicode_blocks[] nxt_aligned(64) = { nxt_unicode_block_000, nxt_unicode_block_001, nxt_unicode_block_002, diff --git a/src/nxt_unicode_macosx_lowcase.h b/src/nxt_unicode_macosx_lowcase.h index d0cc15186..dbb0fc8de 100644 --- a/src/nxt_unicode_macosx_lowcase.h +++ b/src/nxt_unicode_macosx_lowcase.h @@ -4,12 +4,11 @@ * 9267 bytes on 32-bit platforms, 11307 bytes on 64-bit platforms. */ -#define NXT_UNICODE_MAX_LOWCASE 0x0FF3A +#define NXT_UNICODE_MAX_LOWCASE 0x0FF3A -#define NXT_UNICODE_BLOCK_SIZE 128 +#define NXT_UNICODE_BLOCK_SIZE 128 - -static const uint32_t nxt_unicode_block_000[128] nxt_aligned(64) = { +static const uint32_t nxt_unicode_block_000[128] nxt_aligned(64) = { 0x00000, 0x00001, 0x00002, 0x00003, 0x00004, 0x00005, 0x00006, 0x00007, 0x00008, 0x00009, 0x0000A, 0x0000B, 0x0000C, 0x0000D, 0x0000E, 0x0000F, 0x00010, 0x00011, 0x00012, 0x00013, 0x00014, 0x00015, 0x00016, 0x00017, @@ -28,8 +27,7 @@ static const uint32_t nxt_unicode_block_000[128] nxt_aligned(64) = { 0x00078, 0x00079, 0x0007A, 0x0007B, 0x0007C, 0x0007D, 0x0007E, 0x0007F, }; - -static const uint32_t nxt_unicode_block_001[128] nxt_aligned(64) = { +static const uint32_t nxt_unicode_block_001[128] nxt_aligned(64) = { 0x00080, 0x00081, 0x00082, 0x00083, 0x00084, 0x00085, 0x00086, 0x00087, 0x00088, 0x00089, 0x0008A, 0x0008B, 0x0008C, 0x0008D, 0x0008E, 0x0008F, 0x00090, 0x00091, 0x00092, 0x00093, 0x00094, 0x00095, 0x00096, 0x00097, @@ -48,8 +46,7 @@ static const uint32_t nxt_unicode_block_001[128] nxt_aligned(64) = { 0x000F8, 0x000F9, 0x000FA, 0x000FB, 0x000FC, 0x000FD, 0x000FE, 0x000FF, }; - -static const uint32_t nxt_unicode_block_002[128] nxt_aligned(64) = { +static const uint32_t nxt_unicode_block_002[128] nxt_aligned(64) = { 0x00101, 0x00101, 0x00103, 0x00103, 0x00105, 0x00105, 0x00107, 0x00107, 0x00109, 0x00109, 0x0010B, 0x0010B, 0x0010D, 0x0010D, 0x0010F, 0x0010F, 0x00111, 0x00111, 0x00113, 0x00113, 0x00115, 0x00115, 0x00117, 0x00117, @@ -68,8 +65,7 @@ static const uint32_t nxt_unicode_block_002[128] nxt_aligned(64) = { 0x000FF, 0x0017A, 0x0017A, 0x0017C, 0x0017C, 0x0017E, 0x0017E, 0x0017F, }; - -static const uint32_t nxt_unicode_block_003[128] nxt_aligned(64) = { +static const uint32_t nxt_unicode_block_003[128] nxt_aligned(64) = { 0x00180, 0x00253, 0x00183, 0x00183, 0x00185, 0x00185, 0x00254, 0x00188, 0x00188, 0x00256, 0x00257, 0x0018C, 0x0018C, 0x0018D, 0x001DD, 0x00259, 0x0025B, 0x00192, 0x00192, 0x00260, 0x00263, 0x00195, 0x00269, 0x00268, @@ -88,8 +84,7 @@ static const uint32_t nxt_unicode_block_003[128] nxt_aligned(64) = { 0x001F9, 0x001F9, 0x001FB, 0x001FB, 0x001FD, 0x001FD, 0x001FF, 0x001FF, }; - -static const uint32_t nxt_unicode_block_004[128] nxt_aligned(64) = { +static const uint32_t nxt_unicode_block_004[128] nxt_aligned(64) = { 0x00201, 0x00201, 0x00203, 0x00203, 0x00205, 0x00205, 0x00207, 0x00207, 0x00209, 0x00209, 0x0020B, 0x0020B, 0x0020D, 0x0020D, 0x0020F, 0x0020F, 0x00211, 0x00211, 0x00213, 0x00213, 0x00215, 0x00215, 0x00217, 0x00217, @@ -108,8 +103,7 @@ static const uint32_t nxt_unicode_block_004[128] nxt_aligned(64) = { 0x00278, 0x00279, 0x0027A, 0x0027B, 0x0027C, 0x0027D, 0x0027E, 0x0027F, }; - -static const uint32_t nxt_unicode_block_007[128] nxt_aligned(64) = { +static const uint32_t nxt_unicode_block_007[128] nxt_aligned(64) = { 0x00380, 0x00381, 0x00382, 0x00383, 0x00384, 0x00385, 0x003AC, 0x00387, 0x003AD, 0x003AE, 0x003AF, 0x0038B, 0x003CC, 0x0038D, 0x003CD, 0x003CE, 0x00390, 0x003B1, 0x003B2, 0x003B3, 0x003B4, 0x003B5, 0x003B6, 0x003B7, @@ -128,8 +122,7 @@ static const uint32_t nxt_unicode_block_007[128] nxt_aligned(64) = { 0x003F8, 0x003F9, 0x003FA, 0x003FB, 0x003FC, 0x003FD, 0x003FE, 0x003FF, }; - -static const uint32_t nxt_unicode_block_008[128] nxt_aligned(64) = { +static const uint32_t nxt_unicode_block_008[128] nxt_aligned(64) = { 0x00450, 0x00451, 0x00452, 0x00453, 0x00454, 0x00455, 0x00456, 0x00457, 0x00458, 0x00459, 0x0045A, 0x0045B, 0x0045C, 0x0045D, 0x0045E, 0x0045F, 0x00430, 0x00431, 0x00432, 0x00433, 0x00434, 0x00435, 0x00436, 0x00437, @@ -148,8 +141,7 @@ static const uint32_t nxt_unicode_block_008[128] nxt_aligned(64) = { 0x00479, 0x00479, 0x0047B, 0x0047B, 0x0047D, 0x0047D, 0x0047F, 0x0047F, }; - -static const uint32_t nxt_unicode_block_009[128] nxt_aligned(64) = { +static const uint32_t nxt_unicode_block_009[128] nxt_aligned(64) = { 0x00481, 0x00481, 0x00482, 0x00483, 0x00484, 0x00485, 0x00486, 0x00487, 0x00488, 0x00489, 0x0048A, 0x0048B, 0x0048C, 0x0048D, 0x0048E, 0x0048F, 0x00491, 0x00491, 0x00493, 0x00493, 0x00495, 0x00495, 0x00497, 0x00497, @@ -168,8 +160,7 @@ static const uint32_t nxt_unicode_block_009[128] nxt_aligned(64) = { 0x004F9, 0x004F9, 0x004FA, 0x004FB, 0x004FC, 0x004FD, 0x004FE, 0x004FF, }; - -static const uint32_t nxt_unicode_block_00a[128] nxt_aligned(64) = { +static const uint32_t nxt_unicode_block_00a[128] nxt_aligned(64) = { 0x00500, 0x00501, 0x00502, 0x00503, 0x00504, 0x00505, 0x00506, 0x00507, 0x00508, 0x00509, 0x0050A, 0x0050B, 0x0050C, 0x0050D, 0x0050E, 0x0050F, 0x00510, 0x00511, 0x00512, 0x00513, 0x00514, 0x00515, 0x00516, 0x00517, @@ -188,8 +179,7 @@ static const uint32_t nxt_unicode_block_00a[128] nxt_aligned(64) = { 0x00578, 0x00579, 0x0057A, 0x0057B, 0x0057C, 0x0057D, 0x0057E, 0x0057F, }; - -static const uint32_t nxt_unicode_block_03c[128] nxt_aligned(64) = { +static const uint32_t nxt_unicode_block_03c[128] nxt_aligned(64) = { 0x01E01, 0x01E01, 0x01E03, 0x01E03, 0x01E05, 0x01E05, 0x01E07, 0x01E07, 0x01E09, 0x01E09, 0x01E0B, 0x01E0B, 0x01E0D, 0x01E0D, 0x01E0F, 0x01E0F, 0x01E11, 0x01E11, 0x01E13, 0x01E13, 0x01E15, 0x01E15, 0x01E17, 0x01E17, @@ -208,8 +198,7 @@ static const uint32_t nxt_unicode_block_03c[128] nxt_aligned(64) = { 0x01E79, 0x01E79, 0x01E7B, 0x01E7B, 0x01E7D, 0x01E7D, 0x01E7F, 0x01E7F, }; - -static const uint32_t nxt_unicode_block_03d[128] nxt_aligned(64) = { +static const uint32_t nxt_unicode_block_03d[128] nxt_aligned(64) = { 0x01E81, 0x01E81, 0x01E83, 0x01E83, 0x01E85, 0x01E85, 0x01E87, 0x01E87, 0x01E89, 0x01E89, 0x01E8B, 0x01E8B, 0x01E8D, 0x01E8D, 0x01E8F, 0x01E8F, 0x01E91, 0x01E91, 0x01E93, 0x01E93, 0x01E95, 0x01E95, 0x01E96, 0x01E97, @@ -228,8 +217,7 @@ static const uint32_t nxt_unicode_block_03d[128] nxt_aligned(64) = { 0x01EF9, 0x01EF9, 0x01EFA, 0x01EFB, 0x01EFC, 0x01EFD, 0x01EFE, 0x01EFF, }; - -static const uint32_t nxt_unicode_block_03e[128] nxt_aligned(64) = { +static const uint32_t nxt_unicode_block_03e[128] nxt_aligned(64) = { 0x01F00, 0x01F01, 0x01F02, 0x01F03, 0x01F04, 0x01F05, 0x01F06, 0x01F07, 0x01F00, 0x01F01, 0x01F02, 0x01F03, 0x01F04, 0x01F05, 0x01F06, 0x01F07, 0x01F10, 0x01F11, 0x01F12, 0x01F13, 0x01F14, 0x01F15, 0x01F16, 0x01F17, @@ -248,8 +236,7 @@ static const uint32_t nxt_unicode_block_03e[128] nxt_aligned(64) = { 0x01F78, 0x01F79, 0x01F7A, 0x01F7B, 0x01F7C, 0x01F7D, 0x01F7E, 0x01F7F, }; - -static const uint32_t nxt_unicode_block_03f[128] nxt_aligned(64) = { +static const uint32_t nxt_unicode_block_03f[128] nxt_aligned(64) = { 0x01F80, 0x01F81, 0x01F82, 0x01F83, 0x01F84, 0x01F85, 0x01F86, 0x01F87, 0x01F80, 0x01F81, 0x01F82, 0x01F83, 0x01F84, 0x01F85, 0x01F86, 0x01F87, 0x01F90, 0x01F91, 0x01F92, 0x01F93, 0x01F94, 0x01F95, 0x01F96, 0x01F97, @@ -268,8 +255,7 @@ static const uint32_t nxt_unicode_block_03f[128] nxt_aligned(64) = { 0x01F78, 0x01F79, 0x01F7C, 0x01F7D, 0x01FF3, 0x01FFD, 0x01FFE, 0x01FFF, }; - -static const uint32_t nxt_unicode_block_042[128] nxt_aligned(64) = { +static const uint32_t nxt_unicode_block_042[128] nxt_aligned(64) = { 0x02100, 0x02101, 0x02102, 0x02103, 0x02104, 0x02105, 0x02106, 0x02107, 0x02108, 0x02109, 0x0210A, 0x0210B, 0x0210C, 0x0210D, 0x0210E, 0x0210F, 0x02110, 0x02111, 0x02112, 0x02113, 0x02114, 0x02115, 0x02116, 0x02117, @@ -288,8 +274,7 @@ static const uint32_t nxt_unicode_block_042[128] nxt_aligned(64) = { 0x02178, 0x02179, 0x0217A, 0x0217B, 0x0217C, 0x0217D, 0x0217E, 0x0217F, }; - -static const uint32_t nxt_unicode_block_1fe[59] nxt_aligned(64) = { +static const uint32_t nxt_unicode_block_1fe[59] nxt_aligned(64) = { 0x0FF00, 0x0FF01, 0x0FF02, 0x0FF03, 0x0FF04, 0x0FF05, 0x0FF06, 0x0FF07, 0x0FF08, 0x0FF09, 0x0FF0A, 0x0FF0B, 0x0FF0C, 0x0FF0D, 0x0FF0E, 0x0FF0F, 0x0FF10, 0x0FF11, 0x0FF12, 0x0FF13, 0x0FF14, 0x0FF15, 0x0FF16, 0x0FF17, @@ -300,8 +285,7 @@ static const uint32_t nxt_unicode_block_1fe[59] nxt_aligned(64) = { 0x0FF58, 0x0FF59, 0x0FF5A, }; - -static const uint32_t *nxt_unicode_blocks[] nxt_aligned(64) = { +static const uint32_t *nxt_unicode_blocks[] nxt_aligned(64) = { nxt_unicode_block_000, nxt_unicode_block_001, nxt_unicode_block_002, diff --git a/src/nxt_unit.c b/src/nxt_unit.c index 966a6c0fa..bc934d01e 100644 --- a/src/nxt_unit.c +++ b/src/nxt_unit.c @@ -20,119 +20,127 @@ #include #endif -#define NXT_UNIT_MAX_PLAIN_SIZE 1024 -#define NXT_UNIT_LOCAL_BUF_SIZE \ - (NXT_UNIT_MAX_PLAIN_SIZE + sizeof(nxt_port_msg_t)) +#define NXT_UNIT_MAX_PLAIN_SIZE 1024 +#define NXT_UNIT_LOCAL_BUF_SIZE \ + (NXT_UNIT_MAX_PLAIN_SIZE + sizeof(nxt_port_msg_t)) enum { - NXT_QUIT_NORMAL = 0, - NXT_QUIT_GRACEFUL = 1, + NXT_QUIT_NORMAL = 0, + NXT_QUIT_GRACEFUL = 1, }; -typedef struct nxt_unit_impl_s nxt_unit_impl_t; -typedef struct nxt_unit_mmap_s nxt_unit_mmap_t; -typedef struct nxt_unit_mmaps_s nxt_unit_mmaps_t; -typedef struct nxt_unit_process_s nxt_unit_process_t; -typedef struct nxt_unit_mmap_buf_s nxt_unit_mmap_buf_t; -typedef struct nxt_unit_recv_msg_s nxt_unit_recv_msg_t; -typedef struct nxt_unit_read_buf_s nxt_unit_read_buf_t; -typedef struct nxt_unit_ctx_impl_s nxt_unit_ctx_impl_t; -typedef struct nxt_unit_port_impl_s nxt_unit_port_impl_t; -typedef struct nxt_unit_request_info_impl_s nxt_unit_request_info_impl_t; -typedef struct nxt_unit_websocket_frame_impl_s nxt_unit_websocket_frame_impl_t; +typedef struct nxt_unit_impl_s nxt_unit_impl_t; +typedef struct nxt_unit_mmap_s nxt_unit_mmap_t; +typedef struct nxt_unit_mmaps_s nxt_unit_mmaps_t; +typedef struct nxt_unit_process_s nxt_unit_process_t; +typedef struct nxt_unit_mmap_buf_s nxt_unit_mmap_buf_t; +typedef struct nxt_unit_recv_msg_s nxt_unit_recv_msg_t; +typedef struct nxt_unit_read_buf_s nxt_unit_read_buf_t; +typedef struct nxt_unit_ctx_impl_s nxt_unit_ctx_impl_t; +typedef struct nxt_unit_port_impl_s nxt_unit_port_impl_t; +typedef struct nxt_unit_request_info_impl_s nxt_unit_request_info_impl_t; +typedef struct nxt_unit_websocket_frame_impl_s nxt_unit_websocket_frame_impl_t; static nxt_unit_impl_t *nxt_unit_create(nxt_unit_init_t *init); static int nxt_unit_ctx_init(nxt_unit_impl_t *lib, - nxt_unit_ctx_impl_t *ctx_impl, void *data); + nxt_unit_ctx_impl_t *ctx_impl, void *data); nxt_inline void nxt_unit_ctx_use(nxt_unit_ctx_t *ctx); nxt_inline void nxt_unit_ctx_release(nxt_unit_ctx_t *ctx); nxt_inline void nxt_unit_lib_use(nxt_unit_impl_t *lib); nxt_inline void nxt_unit_lib_release(nxt_unit_impl_t *lib); nxt_inline void nxt_unit_mmap_buf_insert(nxt_unit_mmap_buf_t **head, - nxt_unit_mmap_buf_t *mmap_buf); + nxt_unit_mmap_buf_t *mmap_buf); nxt_inline void nxt_unit_mmap_buf_insert_tail(nxt_unit_mmap_buf_t **prev, - nxt_unit_mmap_buf_t *mmap_buf); + nxt_unit_mmap_buf_t *mmap_buf); nxt_inline void nxt_unit_mmap_buf_unlink(nxt_unit_mmap_buf_t *mmap_buf); static int nxt_unit_read_env(nxt_unit_port_t *ready_port, - nxt_unit_port_t *router_port, nxt_unit_port_t *read_port, - int *shared_port_fd, int *shared_queue_fd, - int *log_fd, uint32_t *stream, uint32_t *shm_limit, - uint32_t *request_limit); + nxt_unit_port_t *router_port, + nxt_unit_port_t *read_port, int *shared_port_fd, + int *shared_queue_fd, int *log_fd, + uint32_t *stream, uint32_t *shm_limit, + uint32_t *request_limit); static int nxt_unit_ready(nxt_unit_ctx_t *ctx, int ready_fd, uint32_t stream, - int queue_fd); + int queue_fd); static int nxt_unit_process_msg(nxt_unit_ctx_t *ctx, nxt_unit_read_buf_t *rbuf, - nxt_unit_request_info_t **preq); + nxt_unit_request_info_t **preq); static int nxt_unit_process_new_port(nxt_unit_ctx_t *ctx, - nxt_unit_recv_msg_t *recv_msg); + nxt_unit_recv_msg_t *recv_msg); static int nxt_unit_ctx_ready(nxt_unit_ctx_t *ctx); static int nxt_unit_process_req_headers(nxt_unit_ctx_t *ctx, - nxt_unit_recv_msg_t *recv_msg, nxt_unit_request_info_t **preq); + nxt_unit_recv_msg_t *recv_msg, + nxt_unit_request_info_t **preq); static int nxt_unit_process_req_body(nxt_unit_ctx_t *ctx, - nxt_unit_recv_msg_t *recv_msg); + nxt_unit_recv_msg_t *recv_msg); static int nxt_unit_request_check_response_port(nxt_unit_request_info_t *req, - nxt_unit_port_id_t *port_id); + nxt_unit_port_id_t *port_id); static int nxt_unit_send_req_headers_ack(nxt_unit_request_info_t *req); static int nxt_unit_process_websocket(nxt_unit_ctx_t *ctx, - nxt_unit_recv_msg_t *recv_msg); + nxt_unit_recv_msg_t *recv_msg); static int nxt_unit_process_shm_ack(nxt_unit_ctx_t *ctx); -static nxt_unit_request_info_impl_t *nxt_unit_request_info_get( - nxt_unit_ctx_t *ctx); +static nxt_unit_request_info_impl_t * +nxt_unit_request_info_get(nxt_unit_ctx_t *ctx); static void nxt_unit_request_info_release(nxt_unit_request_info_t *req); static void nxt_unit_request_info_free(nxt_unit_request_info_impl_t *req); -static nxt_unit_websocket_frame_impl_t *nxt_unit_websocket_frame_get( - nxt_unit_ctx_t *ctx); +static nxt_unit_websocket_frame_impl_t * +nxt_unit_websocket_frame_get(nxt_unit_ctx_t *ctx); static void nxt_unit_websocket_frame_release(nxt_unit_websocket_frame_t *ws); static void nxt_unit_websocket_frame_free(nxt_unit_ctx_t *ctx, - nxt_unit_websocket_frame_impl_t *ws); + nxt_unit_websocket_frame_impl_t *ws); static nxt_unit_mmap_buf_t *nxt_unit_mmap_buf_get(nxt_unit_ctx_t *ctx); static void nxt_unit_mmap_buf_release(nxt_unit_mmap_buf_t *mmap_buf); static int nxt_unit_mmap_buf_send(nxt_unit_request_info_t *req, - nxt_unit_mmap_buf_t *mmap_buf, int last); + nxt_unit_mmap_buf_t *mmap_buf, int last); static void nxt_unit_mmap_buf_free(nxt_unit_mmap_buf_t *mmap_buf); static void nxt_unit_free_outgoing_buf(nxt_unit_mmap_buf_t *mmap_buf); static nxt_unit_read_buf_t *nxt_unit_read_buf_get(nxt_unit_ctx_t *ctx); -static nxt_unit_read_buf_t *nxt_unit_read_buf_get_impl( - nxt_unit_ctx_impl_t *ctx_impl); +static nxt_unit_read_buf_t * +nxt_unit_read_buf_get_impl(nxt_unit_ctx_impl_t *ctx_impl); static void nxt_unit_read_buf_release(nxt_unit_ctx_t *ctx, - nxt_unit_read_buf_t *rbuf); -static nxt_unit_mmap_buf_t *nxt_unit_request_preread( - nxt_unit_request_info_t *req, size_t size); + nxt_unit_read_buf_t *rbuf); +static nxt_unit_mmap_buf_t * +nxt_unit_request_preread(nxt_unit_request_info_t *req, size_t size); static ssize_t nxt_unit_buf_read(nxt_unit_buf_t **b, uint64_t *len, void *dst, - size_t size); + size_t size); static nxt_port_mmap_header_t *nxt_unit_mmap_get(nxt_unit_ctx_t *ctx, - nxt_unit_port_t *port, nxt_chunk_id_t *c, int *n, int min_n); + nxt_unit_port_t *port, + nxt_chunk_id_t *c, int *n, + int min_n); static int nxt_unit_send_oosm(nxt_unit_ctx_t *ctx, nxt_unit_port_t *port); static int nxt_unit_wait_shm_ack(nxt_unit_ctx_t *ctx); static nxt_unit_mmap_t *nxt_unit_mmap_at(nxt_unit_mmaps_t *mmaps, uint32_t i); static nxt_port_mmap_header_t *nxt_unit_new_mmap(nxt_unit_ctx_t *ctx, - nxt_unit_port_t *port, int n); + nxt_unit_port_t *port, int n); static int nxt_unit_shm_open(nxt_unit_ctx_t *ctx, size_t size); static int nxt_unit_send_mmap(nxt_unit_ctx_t *ctx, nxt_unit_port_t *port, - int fd); -static int nxt_unit_get_outgoing_buf(nxt_unit_ctx_t *ctx, - nxt_unit_port_t *port, uint32_t size, - uint32_t min_size, nxt_unit_mmap_buf_t *mmap_buf, char *local_buf); + int fd); +static int nxt_unit_get_outgoing_buf(nxt_unit_ctx_t *ctx, nxt_unit_port_t *port, + uint32_t size, uint32_t min_size, + nxt_unit_mmap_buf_t *mmap_buf, + char *local_buf); static int nxt_unit_incoming_mmap(nxt_unit_ctx_t *ctx, pid_t pid, int fd); static void nxt_unit_awake_ctx(nxt_unit_ctx_t *ctx, - nxt_unit_ctx_impl_t *ctx_impl); + nxt_unit_ctx_impl_t *ctx_impl); static int nxt_unit_mmaps_init(nxt_unit_mmaps_t *mmaps); nxt_inline void nxt_unit_process_use(nxt_unit_process_t *process); nxt_inline void nxt_unit_process_release(nxt_unit_process_t *process); static void nxt_unit_mmaps_destroy(nxt_unit_mmaps_t *mmaps); static int nxt_unit_check_rbuf_mmap(nxt_unit_ctx_t *ctx, - nxt_unit_mmaps_t *mmaps, pid_t pid, uint32_t id, - nxt_port_mmap_header_t **hdr, nxt_unit_read_buf_t *rbuf); + nxt_unit_mmaps_t *mmaps, pid_t pid, + uint32_t id, nxt_port_mmap_header_t **hdr, + nxt_unit_read_buf_t *rbuf); static int nxt_unit_mmap_read(nxt_unit_ctx_t *ctx, - nxt_unit_recv_msg_t *recv_msg, nxt_unit_read_buf_t *rbuf); + nxt_unit_recv_msg_t *recv_msg, + nxt_unit_read_buf_t *rbuf); static int nxt_unit_get_mmap(nxt_unit_ctx_t *ctx, pid_t pid, uint32_t id); static void nxt_unit_mmap_release(nxt_unit_ctx_t *ctx, - nxt_port_mmap_header_t *hdr, void *start, uint32_t size); + nxt_port_mmap_header_t *hdr, void *start, + uint32_t size); static int nxt_unit_send_shm_ack(nxt_unit_ctx_t *ctx, pid_t pid); static nxt_unit_process_t *nxt_unit_process_get(nxt_unit_ctx_t *ctx, pid_t pid); static nxt_unit_process_t *nxt_unit_process_find(nxt_unit_impl_t *lib, - pid_t pid, int remove); + pid_t pid, int remove); static nxt_unit_process_t *nxt_unit_process_pop_first(nxt_unit_impl_t *lib); static int nxt_unit_run_once_impl(nxt_unit_ctx_t *ctx); static int nxt_unit_read_buf(nxt_unit_ctx_t *ctx, nxt_unit_read_buf_t *rbuf); @@ -144,6665 +152,6147 @@ nxt_inline int nxt_unit_is_read_socket(nxt_unit_read_buf_t *rbuf); nxt_inline int nxt_unit_is_shm_ack(nxt_unit_read_buf_t *rbuf); nxt_inline int nxt_unit_is_quit(nxt_unit_read_buf_t *rbuf); static int nxt_unit_process_port_msg_impl(nxt_unit_ctx_t *ctx, - nxt_unit_port_t *port); + nxt_unit_port_t *port); static void nxt_unit_ctx_free(nxt_unit_ctx_impl_t *ctx_impl); static nxt_unit_port_t *nxt_unit_create_port(nxt_unit_ctx_t *ctx); static int nxt_unit_send_port(nxt_unit_ctx_t *ctx, nxt_unit_port_t *dst, - nxt_unit_port_t *port, int queue_fd); + nxt_unit_port_t *port, int queue_fd); nxt_inline void nxt_unit_port_use(nxt_unit_port_t *port); nxt_inline void nxt_unit_port_release(nxt_unit_port_t *port); static nxt_unit_port_t *nxt_unit_add_port(nxt_unit_ctx_t *ctx, - nxt_unit_port_t *port, void *queue); + nxt_unit_port_t *port, void *queue); static void nxt_unit_process_awaiting_req(nxt_unit_ctx_t *ctx, - nxt_queue_t *awaiting_req); + nxt_queue_t *awaiting_req); static void nxt_unit_remove_port(nxt_unit_impl_t *lib, nxt_unit_ctx_t *ctx, - nxt_unit_port_id_t *port_id); -static nxt_unit_port_t *nxt_unit_remove_port_unsafe(nxt_unit_impl_t *lib, - nxt_unit_port_id_t *port_id); + nxt_unit_port_id_t *port_id); +static nxt_unit_port_t * +nxt_unit_remove_port_unsafe(nxt_unit_impl_t *lib, nxt_unit_port_id_t *port_id); static void nxt_unit_remove_pid(nxt_unit_impl_t *lib, pid_t pid); static void nxt_unit_remove_process(nxt_unit_impl_t *lib, - nxt_unit_process_t *process); + nxt_unit_process_t *process); static void nxt_unit_quit(nxt_unit_ctx_t *ctx, uint8_t quit_param); static int nxt_unit_get_port(nxt_unit_ctx_t *ctx, nxt_unit_port_id_t *port_id); -static ssize_t nxt_unit_port_send(nxt_unit_ctx_t *ctx, - nxt_unit_port_t *port, const void *buf, size_t buf_size, - const nxt_send_oob_t *oob); -static ssize_t nxt_unit_sendmsg(nxt_unit_ctx_t *ctx, int fd, - const void *buf, size_t buf_size, const nxt_send_oob_t *oob); +static ssize_t nxt_unit_port_send(nxt_unit_ctx_t *ctx, nxt_unit_port_t *port, + const void *buf, size_t buf_size, + const nxt_send_oob_t *oob); +static ssize_t nxt_unit_sendmsg(nxt_unit_ctx_t *ctx, int fd, const void *buf, + size_t buf_size, const nxt_send_oob_t *oob); static int nxt_unit_ctx_port_recv(nxt_unit_ctx_t *ctx, nxt_unit_port_t *port, - nxt_unit_read_buf_t *rbuf); + nxt_unit_read_buf_t *rbuf); nxt_inline void nxt_unit_rbuf_cpy(nxt_unit_read_buf_t *dst, - nxt_unit_read_buf_t *src); + nxt_unit_read_buf_t *src); static int nxt_unit_shared_port_recv(nxt_unit_ctx_t *ctx, nxt_unit_port_t *port, - nxt_unit_read_buf_t *rbuf); + nxt_unit_read_buf_t *rbuf); static int nxt_unit_port_recv(nxt_unit_ctx_t *ctx, nxt_unit_port_t *port, - nxt_unit_read_buf_t *rbuf); + nxt_unit_read_buf_t *rbuf); static int nxt_unit_port_queue_recv(nxt_unit_port_t *port, - nxt_unit_read_buf_t *rbuf); + nxt_unit_read_buf_t *rbuf); static int nxt_unit_app_queue_recv(nxt_unit_ctx_t *ctx, nxt_unit_port_t *port, - nxt_unit_read_buf_t *rbuf); + nxt_unit_read_buf_t *rbuf); nxt_inline int nxt_unit_close(int fd); static int nxt_unit_fd_blocking(int fd); static int nxt_unit_port_hash_add(nxt_lvlhsh_t *port_hash, - nxt_unit_port_t *port); + nxt_unit_port_t *port); static nxt_unit_port_t *nxt_unit_port_hash_find(nxt_lvlhsh_t *port_hash, - nxt_unit_port_id_t *port_id, int remove); + nxt_unit_port_id_t *port_id, + int remove); static int nxt_unit_request_hash_add(nxt_unit_ctx_t *ctx, - nxt_unit_request_info_t *req); -static nxt_unit_request_info_t *nxt_unit_request_hash_find( - nxt_unit_ctx_t *ctx, uint32_t stream, int remove); + nxt_unit_request_info_t *req); +static nxt_unit_request_info_t * +nxt_unit_request_hash_find(nxt_unit_ctx_t *ctx, uint32_t stream, int remove); -static char * nxt_unit_snprint_prefix(char *p, char *end, pid_t pid, - int level); +static char *nxt_unit_snprint_prefix(char *p, char *end, pid_t pid, int level); static void *nxt_unit_lvlhsh_alloc(void *data, size_t size); static void nxt_unit_lvlhsh_free(void *data, void *p); static int nxt_unit_memcasecmp(const void *p1, const void *p2, size_t length); - struct nxt_unit_mmap_buf_s { - nxt_unit_buf_t buf; + nxt_unit_buf_t buf; - nxt_unit_mmap_buf_t *next; - nxt_unit_mmap_buf_t **prev; + nxt_unit_mmap_buf_t *next; + nxt_unit_mmap_buf_t **prev; - nxt_port_mmap_header_t *hdr; - nxt_unit_request_info_t *req; - nxt_unit_ctx_impl_t *ctx_impl; - char *free_ptr; - char *plain_ptr; + nxt_port_mmap_header_t *hdr; + nxt_unit_request_info_t *req; + nxt_unit_ctx_impl_t *ctx_impl; + char *free_ptr; + char *plain_ptr; }; - struct nxt_unit_recv_msg_s { - uint32_t stream; - nxt_pid_t pid; - nxt_port_id_t reply_port; + uint32_t stream; + nxt_pid_t pid; + nxt_port_id_t reply_port; - uint8_t last; /* 1 bit */ - uint8_t mmap; /* 1 bit */ + uint8_t last; /* 1 bit */ + uint8_t mmap; /* 1 bit */ - void *start; - uint32_t size; + void *start; + uint32_t size; - int fd[2]; + int fd[2]; - nxt_unit_mmap_buf_t *incoming_buf; + nxt_unit_mmap_buf_t *incoming_buf; }; - typedef enum { - NXT_UNIT_RS_START = 0, - NXT_UNIT_RS_RESPONSE_INIT, - NXT_UNIT_RS_RESPONSE_HAS_CONTENT, - NXT_UNIT_RS_RESPONSE_SENT, - NXT_UNIT_RS_RELEASED, + NXT_UNIT_RS_START = 0, + NXT_UNIT_RS_RESPONSE_INIT, + NXT_UNIT_RS_RESPONSE_HAS_CONTENT, + NXT_UNIT_RS_RESPONSE_SENT, + NXT_UNIT_RS_RELEASED, } nxt_unit_req_state_t; - struct nxt_unit_request_info_impl_s { - nxt_unit_request_info_t req; + nxt_unit_request_info_t req; - uint32_t stream; + uint32_t stream; - nxt_unit_mmap_buf_t *outgoing_buf; - nxt_unit_mmap_buf_t *incoming_buf; + nxt_unit_mmap_buf_t *outgoing_buf; + nxt_unit_mmap_buf_t *incoming_buf; - nxt_unit_req_state_t state; - uint8_t websocket; - uint8_t in_hash; + nxt_unit_req_state_t state; + uint8_t websocket; + uint8_t in_hash; - /* for nxt_unit_ctx_impl_t.free_req or active_req */ - nxt_queue_link_t link; - /* for nxt_unit_port_impl_t.awaiting_req */ - nxt_queue_link_t port_wait_link; + /* for nxt_unit_ctx_impl_t.free_req or active_req */ + nxt_queue_link_t link; + /* for nxt_unit_port_impl_t.awaiting_req */ + nxt_queue_link_t port_wait_link; - char extra_data[]; + char extra_data[]; }; - struct nxt_unit_websocket_frame_impl_s { - nxt_unit_websocket_frame_t ws; + nxt_unit_websocket_frame_t ws; - nxt_unit_mmap_buf_t *buf; + nxt_unit_mmap_buf_t *buf; - nxt_queue_link_t link; + nxt_queue_link_t link; - nxt_unit_ctx_impl_t *ctx_impl; + nxt_unit_ctx_impl_t *ctx_impl; }; - struct nxt_unit_read_buf_s { - nxt_queue_link_t link; - nxt_unit_ctx_impl_t *ctx_impl; - ssize_t size; - nxt_recv_oob_t oob; - char buf[16384]; + nxt_queue_link_t link; + nxt_unit_ctx_impl_t *ctx_impl; + ssize_t size; + nxt_recv_oob_t oob; + char buf[16384]; }; - struct nxt_unit_ctx_impl_s { - nxt_unit_ctx_t ctx; + nxt_unit_ctx_t ctx; - nxt_atomic_t use_count; - nxt_atomic_t wait_items; + nxt_atomic_t use_count; + nxt_atomic_t wait_items; - pthread_mutex_t mutex; + pthread_mutex_t mutex; - nxt_unit_port_t *read_port; + nxt_unit_port_t *read_port; - nxt_queue_link_t link; + nxt_queue_link_t link; - nxt_unit_mmap_buf_t *free_buf; + nxt_unit_mmap_buf_t *free_buf; - /* of nxt_unit_request_info_impl_t */ - nxt_queue_t free_req; + /* of nxt_unit_request_info_impl_t */ + nxt_queue_t free_req; - /* of nxt_unit_websocket_frame_impl_t */ - nxt_queue_t free_ws; + /* of nxt_unit_websocket_frame_impl_t */ + nxt_queue_t free_ws; - /* of nxt_unit_request_info_impl_t */ - nxt_queue_t active_req; + /* of nxt_unit_request_info_impl_t */ + nxt_queue_t active_req; - /* of nxt_unit_request_info_impl_t */ - nxt_lvlhsh_t requests; + /* of nxt_unit_request_info_impl_t */ + nxt_lvlhsh_t requests; - /* of nxt_unit_request_info_impl_t */ - nxt_queue_t ready_req; + /* of nxt_unit_request_info_impl_t */ + nxt_queue_t ready_req; - /* of nxt_unit_read_buf_t */ - nxt_queue_t pending_rbuf; + /* of nxt_unit_read_buf_t */ + nxt_queue_t pending_rbuf; - /* of nxt_unit_read_buf_t */ - nxt_queue_t free_rbuf; + /* of nxt_unit_read_buf_t */ + nxt_queue_t free_rbuf; - uint8_t online; /* 1 bit */ - uint8_t ready; /* 1 bit */ - uint8_t quit_param; + uint8_t online; /* 1 bit */ + uint8_t ready; /* 1 bit */ + uint8_t quit_param; - nxt_unit_mmap_buf_t ctx_buf[2]; - nxt_unit_read_buf_t ctx_read_buf; + nxt_unit_mmap_buf_t ctx_buf[2]; + nxt_unit_read_buf_t ctx_read_buf; - nxt_unit_request_info_impl_t req; + nxt_unit_request_info_impl_t req; }; - struct nxt_unit_mmap_s { - nxt_port_mmap_header_t *hdr; - pthread_t src_thread; + nxt_port_mmap_header_t *hdr; + pthread_t src_thread; - /* of nxt_unit_read_buf_t */ - nxt_queue_t awaiting_rbuf; + /* of nxt_unit_read_buf_t */ + nxt_queue_t awaiting_rbuf; }; - struct nxt_unit_mmaps_s { - pthread_mutex_t mutex; - uint32_t size; - uint32_t cap; - nxt_atomic_t allocated_chunks; - nxt_unit_mmap_t *elts; + pthread_mutex_t mutex; + uint32_t size; + uint32_t cap; + nxt_atomic_t allocated_chunks; + nxt_unit_mmap_t *elts; }; - struct nxt_unit_impl_s { - nxt_unit_t unit; - nxt_unit_callbacks_t callbacks; + nxt_unit_t unit; + nxt_unit_callbacks_t callbacks; - nxt_atomic_t use_count; - nxt_atomic_t request_count; + nxt_atomic_t use_count; + nxt_atomic_t request_count; - uint32_t request_data_size; - uint32_t shm_mmap_limit; - uint32_t request_limit; + uint32_t request_data_size; + uint32_t shm_mmap_limit; + uint32_t request_limit; - pthread_mutex_t mutex; + pthread_mutex_t mutex; - nxt_lvlhsh_t processes; /* of nxt_unit_process_t */ - nxt_lvlhsh_t ports; /* of nxt_unit_port_impl_t */ + nxt_lvlhsh_t processes; /* of nxt_unit_process_t */ + nxt_lvlhsh_t ports; /* of nxt_unit_port_impl_t */ - nxt_unit_port_t *router_port; - nxt_unit_port_t *shared_port; + nxt_unit_port_t *router_port; + nxt_unit_port_t *shared_port; - nxt_queue_t contexts; /* of nxt_unit_ctx_impl_t */ + nxt_queue_t contexts; /* of nxt_unit_ctx_impl_t */ - nxt_unit_mmaps_t incoming; - nxt_unit_mmaps_t outgoing; + nxt_unit_mmaps_t incoming; + nxt_unit_mmaps_t outgoing; - pid_t pid; - int log_fd; + pid_t pid; + int log_fd; - nxt_unit_ctx_impl_t main_ctx; + nxt_unit_ctx_impl_t main_ctx; }; - struct nxt_unit_port_impl_s { - nxt_unit_port_t port; + nxt_unit_port_t port; - nxt_atomic_t use_count; + nxt_atomic_t use_count; - /* for nxt_unit_process_t.ports */ - nxt_queue_link_t link; - nxt_unit_process_t *process; + /* for nxt_unit_process_t.ports */ + nxt_queue_link_t link; + nxt_unit_process_t *process; - /* of nxt_unit_request_info_impl_t */ - nxt_queue_t awaiting_req; + /* of nxt_unit_request_info_impl_t */ + nxt_queue_t awaiting_req; - int ready; + int ready; - void *queue; + void *queue; - int from_socket; - nxt_unit_read_buf_t *socket_rbuf; + int from_socket; + nxt_unit_read_buf_t *socket_rbuf; }; - struct nxt_unit_process_s { - pid_t pid; + pid_t pid; - nxt_queue_t ports; /* of nxt_unit_port_impl_t */ + nxt_queue_t ports; /* of nxt_unit_port_impl_t */ - nxt_unit_impl_t *lib; + nxt_unit_impl_t *lib; - nxt_atomic_t use_count; + nxt_atomic_t use_count; - uint32_t next_port_id; + uint32_t next_port_id; }; - /* Explicitly using 32 bit types to avoid possible alignment. */ typedef struct { - int32_t pid; - uint32_t id; + int32_t pid; + uint32_t id; } nxt_unit_port_hash_id_t; +static pid_t nxt_unit_pid; -static pid_t nxt_unit_pid; - +nxt_unit_ctx_t *nxt_unit_init(nxt_unit_init_t *init) { + int rc, queue_fd, shared_queue_fd; + void *mem; + uint32_t ready_stream, shm_limit, request_limit; + nxt_unit_ctx_t *ctx; + nxt_unit_impl_t *lib; + nxt_unit_port_t ready_port, router_port, read_port, shared_port; -nxt_unit_ctx_t * -nxt_unit_init(nxt_unit_init_t *init) -{ - int rc, queue_fd, shared_queue_fd; - void *mem; - uint32_t ready_stream, shm_limit, request_limit; - nxt_unit_ctx_t *ctx; - nxt_unit_impl_t *lib; - nxt_unit_port_t ready_port, router_port, read_port, shared_port; + nxt_unit_pid = getpid(); - nxt_unit_pid = getpid(); - - lib = nxt_unit_create(init); - if (nxt_slow_path(lib == NULL)) { - return NULL; + lib = nxt_unit_create(init); + if (nxt_slow_path(lib == NULL)) { + return NULL; + } + + queue_fd = -1; + mem = MAP_FAILED; + shared_port.out_fd = -1; + shared_port.data = NULL; + + if (init->ready_port.id.pid != 0 && init->ready_stream != 0 && + init->read_port.id.pid != 0) { + ready_port = init->ready_port; + ready_stream = init->ready_stream; + router_port = init->router_port; + read_port = init->read_port; + lib->log_fd = init->log_fd; + + nxt_unit_port_id_init(&ready_port.id, ready_port.id.pid, ready_port.id.id); + nxt_unit_port_id_init(&router_port.id, router_port.id.pid, + router_port.id.id); + nxt_unit_port_id_init(&read_port.id, read_port.id.pid, read_port.id.id); + + shared_port.in_fd = init->shared_port_fd; + shared_queue_fd = init->shared_queue_fd; + + } else { + rc = nxt_unit_read_env(&ready_port, &router_port, &read_port, + &shared_port.in_fd, &shared_queue_fd, &lib->log_fd, + &ready_stream, &shm_limit, &request_limit); + if (nxt_slow_path(rc != NXT_UNIT_OK)) { + goto fail; } - queue_fd = -1; - mem = MAP_FAILED; - shared_port.out_fd = -1; - shared_port.data = NULL; - - if (init->ready_port.id.pid != 0 - && init->ready_stream != 0 - && init->read_port.id.pid != 0) - { - ready_port = init->ready_port; - ready_stream = init->ready_stream; - router_port = init->router_port; - read_port = init->read_port; - lib->log_fd = init->log_fd; - - nxt_unit_port_id_init(&ready_port.id, ready_port.id.pid, - ready_port.id.id); - nxt_unit_port_id_init(&router_port.id, router_port.id.pid, - router_port.id.id); - nxt_unit_port_id_init(&read_port.id, read_port.id.pid, - read_port.id.id); - - shared_port.in_fd = init->shared_port_fd; - shared_queue_fd = init->shared_queue_fd; - - } else { - rc = nxt_unit_read_env(&ready_port, &router_port, &read_port, - &shared_port.in_fd, &shared_queue_fd, - &lib->log_fd, &ready_stream, &shm_limit, - &request_limit); - if (nxt_slow_path(rc != NXT_UNIT_OK)) { - goto fail; - } - - lib->shm_mmap_limit = (shm_limit + PORT_MMAP_DATA_SIZE - 1) - / PORT_MMAP_DATA_SIZE; - lib->request_limit = request_limit; - } + lib->shm_mmap_limit = + (shm_limit + PORT_MMAP_DATA_SIZE - 1) / PORT_MMAP_DATA_SIZE; + lib->request_limit = request_limit; + } - if (nxt_slow_path(lib->shm_mmap_limit < 1)) { - lib->shm_mmap_limit = 1; - } + if (nxt_slow_path(lib->shm_mmap_limit < 1)) { + lib->shm_mmap_limit = 1; + } - lib->pid = read_port.id.pid; - nxt_unit_pid = lib->pid; + lib->pid = read_port.id.pid; + nxt_unit_pid = lib->pid; - ctx = &lib->main_ctx.ctx; + ctx = &lib->main_ctx.ctx; - rc = nxt_unit_fd_blocking(router_port.out_fd); - if (nxt_slow_path(rc != NXT_UNIT_OK)) { - goto fail; - } + rc = nxt_unit_fd_blocking(router_port.out_fd); + if (nxt_slow_path(rc != NXT_UNIT_OK)) { + goto fail; + } - lib->router_port = nxt_unit_add_port(ctx, &router_port, NULL); - if (nxt_slow_path(lib->router_port == NULL)) { - nxt_unit_alert(NULL, "failed to add router_port"); + lib->router_port = nxt_unit_add_port(ctx, &router_port, NULL); + if (nxt_slow_path(lib->router_port == NULL)) { + nxt_unit_alert(NULL, "failed to add router_port"); - goto fail; - } + goto fail; + } - queue_fd = nxt_unit_shm_open(ctx, sizeof(nxt_port_queue_t)); - if (nxt_slow_path(queue_fd == -1)) { - goto fail; - } + queue_fd = nxt_unit_shm_open(ctx, sizeof(nxt_port_queue_t)); + if (nxt_slow_path(queue_fd == -1)) { + goto fail; + } - mem = mmap(NULL, sizeof(nxt_port_queue_t), - PROT_READ | PROT_WRITE, MAP_SHARED, queue_fd, 0); - if (nxt_slow_path(mem == MAP_FAILED)) { - nxt_unit_alert(ctx, "mmap(%d) failed: %s (%d)", queue_fd, - strerror(errno), errno); + mem = mmap(NULL, sizeof(nxt_port_queue_t), PROT_READ | PROT_WRITE, MAP_SHARED, + queue_fd, 0); + if (nxt_slow_path(mem == MAP_FAILED)) { + nxt_unit_alert(ctx, "mmap(%d) failed: %s (%d)", queue_fd, strerror(errno), + errno); - goto fail; - } + goto fail; + } - nxt_port_queue_init(mem); + nxt_port_queue_init(mem); - rc = nxt_unit_fd_blocking(read_port.in_fd); - if (nxt_slow_path(rc != NXT_UNIT_OK)) { - goto fail; - } + rc = nxt_unit_fd_blocking(read_port.in_fd); + if (nxt_slow_path(rc != NXT_UNIT_OK)) { + goto fail; + } - lib->main_ctx.read_port = nxt_unit_add_port(ctx, &read_port, mem); - if (nxt_slow_path(lib->main_ctx.read_port == NULL)) { - nxt_unit_alert(NULL, "failed to add read_port"); + lib->main_ctx.read_port = nxt_unit_add_port(ctx, &read_port, mem); + if (nxt_slow_path(lib->main_ctx.read_port == NULL)) { + nxt_unit_alert(NULL, "failed to add read_port"); - goto fail; - } + goto fail; + } - rc = nxt_unit_fd_blocking(ready_port.out_fd); - if (nxt_slow_path(rc != NXT_UNIT_OK)) { - goto fail; - } + rc = nxt_unit_fd_blocking(ready_port.out_fd); + if (nxt_slow_path(rc != NXT_UNIT_OK)) { + goto fail; + } - nxt_unit_port_id_init(&shared_port.id, read_port.id.pid, - NXT_UNIT_SHARED_PORT_ID); + nxt_unit_port_id_init(&shared_port.id, read_port.id.pid, + NXT_UNIT_SHARED_PORT_ID); - mem = mmap(NULL, sizeof(nxt_app_queue_t), PROT_READ | PROT_WRITE, - MAP_SHARED, shared_queue_fd, 0); - if (nxt_slow_path(mem == MAP_FAILED)) { - nxt_unit_alert(ctx, "mmap(%d) failed: %s (%d)", shared_queue_fd, - strerror(errno), errno); + mem = mmap(NULL, sizeof(nxt_app_queue_t), PROT_READ | PROT_WRITE, MAP_SHARED, + shared_queue_fd, 0); + if (nxt_slow_path(mem == MAP_FAILED)) { + nxt_unit_alert(ctx, "mmap(%d) failed: %s (%d)", shared_queue_fd, + strerror(errno), errno); - goto fail; - } + goto fail; + } - nxt_unit_close(shared_queue_fd); + nxt_unit_close(shared_queue_fd); - lib->shared_port = nxt_unit_add_port(ctx, &shared_port, mem); - if (nxt_slow_path(lib->shared_port == NULL)) { - nxt_unit_alert(NULL, "failed to add shared_port"); + lib->shared_port = nxt_unit_add_port(ctx, &shared_port, mem); + if (nxt_slow_path(lib->shared_port == NULL)) { + nxt_unit_alert(NULL, "failed to add shared_port"); - goto fail; - } + goto fail; + } - rc = nxt_unit_ready(ctx, ready_port.out_fd, ready_stream, queue_fd); - if (nxt_slow_path(rc != NXT_UNIT_OK)) { - nxt_unit_alert(NULL, "failed to send READY message"); + rc = nxt_unit_ready(ctx, ready_port.out_fd, ready_stream, queue_fd); + if (nxt_slow_path(rc != NXT_UNIT_OK)) { + nxt_unit_alert(NULL, "failed to send READY message"); - goto fail; - } + goto fail; + } - nxt_unit_close(ready_port.out_fd); - nxt_unit_close(queue_fd); + nxt_unit_close(ready_port.out_fd); + nxt_unit_close(queue_fd); - return ctx; + return ctx; fail: - if (mem != MAP_FAILED) { - munmap(mem, sizeof(nxt_port_queue_t)); - } + if (mem != MAP_FAILED) { + munmap(mem, sizeof(nxt_port_queue_t)); + } - if (queue_fd != -1) { - nxt_unit_close(queue_fd); - } + if (queue_fd != -1) { + nxt_unit_close(queue_fd); + } - nxt_unit_ctx_release(&lib->main_ctx.ctx); + nxt_unit_ctx_release(&lib->main_ctx.ctx); - return NULL; + return NULL; } +static nxt_unit_impl_t *nxt_unit_create(nxt_unit_init_t *init) { + int rc; + nxt_unit_impl_t *lib; -static nxt_unit_impl_t * -nxt_unit_create(nxt_unit_init_t *init) -{ - int rc; - nxt_unit_impl_t *lib; + if (nxt_slow_path(init->callbacks.request_handler == NULL)) { + nxt_unit_alert(NULL, "request_handler is NULL"); - if (nxt_slow_path(init->callbacks.request_handler == NULL)) { - nxt_unit_alert(NULL, "request_handler is NULL"); - - return NULL; - } + return NULL; + } - lib = nxt_unit_malloc(NULL, - sizeof(nxt_unit_impl_t) + init->request_data_size); - if (nxt_slow_path(lib == NULL)) { - nxt_unit_alert(NULL, "failed to allocate unit struct"); + lib = + nxt_unit_malloc(NULL, sizeof(nxt_unit_impl_t) + init->request_data_size); + if (nxt_slow_path(lib == NULL)) { + nxt_unit_alert(NULL, "failed to allocate unit struct"); - return NULL; - } + return NULL; + } - rc = pthread_mutex_init(&lib->mutex, NULL); - if (nxt_slow_path(rc != 0)) { - nxt_unit_alert(NULL, "failed to initialize mutex (%d)", rc); + rc = pthread_mutex_init(&lib->mutex, NULL); + if (nxt_slow_path(rc != 0)) { + nxt_unit_alert(NULL, "failed to initialize mutex (%d)", rc); - goto out_unit_free; - } + goto out_unit_free; + } - lib->unit.data = init->data; - lib->callbacks = init->callbacks; + lib->unit.data = init->data; + lib->callbacks = init->callbacks; - lib->request_data_size = init->request_data_size; - lib->shm_mmap_limit = (init->shm_limit + PORT_MMAP_DATA_SIZE - 1) - / PORT_MMAP_DATA_SIZE; - lib->request_limit = init->request_limit; + lib->request_data_size = init->request_data_size; + lib->shm_mmap_limit = + (init->shm_limit + PORT_MMAP_DATA_SIZE - 1) / PORT_MMAP_DATA_SIZE; + lib->request_limit = init->request_limit; - lib->processes.slot = NULL; - lib->ports.slot = NULL; + lib->processes.slot = NULL; + lib->ports.slot = NULL; - lib->log_fd = STDERR_FILENO; + lib->log_fd = STDERR_FILENO; - nxt_queue_init(&lib->contexts); + nxt_queue_init(&lib->contexts); - lib->use_count = 0; - lib->request_count = 0; - lib->router_port = NULL; - lib->shared_port = NULL; + lib->use_count = 0; + lib->request_count = 0; + lib->router_port = NULL; + lib->shared_port = NULL; - rc = nxt_unit_ctx_init(lib, &lib->main_ctx, init->ctx_data); - if (nxt_slow_path(rc != NXT_UNIT_OK)) { - goto out_mutex_destroy; - } + rc = nxt_unit_ctx_init(lib, &lib->main_ctx, init->ctx_data); + if (nxt_slow_path(rc != NXT_UNIT_OK)) { + goto out_mutex_destroy; + } - rc = nxt_unit_mmaps_init(&lib->incoming); - if (nxt_slow_path(rc != 0)) { - nxt_unit_alert(NULL, "failed to initialize mutex (%d)", rc); + rc = nxt_unit_mmaps_init(&lib->incoming); + if (nxt_slow_path(rc != 0)) { + nxt_unit_alert(NULL, "failed to initialize mutex (%d)", rc); - goto out_ctx_free; - } + goto out_ctx_free; + } - rc = nxt_unit_mmaps_init(&lib->outgoing); - if (nxt_slow_path(rc != 0)) { - nxt_unit_alert(NULL, "failed to initialize mutex (%d)", rc); + rc = nxt_unit_mmaps_init(&lib->outgoing); + if (nxt_slow_path(rc != 0)) { + nxt_unit_alert(NULL, "failed to initialize mutex (%d)", rc); - goto out_mmaps_destroy; - } + goto out_mmaps_destroy; + } - return lib; + return lib; out_mmaps_destroy: - nxt_unit_mmaps_destroy(&lib->incoming); + nxt_unit_mmaps_destroy(&lib->incoming); out_ctx_free: - nxt_unit_ctx_free(&lib->main_ctx); + nxt_unit_ctx_free(&lib->main_ctx); out_mutex_destroy: - pthread_mutex_destroy(&lib->mutex); + pthread_mutex_destroy(&lib->mutex); out_unit_free: - nxt_unit_free(NULL, lib); + nxt_unit_free(NULL, lib); - return NULL; + return NULL; } +static int nxt_unit_ctx_init(nxt_unit_impl_t *lib, + nxt_unit_ctx_impl_t *ctx_impl, void *data) { + int rc; -static int -nxt_unit_ctx_init(nxt_unit_impl_t *lib, nxt_unit_ctx_impl_t *ctx_impl, - void *data) -{ - int rc; - - ctx_impl->ctx.data = data; - ctx_impl->ctx.unit = &lib->unit; + ctx_impl->ctx.data = data; + ctx_impl->ctx.unit = &lib->unit; - rc = pthread_mutex_init(&ctx_impl->mutex, NULL); - if (nxt_slow_path(rc != 0)) { - nxt_unit_alert(NULL, "failed to initialize mutex (%d)", rc); + rc = pthread_mutex_init(&ctx_impl->mutex, NULL); + if (nxt_slow_path(rc != 0)) { + nxt_unit_alert(NULL, "failed to initialize mutex (%d)", rc); - return NXT_UNIT_ERROR; - } + return NXT_UNIT_ERROR; + } - nxt_unit_lib_use(lib); + nxt_unit_lib_use(lib); - pthread_mutex_lock(&lib->mutex); + pthread_mutex_lock(&lib->mutex); - nxt_queue_insert_tail(&lib->contexts, &ctx_impl->link); + nxt_queue_insert_tail(&lib->contexts, &ctx_impl->link); - pthread_mutex_unlock(&lib->mutex); + pthread_mutex_unlock(&lib->mutex); - ctx_impl->use_count = 1; - ctx_impl->wait_items = 0; - ctx_impl->online = 1; - ctx_impl->ready = 0; - ctx_impl->quit_param = NXT_QUIT_GRACEFUL; + ctx_impl->use_count = 1; + ctx_impl->wait_items = 0; + ctx_impl->online = 1; + ctx_impl->ready = 0; + ctx_impl->quit_param = NXT_QUIT_GRACEFUL; - nxt_queue_init(&ctx_impl->free_req); - nxt_queue_init(&ctx_impl->free_ws); - nxt_queue_init(&ctx_impl->active_req); - nxt_queue_init(&ctx_impl->ready_req); - nxt_queue_init(&ctx_impl->pending_rbuf); - nxt_queue_init(&ctx_impl->free_rbuf); + nxt_queue_init(&ctx_impl->free_req); + nxt_queue_init(&ctx_impl->free_ws); + nxt_queue_init(&ctx_impl->active_req); + nxt_queue_init(&ctx_impl->ready_req); + nxt_queue_init(&ctx_impl->pending_rbuf); + nxt_queue_init(&ctx_impl->free_rbuf); - ctx_impl->free_buf = NULL; - nxt_unit_mmap_buf_insert(&ctx_impl->free_buf, &ctx_impl->ctx_buf[1]); - nxt_unit_mmap_buf_insert(&ctx_impl->free_buf, &ctx_impl->ctx_buf[0]); + ctx_impl->free_buf = NULL; + nxt_unit_mmap_buf_insert(&ctx_impl->free_buf, &ctx_impl->ctx_buf[1]); + nxt_unit_mmap_buf_insert(&ctx_impl->free_buf, &ctx_impl->ctx_buf[0]); - nxt_queue_insert_tail(&ctx_impl->free_req, &ctx_impl->req.link); - nxt_queue_insert_tail(&ctx_impl->free_rbuf, &ctx_impl->ctx_read_buf.link); + nxt_queue_insert_tail(&ctx_impl->free_req, &ctx_impl->req.link); + nxt_queue_insert_tail(&ctx_impl->free_rbuf, &ctx_impl->ctx_read_buf.link); - ctx_impl->ctx_read_buf.ctx_impl = ctx_impl; + ctx_impl->ctx_read_buf.ctx_impl = ctx_impl; - ctx_impl->req.req.ctx = &ctx_impl->ctx; - ctx_impl->req.req.unit = &lib->unit; + ctx_impl->req.req.ctx = &ctx_impl->ctx; + ctx_impl->req.req.unit = &lib->unit; - ctx_impl->read_port = NULL; - ctx_impl->requests.slot = 0; + ctx_impl->read_port = NULL; + ctx_impl->requests.slot = 0; - return NXT_UNIT_OK; + return NXT_UNIT_OK; } +nxt_inline void nxt_unit_ctx_use(nxt_unit_ctx_t *ctx) { + nxt_unit_ctx_impl_t *ctx_impl; -nxt_inline void -nxt_unit_ctx_use(nxt_unit_ctx_t *ctx) -{ - nxt_unit_ctx_impl_t *ctx_impl; + ctx_impl = nxt_container_of(ctx, nxt_unit_ctx_impl_t, ctx); - ctx_impl = nxt_container_of(ctx, nxt_unit_ctx_impl_t, ctx); - - nxt_atomic_fetch_add(&ctx_impl->use_count, 1); + nxt_atomic_fetch_add(&ctx_impl->use_count, 1); } +nxt_inline void nxt_unit_ctx_release(nxt_unit_ctx_t *ctx) { + long c; + nxt_unit_ctx_impl_t *ctx_impl; -nxt_inline void -nxt_unit_ctx_release(nxt_unit_ctx_t *ctx) -{ - long c; - nxt_unit_ctx_impl_t *ctx_impl; - - ctx_impl = nxt_container_of(ctx, nxt_unit_ctx_impl_t, ctx); + ctx_impl = nxt_container_of(ctx, nxt_unit_ctx_impl_t, ctx); - c = nxt_atomic_fetch_add(&ctx_impl->use_count, -1); + c = nxt_atomic_fetch_add(&ctx_impl->use_count, -1); - if (c == 1) { - nxt_unit_ctx_free(ctx_impl); - } + if (c == 1) { + nxt_unit_ctx_free(ctx_impl); + } } - -nxt_inline void -nxt_unit_lib_use(nxt_unit_impl_t *lib) -{ - nxt_atomic_fetch_add(&lib->use_count, 1); +nxt_inline void nxt_unit_lib_use(nxt_unit_impl_t *lib) { + nxt_atomic_fetch_add(&lib->use_count, 1); } +nxt_inline void nxt_unit_lib_release(nxt_unit_impl_t *lib) { + long c; + nxt_unit_process_t *process; -nxt_inline void -nxt_unit_lib_release(nxt_unit_impl_t *lib) -{ - long c; - nxt_unit_process_t *process; + c = nxt_atomic_fetch_add(&lib->use_count, -1); - c = nxt_atomic_fetch_add(&lib->use_count, -1); + if (c == 1) { + for (;;) { + pthread_mutex_lock(&lib->mutex); - if (c == 1) { - for ( ;; ) { - pthread_mutex_lock(&lib->mutex); - - process = nxt_unit_process_pop_first(lib); - if (process == NULL) { - pthread_mutex_unlock(&lib->mutex); + process = nxt_unit_process_pop_first(lib); + if (process == NULL) { + pthread_mutex_unlock(&lib->mutex); - break; - } + break; + } - nxt_unit_remove_process(lib, process); - } + nxt_unit_remove_process(lib, process); + } - pthread_mutex_destroy(&lib->mutex); + pthread_mutex_destroy(&lib->mutex); - if (nxt_fast_path(lib->router_port != NULL)) { - nxt_unit_port_release(lib->router_port); - } + if (nxt_fast_path(lib->router_port != NULL)) { + nxt_unit_port_release(lib->router_port); + } - if (nxt_fast_path(lib->shared_port != NULL)) { - nxt_unit_port_release(lib->shared_port); - } + if (nxt_fast_path(lib->shared_port != NULL)) { + nxt_unit_port_release(lib->shared_port); + } - nxt_unit_mmaps_destroy(&lib->incoming); - nxt_unit_mmaps_destroy(&lib->outgoing); + nxt_unit_mmaps_destroy(&lib->incoming); + nxt_unit_mmaps_destroy(&lib->outgoing); - nxt_unit_free(NULL, lib); - } + nxt_unit_free(NULL, lib); + } } +nxt_inline void nxt_unit_mmap_buf_insert(nxt_unit_mmap_buf_t **head, + nxt_unit_mmap_buf_t *mmap_buf) { + mmap_buf->next = *head; -nxt_inline void -nxt_unit_mmap_buf_insert(nxt_unit_mmap_buf_t **head, - nxt_unit_mmap_buf_t *mmap_buf) -{ - mmap_buf->next = *head; - - if (mmap_buf->next != NULL) { - mmap_buf->next->prev = &mmap_buf->next; - } + if (mmap_buf->next != NULL) { + mmap_buf->next->prev = &mmap_buf->next; + } - *head = mmap_buf; - mmap_buf->prev = head; + *head = mmap_buf; + mmap_buf->prev = head; } +nxt_inline void nxt_unit_mmap_buf_insert_tail(nxt_unit_mmap_buf_t **prev, + nxt_unit_mmap_buf_t *mmap_buf) { + while (*prev != NULL) { + prev = &(*prev)->next; + } -nxt_inline void -nxt_unit_mmap_buf_insert_tail(nxt_unit_mmap_buf_t **prev, - nxt_unit_mmap_buf_t *mmap_buf) -{ - while (*prev != NULL) { - prev = &(*prev)->next; - } - - nxt_unit_mmap_buf_insert(prev, mmap_buf); + nxt_unit_mmap_buf_insert(prev, mmap_buf); } +nxt_inline void nxt_unit_mmap_buf_unlink(nxt_unit_mmap_buf_t *mmap_buf) { + nxt_unit_mmap_buf_t **prev; -nxt_inline void -nxt_unit_mmap_buf_unlink(nxt_unit_mmap_buf_t *mmap_buf) -{ - nxt_unit_mmap_buf_t **prev; - - prev = mmap_buf->prev; + prev = mmap_buf->prev; - if (mmap_buf->next != NULL) { - mmap_buf->next->prev = prev; - } + if (mmap_buf->next != NULL) { + mmap_buf->next->prev = prev; + } - if (prev != NULL) { - *prev = mmap_buf->next; - } + if (prev != NULL) { + *prev = mmap_buf->next; + } } +static int nxt_unit_read_env(nxt_unit_port_t *ready_port, + nxt_unit_port_t *router_port, + nxt_unit_port_t *read_port, int *shared_port_fd, + int *shared_queue_fd, int *log_fd, + uint32_t *stream, uint32_t *shm_limit, + uint32_t *request_limit) { + int rc; + int ready_fd, router_fd, read_in_fd, read_out_fd; + char *unit_init, *version_end, *vars; + size_t version_length; + int64_t ready_pid, router_pid, read_pid; + uint32_t ready_stream, router_id, ready_id, read_id; + + unit_init = getenv(NXT_UNIT_INIT_ENV); + if (nxt_slow_path(unit_init == NULL)) { + nxt_unit_alert(NULL, "%s is not in the current environment", + NXT_UNIT_INIT_ENV); -static int -nxt_unit_read_env(nxt_unit_port_t *ready_port, nxt_unit_port_t *router_port, - nxt_unit_port_t *read_port, int *shared_port_fd, int *shared_queue_fd, - int *log_fd, uint32_t *stream, - uint32_t *shm_limit, uint32_t *request_limit) -{ - int rc; - int ready_fd, router_fd, read_in_fd, read_out_fd; - char *unit_init, *version_end, *vars; - size_t version_length; - int64_t ready_pid, router_pid, read_pid; - uint32_t ready_stream, router_id, ready_id, read_id; - - unit_init = getenv(NXT_UNIT_INIT_ENV); - if (nxt_slow_path(unit_init == NULL)) { - nxt_unit_alert(NULL, "%s is not in the current environment", - NXT_UNIT_INIT_ENV); + return NXT_UNIT_ERROR; + } - return NXT_UNIT_ERROR; - } + version_end = strchr(unit_init, ';'); + if (nxt_slow_path(version_end == NULL)) { + nxt_unit_alert(NULL, "Unit version not found in %s=\"%s\"", + NXT_UNIT_INIT_ENV, unit_init); - version_end = strchr(unit_init, ';'); - if (nxt_slow_path(version_end == NULL)) { - nxt_unit_alert(NULL, "Unit version not found in %s=\"%s\"", - NXT_UNIT_INIT_ENV, unit_init); + return NXT_UNIT_ERROR; + } - return NXT_UNIT_ERROR; - } + version_length = version_end - unit_init; - version_length = version_end - unit_init; + rc = version_length != nxt_length(NXT_VERSION) || + memcmp(unit_init, NXT_VERSION, nxt_length(NXT_VERSION)); - rc = version_length != nxt_length(NXT_VERSION) - || memcmp(unit_init, NXT_VERSION, nxt_length(NXT_VERSION)); + if (nxt_slow_path(rc != 0)) { + nxt_unit_alert(NULL, + "versions mismatch: the Unit daemon has version " + "%.*s, while the app was compiled with libunit %s", + (int)version_length, unit_init, NXT_VERSION); - if (nxt_slow_path(rc != 0)) { - nxt_unit_alert(NULL, "versions mismatch: the Unit daemon has version " - "%.*s, while the app was compiled with libunit %s", - (int) version_length, unit_init, NXT_VERSION); + return NXT_UNIT_ERROR; + } + + vars = version_end + 1; + + rc = sscanf(vars, + "%" PRIu32 ";" + "%" PRId64 ",%" PRIu32 ",%d;" + "%" PRId64 ",%" PRIu32 ",%d;" + "%" PRId64 ",%" PRIu32 ",%d,%d;" + "%d,%d;" + "%d,%" PRIu32 ",%" PRIu32, + &ready_stream, &ready_pid, &ready_id, &ready_fd, &router_pid, + &router_id, &router_fd, &read_pid, &read_id, &read_in_fd, + &read_out_fd, shared_port_fd, shared_queue_fd, log_fd, shm_limit, + request_limit); + + if (nxt_slow_path(rc == EOF)) { + nxt_unit_alert(NULL, "sscanf(%s) failed: %s (%d) for %s env", vars, + strerror(errno), errno, NXT_UNIT_INIT_ENV); - return NXT_UNIT_ERROR; - } + return NXT_UNIT_ERROR; + } - vars = version_end + 1; + if (nxt_slow_path(rc != 16)) { + nxt_unit_alert(NULL, + "invalid number of variables in %s env: " + "found %d of %d in %s", + NXT_UNIT_INIT_ENV, rc, 16, vars); - rc = sscanf(vars, - "%"PRIu32";" - "%"PRId64",%"PRIu32",%d;" - "%"PRId64",%"PRIu32",%d;" - "%"PRId64",%"PRIu32",%d,%d;" - "%d,%d;" - "%d,%"PRIu32",%"PRIu32, - &ready_stream, - &ready_pid, &ready_id, &ready_fd, - &router_pid, &router_id, &router_fd, - &read_pid, &read_id, &read_in_fd, &read_out_fd, - shared_port_fd, shared_queue_fd, - log_fd, shm_limit, request_limit); + return NXT_UNIT_ERROR; + } - if (nxt_slow_path(rc == EOF)) { - nxt_unit_alert(NULL, "sscanf(%s) failed: %s (%d) for %s env", - vars, strerror(errno), errno, NXT_UNIT_INIT_ENV); + nxt_unit_debug(NULL, "%s='%s'", NXT_UNIT_INIT_ENV, unit_init); - return NXT_UNIT_ERROR; - } + nxt_unit_port_id_init(&ready_port->id, (pid_t)ready_pid, ready_id); - if (nxt_slow_path(rc != 16)) { - nxt_unit_alert(NULL, "invalid number of variables in %s env: " - "found %d of %d in %s", NXT_UNIT_INIT_ENV, rc, 16, vars); + ready_port->in_fd = -1; + ready_port->out_fd = ready_fd; + ready_port->data = NULL; - return NXT_UNIT_ERROR; - } + nxt_unit_port_id_init(&router_port->id, (pid_t)router_pid, router_id); - nxt_unit_debug(NULL, "%s='%s'", NXT_UNIT_INIT_ENV, unit_init); + router_port->in_fd = -1; + router_port->out_fd = router_fd; + router_port->data = NULL; - nxt_unit_port_id_init(&ready_port->id, (pid_t) ready_pid, ready_id); + nxt_unit_port_id_init(&read_port->id, (pid_t)read_pid, read_id); - ready_port->in_fd = -1; - ready_port->out_fd = ready_fd; - ready_port->data = NULL; + read_port->in_fd = read_in_fd; + read_port->out_fd = read_out_fd; + read_port->data = NULL; - nxt_unit_port_id_init(&router_port->id, (pid_t) router_pid, router_id); + *stream = ready_stream; - router_port->in_fd = -1; - router_port->out_fd = router_fd; - router_port->data = NULL; + return NXT_UNIT_OK; +} - nxt_unit_port_id_init(&read_port->id, (pid_t) read_pid, read_id); +static int nxt_unit_ready(nxt_unit_ctx_t *ctx, int ready_fd, uint32_t stream, + int queue_fd) { + ssize_t res; + nxt_send_oob_t oob; + nxt_port_msg_t msg; + nxt_unit_impl_t *lib; + int fds[2] = {queue_fd, -1}; + + lib = nxt_container_of(ctx->unit, nxt_unit_impl_t, unit); + + msg.stream = stream; + msg.pid = lib->pid; + msg.reply_port = 0; + msg.type = _NXT_PORT_MSG_PROCESS_READY; + msg.last = 1; + msg.mmap = 0; + msg.nf = 0; + msg.mf = 0; + + nxt_socket_msg_oob_init(&oob, fds); + + res = nxt_unit_sendmsg(ctx, ready_fd, &msg, sizeof(msg), &oob); + if (res != sizeof(msg)) { + return NXT_UNIT_ERROR; + } - read_port->in_fd = read_in_fd; - read_port->out_fd = read_out_fd; - read_port->data = NULL; + return NXT_UNIT_OK; +} - *stream = ready_stream; +static int nxt_unit_process_msg(nxt_unit_ctx_t *ctx, nxt_unit_read_buf_t *rbuf, + nxt_unit_request_info_t **preq) { + int rc; + pid_t pid; + uint8_t quit_param; + nxt_port_msg_t *port_msg; + nxt_unit_impl_t *lib; + nxt_unit_recv_msg_t recv_msg; + + lib = nxt_container_of(ctx->unit, nxt_unit_impl_t, unit); + + recv_msg.incoming_buf = NULL; + recv_msg.fd[0] = -1; + recv_msg.fd[1] = -1; + + rc = nxt_socket_msg_oob_get_fds(&rbuf->oob, recv_msg.fd); + if (nxt_slow_path(rc != NXT_OK)) { + nxt_unit_alert(ctx, "failed to receive file descriptor over cmsg"); + rc = NXT_UNIT_ERROR; + goto done; + } - return NXT_UNIT_OK; -} + if (nxt_slow_path(rbuf->size < (ssize_t)sizeof(nxt_port_msg_t))) { + if (nxt_slow_path(rbuf->size == 0)) { + nxt_unit_debug(ctx, "read port closed"); + nxt_unit_quit(ctx, NXT_QUIT_GRACEFUL); + rc = NXT_UNIT_OK; + goto done; + } -static int -nxt_unit_ready(nxt_unit_ctx_t *ctx, int ready_fd, uint32_t stream, int queue_fd) -{ - ssize_t res; - nxt_send_oob_t oob; - nxt_port_msg_t msg; - nxt_unit_impl_t *lib; - int fds[2] = {queue_fd, -1}; + nxt_unit_alert(ctx, "message too small (%d bytes)", (int)rbuf->size); - lib = nxt_container_of(ctx->unit, nxt_unit_impl_t, unit); + rc = NXT_UNIT_ERROR; + goto done; + } - msg.stream = stream; - msg.pid = lib->pid; - msg.reply_port = 0; - msg.type = _NXT_PORT_MSG_PROCESS_READY; - msg.last = 1; - msg.mmap = 0; - msg.nf = 0; - msg.mf = 0; + port_msg = (nxt_port_msg_t *)rbuf->buf; - nxt_socket_msg_oob_init(&oob, fds); + nxt_unit_debug(ctx, "#%" PRIu32 ": process message %d fd[0] %d fd[1] %d", + port_msg->stream, (int)port_msg->type, recv_msg.fd[0], + recv_msg.fd[1]); - res = nxt_unit_sendmsg(ctx, ready_fd, &msg, sizeof(msg), &oob); - if (res != sizeof(msg)) { - return NXT_UNIT_ERROR; - } + recv_msg.stream = port_msg->stream; + recv_msg.pid = port_msg->pid; + recv_msg.reply_port = port_msg->reply_port; + recv_msg.last = port_msg->last; + recv_msg.mmap = port_msg->mmap; - return NXT_UNIT_OK; -} + recv_msg.start = port_msg + 1; + recv_msg.size = rbuf->size - sizeof(nxt_port_msg_t); + if (nxt_slow_path(port_msg->type >= NXT_PORT_MSG_MAX)) { + nxt_unit_alert(ctx, "#%" PRIu32 ": unknown message type (%d)", + port_msg->stream, (int)port_msg->type); + rc = NXT_UNIT_ERROR; + goto done; + } -static int -nxt_unit_process_msg(nxt_unit_ctx_t *ctx, nxt_unit_read_buf_t *rbuf, - nxt_unit_request_info_t **preq) -{ - int rc; - pid_t pid; - uint8_t quit_param; - nxt_port_msg_t *port_msg; - nxt_unit_impl_t *lib; - nxt_unit_recv_msg_t recv_msg; + /* Fragmentation is unsupported. */ + if (nxt_slow_path(port_msg->nf != 0 || port_msg->mf != 0)) { + nxt_unit_alert(ctx, "#%" PRIu32 ": fragmented message type (%d)", + port_msg->stream, (int)port_msg->type); + rc = NXT_UNIT_ERROR; + goto done; + } - lib = nxt_container_of(ctx->unit, nxt_unit_impl_t, unit); + if (port_msg->mmap) { + rc = nxt_unit_mmap_read(ctx, &recv_msg, rbuf); - recv_msg.incoming_buf = NULL; - recv_msg.fd[0] = -1; - recv_msg.fd[1] = -1; + if (nxt_slow_path(rc != NXT_UNIT_OK)) { + if (rc == NXT_UNIT_AGAIN) { + recv_msg.fd[0] = -1; + recv_msg.fd[1] = -1; + } - rc = nxt_socket_msg_oob_get_fds(&rbuf->oob, recv_msg.fd); - if (nxt_slow_path(rc != NXT_OK)) { - nxt_unit_alert(ctx, "failed to receive file descriptor over cmsg"); - rc = NXT_UNIT_ERROR; - goto done; + goto done; } + } - if (nxt_slow_path(rbuf->size < (ssize_t) sizeof(nxt_port_msg_t))) { - if (nxt_slow_path(rbuf->size == 0)) { - nxt_unit_debug(ctx, "read port closed"); + switch (port_msg->type) { - nxt_unit_quit(ctx, NXT_QUIT_GRACEFUL); - rc = NXT_UNIT_OK; - goto done; - } + case _NXT_PORT_MSG_RPC_READY: + rc = NXT_UNIT_OK; + break; - nxt_unit_alert(ctx, "message too small (%d bytes)", (int) rbuf->size); + case _NXT_PORT_MSG_QUIT: + if (recv_msg.size == sizeof(quit_param)) { + memcpy(&quit_param, recv_msg.start, sizeof(quit_param)); - rc = NXT_UNIT_ERROR; - goto done; + } else { + quit_param = NXT_QUIT_NORMAL; } - port_msg = (nxt_port_msg_t *) rbuf->buf; + nxt_unit_debug(ctx, "#%" PRIu32 ": %squit", port_msg->stream, + (quit_param == NXT_QUIT_GRACEFUL ? "graceful " : "")); - nxt_unit_debug(ctx, "#%"PRIu32": process message %d fd[0] %d fd[1] %d", - port_msg->stream, (int) port_msg->type, - recv_msg.fd[0], recv_msg.fd[1]); + nxt_unit_quit(ctx, quit_param); - recv_msg.stream = port_msg->stream; - recv_msg.pid = port_msg->pid; - recv_msg.reply_port = port_msg->reply_port; - recv_msg.last = port_msg->last; - recv_msg.mmap = port_msg->mmap; + rc = NXT_UNIT_OK; + break; - recv_msg.start = port_msg + 1; - recv_msg.size = rbuf->size - sizeof(nxt_port_msg_t); + case _NXT_PORT_MSG_NEW_PORT: + rc = nxt_unit_process_new_port(ctx, &recv_msg); + break; - if (nxt_slow_path(port_msg->type >= NXT_PORT_MSG_MAX)) { - nxt_unit_alert(ctx, "#%"PRIu32": unknown message type (%d)", - port_msg->stream, (int) port_msg->type); - rc = NXT_UNIT_ERROR; - goto done; - } + case _NXT_PORT_MSG_PORT_ACK: + rc = nxt_unit_ctx_ready(ctx); + break; - /* Fragmentation is unsupported. */ - if (nxt_slow_path(port_msg->nf != 0 || port_msg->mf != 0)) { - nxt_unit_alert(ctx, "#%"PRIu32": fragmented message type (%d)", - port_msg->stream, (int) port_msg->type); - rc = NXT_UNIT_ERROR; - goto done; + case _NXT_PORT_MSG_CHANGE_FILE: + nxt_unit_debug(ctx, "#%" PRIu32 ": change_file: fd %d", port_msg->stream, + recv_msg.fd[0]); + + if (dup2(recv_msg.fd[0], lib->log_fd) == -1) { + nxt_unit_alert(ctx, "#%" PRIu32 ": dup2(%d, %d) failed: %s (%d)", + port_msg->stream, recv_msg.fd[0], lib->log_fd, + strerror(errno), errno); + + rc = NXT_UNIT_ERROR; + goto done; } - if (port_msg->mmap) { - rc = nxt_unit_mmap_read(ctx, &recv_msg, rbuf); + rc = NXT_UNIT_OK; + break; - if (nxt_slow_path(rc != NXT_UNIT_OK)) { - if (rc == NXT_UNIT_AGAIN) { - recv_msg.fd[0] = -1; - recv_msg.fd[1] = -1; - } + case _NXT_PORT_MSG_MMAP: + if (nxt_slow_path(recv_msg.fd[0] < 0)) { + nxt_unit_alert(ctx, "#%" PRIu32 ": invalid fd %d for mmap", + port_msg->stream, recv_msg.fd[0]); - goto done; - } + rc = NXT_UNIT_ERROR; + goto done; } - switch (port_msg->type) { + rc = nxt_unit_incoming_mmap(ctx, port_msg->pid, recv_msg.fd[0]); + break; - case _NXT_PORT_MSG_RPC_READY: - rc = NXT_UNIT_OK; - break; + case _NXT_PORT_MSG_REQ_HEADERS: + rc = nxt_unit_process_req_headers(ctx, &recv_msg, preq); + break; - case _NXT_PORT_MSG_QUIT: - if (recv_msg.size == sizeof(quit_param)) { - memcpy(&quit_param, recv_msg.start, sizeof(quit_param)); + case _NXT_PORT_MSG_REQ_BODY: + rc = nxt_unit_process_req_body(ctx, &recv_msg); + break; - } else { - quit_param = NXT_QUIT_NORMAL; - } + case _NXT_PORT_MSG_WEBSOCKET: + rc = nxt_unit_process_websocket(ctx, &recv_msg); + break; + + case _NXT_PORT_MSG_REMOVE_PID: + if (nxt_slow_path(recv_msg.size != sizeof(pid))) { + nxt_unit_alert(ctx, + "#%" PRIu32 ": remove_pid: invalid message size " + "(%d != %d)", + port_msg->stream, (int)recv_msg.size, (int)sizeof(pid)); - nxt_unit_debug(ctx, "#%"PRIu32": %squit", port_msg->stream, - (quit_param == NXT_QUIT_GRACEFUL ? "graceful " : "")); + rc = NXT_UNIT_ERROR; + goto done; + } - nxt_unit_quit(ctx, quit_param); + memcpy(&pid, recv_msg.start, sizeof(pid)); - rc = NXT_UNIT_OK; - break; + nxt_unit_debug(ctx, "#%" PRIu32 ": remove_pid: %d", port_msg->stream, + (int)pid); - case _NXT_PORT_MSG_NEW_PORT: - rc = nxt_unit_process_new_port(ctx, &recv_msg); - break; + nxt_unit_remove_pid(lib, pid); - case _NXT_PORT_MSG_PORT_ACK: - rc = nxt_unit_ctx_ready(ctx); - break; + rc = NXT_UNIT_OK; + break; - case _NXT_PORT_MSG_CHANGE_FILE: - nxt_unit_debug(ctx, "#%"PRIu32": change_file: fd %d", - port_msg->stream, recv_msg.fd[0]); + case _NXT_PORT_MSG_SHM_ACK: + rc = nxt_unit_process_shm_ack(ctx); + break; - if (dup2(recv_msg.fd[0], lib->log_fd) == -1) { - nxt_unit_alert(ctx, "#%"PRIu32": dup2(%d, %d) failed: %s (%d)", - port_msg->stream, recv_msg.fd[0], lib->log_fd, - strerror(errno), errno); + default: + nxt_unit_alert(ctx, "#%" PRIu32 ": ignore message type: %d", + port_msg->stream, (int)port_msg->type); - rc = NXT_UNIT_ERROR; - goto done; - } + rc = NXT_UNIT_ERROR; + goto done; + } - rc = NXT_UNIT_OK; - break; +done: - case _NXT_PORT_MSG_MMAP: - if (nxt_slow_path(recv_msg.fd[0] < 0)) { - nxt_unit_alert(ctx, "#%"PRIu32": invalid fd %d for mmap", - port_msg->stream, recv_msg.fd[0]); + if (recv_msg.fd[0] != -1) { + nxt_unit_close(recv_msg.fd[0]); + } - rc = NXT_UNIT_ERROR; - goto done; - } + if (recv_msg.fd[1] != -1) { + nxt_unit_close(recv_msg.fd[1]); + } - rc = nxt_unit_incoming_mmap(ctx, port_msg->pid, recv_msg.fd[0]); - break; + while (recv_msg.incoming_buf != NULL) { + nxt_unit_mmap_buf_free(recv_msg.incoming_buf); + } - case _NXT_PORT_MSG_REQ_HEADERS: - rc = nxt_unit_process_req_headers(ctx, &recv_msg, preq); - break; + if (nxt_fast_path(rc != NXT_UNIT_AGAIN)) { +#if (NXT_DEBUG) + memset(rbuf->buf, 0xAC, rbuf->size); +#endif + nxt_unit_read_buf_release(ctx, rbuf); + } - case _NXT_PORT_MSG_REQ_BODY: - rc = nxt_unit_process_req_body(ctx, &recv_msg); - break; + return rc; +} - case _NXT_PORT_MSG_WEBSOCKET: - rc = nxt_unit_process_websocket(ctx, &recv_msg); - break; +static int nxt_unit_process_new_port(nxt_unit_ctx_t *ctx, + nxt_unit_recv_msg_t *recv_msg) { + void *mem; + nxt_unit_port_t new_port, *port; + nxt_port_msg_new_port_t *new_port_msg; - case _NXT_PORT_MSG_REMOVE_PID: - if (nxt_slow_path(recv_msg.size != sizeof(pid))) { - nxt_unit_alert(ctx, "#%"PRIu32": remove_pid: invalid message size " - "(%d != %d)", port_msg->stream, (int) recv_msg.size, - (int) sizeof(pid)); + if (nxt_slow_path(recv_msg->size != sizeof(nxt_port_msg_new_port_t))) { + nxt_unit_warn(ctx, + "#%" PRIu32 ": new_port: " + "invalid message size (%d)", + recv_msg->stream, (int)recv_msg->size); - rc = NXT_UNIT_ERROR; - goto done; - } + return NXT_UNIT_ERROR; + } - memcpy(&pid, recv_msg.start, sizeof(pid)); + if (nxt_slow_path(recv_msg->fd[0] < 0)) { + nxt_unit_alert(ctx, "#%" PRIu32 ": invalid fd %d for new port", + recv_msg->stream, recv_msg->fd[0]); - nxt_unit_debug(ctx, "#%"PRIu32": remove_pid: %d", - port_msg->stream, (int) pid); + return NXT_UNIT_ERROR; + } - nxt_unit_remove_pid(lib, pid); + new_port_msg = recv_msg->start; - rc = NXT_UNIT_OK; - break; + nxt_unit_debug(ctx, "#%" PRIu32 ": new_port: port{%d,%d} fd[0] %d fd[1] %d", + recv_msg->stream, (int)new_port_msg->pid, + (int)new_port_msg->id, recv_msg->fd[0], recv_msg->fd[1]); - case _NXT_PORT_MSG_SHM_ACK: - rc = nxt_unit_process_shm_ack(ctx); - break; + if (nxt_slow_path(nxt_unit_fd_blocking(recv_msg->fd[0]) != NXT_UNIT_OK)) { + return NXT_UNIT_ERROR; + } - default: - nxt_unit_alert(ctx, "#%"PRIu32": ignore message type: %d", - port_msg->stream, (int) port_msg->type); + nxt_unit_port_id_init(&new_port.id, new_port_msg->pid, new_port_msg->id); - rc = NXT_UNIT_ERROR; - goto done; - } + new_port.in_fd = -1; + new_port.out_fd = recv_msg->fd[0]; -done: + mem = mmap(NULL, sizeof(nxt_port_queue_t), PROT_READ | PROT_WRITE, MAP_SHARED, + recv_msg->fd[1], 0); - if (recv_msg.fd[0] != -1) { - nxt_unit_close(recv_msg.fd[0]); - } + if (nxt_slow_path(mem == MAP_FAILED)) { + nxt_unit_alert(ctx, "mmap(%d) failed: %s (%d)", recv_msg->fd[1], + strerror(errno), errno); - if (recv_msg.fd[1] != -1) { - nxt_unit_close(recv_msg.fd[1]); - } + return NXT_UNIT_ERROR; + } - while (recv_msg.incoming_buf != NULL) { - nxt_unit_mmap_buf_free(recv_msg.incoming_buf); - } + new_port.data = NULL; - if (nxt_fast_path(rc != NXT_UNIT_AGAIN)) { -#if (NXT_DEBUG) - memset(rbuf->buf, 0xAC, rbuf->size); -#endif - nxt_unit_read_buf_release(ctx, rbuf); - } + recv_msg->fd[0] = -1; - return rc; + port = nxt_unit_add_port(ctx, &new_port, mem); + if (nxt_slow_path(port == NULL)) { + return NXT_UNIT_ERROR; + } + + nxt_unit_port_release(port); + + return NXT_UNIT_OK; } +static int nxt_unit_ctx_ready(nxt_unit_ctx_t *ctx) { + nxt_unit_impl_t *lib; + nxt_unit_ctx_impl_t *ctx_impl; -static int -nxt_unit_process_new_port(nxt_unit_ctx_t *ctx, nxt_unit_recv_msg_t *recv_msg) -{ - void *mem; - nxt_unit_port_t new_port, *port; - nxt_port_msg_new_port_t *new_port_msg; + ctx_impl = nxt_container_of(ctx, nxt_unit_ctx_impl_t, ctx); - if (nxt_slow_path(recv_msg->size != sizeof(nxt_port_msg_new_port_t))) { - nxt_unit_warn(ctx, "#%"PRIu32": new_port: " - "invalid message size (%d)", - recv_msg->stream, (int) recv_msg->size); + if (nxt_slow_path(ctx_impl->ready)) { + return NXT_UNIT_OK; + } - return NXT_UNIT_ERROR; - } + ctx_impl->ready = 1; - if (nxt_slow_path(recv_msg->fd[0] < 0)) { - nxt_unit_alert(ctx, "#%"PRIu32": invalid fd %d for new port", - recv_msg->stream, recv_msg->fd[0]); + lib = nxt_container_of(ctx->unit, nxt_unit_impl_t, unit); - return NXT_UNIT_ERROR; - } + /* Call ready_handler() only for main context. */ + if (&lib->main_ctx == ctx_impl && lib->callbacks.ready_handler != NULL) { + return lib->callbacks.ready_handler(ctx); + } - new_port_msg = recv_msg->start; + if (&lib->main_ctx != ctx_impl) { + /* Check if the main context is already stopped or quit. */ + if (nxt_slow_path(!lib->main_ctx.ready)) { + ctx_impl->ready = 0; - nxt_unit_debug(ctx, "#%"PRIu32": new_port: port{%d,%d} fd[0] %d fd[1] %d", - recv_msg->stream, (int) new_port_msg->pid, - (int) new_port_msg->id, recv_msg->fd[0], recv_msg->fd[1]); + nxt_unit_quit(ctx, lib->main_ctx.quit_param); - if (nxt_slow_path(nxt_unit_fd_blocking(recv_msg->fd[0]) != NXT_UNIT_OK)) { - return NXT_UNIT_ERROR; + return NXT_UNIT_OK; } - nxt_unit_port_id_init(&new_port.id, new_port_msg->pid, new_port_msg->id); + if (lib->callbacks.add_port != NULL) { + lib->callbacks.add_port(ctx, lib->shared_port); + } + } - new_port.in_fd = -1; - new_port.out_fd = recv_msg->fd[0]; + return NXT_UNIT_OK; +} - mem = mmap(NULL, sizeof(nxt_port_queue_t), PROT_READ | PROT_WRITE, - MAP_SHARED, recv_msg->fd[1], 0); +static int nxt_unit_process_req_headers(nxt_unit_ctx_t *ctx, + nxt_unit_recv_msg_t *recv_msg, + nxt_unit_request_info_t **preq) { + int res; + nxt_unit_impl_t *lib; + nxt_unit_port_id_t port_id; + nxt_unit_request_t *r; + nxt_unit_mmap_buf_t *b; + nxt_unit_request_info_t *req; + nxt_unit_request_info_impl_t *req_impl; + + if (nxt_slow_path(recv_msg->mmap == 0)) { + nxt_unit_warn(ctx, "#%" PRIu32 ": data is not in shared memory", + recv_msg->stream); - if (nxt_slow_path(mem == MAP_FAILED)) { - nxt_unit_alert(ctx, "mmap(%d) failed: %s (%d)", recv_msg->fd[1], - strerror(errno), errno); + return NXT_UNIT_ERROR; + } - return NXT_UNIT_ERROR; - } + if (nxt_slow_path(recv_msg->size < sizeof(nxt_unit_request_t))) { + nxt_unit_warn(ctx, + "#%" PRIu32 ": data too short: %d while at least " + "%d expected", + recv_msg->stream, (int)recv_msg->size, + (int)sizeof(nxt_unit_request_t)); - new_port.data = NULL; + return NXT_UNIT_ERROR; + } - recv_msg->fd[0] = -1; + req_impl = nxt_unit_request_info_get(ctx); + if (nxt_slow_path(req_impl == NULL)) { + nxt_unit_warn(ctx, "#%" PRIu32 ": request info allocation failed", + recv_msg->stream); - port = nxt_unit_add_port(ctx, &new_port, mem); - if (nxt_slow_path(port == NULL)) { - return NXT_UNIT_ERROR; - } + return NXT_UNIT_ERROR; + } - nxt_unit_port_release(port); + req = &req_impl->req; - return NXT_UNIT_OK; -} + req->request = recv_msg->start; + b = recv_msg->incoming_buf; -static int -nxt_unit_ctx_ready(nxt_unit_ctx_t *ctx) -{ - nxt_unit_impl_t *lib; - nxt_unit_ctx_impl_t *ctx_impl; + req->request_buf = &b->buf; + req->response = NULL; + req->response_buf = NULL; - ctx_impl = nxt_container_of(ctx, nxt_unit_ctx_impl_t, ctx); + r = req->request; - if (nxt_slow_path(ctx_impl->ready)) { - return NXT_UNIT_OK; - } + req->content_length = r->content_length; - ctx_impl->ready = 1; + req->content_buf = req->request_buf; + req->content_buf->free = nxt_unit_sptr_get(&r->preread_content); - lib = nxt_container_of(ctx->unit, nxt_unit_impl_t, unit); + req_impl->stream = recv_msg->stream; - /* Call ready_handler() only for main context. */ - if (&lib->main_ctx == ctx_impl && lib->callbacks.ready_handler != NULL) { - return lib->callbacks.ready_handler(ctx); - } + req_impl->outgoing_buf = NULL; - if (&lib->main_ctx != ctx_impl) { - /* Check if the main context is already stopped or quit. */ - if (nxt_slow_path(!lib->main_ctx.ready)) { - ctx_impl->ready = 0; + for (b = recv_msg->incoming_buf; b != NULL; b = b->next) { + b->req = req; + } - nxt_unit_quit(ctx, lib->main_ctx.quit_param); + /* "Move" incoming buffer list to req_impl. */ + req_impl->incoming_buf = recv_msg->incoming_buf; + req_impl->incoming_buf->prev = &req_impl->incoming_buf; + recv_msg->incoming_buf = NULL; - return NXT_UNIT_OK; - } + req->content_fd = recv_msg->fd[0]; + recv_msg->fd[0] = -1; - if (lib->callbacks.add_port != NULL) { - lib->callbacks.add_port(ctx, lib->shared_port); - } - } + req->response_max_fields = 0; + req_impl->state = NXT_UNIT_RS_START; + req_impl->websocket = 0; + req_impl->in_hash = 0; - return NXT_UNIT_OK; -} + nxt_unit_debug(ctx, "#%" PRIu32 ": %.*s %.*s (%d)", recv_msg->stream, + (int)r->method_length, (char *)nxt_unit_sptr_get(&r->method), + (int)r->target_length, (char *)nxt_unit_sptr_get(&r->target), + (int)r->content_length); + nxt_unit_port_id_init(&port_id, recv_msg->pid, recv_msg->reply_port); -static int -nxt_unit_process_req_headers(nxt_unit_ctx_t *ctx, nxt_unit_recv_msg_t *recv_msg, - nxt_unit_request_info_t **preq) -{ - int res; - nxt_unit_impl_t *lib; - nxt_unit_port_id_t port_id; - nxt_unit_request_t *r; - nxt_unit_mmap_buf_t *b; - nxt_unit_request_info_t *req; - nxt_unit_request_info_impl_t *req_impl; + res = nxt_unit_request_check_response_port(req, &port_id); + if (nxt_slow_path(res == NXT_UNIT_ERROR)) { + return NXT_UNIT_ERROR; + } - if (nxt_slow_path(recv_msg->mmap == 0)) { - nxt_unit_warn(ctx, "#%"PRIu32": data is not in shared memory", - recv_msg->stream); + if (nxt_fast_path(res == NXT_UNIT_OK)) { + res = nxt_unit_send_req_headers_ack(req); + if (nxt_slow_path(res == NXT_UNIT_ERROR)) { + nxt_unit_request_done(req, NXT_UNIT_ERROR); - return NXT_UNIT_ERROR; + return NXT_UNIT_ERROR; } - if (nxt_slow_path(recv_msg->size < sizeof(nxt_unit_request_t))) { - nxt_unit_warn(ctx, "#%"PRIu32": data too short: %d while at least " - "%d expected", recv_msg->stream, (int) recv_msg->size, - (int) sizeof(nxt_unit_request_t)); + lib = nxt_container_of(ctx->unit, nxt_unit_impl_t, unit); - return NXT_UNIT_ERROR; - } + if (req->content_length > + (uint64_t)(req->content_buf->end - req->content_buf->free)) { + res = nxt_unit_request_hash_add(ctx, req); + if (nxt_slow_path(res != NXT_UNIT_OK)) { + nxt_unit_req_warn(req, "failed to add request to hash"); - req_impl = nxt_unit_request_info_get(ctx); - if (nxt_slow_path(req_impl == NULL)) { - nxt_unit_warn(ctx, "#%"PRIu32": request info allocation failed", - recv_msg->stream); + nxt_unit_request_done(req, NXT_UNIT_ERROR); return NXT_UNIT_ERROR; - } - - req = &req_impl->req; + } - req->request = recv_msg->start; + /* + * If application have separate data handler, we may start + * request processing and process data when it is arrived. + */ + if (lib->callbacks.data_handler == NULL) { + return NXT_UNIT_OK; + } + } - b = recv_msg->incoming_buf; + if (preq == NULL) { + lib->callbacks.request_handler(req); - req->request_buf = &b->buf; - req->response = NULL; - req->response_buf = NULL; + } else { + *preq = req; + } + } - r = req->request; + return NXT_UNIT_OK; +} - req->content_length = r->content_length; +static int nxt_unit_process_req_body(nxt_unit_ctx_t *ctx, + nxt_unit_recv_msg_t *recv_msg) { + uint64_t l; + nxt_unit_impl_t *lib; + nxt_unit_mmap_buf_t *b; + nxt_unit_request_info_t *req; + + req = nxt_unit_request_hash_find(ctx, recv_msg->stream, recv_msg->last); + if (req == NULL) { + return NXT_UNIT_OK; + } - req->content_buf = req->request_buf; - req->content_buf->free = nxt_unit_sptr_get(&r->preread_content); + l = req->content_buf->end - req->content_buf->free; - req_impl->stream = recv_msg->stream; + for (b = recv_msg->incoming_buf; b != NULL; b = b->next) { + b->req = req; + l += b->buf.end - b->buf.free; + } - req_impl->outgoing_buf = NULL; + if (recv_msg->incoming_buf != NULL) { + b = nxt_container_of(req->content_buf, nxt_unit_mmap_buf_t, buf); - for (b = recv_msg->incoming_buf; b != NULL; b = b->next) { - b->req = req; + while (b->next != NULL) { + b = b->next; } /* "Move" incoming buffer list to req_impl. */ - req_impl->incoming_buf = recv_msg->incoming_buf; - req_impl->incoming_buf->prev = &req_impl->incoming_buf; + b->next = recv_msg->incoming_buf; + b->next->prev = &b->next; + recv_msg->incoming_buf = NULL; + } - req->content_fd = recv_msg->fd[0]; - recv_msg->fd[0] = -1; + req->content_fd = recv_msg->fd[0]; + recv_msg->fd[0] = -1; - req->response_max_fields = 0; - req_impl->state = NXT_UNIT_RS_START; - req_impl->websocket = 0; - req_impl->in_hash = 0; + lib = nxt_container_of(ctx->unit, nxt_unit_impl_t, unit); - nxt_unit_debug(ctx, "#%"PRIu32": %.*s %.*s (%d)", recv_msg->stream, - (int) r->method_length, - (char *) nxt_unit_sptr_get(&r->method), - (int) r->target_length, - (char *) nxt_unit_sptr_get(&r->target), - (int) r->content_length); + if (lib->callbacks.data_handler != NULL) { + lib->callbacks.data_handler(req); - nxt_unit_port_id_init(&port_id, recv_msg->pid, recv_msg->reply_port); + return NXT_UNIT_OK; + } - res = nxt_unit_request_check_response_port(req, &port_id); - if (nxt_slow_path(res == NXT_UNIT_ERROR)) { - return NXT_UNIT_ERROR; - } + if (req->content_fd != -1 || l == req->content_length) { + lib->callbacks.request_handler(req); + } - if (nxt_fast_path(res == NXT_UNIT_OK)) { - res = nxt_unit_send_req_headers_ack(req); - if (nxt_slow_path(res == NXT_UNIT_ERROR)) { - nxt_unit_request_done(req, NXT_UNIT_ERROR); + return NXT_UNIT_OK; +} - return NXT_UNIT_ERROR; - } +static int nxt_unit_request_check_response_port(nxt_unit_request_info_t *req, + nxt_unit_port_id_t *port_id) { + int res; + nxt_unit_ctx_t *ctx; + nxt_unit_impl_t *lib; + nxt_unit_port_t *port; + nxt_unit_process_t *process; + nxt_unit_ctx_impl_t *ctx_impl; + nxt_unit_port_impl_t *port_impl; + nxt_unit_request_info_impl_t *req_impl; - lib = nxt_container_of(ctx->unit, nxt_unit_impl_t, unit); + ctx = req->ctx; + lib = nxt_container_of(ctx->unit, nxt_unit_impl_t, unit); + ctx_impl = nxt_container_of(ctx, nxt_unit_ctx_impl_t, ctx); - if (req->content_length - > (uint64_t) (req->content_buf->end - req->content_buf->free)) - { - res = nxt_unit_request_hash_add(ctx, req); - if (nxt_slow_path(res != NXT_UNIT_OK)) { - nxt_unit_req_warn(req, "failed to add request to hash"); + pthread_mutex_lock(&lib->mutex); - nxt_unit_request_done(req, NXT_UNIT_ERROR); + port = nxt_unit_port_hash_find(&lib->ports, port_id, 0); - return NXT_UNIT_ERROR; - } + if (nxt_fast_path(port != NULL)) { + port_impl = nxt_container_of(port, nxt_unit_port_impl_t, port); + req->response_port = port; - /* - * If application have separate data handler, we may start - * request processing and process data when it is arrived. - */ - if (lib->callbacks.data_handler == NULL) { - return NXT_UNIT_OK; - } - } + if (nxt_fast_path(port_impl->ready)) { + pthread_mutex_unlock(&lib->mutex); - if (preq == NULL) { - lib->callbacks.request_handler(req); + nxt_unit_debug(ctx, "check_response_port: found port{%d,%d}", + (int)port->id.pid, (int)port->id.id); - } else { - *preq = req; - } + return NXT_UNIT_OK; } - return NXT_UNIT_OK; -} + nxt_unit_debug(ctx, + "check_response_port: " + "port{%d,%d} already requested", + (int)port->id.pid, (int)port->id.id); + req_impl = nxt_container_of(req, nxt_unit_request_info_impl_t, req); -static int -nxt_unit_process_req_body(nxt_unit_ctx_t *ctx, nxt_unit_recv_msg_t *recv_msg) -{ - uint64_t l; - nxt_unit_impl_t *lib; - nxt_unit_mmap_buf_t *b; - nxt_unit_request_info_t *req; + nxt_queue_insert_tail(&port_impl->awaiting_req, &req_impl->port_wait_link); - req = nxt_unit_request_hash_find(ctx, recv_msg->stream, recv_msg->last); - if (req == NULL) { - return NXT_UNIT_OK; - } + pthread_mutex_unlock(&lib->mutex); - l = req->content_buf->end - req->content_buf->free; + nxt_atomic_fetch_add(&ctx_impl->wait_items, 1); - for (b = recv_msg->incoming_buf; b != NULL; b = b->next) { - b->req = req; - l += b->buf.end - b->buf.free; - } + return NXT_UNIT_AGAIN; + } - if (recv_msg->incoming_buf != NULL) { - b = nxt_container_of(req->content_buf, nxt_unit_mmap_buf_t, buf); + port_impl = nxt_unit_malloc(ctx, sizeof(nxt_unit_port_impl_t)); + if (nxt_slow_path(port_impl == NULL)) { + nxt_unit_alert(ctx, "check_response_port: malloc(%d) failed", + (int)sizeof(nxt_unit_port_impl_t)); - while (b->next != NULL) { - b = b->next; - } + pthread_mutex_unlock(&lib->mutex); - /* "Move" incoming buffer list to req_impl. */ - b->next = recv_msg->incoming_buf; - b->next->prev = &b->next; + return NXT_UNIT_ERROR; + } - recv_msg->incoming_buf = NULL; - } + port = &port_impl->port; - req->content_fd = recv_msg->fd[0]; - recv_msg->fd[0] = -1; + port->id = *port_id; + port->in_fd = -1; + port->out_fd = -1; + port->data = NULL; - lib = nxt_container_of(ctx->unit, nxt_unit_impl_t, unit); + res = nxt_unit_port_hash_add(&lib->ports, port); + if (nxt_slow_path(res != NXT_UNIT_OK)) { + nxt_unit_alert(ctx, "check_response_port: %d,%d hash_add failed", + port->id.pid, port->id.id); - if (lib->callbacks.data_handler != NULL) { - lib->callbacks.data_handler(req); + pthread_mutex_unlock(&lib->mutex); - return NXT_UNIT_OK; - } + nxt_unit_free(ctx, port); - if (req->content_fd != -1 || l == req->content_length) { - lib->callbacks.request_handler(req); - } + return NXT_UNIT_ERROR; + } - return NXT_UNIT_OK; -} + process = nxt_unit_process_find(lib, port_id->pid, 0); + if (nxt_slow_path(process == NULL)) { + nxt_unit_alert(ctx, "check_response_port: process %d not found", + port->id.pid); + nxt_unit_port_hash_find(&lib->ports, port_id, 1); -static int -nxt_unit_request_check_response_port(nxt_unit_request_info_t *req, - nxt_unit_port_id_t *port_id) -{ - int res; - nxt_unit_ctx_t *ctx; - nxt_unit_impl_t *lib; - nxt_unit_port_t *port; - nxt_unit_process_t *process; - nxt_unit_ctx_impl_t *ctx_impl; - nxt_unit_port_impl_t *port_impl; - nxt_unit_request_info_impl_t *req_impl; + pthread_mutex_unlock(&lib->mutex); - ctx = req->ctx; - lib = nxt_container_of(ctx->unit, nxt_unit_impl_t, unit); - ctx_impl = nxt_container_of(ctx, nxt_unit_ctx_impl_t, ctx); + nxt_unit_free(ctx, port); - pthread_mutex_lock(&lib->mutex); + return NXT_UNIT_ERROR; + } - port = nxt_unit_port_hash_find(&lib->ports, port_id, 0); + nxt_queue_insert_tail(&process->ports, &port_impl->link); - if (nxt_fast_path(port != NULL)) { - port_impl = nxt_container_of(port, nxt_unit_port_impl_t, port); - req->response_port = port; + port_impl->process = process; + port_impl->queue = NULL; + port_impl->from_socket = 0; + port_impl->socket_rbuf = NULL; - if (nxt_fast_path(port_impl->ready)) { - pthread_mutex_unlock(&lib->mutex); + nxt_queue_init(&port_impl->awaiting_req); - nxt_unit_debug(ctx, "check_response_port: found port{%d,%d}", - (int) port->id.pid, (int) port->id.id); + req_impl = nxt_container_of(req, nxt_unit_request_info_impl_t, req); - return NXT_UNIT_OK; - } + nxt_queue_insert_tail(&port_impl->awaiting_req, &req_impl->port_wait_link); - nxt_unit_debug(ctx, "check_response_port: " - "port{%d,%d} already requested", - (int) port->id.pid, (int) port->id.id); + port_impl->use_count = 2; + port_impl->ready = 0; - req_impl = nxt_container_of(req, nxt_unit_request_info_impl_t, req); + req->response_port = port; - nxt_queue_insert_tail(&port_impl->awaiting_req, - &req_impl->port_wait_link); + pthread_mutex_unlock(&lib->mutex); - pthread_mutex_unlock(&lib->mutex); + res = nxt_unit_get_port(ctx, port_id); + if (nxt_slow_path(res == NXT_UNIT_ERROR)) { + return NXT_UNIT_ERROR; + } - nxt_atomic_fetch_add(&ctx_impl->wait_items, 1); + nxt_atomic_fetch_add(&ctx_impl->wait_items, 1); - return NXT_UNIT_AGAIN; - } + return NXT_UNIT_AGAIN; +} - port_impl = nxt_unit_malloc(ctx, sizeof(nxt_unit_port_impl_t)); - if (nxt_slow_path(port_impl == NULL)) { - nxt_unit_alert(ctx, "check_response_port: malloc(%d) failed", - (int) sizeof(nxt_unit_port_impl_t)); +static int nxt_unit_send_req_headers_ack(nxt_unit_request_info_t *req) { + ssize_t res; + nxt_port_msg_t msg; + nxt_unit_impl_t *lib; + nxt_unit_ctx_impl_t *ctx_impl; + nxt_unit_request_info_impl_t *req_impl; - pthread_mutex_unlock(&lib->mutex); + lib = nxt_container_of(req->ctx->unit, nxt_unit_impl_t, unit); + ctx_impl = nxt_container_of(req->ctx, nxt_unit_ctx_impl_t, ctx); + req_impl = nxt_container_of(req, nxt_unit_request_info_impl_t, req); - return NXT_UNIT_ERROR; - } + memset(&msg, 0, sizeof(nxt_port_msg_t)); - port = &port_impl->port; + msg.stream = req_impl->stream; + msg.pid = lib->pid; + msg.reply_port = ctx_impl->read_port->id.id; + msg.type = _NXT_PORT_MSG_REQ_HEADERS_ACK; - port->id = *port_id; - port->in_fd = -1; - port->out_fd = -1; - port->data = NULL; + res = + nxt_unit_port_send(req->ctx, req->response_port, &msg, sizeof(msg), NULL); + if (nxt_slow_path(res != sizeof(msg))) { + return NXT_UNIT_ERROR; + } - res = nxt_unit_port_hash_add(&lib->ports, port); - if (nxt_slow_path(res != NXT_UNIT_OK)) { - nxt_unit_alert(ctx, "check_response_port: %d,%d hash_add failed", - port->id.pid, port->id.id); + return NXT_UNIT_OK; +} - pthread_mutex_unlock(&lib->mutex); +static int nxt_unit_process_websocket(nxt_unit_ctx_t *ctx, + nxt_unit_recv_msg_t *recv_msg) { + size_t hsize; + nxt_unit_impl_t *lib; + nxt_unit_mmap_buf_t *b; + nxt_unit_callbacks_t *cb; + nxt_unit_request_info_t *req; + nxt_unit_request_info_impl_t *req_impl; + nxt_unit_websocket_frame_impl_t *ws_impl; + + req = nxt_unit_request_hash_find(ctx, recv_msg->stream, recv_msg->last); + if (nxt_slow_path(req == NULL)) { + return NXT_UNIT_OK; + } - nxt_unit_free(ctx, port); + req_impl = nxt_container_of(req, nxt_unit_request_info_impl_t, req); - return NXT_UNIT_ERROR; + lib = nxt_container_of(ctx->unit, nxt_unit_impl_t, unit); + cb = &lib->callbacks; + + if (cb->websocket_handler && recv_msg->size >= 2) { + ws_impl = nxt_unit_websocket_frame_get(ctx); + if (nxt_slow_path(ws_impl == NULL)) { + nxt_unit_warn(ctx, "#%" PRIu32 ": websocket frame allocation failed", + req_impl->stream); + + return NXT_UNIT_ERROR; } - process = nxt_unit_process_find(lib, port_id->pid, 0); - if (nxt_slow_path(process == NULL)) { - nxt_unit_alert(ctx, "check_response_port: process %d not found", - port->id.pid); + ws_impl->ws.req = req; - nxt_unit_port_hash_find(&lib->ports, port_id, 1); + ws_impl->buf = NULL; - pthread_mutex_unlock(&lib->mutex); + if (recv_msg->mmap) { + for (b = recv_msg->incoming_buf; b != NULL; b = b->next) { + b->req = req; + } - nxt_unit_free(ctx, port); + /* "Move" incoming buffer list to ws_impl. */ + ws_impl->buf = recv_msg->incoming_buf; + ws_impl->buf->prev = &ws_impl->buf; + recv_msg->incoming_buf = NULL; - return NXT_UNIT_ERROR; - } + b = ws_impl->buf; - nxt_queue_insert_tail(&process->ports, &port_impl->link); + } else { + b = nxt_unit_mmap_buf_get(ctx); + if (nxt_slow_path(b == NULL)) { + nxt_unit_alert(ctx, "#%" PRIu32 ": failed to allocate buf", + req_impl->stream); - port_impl->process = process; - port_impl->queue = NULL; - port_impl->from_socket = 0; - port_impl->socket_rbuf = NULL; + nxt_unit_websocket_frame_release(&ws_impl->ws); - nxt_queue_init(&port_impl->awaiting_req); + return NXT_UNIT_ERROR; + } - req_impl = nxt_container_of(req, nxt_unit_request_info_impl_t, req); + b->req = req; + b->buf.start = recv_msg->start; + b->buf.free = b->buf.start; + b->buf.end = b->buf.start + recv_msg->size; - nxt_queue_insert_tail(&port_impl->awaiting_req, &req_impl->port_wait_link); + nxt_unit_mmap_buf_insert(&ws_impl->buf, b); + } - port_impl->use_count = 2; - port_impl->ready = 0; + ws_impl->ws.header = (void *)b->buf.start; + ws_impl->ws.payload_len = + nxt_websocket_frame_payload_len(ws_impl->ws.header); - req->response_port = port; + hsize = nxt_websocket_frame_header_size(ws_impl->ws.header); - pthread_mutex_unlock(&lib->mutex); + if (ws_impl->ws.header->mask) { + ws_impl->ws.mask = (uint8_t *)b->buf.start + hsize - 4; - res = nxt_unit_get_port(ctx, port_id); - if (nxt_slow_path(res == NXT_UNIT_ERROR)) { - return NXT_UNIT_ERROR; + } else { + ws_impl->ws.mask = NULL; } - nxt_atomic_fetch_add(&ctx_impl->wait_items, 1); - - return NXT_UNIT_AGAIN; -} + b->buf.free += hsize; + ws_impl->ws.content_buf = &b->buf; + ws_impl->ws.content_length = ws_impl->ws.payload_len; -static int -nxt_unit_send_req_headers_ack(nxt_unit_request_info_t *req) -{ - ssize_t res; - nxt_port_msg_t msg; - nxt_unit_impl_t *lib; - nxt_unit_ctx_impl_t *ctx_impl; - nxt_unit_request_info_impl_t *req_impl; + nxt_unit_req_debug(req, + "websocket_handler: opcode=%d, " + "payload_len=%" PRIu64, + ws_impl->ws.header->opcode, ws_impl->ws.payload_len); - lib = nxt_container_of(req->ctx->unit, nxt_unit_impl_t, unit); - ctx_impl = nxt_container_of(req->ctx, nxt_unit_ctx_impl_t, ctx); - req_impl = nxt_container_of(req, nxt_unit_request_info_impl_t, req); + cb->websocket_handler(&ws_impl->ws); + } - memset(&msg, 0, sizeof(nxt_port_msg_t)); + if (recv_msg->last) { + if (cb->close_handler) { + nxt_unit_req_debug(req, "close_handler"); - msg.stream = req_impl->stream; - msg.pid = lib->pid; - msg.reply_port = ctx_impl->read_port->id.id; - msg.type = _NXT_PORT_MSG_REQ_HEADERS_ACK; + cb->close_handler(req); - res = nxt_unit_port_send(req->ctx, req->response_port, - &msg, sizeof(msg), NULL); - if (nxt_slow_path(res != sizeof(msg))) { - return NXT_UNIT_ERROR; + } else { + nxt_unit_request_done(req, NXT_UNIT_ERROR); } + } - return NXT_UNIT_OK; + return NXT_UNIT_OK; } +static int nxt_unit_process_shm_ack(nxt_unit_ctx_t *ctx) { + nxt_unit_impl_t *lib; + nxt_unit_callbacks_t *cb; -static int -nxt_unit_process_websocket(nxt_unit_ctx_t *ctx, nxt_unit_recv_msg_t *recv_msg) -{ - size_t hsize; - nxt_unit_impl_t *lib; - nxt_unit_mmap_buf_t *b; - nxt_unit_callbacks_t *cb; - nxt_unit_request_info_t *req; - nxt_unit_request_info_impl_t *req_impl; - nxt_unit_websocket_frame_impl_t *ws_impl; + lib = nxt_container_of(ctx->unit, nxt_unit_impl_t, unit); + cb = &lib->callbacks; - req = nxt_unit_request_hash_find(ctx, recv_msg->stream, recv_msg->last); - if (nxt_slow_path(req == NULL)) { - return NXT_UNIT_OK; - } + if (cb->shm_ack_handler != NULL) { + cb->shm_ack_handler(ctx); + } - req_impl = nxt_container_of(req, nxt_unit_request_info_impl_t, req); + return NXT_UNIT_OK; +} - lib = nxt_container_of(ctx->unit, nxt_unit_impl_t, unit); - cb = &lib->callbacks; +static nxt_unit_request_info_impl_t * +nxt_unit_request_info_get(nxt_unit_ctx_t *ctx) { + nxt_unit_impl_t *lib; + nxt_queue_link_t *lnk; + nxt_unit_ctx_impl_t *ctx_impl; + nxt_unit_request_info_impl_t *req_impl; - if (cb->websocket_handler && recv_msg->size >= 2) { - ws_impl = nxt_unit_websocket_frame_get(ctx); - if (nxt_slow_path(ws_impl == NULL)) { - nxt_unit_warn(ctx, "#%"PRIu32": websocket frame allocation failed", - req_impl->stream); + ctx_impl = nxt_container_of(ctx, nxt_unit_ctx_impl_t, ctx); - return NXT_UNIT_ERROR; - } + lib = nxt_container_of(ctx->unit, nxt_unit_impl_t, unit); - ws_impl->ws.req = req; + pthread_mutex_lock(&ctx_impl->mutex); - ws_impl->buf = NULL; + if (nxt_queue_is_empty(&ctx_impl->free_req)) { + pthread_mutex_unlock(&ctx_impl->mutex); - if (recv_msg->mmap) { - for (b = recv_msg->incoming_buf; b != NULL; b = b->next) { - b->req = req; - } + req_impl = nxt_unit_malloc(ctx, sizeof(nxt_unit_request_info_impl_t) + + lib->request_data_size); + if (nxt_slow_path(req_impl == NULL)) { + return NULL; + } - /* "Move" incoming buffer list to ws_impl. */ - ws_impl->buf = recv_msg->incoming_buf; - ws_impl->buf->prev = &ws_impl->buf; - recv_msg->incoming_buf = NULL; + req_impl->req.unit = ctx->unit; + req_impl->req.ctx = ctx; - b = ws_impl->buf; + pthread_mutex_lock(&ctx_impl->mutex); - } else { - b = nxt_unit_mmap_buf_get(ctx); - if (nxt_slow_path(b == NULL)) { - nxt_unit_alert(ctx, "#%"PRIu32": failed to allocate buf", - req_impl->stream); + } else { + lnk = nxt_queue_first(&ctx_impl->free_req); + nxt_queue_remove(lnk); - nxt_unit_websocket_frame_release(&ws_impl->ws); + req_impl = nxt_container_of(lnk, nxt_unit_request_info_impl_t, link); + } - return NXT_UNIT_ERROR; - } + nxt_queue_insert_tail(&ctx_impl->active_req, &req_impl->link); - b->req = req; - b->buf.start = recv_msg->start; - b->buf.free = b->buf.start; - b->buf.end = b->buf.start + recv_msg->size; + pthread_mutex_unlock(&ctx_impl->mutex); - nxt_unit_mmap_buf_insert(&ws_impl->buf, b); - } + req_impl->req.data = lib->request_data_size ? req_impl->extra_data : NULL; - ws_impl->ws.header = (void *) b->buf.start; - ws_impl->ws.payload_len = nxt_websocket_frame_payload_len( - ws_impl->ws.header); + return req_impl; +} - hsize = nxt_websocket_frame_header_size(ws_impl->ws.header); +static void nxt_unit_request_info_release(nxt_unit_request_info_t *req) { + nxt_unit_ctx_t *ctx; + nxt_unit_ctx_impl_t *ctx_impl; + nxt_unit_request_info_impl_t *req_impl; - if (ws_impl->ws.header->mask) { - ws_impl->ws.mask = (uint8_t *) b->buf.start + hsize - 4; + ctx = req->ctx; + ctx_impl = nxt_container_of(ctx, nxt_unit_ctx_impl_t, ctx); + req_impl = nxt_container_of(req, nxt_unit_request_info_impl_t, req); - } else { - ws_impl->ws.mask = NULL; - } + req->response = NULL; + req->response_buf = NULL; - b->buf.free += hsize; + if (req_impl->in_hash) { + nxt_unit_request_hash_find(req->ctx, req_impl->stream, 1); + } - ws_impl->ws.content_buf = &b->buf; - ws_impl->ws.content_length = ws_impl->ws.payload_len; + while (req_impl->outgoing_buf != NULL) { + nxt_unit_mmap_buf_free(req_impl->outgoing_buf); + } - nxt_unit_req_debug(req, "websocket_handler: opcode=%d, " - "payload_len=%"PRIu64, - ws_impl->ws.header->opcode, - ws_impl->ws.payload_len); + while (req_impl->incoming_buf != NULL) { + nxt_unit_mmap_buf_free(req_impl->incoming_buf); + } - cb->websocket_handler(&ws_impl->ws); - } + if (req->content_fd != -1) { + nxt_unit_close(req->content_fd); - if (recv_msg->last) { - if (cb->close_handler) { - nxt_unit_req_debug(req, "close_handler"); + req->content_fd = -1; + } - cb->close_handler(req); + if (req->response_port != NULL) { + nxt_unit_port_release(req->response_port); - } else { - nxt_unit_request_done(req, NXT_UNIT_ERROR); - } - } + req->response_port = NULL; + } - return NXT_UNIT_OK; -} + req_impl->state = NXT_UNIT_RS_RELEASED; + pthread_mutex_lock(&ctx_impl->mutex); -static int -nxt_unit_process_shm_ack(nxt_unit_ctx_t *ctx) -{ - nxt_unit_impl_t *lib; - nxt_unit_callbacks_t *cb; + nxt_queue_remove(&req_impl->link); - lib = nxt_container_of(ctx->unit, nxt_unit_impl_t, unit); - cb = &lib->callbacks; + nxt_queue_insert_tail(&ctx_impl->free_req, &req_impl->link); - if (cb->shm_ack_handler != NULL) { - cb->shm_ack_handler(ctx); - } + pthread_mutex_unlock(&ctx_impl->mutex); - return NXT_UNIT_OK; + if (nxt_slow_path(!nxt_unit_chk_ready(ctx))) { + nxt_unit_quit(ctx, NXT_QUIT_GRACEFUL); + } } +static void nxt_unit_request_info_free(nxt_unit_request_info_impl_t *req_impl) { + nxt_unit_ctx_impl_t *ctx_impl; -static nxt_unit_request_info_impl_t * -nxt_unit_request_info_get(nxt_unit_ctx_t *ctx) -{ - nxt_unit_impl_t *lib; - nxt_queue_link_t *lnk; - nxt_unit_ctx_impl_t *ctx_impl; - nxt_unit_request_info_impl_t *req_impl; - - ctx_impl = nxt_container_of(ctx, nxt_unit_ctx_impl_t, ctx); - - lib = nxt_container_of(ctx->unit, nxt_unit_impl_t, unit); + ctx_impl = nxt_container_of(req_impl->req.ctx, nxt_unit_ctx_impl_t, ctx); - pthread_mutex_lock(&ctx_impl->mutex); + nxt_queue_remove(&req_impl->link); - if (nxt_queue_is_empty(&ctx_impl->free_req)) { - pthread_mutex_unlock(&ctx_impl->mutex); + if (req_impl != &ctx_impl->req) { + nxt_unit_free(&ctx_impl->ctx, req_impl); + } +} - req_impl = nxt_unit_malloc(ctx, sizeof(nxt_unit_request_info_impl_t) - + lib->request_data_size); - if (nxt_slow_path(req_impl == NULL)) { - return NULL; - } +static nxt_unit_websocket_frame_impl_t * +nxt_unit_websocket_frame_get(nxt_unit_ctx_t *ctx) { + nxt_queue_link_t *lnk; + nxt_unit_ctx_impl_t *ctx_impl; + nxt_unit_websocket_frame_impl_t *ws_impl; - req_impl->req.unit = ctx->unit; - req_impl->req.ctx = ctx; + ctx_impl = nxt_container_of(ctx, nxt_unit_ctx_impl_t, ctx); - pthread_mutex_lock(&ctx_impl->mutex); + pthread_mutex_lock(&ctx_impl->mutex); - } else { - lnk = nxt_queue_first(&ctx_impl->free_req); - nxt_queue_remove(lnk); + if (nxt_queue_is_empty(&ctx_impl->free_ws)) { + pthread_mutex_unlock(&ctx_impl->mutex); - req_impl = nxt_container_of(lnk, nxt_unit_request_info_impl_t, link); + ws_impl = nxt_unit_malloc(ctx, sizeof(nxt_unit_websocket_frame_impl_t)); + if (nxt_slow_path(ws_impl == NULL)) { + return NULL; } - nxt_queue_insert_tail(&ctx_impl->active_req, &req_impl->link); + } else { + lnk = nxt_queue_first(&ctx_impl->free_ws); + nxt_queue_remove(lnk); pthread_mutex_unlock(&ctx_impl->mutex); - req_impl->req.data = lib->request_data_size ? req_impl->extra_data : NULL; + ws_impl = nxt_container_of(lnk, nxt_unit_websocket_frame_impl_t, link); + } - return req_impl; + ws_impl->ctx_impl = ctx_impl; + + return ws_impl; } +static void nxt_unit_websocket_frame_release(nxt_unit_websocket_frame_t *ws) { + nxt_unit_websocket_frame_impl_t *ws_impl; -static void -nxt_unit_request_info_release(nxt_unit_request_info_t *req) -{ - nxt_unit_ctx_t *ctx; - nxt_unit_ctx_impl_t *ctx_impl; - nxt_unit_request_info_impl_t *req_impl; - - ctx = req->ctx; - ctx_impl = nxt_container_of(ctx, nxt_unit_ctx_impl_t, ctx); - req_impl = nxt_container_of(req, nxt_unit_request_info_impl_t, req); + ws_impl = nxt_container_of(ws, nxt_unit_websocket_frame_impl_t, ws); - req->response = NULL; - req->response_buf = NULL; + while (ws_impl->buf != NULL) { + nxt_unit_mmap_buf_free(ws_impl->buf); + } - if (req_impl->in_hash) { - nxt_unit_request_hash_find(req->ctx, req_impl->stream, 1); - } + ws->req = NULL; - while (req_impl->outgoing_buf != NULL) { - nxt_unit_mmap_buf_free(req_impl->outgoing_buf); - } + pthread_mutex_lock(&ws_impl->ctx_impl->mutex); - while (req_impl->incoming_buf != NULL) { - nxt_unit_mmap_buf_free(req_impl->incoming_buf); - } + nxt_queue_insert_tail(&ws_impl->ctx_impl->free_ws, &ws_impl->link); - if (req->content_fd != -1) { - nxt_unit_close(req->content_fd); + pthread_mutex_unlock(&ws_impl->ctx_impl->mutex); +} - req->content_fd = -1; - } +static void +nxt_unit_websocket_frame_free(nxt_unit_ctx_t *ctx, + nxt_unit_websocket_frame_impl_t *ws_impl) { + nxt_queue_remove(&ws_impl->link); - if (req->response_port != NULL) { - nxt_unit_port_release(req->response_port); + nxt_unit_free(ctx, ws_impl); +} - req->response_port = NULL; - } +uint16_t nxt_unit_field_hash(const char *name, size_t name_length) { + u_char ch; + uint32_t hash; + const char *p, *end; - req_impl->state = NXT_UNIT_RS_RELEASED; + hash = 159406; /* Magic value copied from nxt_http_parse.c */ + end = name + name_length; - pthread_mutex_lock(&ctx_impl->mutex); + for (p = name; p < end; p++) { + ch = *p; + hash = (hash << 4) + hash + nxt_lowcase(ch); + } + + hash = (hash >> 16) ^ hash; - nxt_queue_remove(&req_impl->link); + return hash; +} - nxt_queue_insert_tail(&ctx_impl->free_req, &req_impl->link); +void nxt_unit_request_group_dup_fields(nxt_unit_request_info_t *req) { + char *name; + uint32_t i, j; + nxt_unit_field_t *fields, f; + nxt_unit_request_t *r; - pthread_mutex_unlock(&ctx_impl->mutex); + static const nxt_str_t content_length = nxt_string("content-length"); + static const nxt_str_t content_type = nxt_string("content-type"); + static const nxt_str_t cookie = nxt_string("cookie"); - if (nxt_slow_path(!nxt_unit_chk_ready(ctx))) { - nxt_unit_quit(ctx, NXT_QUIT_GRACEFUL); - } -} + nxt_unit_req_debug(req, "group_dup_fields"); + r = req->request; + fields = r->fields; -static void -nxt_unit_request_info_free(nxt_unit_request_info_impl_t *req_impl) -{ - nxt_unit_ctx_impl_t *ctx_impl; + for (i = 0; i < r->fields_count; i++) { + name = nxt_unit_sptr_get(&fields[i].name); - ctx_impl = nxt_container_of(req_impl->req.ctx, nxt_unit_ctx_impl_t, ctx); + switch (fields[i].hash) { + case NXT_UNIT_HASH_CONTENT_LENGTH: + if (fields[i].name_length == content_length.length && + nxt_unit_memcasecmp(name, content_length.start, + content_length.length) == 0) { + r->content_length_field = i; + } - nxt_queue_remove(&req_impl->link); + break; - if (req_impl != &ctx_impl->req) { - nxt_unit_free(&ctx_impl->ctx, req_impl); - } -} + case NXT_UNIT_HASH_CONTENT_TYPE: + if (fields[i].name_length == content_type.length && + nxt_unit_memcasecmp(name, content_type.start, content_type.length) == + 0) { + r->content_type_field = i; + } + break; -static nxt_unit_websocket_frame_impl_t * -nxt_unit_websocket_frame_get(nxt_unit_ctx_t *ctx) -{ - nxt_queue_link_t *lnk; - nxt_unit_ctx_impl_t *ctx_impl; - nxt_unit_websocket_frame_impl_t *ws_impl; + case NXT_UNIT_HASH_COOKIE: + if (fields[i].name_length == cookie.length && + nxt_unit_memcasecmp(name, cookie.start, cookie.length) == 0) { + r->cookie_field = i; + } - ctx_impl = nxt_container_of(ctx, nxt_unit_ctx_impl_t, ctx); + break; + } - pthread_mutex_lock(&ctx_impl->mutex); + for (j = i + 1; j < r->fields_count; j++) { + if (fields[i].hash != fields[j].hash || + fields[i].name_length != fields[j].name_length || + nxt_unit_memcasecmp(name, nxt_unit_sptr_get(&fields[j].name), + fields[j].name_length) != 0) { + continue; + } - if (nxt_queue_is_empty(&ctx_impl->free_ws)) { - pthread_mutex_unlock(&ctx_impl->mutex); + f = fields[j]; + f.value.offset += (j - (i + 1)) * sizeof(f); - ws_impl = nxt_unit_malloc(ctx, sizeof(nxt_unit_websocket_frame_impl_t)); - if (nxt_slow_path(ws_impl == NULL)) { - return NULL; - } + while (j > i + 1) { + fields[j] = fields[j - 1]; + fields[j].name.offset -= sizeof(f); + fields[j].value.offset -= sizeof(f); + j--; + } - } else { - lnk = nxt_queue_first(&ctx_impl->free_ws); - nxt_queue_remove(lnk); + fields[j] = f; - pthread_mutex_unlock(&ctx_impl->mutex); + /* Assign the same name pointer for further grouping simplicity. */ + nxt_unit_sptr_set(&fields[j].name, name); - ws_impl = nxt_container_of(lnk, nxt_unit_websocket_frame_impl_t, link); + i++; } + } +} - ws_impl->ctx_impl = ctx_impl; +int nxt_unit_response_init(nxt_unit_request_info_t *req, uint16_t status, + uint32_t max_fields_count, + uint32_t max_fields_size) { + uint32_t buf_size; + nxt_unit_buf_t *buf; + nxt_unit_request_info_impl_t *req_impl; - return ws_impl; -} + req_impl = nxt_container_of(req, nxt_unit_request_info_impl_t, req); + if (nxt_slow_path(req_impl->state >= NXT_UNIT_RS_RESPONSE_SENT)) { + nxt_unit_req_warn(req, "init: response already sent"); -static void -nxt_unit_websocket_frame_release(nxt_unit_websocket_frame_t *ws) -{ - nxt_unit_websocket_frame_impl_t *ws_impl; + return NXT_UNIT_ERROR; + } - ws_impl = nxt_container_of(ws, nxt_unit_websocket_frame_impl_t, ws); + nxt_unit_req_debug(req, "init: %d, max fields %d/%d", (int)status, + (int)max_fields_count, (int)max_fields_size); - while (ws_impl->buf != NULL) { - nxt_unit_mmap_buf_free(ws_impl->buf); - } + if (nxt_slow_path(req_impl->state >= NXT_UNIT_RS_RESPONSE_INIT)) { + nxt_unit_req_debug(req, "duplicate response init"); + } - ws->req = NULL; + /* + * Each field name and value 0-terminated by libunit, + * this is the reason of '+ 2' below. + */ + buf_size = sizeof(nxt_unit_response_t) + + max_fields_count * (sizeof(nxt_unit_field_t) + 2) + + max_fields_size; - pthread_mutex_lock(&ws_impl->ctx_impl->mutex); + if (nxt_slow_path(req->response_buf != NULL)) { + buf = req->response_buf; - nxt_queue_insert_tail(&ws_impl->ctx_impl->free_ws, &ws_impl->link); + if (nxt_fast_path(buf_size <= (uint32_t)(buf->end - buf->start))) { + goto init_response; + } - pthread_mutex_unlock(&ws_impl->ctx_impl->mutex); -} + nxt_unit_buf_free(buf); + req->response_buf = NULL; + req->response = NULL; + req->response_max_fields = 0; -static void -nxt_unit_websocket_frame_free(nxt_unit_ctx_t *ctx, - nxt_unit_websocket_frame_impl_t *ws_impl) -{ - nxt_queue_remove(&ws_impl->link); + req_impl->state = NXT_UNIT_RS_START; + } - nxt_unit_free(ctx, ws_impl); -} + buf = nxt_unit_response_buf_alloc(req, buf_size); + if (nxt_slow_path(buf == NULL)) { + return NXT_UNIT_ERROR; + } +init_response: -uint16_t -nxt_unit_field_hash(const char *name, size_t name_length) -{ - u_char ch; - uint32_t hash; - const char *p, *end; + memset(buf->start, 0, sizeof(nxt_unit_response_t)); - hash = 159406; /* Magic value copied from nxt_http_parse.c */ - end = name + name_length; + req->response_buf = buf; - for (p = name; p < end; p++) { - ch = *p; - hash = (hash << 4) + hash + nxt_lowcase(ch); - } + req->response = (nxt_unit_response_t *)buf->start; + req->response->status = status; - hash = (hash >> 16) ^ hash; + buf->free = buf->start + sizeof(nxt_unit_response_t) + + max_fields_count * sizeof(nxt_unit_field_t); - return hash; -} + req->response_max_fields = max_fields_count; + req_impl->state = NXT_UNIT_RS_RESPONSE_INIT; + return NXT_UNIT_OK; +} -void -nxt_unit_request_group_dup_fields(nxt_unit_request_info_t *req) -{ - char *name; - uint32_t i, j; - nxt_unit_field_t *fields, f; - nxt_unit_request_t *r; +int nxt_unit_response_realloc(nxt_unit_request_info_t *req, + uint32_t max_fields_count, + uint32_t max_fields_size) { + char *p; + uint32_t i, buf_size; + nxt_unit_buf_t *buf; + nxt_unit_field_t *f, *src; + nxt_unit_response_t *resp; + nxt_unit_request_info_impl_t *req_impl; - static const nxt_str_t content_length = nxt_string("content-length"); - static const nxt_str_t content_type = nxt_string("content-type"); - static const nxt_str_t cookie = nxt_string("cookie"); + req_impl = nxt_container_of(req, nxt_unit_request_info_impl_t, req); - nxt_unit_req_debug(req, "group_dup_fields"); + if (nxt_slow_path(req_impl->state < NXT_UNIT_RS_RESPONSE_INIT)) { + nxt_unit_req_warn(req, "realloc: response not init"); - r = req->request; - fields = r->fields; + return NXT_UNIT_ERROR; + } - for (i = 0; i < r->fields_count; i++) { - name = nxt_unit_sptr_get(&fields[i].name); + if (nxt_slow_path(req_impl->state >= NXT_UNIT_RS_RESPONSE_SENT)) { + nxt_unit_req_warn(req, "realloc: response already sent"); - switch (fields[i].hash) { - case NXT_UNIT_HASH_CONTENT_LENGTH: - if (fields[i].name_length == content_length.length - && nxt_unit_memcasecmp(name, content_length.start, - content_length.length) == 0) - { - r->content_length_field = i; - } + return NXT_UNIT_ERROR; + } - break; + if (nxt_slow_path(max_fields_count < req->response->fields_count)) { + nxt_unit_req_warn(req, "realloc: new max_fields_count is too small"); - case NXT_UNIT_HASH_CONTENT_TYPE: - if (fields[i].name_length == content_type.length - && nxt_unit_memcasecmp(name, content_type.start, - content_type.length) == 0) - { - r->content_type_field = i; - } + return NXT_UNIT_ERROR; + } - break; + /* + * Each field name and value 0-terminated by libunit, + * this is the reason of '+ 2' below. + */ + buf_size = sizeof(nxt_unit_response_t) + + max_fields_count * (sizeof(nxt_unit_field_t) + 2) + + max_fields_size; - case NXT_UNIT_HASH_COOKIE: - if (fields[i].name_length == cookie.length - && nxt_unit_memcasecmp(name, cookie.start, - cookie.length) == 0) - { - r->cookie_field = i; - } + nxt_unit_req_debug(req, "realloc %" PRIu32 "", buf_size); - break; - } + buf = nxt_unit_response_buf_alloc(req, buf_size); + if (nxt_slow_path(buf == NULL)) { + nxt_unit_req_warn(req, "realloc: new buf allocation failed"); + return NXT_UNIT_ERROR; + } - for (j = i + 1; j < r->fields_count; j++) { - if (fields[i].hash != fields[j].hash - || fields[i].name_length != fields[j].name_length - || nxt_unit_memcasecmp(name, - nxt_unit_sptr_get(&fields[j].name), - fields[j].name_length) != 0) - { - continue; - } + resp = (nxt_unit_response_t *)buf->start; - f = fields[j]; - f.value.offset += (j - (i + 1)) * sizeof(f); + memset(resp, 0, sizeof(nxt_unit_response_t)); - while (j > i + 1) { - fields[j] = fields[j - 1]; - fields[j].name.offset -= sizeof(f); - fields[j].value.offset -= sizeof(f); - j--; - } + resp->status = req->response->status; + resp->content_length = req->response->content_length; - fields[j] = f; + p = buf->start + sizeof(nxt_unit_response_t) + + max_fields_count * sizeof(nxt_unit_field_t); + f = resp->fields; - /* Assign the same name pointer for further grouping simplicity. */ - nxt_unit_sptr_set(&fields[j].name, name); + for (i = 0; i < req->response->fields_count; i++) { + src = req->response->fields + i; - i++; - } + if (nxt_slow_path(src->skip != 0)) { + continue; } -} + if (nxt_slow_path(src->name_length + src->value_length + 2 > + (uint32_t)(buf->end - p))) { + nxt_unit_req_warn(req, + "realloc: not enough space for field" + " #%" PRIu32 " (%p), (%" PRIu32 " + %" PRIu32 + ") required", + i, src, src->name_length, src->value_length); -int -nxt_unit_response_init(nxt_unit_request_info_t *req, - uint16_t status, uint32_t max_fields_count, uint32_t max_fields_size) -{ - uint32_t buf_size; - nxt_unit_buf_t *buf; - nxt_unit_request_info_impl_t *req_impl; + goto fail; + } - req_impl = nxt_container_of(req, nxt_unit_request_info_impl_t, req); + nxt_unit_sptr_set(&f->name, p); + p = nxt_cpymem(p, nxt_unit_sptr_get(&src->name), src->name_length); + *p++ = '\0'; - if (nxt_slow_path(req_impl->state >= NXT_UNIT_RS_RESPONSE_SENT)) { - nxt_unit_req_warn(req, "init: response already sent"); + nxt_unit_sptr_set(&f->value, p); + p = nxt_cpymem(p, nxt_unit_sptr_get(&src->value), src->value_length); + *p++ = '\0'; - return NXT_UNIT_ERROR; - } + f->hash = src->hash; + f->skip = 0; + f->name_length = src->name_length; + f->value_length = src->value_length; + + resp->fields_count++; + f++; + } - nxt_unit_req_debug(req, "init: %d, max fields %d/%d", (int) status, - (int) max_fields_count, (int) max_fields_size); + if (req->response->piggyback_content_length > 0) { + if (nxt_slow_path(req->response->piggyback_content_length > + (uint32_t)(buf->end - p))) { + nxt_unit_req_warn(req, + "realloc: not enought space for content" + " #%" PRIu32 ", %" PRIu32 " required", + i, req->response->piggyback_content_length); - if (nxt_slow_path(req_impl->state >= NXT_UNIT_RS_RESPONSE_INIT)) { - nxt_unit_req_debug(req, "duplicate response init"); + goto fail; } - /* - * Each field name and value 0-terminated by libunit, - * this is the reason of '+ 2' below. - */ - buf_size = sizeof(nxt_unit_response_t) - + max_fields_count * (sizeof(nxt_unit_field_t) + 2) - + max_fields_size; + resp->piggyback_content_length = req->response->piggyback_content_length; - if (nxt_slow_path(req->response_buf != NULL)) { - buf = req->response_buf; + nxt_unit_sptr_set(&resp->piggyback_content, p); + p = nxt_cpymem(p, nxt_unit_sptr_get(&req->response->piggyback_content), + req->response->piggyback_content_length); + } - if (nxt_fast_path(buf_size <= (uint32_t) (buf->end - buf->start))) { - goto init_response; - } + buf->free = p; - nxt_unit_buf_free(buf); + nxt_unit_buf_free(req->response_buf); - req->response_buf = NULL; - req->response = NULL; - req->response_max_fields = 0; + req->response = resp; + req->response_buf = buf; + req->response_max_fields = max_fields_count; - req_impl->state = NXT_UNIT_RS_START; - } + return NXT_UNIT_OK; - buf = nxt_unit_response_buf_alloc(req, buf_size); - if (nxt_slow_path(buf == NULL)) { - return NXT_UNIT_ERROR; - } +fail: -init_response: + nxt_unit_buf_free(buf); - memset(buf->start, 0, sizeof(nxt_unit_response_t)); + return NXT_UNIT_ERROR; +} - req->response_buf = buf; +int nxt_unit_response_is_init(nxt_unit_request_info_t *req) { + nxt_unit_request_info_impl_t *req_impl; - req->response = (nxt_unit_response_t *) buf->start; - req->response->status = status; + req_impl = nxt_container_of(req, nxt_unit_request_info_impl_t, req); - buf->free = buf->start + sizeof(nxt_unit_response_t) - + max_fields_count * sizeof(nxt_unit_field_t); + return req_impl->state >= NXT_UNIT_RS_RESPONSE_INIT; +} - req->response_max_fields = max_fields_count; - req_impl->state = NXT_UNIT_RS_RESPONSE_INIT; +int nxt_unit_response_add_field(nxt_unit_request_info_t *req, const char *name, + uint8_t name_length, const char *value, + uint32_t value_length) { + nxt_unit_buf_t *buf; + nxt_unit_field_t *f; + nxt_unit_response_t *resp; + nxt_unit_request_info_impl_t *req_impl; - return NXT_UNIT_OK; -} + req_impl = nxt_container_of(req, nxt_unit_request_info_impl_t, req); + if (nxt_slow_path(req_impl->state != NXT_UNIT_RS_RESPONSE_INIT)) { + nxt_unit_req_warn(req, "add_field: response not initialized or " + "already sent"); -int -nxt_unit_response_realloc(nxt_unit_request_info_t *req, - uint32_t max_fields_count, uint32_t max_fields_size) -{ - char *p; - uint32_t i, buf_size; - nxt_unit_buf_t *buf; - nxt_unit_field_t *f, *src; - nxt_unit_response_t *resp; - nxt_unit_request_info_impl_t *req_impl; + return NXT_UNIT_ERROR; + } - req_impl = nxt_container_of(req, nxt_unit_request_info_impl_t, req); + resp = req->response; - if (nxt_slow_path(req_impl->state < NXT_UNIT_RS_RESPONSE_INIT)) { - nxt_unit_req_warn(req, "realloc: response not init"); + if (nxt_slow_path(resp->fields_count >= req->response_max_fields)) { + nxt_unit_req_warn(req, "add_field: too many response fields (%d)", + (int)resp->fields_count); - return NXT_UNIT_ERROR; - } + return NXT_UNIT_ERROR; + } - if (nxt_slow_path(req_impl->state >= NXT_UNIT_RS_RESPONSE_SENT)) { - nxt_unit_req_warn(req, "realloc: response already sent"); + buf = req->response_buf; - return NXT_UNIT_ERROR; - } + if (nxt_slow_path(name_length + value_length + 2 > + (uint32_t)(buf->end - buf->free))) { + nxt_unit_req_warn(req, "add_field: response buffer overflow"); - if (nxt_slow_path(max_fields_count < req->response->fields_count)) { - nxt_unit_req_warn(req, "realloc: new max_fields_count is too small"); + return NXT_UNIT_ERROR; + } - return NXT_UNIT_ERROR; - } + nxt_unit_req_debug(req, "add_field #%" PRIu32 ": %.*s: %.*s", + resp->fields_count, (int)name_length, name, + (int)value_length, value); - /* - * Each field name and value 0-terminated by libunit, - * this is the reason of '+ 2' below. - */ - buf_size = sizeof(nxt_unit_response_t) - + max_fields_count * (sizeof(nxt_unit_field_t) + 2) - + max_fields_size; + f = resp->fields + resp->fields_count; - nxt_unit_req_debug(req, "realloc %"PRIu32"", buf_size); + nxt_unit_sptr_set(&f->name, buf->free); + buf->free = nxt_cpymem(buf->free, name, name_length); + *buf->free++ = '\0'; - buf = nxt_unit_response_buf_alloc(req, buf_size); - if (nxt_slow_path(buf == NULL)) { - nxt_unit_req_warn(req, "realloc: new buf allocation failed"); - return NXT_UNIT_ERROR; - } + nxt_unit_sptr_set(&f->value, buf->free); + buf->free = nxt_cpymem(buf->free, value, value_length); + *buf->free++ = '\0'; - resp = (nxt_unit_response_t *) buf->start; + f->hash = nxt_unit_field_hash(name, name_length); + f->skip = 0; + f->name_length = name_length; + f->value_length = value_length; - memset(resp, 0, sizeof(nxt_unit_response_t)); + resp->fields_count++; - resp->status = req->response->status; - resp->content_length = req->response->content_length; + return NXT_UNIT_OK; +} - p = buf->start + sizeof(nxt_unit_response_t) - + max_fields_count * sizeof(nxt_unit_field_t); - f = resp->fields; +int nxt_unit_response_add_content(nxt_unit_request_info_t *req, const void *src, + uint32_t size) { + nxt_unit_buf_t *buf; + nxt_unit_response_t *resp; + nxt_unit_request_info_impl_t *req_impl; - for (i = 0; i < req->response->fields_count; i++) { - src = req->response->fields + i; + req_impl = nxt_container_of(req, nxt_unit_request_info_impl_t, req); - if (nxt_slow_path(src->skip != 0)) { - continue; - } + if (nxt_slow_path(req_impl->state < NXT_UNIT_RS_RESPONSE_INIT)) { + nxt_unit_req_warn(req, "add_content: response not initialized yet"); - if (nxt_slow_path(src->name_length + src->value_length + 2 - > (uint32_t) (buf->end - p))) - { - nxt_unit_req_warn(req, "realloc: not enough space for field" - " #%"PRIu32" (%p), (%"PRIu32" + %"PRIu32") required", - i, src, src->name_length, src->value_length); + return NXT_UNIT_ERROR; + } - goto fail; - } + if (nxt_slow_path(req_impl->state >= NXT_UNIT_RS_RESPONSE_SENT)) { + nxt_unit_req_warn(req, "add_content: response already sent"); - nxt_unit_sptr_set(&f->name, p); - p = nxt_cpymem(p, nxt_unit_sptr_get(&src->name), src->name_length); - *p++ = '\0'; + return NXT_UNIT_ERROR; + } - nxt_unit_sptr_set(&f->value, p); - p = nxt_cpymem(p, nxt_unit_sptr_get(&src->value), src->value_length); - *p++ = '\0'; + buf = req->response_buf; - f->hash = src->hash; - f->skip = 0; - f->name_length = src->name_length; - f->value_length = src->value_length; + if (nxt_slow_path(size > (uint32_t)(buf->end - buf->free))) { + nxt_unit_req_warn(req, "add_content: buffer overflow"); - resp->fields_count++; - f++; - } + return NXT_UNIT_ERROR; + } - if (req->response->piggyback_content_length > 0) { - if (nxt_slow_path(req->response->piggyback_content_length - > (uint32_t) (buf->end - p))) - { - nxt_unit_req_warn(req, "realloc: not enought space for content" - " #%"PRIu32", %"PRIu32" required", - i, req->response->piggyback_content_length); + resp = req->response; - goto fail; - } + if (resp->piggyback_content_length == 0) { + nxt_unit_sptr_set(&resp->piggyback_content, buf->free); + req_impl->state = NXT_UNIT_RS_RESPONSE_HAS_CONTENT; + } - resp->piggyback_content_length = - req->response->piggyback_content_length; + resp->piggyback_content_length += size; - nxt_unit_sptr_set(&resp->piggyback_content, p); - p = nxt_cpymem(p, nxt_unit_sptr_get(&req->response->piggyback_content), - req->response->piggyback_content_length); - } + buf->free = nxt_cpymem(buf->free, src, size); - buf->free = p; + return NXT_UNIT_OK; +} - nxt_unit_buf_free(req->response_buf); +int nxt_unit_response_send(nxt_unit_request_info_t *req) { + int rc; + nxt_unit_mmap_buf_t *mmap_buf; + nxt_unit_request_info_impl_t *req_impl; - req->response = resp; - req->response_buf = buf; - req->response_max_fields = max_fields_count; + req_impl = nxt_container_of(req, nxt_unit_request_info_impl_t, req); - return NXT_UNIT_OK; + if (nxt_slow_path(req_impl->state < NXT_UNIT_RS_RESPONSE_INIT)) { + nxt_unit_req_warn(req, "send: response is not initialized yet"); -fail: + return NXT_UNIT_ERROR; + } - nxt_unit_buf_free(buf); + if (nxt_slow_path(req_impl->state >= NXT_UNIT_RS_RESPONSE_SENT)) { + nxt_unit_req_warn(req, "send: response already sent"); return NXT_UNIT_ERROR; -} + } + if (req->request->websocket_handshake && req->response->status == 101) { + nxt_unit_response_upgrade(req); + } -int -nxt_unit_response_is_init(nxt_unit_request_info_t *req) -{ - nxt_unit_request_info_impl_t *req_impl; + nxt_unit_req_debug(req, "send: %" PRIu32 " fields, %d bytes", + req->response->fields_count, + (int)(req->response_buf->free - req->response_buf->start)); - req_impl = nxt_container_of(req, nxt_unit_request_info_impl_t, req); + mmap_buf = nxt_container_of(req->response_buf, nxt_unit_mmap_buf_t, buf); - return req_impl->state >= NXT_UNIT_RS_RESPONSE_INIT; -} + rc = nxt_unit_mmap_buf_send(req, mmap_buf, 0); + if (nxt_fast_path(rc == NXT_UNIT_OK)) { + req->response = NULL; + req->response_buf = NULL; + req_impl->state = NXT_UNIT_RS_RESPONSE_SENT; + nxt_unit_mmap_buf_free(mmap_buf); + } -int -nxt_unit_response_add_field(nxt_unit_request_info_t *req, - const char *name, uint8_t name_length, - const char *value, uint32_t value_length) -{ - nxt_unit_buf_t *buf; - nxt_unit_field_t *f; - nxt_unit_response_t *resp; - nxt_unit_request_info_impl_t *req_impl; + return rc; +} - req_impl = nxt_container_of(req, nxt_unit_request_info_impl_t, req); +int nxt_unit_response_is_sent(nxt_unit_request_info_t *req) { + nxt_unit_request_info_impl_t *req_impl; - if (nxt_slow_path(req_impl->state != NXT_UNIT_RS_RESPONSE_INIT)) { - nxt_unit_req_warn(req, "add_field: response not initialized or " - "already sent"); + req_impl = nxt_container_of(req, nxt_unit_request_info_impl_t, req); - return NXT_UNIT_ERROR; - } + return req_impl->state >= NXT_UNIT_RS_RESPONSE_SENT; +} - resp = req->response; +nxt_unit_buf_t *nxt_unit_response_buf_alloc(nxt_unit_request_info_t *req, + uint32_t size) { + int rc; + nxt_unit_mmap_buf_t *mmap_buf; + nxt_unit_request_info_impl_t *req_impl; - if (nxt_slow_path(resp->fields_count >= req->response_max_fields)) { - nxt_unit_req_warn(req, "add_field: too many response fields (%d)", - (int) resp->fields_count); + if (nxt_slow_path(size > PORT_MMAP_DATA_SIZE)) { + nxt_unit_req_warn(req, + "response_buf_alloc: " + "requested buffer (%" PRIu32 ") too big", + size); - return NXT_UNIT_ERROR; - } + return NULL; + } - buf = req->response_buf; + nxt_unit_req_debug(req, "response_buf_alloc: %" PRIu32, size); - if (nxt_slow_path(name_length + value_length + 2 - > (uint32_t) (buf->end - buf->free))) - { - nxt_unit_req_warn(req, "add_field: response buffer overflow"); + req_impl = nxt_container_of(req, nxt_unit_request_info_impl_t, req); - return NXT_UNIT_ERROR; - } + mmap_buf = nxt_unit_mmap_buf_get(req->ctx); + if (nxt_slow_path(mmap_buf == NULL)) { + nxt_unit_req_alert(req, "response_buf_alloc: failed to allocate buf"); - nxt_unit_req_debug(req, "add_field #%"PRIu32": %.*s: %.*s", - resp->fields_count, - (int) name_length, name, - (int) value_length, value); + return NULL; + } - f = resp->fields + resp->fields_count; + mmap_buf->req = req; - nxt_unit_sptr_set(&f->name, buf->free); - buf->free = nxt_cpymem(buf->free, name, name_length); - *buf->free++ = '\0'; + nxt_unit_mmap_buf_insert_tail(&req_impl->outgoing_buf, mmap_buf); - nxt_unit_sptr_set(&f->value, buf->free); - buf->free = nxt_cpymem(buf->free, value, value_length); - *buf->free++ = '\0'; + rc = nxt_unit_get_outgoing_buf(req->ctx, req->response_port, size, size, + mmap_buf, NULL); + if (nxt_slow_path(rc != NXT_UNIT_OK)) { + nxt_unit_mmap_buf_release(mmap_buf); - f->hash = nxt_unit_field_hash(name, name_length); - f->skip = 0; - f->name_length = name_length; - f->value_length = value_length; + nxt_unit_req_alert(req, "response_buf_alloc: failed to get out buf"); - resp->fields_count++; + return NULL; + } - return NXT_UNIT_OK; + return &mmap_buf->buf; } +static nxt_unit_mmap_buf_t *nxt_unit_mmap_buf_get(nxt_unit_ctx_t *ctx) { + nxt_unit_mmap_buf_t *mmap_buf; + nxt_unit_ctx_impl_t *ctx_impl; -int -nxt_unit_response_add_content(nxt_unit_request_info_t *req, - const void* src, uint32_t size) -{ - nxt_unit_buf_t *buf; - nxt_unit_response_t *resp; - nxt_unit_request_info_impl_t *req_impl; + ctx_impl = nxt_container_of(ctx, nxt_unit_ctx_impl_t, ctx); - req_impl = nxt_container_of(req, nxt_unit_request_info_impl_t, req); + pthread_mutex_lock(&ctx_impl->mutex); - if (nxt_slow_path(req_impl->state < NXT_UNIT_RS_RESPONSE_INIT)) { - nxt_unit_req_warn(req, "add_content: response not initialized yet"); + if (ctx_impl->free_buf == NULL) { + pthread_mutex_unlock(&ctx_impl->mutex); - return NXT_UNIT_ERROR; + mmap_buf = nxt_unit_malloc(ctx, sizeof(nxt_unit_mmap_buf_t)); + if (nxt_slow_path(mmap_buf == NULL)) { + return NULL; } - if (nxt_slow_path(req_impl->state >= NXT_UNIT_RS_RESPONSE_SENT)) { - nxt_unit_req_warn(req, "add_content: response already sent"); + } else { + mmap_buf = ctx_impl->free_buf; - return NXT_UNIT_ERROR; - } + nxt_unit_mmap_buf_unlink(mmap_buf); - buf = req->response_buf; + pthread_mutex_unlock(&ctx_impl->mutex); + } - if (nxt_slow_path(size > (uint32_t) (buf->end - buf->free))) { - nxt_unit_req_warn(req, "add_content: buffer overflow"); + mmap_buf->ctx_impl = ctx_impl; - return NXT_UNIT_ERROR; - } + mmap_buf->hdr = NULL; + mmap_buf->free_ptr = NULL; - resp = req->response; + return mmap_buf; +} - if (resp->piggyback_content_length == 0) { - nxt_unit_sptr_set(&resp->piggyback_content, buf->free); - req_impl->state = NXT_UNIT_RS_RESPONSE_HAS_CONTENT; - } +static void nxt_unit_mmap_buf_release(nxt_unit_mmap_buf_t *mmap_buf) { + nxt_unit_mmap_buf_unlink(mmap_buf); - resp->piggyback_content_length += size; + pthread_mutex_lock(&mmap_buf->ctx_impl->mutex); - buf->free = nxt_cpymem(buf->free, src, size); + nxt_unit_mmap_buf_insert(&mmap_buf->ctx_impl->free_buf, mmap_buf); - return NXT_UNIT_OK; + pthread_mutex_unlock(&mmap_buf->ctx_impl->mutex); } +int nxt_unit_request_is_websocket_handshake(nxt_unit_request_info_t *req) { + return req->request->websocket_handshake; +} -int -nxt_unit_response_send(nxt_unit_request_info_t *req) -{ - int rc; - nxt_unit_mmap_buf_t *mmap_buf; - nxt_unit_request_info_impl_t *req_impl; +int nxt_unit_response_upgrade(nxt_unit_request_info_t *req) { + int rc; + nxt_unit_request_info_impl_t *req_impl; - req_impl = nxt_container_of(req, nxt_unit_request_info_impl_t, req); + req_impl = nxt_container_of(req, nxt_unit_request_info_impl_t, req); - if (nxt_slow_path(req_impl->state < NXT_UNIT_RS_RESPONSE_INIT)) { - nxt_unit_req_warn(req, "send: response is not initialized yet"); + if (nxt_slow_path(req_impl->websocket != 0)) { + nxt_unit_req_debug(req, "upgrade: already upgraded"); - return NXT_UNIT_ERROR; - } + return NXT_UNIT_OK; + } - if (nxt_slow_path(req_impl->state >= NXT_UNIT_RS_RESPONSE_SENT)) { - nxt_unit_req_warn(req, "send: response already sent"); + if (nxt_slow_path(req_impl->state < NXT_UNIT_RS_RESPONSE_INIT)) { + nxt_unit_req_warn(req, "upgrade: response is not initialized yet"); - return NXT_UNIT_ERROR; - } + return NXT_UNIT_ERROR; + } - if (req->request->websocket_handshake && req->response->status == 101) { - nxt_unit_response_upgrade(req); - } + if (nxt_slow_path(req_impl->state >= NXT_UNIT_RS_RESPONSE_SENT)) { + nxt_unit_req_warn(req, "upgrade: response already sent"); - nxt_unit_req_debug(req, "send: %"PRIu32" fields, %d bytes", - req->response->fields_count, - (int) (req->response_buf->free - - req->response_buf->start)); + return NXT_UNIT_ERROR; + } - mmap_buf = nxt_container_of(req->response_buf, nxt_unit_mmap_buf_t, buf); + rc = nxt_unit_request_hash_add(req->ctx, req); + if (nxt_slow_path(rc != NXT_UNIT_OK)) { + nxt_unit_req_warn(req, "upgrade: failed to add request to hash"); - rc = nxt_unit_mmap_buf_send(req, mmap_buf, 0); - if (nxt_fast_path(rc == NXT_UNIT_OK)) { - req->response = NULL; - req->response_buf = NULL; - req_impl->state = NXT_UNIT_RS_RESPONSE_SENT; + return NXT_UNIT_ERROR; + } - nxt_unit_mmap_buf_free(mmap_buf); - } + req_impl->websocket = 1; - return rc; -} + req->response->status = 101; + return NXT_UNIT_OK; +} -int -nxt_unit_response_is_sent(nxt_unit_request_info_t *req) -{ - nxt_unit_request_info_impl_t *req_impl; +int nxt_unit_response_is_websocket(nxt_unit_request_info_t *req) { + nxt_unit_request_info_impl_t *req_impl; - req_impl = nxt_container_of(req, nxt_unit_request_info_impl_t, req); + req_impl = nxt_container_of(req, nxt_unit_request_info_impl_t, req); - return req_impl->state >= NXT_UNIT_RS_RESPONSE_SENT; + return req_impl->websocket; } +nxt_unit_request_info_t *nxt_unit_get_request_info_from_data(void *data) { + nxt_unit_request_info_impl_t *req_impl; -nxt_unit_buf_t * -nxt_unit_response_buf_alloc(nxt_unit_request_info_t *req, uint32_t size) -{ - int rc; - nxt_unit_mmap_buf_t *mmap_buf; - nxt_unit_request_info_impl_t *req_impl; + req_impl = nxt_container_of(data, nxt_unit_request_info_impl_t, extra_data); - if (nxt_slow_path(size > PORT_MMAP_DATA_SIZE)) { - nxt_unit_req_warn(req, "response_buf_alloc: " - "requested buffer (%"PRIu32") too big", size); + return &req_impl->req; +} - return NULL; - } +int nxt_unit_buf_send(nxt_unit_buf_t *buf) { + int rc; + nxt_unit_mmap_buf_t *mmap_buf; + nxt_unit_request_info_t *req; + nxt_unit_request_info_impl_t *req_impl; - nxt_unit_req_debug(req, "response_buf_alloc: %"PRIu32, size); + mmap_buf = nxt_container_of(buf, nxt_unit_mmap_buf_t, buf); - req_impl = nxt_container_of(req, nxt_unit_request_info_impl_t, req); - - mmap_buf = nxt_unit_mmap_buf_get(req->ctx); - if (nxt_slow_path(mmap_buf == NULL)) { - nxt_unit_req_alert(req, "response_buf_alloc: failed to allocate buf"); - - return NULL; - } - - mmap_buf->req = req; - - nxt_unit_mmap_buf_insert_tail(&req_impl->outgoing_buf, mmap_buf); - - rc = nxt_unit_get_outgoing_buf(req->ctx, req->response_port, - size, size, mmap_buf, - NULL); - if (nxt_slow_path(rc != NXT_UNIT_OK)) { - nxt_unit_mmap_buf_release(mmap_buf); - - nxt_unit_req_alert(req, "response_buf_alloc: failed to get out buf"); - - return NULL; - } - - return &mmap_buf->buf; -} - - -static nxt_unit_mmap_buf_t * -nxt_unit_mmap_buf_get(nxt_unit_ctx_t *ctx) -{ - nxt_unit_mmap_buf_t *mmap_buf; - nxt_unit_ctx_impl_t *ctx_impl; - - ctx_impl = nxt_container_of(ctx, nxt_unit_ctx_impl_t, ctx); - - pthread_mutex_lock(&ctx_impl->mutex); - - if (ctx_impl->free_buf == NULL) { - pthread_mutex_unlock(&ctx_impl->mutex); - - mmap_buf = nxt_unit_malloc(ctx, sizeof(nxt_unit_mmap_buf_t)); - if (nxt_slow_path(mmap_buf == NULL)) { - return NULL; - } - - } else { - mmap_buf = ctx_impl->free_buf; - - nxt_unit_mmap_buf_unlink(mmap_buf); - - pthread_mutex_unlock(&ctx_impl->mutex); - } + req = mmap_buf->req; + req_impl = nxt_container_of(req, nxt_unit_request_info_impl_t, req); - mmap_buf->ctx_impl = ctx_impl; - - mmap_buf->hdr = NULL; - mmap_buf->free_ptr = NULL; - - return mmap_buf; -} - - -static void -nxt_unit_mmap_buf_release(nxt_unit_mmap_buf_t *mmap_buf) -{ - nxt_unit_mmap_buf_unlink(mmap_buf); + nxt_unit_req_debug(req, "buf_send: %d bytes", (int)(buf->free - buf->start)); - pthread_mutex_lock(&mmap_buf->ctx_impl->mutex); + if (nxt_slow_path(req_impl->state < NXT_UNIT_RS_RESPONSE_INIT)) { + nxt_unit_req_warn(req, "buf_send: response not initialized yet"); - nxt_unit_mmap_buf_insert(&mmap_buf->ctx_impl->free_buf, mmap_buf); - - pthread_mutex_unlock(&mmap_buf->ctx_impl->mutex); -} - - -int -nxt_unit_request_is_websocket_handshake(nxt_unit_request_info_t *req) -{ - return req->request->websocket_handshake; -} - - -int -nxt_unit_response_upgrade(nxt_unit_request_info_t *req) -{ - int rc; - nxt_unit_request_info_impl_t *req_impl; - - req_impl = nxt_container_of(req, nxt_unit_request_info_impl_t, req); - - if (nxt_slow_path(req_impl->websocket != 0)) { - nxt_unit_req_debug(req, "upgrade: already upgraded"); - - return NXT_UNIT_OK; - } - - if (nxt_slow_path(req_impl->state < NXT_UNIT_RS_RESPONSE_INIT)) { - nxt_unit_req_warn(req, "upgrade: response is not initialized yet"); - - return NXT_UNIT_ERROR; - } + return NXT_UNIT_ERROR; + } - if (nxt_slow_path(req_impl->state >= NXT_UNIT_RS_RESPONSE_SENT)) { - nxt_unit_req_warn(req, "upgrade: response already sent"); + if (nxt_slow_path(req_impl->state < NXT_UNIT_RS_RESPONSE_SENT)) { + nxt_unit_req_warn(req, "buf_send: headers not sent yet"); - return NXT_UNIT_ERROR; - } + return NXT_UNIT_ERROR; + } - rc = nxt_unit_request_hash_add(req->ctx, req); + if (nxt_fast_path(buf->free > buf->start)) { + rc = nxt_unit_mmap_buf_send(req, mmap_buf, 0); if (nxt_slow_path(rc != NXT_UNIT_OK)) { - nxt_unit_req_warn(req, "upgrade: failed to add request to hash"); - - return NXT_UNIT_ERROR; + return rc; } + } - req_impl->websocket = 1; - - req->response->status = 101; + nxt_unit_mmap_buf_free(mmap_buf); - return NXT_UNIT_OK; + return NXT_UNIT_OK; } +static void nxt_unit_buf_send_done(nxt_unit_buf_t *buf) { + int rc; + nxt_unit_mmap_buf_t *mmap_buf; + nxt_unit_request_info_t *req; -int -nxt_unit_response_is_websocket(nxt_unit_request_info_t *req) -{ - nxt_unit_request_info_impl_t *req_impl; - - req_impl = nxt_container_of(req, nxt_unit_request_info_impl_t, req); - - return req_impl->websocket; -} + mmap_buf = nxt_container_of(buf, nxt_unit_mmap_buf_t, buf); + req = mmap_buf->req; -nxt_unit_request_info_t * -nxt_unit_get_request_info_from_data(void *data) -{ - nxt_unit_request_info_impl_t *req_impl; + rc = nxt_unit_mmap_buf_send(req, mmap_buf, 1); + if (nxt_slow_path(rc == NXT_UNIT_OK)) { + nxt_unit_mmap_buf_free(mmap_buf); - req_impl = nxt_container_of(data, nxt_unit_request_info_impl_t, extra_data); + nxt_unit_request_info_release(req); - return &req_impl->req; + } else { + nxt_unit_request_done(req, rc); + } } - -int -nxt_unit_buf_send(nxt_unit_buf_t *buf) -{ - int rc; - nxt_unit_mmap_buf_t *mmap_buf; - nxt_unit_request_info_t *req; - nxt_unit_request_info_impl_t *req_impl; - - mmap_buf = nxt_container_of(buf, nxt_unit_mmap_buf_t, buf); - - req = mmap_buf->req; - req_impl = nxt_container_of(req, nxt_unit_request_info_impl_t, req); - - nxt_unit_req_debug(req, "buf_send: %d bytes", - (int) (buf->free - buf->start)); - - if (nxt_slow_path(req_impl->state < NXT_UNIT_RS_RESPONSE_INIT)) { - nxt_unit_req_warn(req, "buf_send: response not initialized yet"); - - return NXT_UNIT_ERROR; - } - - if (nxt_slow_path(req_impl->state < NXT_UNIT_RS_RESPONSE_SENT)) { - nxt_unit_req_warn(req, "buf_send: headers not sent yet"); - - return NXT_UNIT_ERROR; - } - - if (nxt_fast_path(buf->free > buf->start)) { - rc = nxt_unit_mmap_buf_send(req, mmap_buf, 0); - if (nxt_slow_path(rc != NXT_UNIT_OK)) { - return rc; - } +static int nxt_unit_mmap_buf_send(nxt_unit_request_info_t *req, + nxt_unit_mmap_buf_t *mmap_buf, int last) { + struct { + nxt_port_msg_t msg; + nxt_port_mmap_msg_t mmap_msg; + } m; + + int rc; + u_char *last_used, *first_free; + ssize_t res; + nxt_chunk_id_t first_free_chunk; + nxt_unit_buf_t *buf; + nxt_unit_impl_t *lib; + nxt_port_mmap_header_t *hdr; + nxt_unit_request_info_impl_t *req_impl; + + lib = nxt_container_of(req->ctx->unit, nxt_unit_impl_t, unit); + req_impl = nxt_container_of(req, nxt_unit_request_info_impl_t, req); + + buf = &mmap_buf->buf; + hdr = mmap_buf->hdr; + + m.mmap_msg.size = buf->free - buf->start; + + m.msg.stream = req_impl->stream; + m.msg.pid = lib->pid; + m.msg.reply_port = 0; + m.msg.type = _NXT_PORT_MSG_DATA; + m.msg.last = last != 0; + m.msg.mmap = hdr != NULL && m.mmap_msg.size > 0; + m.msg.nf = 0; + m.msg.mf = 0; + + rc = NXT_UNIT_ERROR; + + if (m.msg.mmap) { + m.mmap_msg.mmap_id = hdr->id; + m.mmap_msg.chunk_id = nxt_port_mmap_chunk_id(hdr, (u_char *)buf->start); + + nxt_unit_debug(req->ctx, "#%" PRIu32 ": send mmap: (%d,%d,%d)", + req_impl->stream, (int)m.mmap_msg.mmap_id, + (int)m.mmap_msg.chunk_id, (int)m.mmap_msg.size); + + res = nxt_unit_port_send(req->ctx, req->response_port, &m, sizeof(m), NULL); + if (nxt_slow_path(res != sizeof(m))) { + goto free_buf; } - nxt_unit_mmap_buf_free(mmap_buf); - - return NXT_UNIT_OK; -} - - -static void -nxt_unit_buf_send_done(nxt_unit_buf_t *buf) -{ - int rc; - nxt_unit_mmap_buf_t *mmap_buf; - nxt_unit_request_info_t *req; - - mmap_buf = nxt_container_of(buf, nxt_unit_mmap_buf_t, buf); + last_used = (u_char *)buf->free - 1; + first_free_chunk = nxt_port_mmap_chunk_id(hdr, last_used) + 1; - req = mmap_buf->req; + if (buf->end - buf->free >= PORT_MMAP_CHUNK_SIZE) { + first_free = nxt_port_mmap_chunk_start(hdr, first_free_chunk); - rc = nxt_unit_mmap_buf_send(req, mmap_buf, 1); - if (nxt_slow_path(rc == NXT_UNIT_OK)) { - nxt_unit_mmap_buf_free(mmap_buf); + buf->start = (char *)first_free; + buf->free = buf->start; - nxt_unit_request_info_release(req); + if (buf->end < buf->start) { + buf->end = buf->start; + } } else { - nxt_unit_request_done(req, rc); - } -} + buf->start = NULL; + buf->free = NULL; + buf->end = NULL; + mmap_buf->hdr = NULL; + } -static int -nxt_unit_mmap_buf_send(nxt_unit_request_info_t *req, - nxt_unit_mmap_buf_t *mmap_buf, int last) -{ - struct { - nxt_port_msg_t msg; - nxt_port_mmap_msg_t mmap_msg; - } m; - - int rc; - u_char *last_used, *first_free; - ssize_t res; - nxt_chunk_id_t first_free_chunk; - nxt_unit_buf_t *buf; - nxt_unit_impl_t *lib; - nxt_port_mmap_header_t *hdr; - nxt_unit_request_info_impl_t *req_impl; - - lib = nxt_container_of(req->ctx->unit, nxt_unit_impl_t, unit); - req_impl = nxt_container_of(req, nxt_unit_request_info_impl_t, req); - - buf = &mmap_buf->buf; - hdr = mmap_buf->hdr; - - m.mmap_msg.size = buf->free - buf->start; - - m.msg.stream = req_impl->stream; - m.msg.pid = lib->pid; - m.msg.reply_port = 0; - m.msg.type = _NXT_PORT_MSG_DATA; - m.msg.last = last != 0; - m.msg.mmap = hdr != NULL && m.mmap_msg.size > 0; - m.msg.nf = 0; - m.msg.mf = 0; - - rc = NXT_UNIT_ERROR; - - if (m.msg.mmap) { - m.mmap_msg.mmap_id = hdr->id; - m.mmap_msg.chunk_id = nxt_port_mmap_chunk_id(hdr, - (u_char *) buf->start); - - nxt_unit_debug(req->ctx, "#%"PRIu32": send mmap: (%d,%d,%d)", - req_impl->stream, - (int) m.mmap_msg.mmap_id, - (int) m.mmap_msg.chunk_id, - (int) m.mmap_msg.size); - - res = nxt_unit_port_send(req->ctx, req->response_port, &m, sizeof(m), - NULL); - if (nxt_slow_path(res != sizeof(m))) { - goto free_buf; - } - - last_used = (u_char *) buf->free - 1; - first_free_chunk = nxt_port_mmap_chunk_id(hdr, last_used) + 1; - - if (buf->end - buf->free >= PORT_MMAP_CHUNK_SIZE) { - first_free = nxt_port_mmap_chunk_start(hdr, first_free_chunk); - - buf->start = (char *) first_free; - buf->free = buf->start; - - if (buf->end < buf->start) { - buf->end = buf->start; - } - - } else { - buf->start = NULL; - buf->free = NULL; - buf->end = NULL; - - mmap_buf->hdr = NULL; - } + nxt_atomic_fetch_add(&lib->outgoing.allocated_chunks, + (int)m.mmap_msg.chunk_id - (int)first_free_chunk); - nxt_atomic_fetch_add(&lib->outgoing.allocated_chunks, - (int) m.mmap_msg.chunk_id - (int) first_free_chunk); + nxt_unit_debug(req->ctx, "allocated_chunks %d", + (int)lib->outgoing.allocated_chunks); - nxt_unit_debug(req->ctx, "allocated_chunks %d", - (int) lib->outgoing.allocated_chunks); + } else { + if (nxt_slow_path(mmap_buf->plain_ptr == NULL || + mmap_buf->plain_ptr > buf->start - sizeof(m.msg))) { + nxt_unit_alert(req->ctx, + "#%" PRIu32 ": failed to send plain memory buffer" + ": no space reserved for message header", + req_impl->stream); - } else { - if (nxt_slow_path(mmap_buf->plain_ptr == NULL - || mmap_buf->plain_ptr > buf->start - sizeof(m.msg))) - { - nxt_unit_alert(req->ctx, - "#%"PRIu32": failed to send plain memory buffer" - ": no space reserved for message header", - req_impl->stream); - - goto free_buf; - } + goto free_buf; + } - memcpy(buf->start - sizeof(m.msg), &m.msg, sizeof(m.msg)); + memcpy(buf->start - sizeof(m.msg), &m.msg, sizeof(m.msg)); - nxt_unit_debug(req->ctx, "#%"PRIu32": send plain: %d", - req_impl->stream, - (int) (sizeof(m.msg) + m.mmap_msg.size)); + nxt_unit_debug(req->ctx, "#%" PRIu32 ": send plain: %d", req_impl->stream, + (int)(sizeof(m.msg) + m.mmap_msg.size)); - res = nxt_unit_port_send(req->ctx, req->response_port, - buf->start - sizeof(m.msg), - m.mmap_msg.size + sizeof(m.msg), NULL); + res = nxt_unit_port_send(req->ctx, req->response_port, + buf->start - sizeof(m.msg), + m.mmap_msg.size + sizeof(m.msg), NULL); - if (nxt_slow_path(res != (ssize_t) (m.mmap_msg.size + sizeof(m.msg)))) { - goto free_buf; - } + if (nxt_slow_path(res != (ssize_t)(m.mmap_msg.size + sizeof(m.msg)))) { + goto free_buf; } + } - rc = NXT_UNIT_OK; + rc = NXT_UNIT_OK; free_buf: - nxt_unit_free_outgoing_buf(mmap_buf); + nxt_unit_free_outgoing_buf(mmap_buf); - return rc; + return rc; } - -void -nxt_unit_buf_free(nxt_unit_buf_t *buf) -{ - nxt_unit_mmap_buf_free(nxt_container_of(buf, nxt_unit_mmap_buf_t, buf)); +void nxt_unit_buf_free(nxt_unit_buf_t *buf) { + nxt_unit_mmap_buf_free(nxt_container_of(buf, nxt_unit_mmap_buf_t, buf)); } +static void nxt_unit_mmap_buf_free(nxt_unit_mmap_buf_t *mmap_buf) { + nxt_unit_free_outgoing_buf(mmap_buf); -static void -nxt_unit_mmap_buf_free(nxt_unit_mmap_buf_t *mmap_buf) -{ - nxt_unit_free_outgoing_buf(mmap_buf); - - nxt_unit_mmap_buf_release(mmap_buf); + nxt_unit_mmap_buf_release(mmap_buf); } +static void nxt_unit_free_outgoing_buf(nxt_unit_mmap_buf_t *mmap_buf) { + if (mmap_buf->hdr != NULL) { + nxt_unit_mmap_release(&mmap_buf->ctx_impl->ctx, mmap_buf->hdr, + mmap_buf->buf.start, + mmap_buf->buf.end - mmap_buf->buf.start); -static void -nxt_unit_free_outgoing_buf(nxt_unit_mmap_buf_t *mmap_buf) -{ - if (mmap_buf->hdr != NULL) { - nxt_unit_mmap_release(&mmap_buf->ctx_impl->ctx, - mmap_buf->hdr, mmap_buf->buf.start, - mmap_buf->buf.end - mmap_buf->buf.start); - - mmap_buf->hdr = NULL; + mmap_buf->hdr = NULL; - return; - } + return; + } - if (mmap_buf->free_ptr != NULL) { - nxt_unit_free(&mmap_buf->ctx_impl->ctx, mmap_buf->free_ptr); + if (mmap_buf->free_ptr != NULL) { + nxt_unit_free(&mmap_buf->ctx_impl->ctx, mmap_buf->free_ptr); - mmap_buf->free_ptr = NULL; - } + mmap_buf->free_ptr = NULL; + } } +static nxt_unit_read_buf_t *nxt_unit_read_buf_get(nxt_unit_ctx_t *ctx) { + nxt_unit_ctx_impl_t *ctx_impl; + nxt_unit_read_buf_t *rbuf; -static nxt_unit_read_buf_t * -nxt_unit_read_buf_get(nxt_unit_ctx_t *ctx) -{ - nxt_unit_ctx_impl_t *ctx_impl; - nxt_unit_read_buf_t *rbuf; - - ctx_impl = nxt_container_of(ctx, nxt_unit_ctx_impl_t, ctx); + ctx_impl = nxt_container_of(ctx, nxt_unit_ctx_impl_t, ctx); - pthread_mutex_lock(&ctx_impl->mutex); + pthread_mutex_lock(&ctx_impl->mutex); - rbuf = nxt_unit_read_buf_get_impl(ctx_impl); + rbuf = nxt_unit_read_buf_get_impl(ctx_impl); - pthread_mutex_unlock(&ctx_impl->mutex); + pthread_mutex_unlock(&ctx_impl->mutex); - rbuf->oob.size = 0; + rbuf->oob.size = 0; - return rbuf; + return rbuf; } - static nxt_unit_read_buf_t * -nxt_unit_read_buf_get_impl(nxt_unit_ctx_impl_t *ctx_impl) -{ - nxt_queue_link_t *link; - nxt_unit_read_buf_t *rbuf; - - if (!nxt_queue_is_empty(&ctx_impl->free_rbuf)) { - link = nxt_queue_first(&ctx_impl->free_rbuf); - nxt_queue_remove(link); +nxt_unit_read_buf_get_impl(nxt_unit_ctx_impl_t *ctx_impl) { + nxt_queue_link_t *link; + nxt_unit_read_buf_t *rbuf; - rbuf = nxt_container_of(link, nxt_unit_read_buf_t, link); + if (!nxt_queue_is_empty(&ctx_impl->free_rbuf)) { + link = nxt_queue_first(&ctx_impl->free_rbuf); + nxt_queue_remove(link); - return rbuf; - } - - rbuf = nxt_unit_malloc(&ctx_impl->ctx, sizeof(nxt_unit_read_buf_t)); - - if (nxt_fast_path(rbuf != NULL)) { - rbuf->ctx_impl = ctx_impl; - } + rbuf = nxt_container_of(link, nxt_unit_read_buf_t, link); return rbuf; -} - + } -static void -nxt_unit_read_buf_release(nxt_unit_ctx_t *ctx, - nxt_unit_read_buf_t *rbuf) -{ - nxt_unit_ctx_impl_t *ctx_impl; - - ctx_impl = nxt_container_of(ctx, nxt_unit_ctx_impl_t, ctx); - - pthread_mutex_lock(&ctx_impl->mutex); + rbuf = nxt_unit_malloc(&ctx_impl->ctx, sizeof(nxt_unit_read_buf_t)); - nxt_queue_insert_head(&ctx_impl->free_rbuf, &rbuf->link); + if (nxt_fast_path(rbuf != NULL)) { + rbuf->ctx_impl = ctx_impl; + } - pthread_mutex_unlock(&ctx_impl->mutex); + return rbuf; } +static void nxt_unit_read_buf_release(nxt_unit_ctx_t *ctx, + nxt_unit_read_buf_t *rbuf) { + nxt_unit_ctx_impl_t *ctx_impl; -nxt_unit_buf_t * -nxt_unit_buf_next(nxt_unit_buf_t *buf) -{ - nxt_unit_mmap_buf_t *mmap_buf; + ctx_impl = nxt_container_of(ctx, nxt_unit_ctx_impl_t, ctx); - mmap_buf = nxt_container_of(buf, nxt_unit_mmap_buf_t, buf); + pthread_mutex_lock(&ctx_impl->mutex); - if (mmap_buf->next == NULL) { - return NULL; - } + nxt_queue_insert_head(&ctx_impl->free_rbuf, &rbuf->link); - return &mmap_buf->next->buf; + pthread_mutex_unlock(&ctx_impl->mutex); } +nxt_unit_buf_t *nxt_unit_buf_next(nxt_unit_buf_t *buf) { + nxt_unit_mmap_buf_t *mmap_buf; -uint32_t -nxt_unit_buf_max(void) -{ - return PORT_MMAP_DATA_SIZE; -} + mmap_buf = nxt_container_of(buf, nxt_unit_mmap_buf_t, buf); + if (mmap_buf->next == NULL) { + return NULL; + } -uint32_t -nxt_unit_buf_min(void) -{ - return PORT_MMAP_CHUNK_SIZE; + return &mmap_buf->next->buf; } +uint32_t nxt_unit_buf_max(void) { return PORT_MMAP_DATA_SIZE; } -int -nxt_unit_response_write(nxt_unit_request_info_t *req, const void *start, - size_t size) -{ - ssize_t res; - - res = nxt_unit_response_write_nb(req, start, size, size); - - return res < 0 ? -res : NXT_UNIT_OK; -} - +uint32_t nxt_unit_buf_min(void) { return PORT_MMAP_CHUNK_SIZE; } -ssize_t -nxt_unit_response_write_nb(nxt_unit_request_info_t *req, const void *start, - size_t size, size_t min_size) -{ - int rc; - ssize_t sent; - uint32_t part_size, min_part_size, buf_size; - const char *part_start; - nxt_unit_mmap_buf_t mmap_buf; - nxt_unit_request_info_impl_t *req_impl; - char local_buf[NXT_UNIT_LOCAL_BUF_SIZE]; +int nxt_unit_response_write(nxt_unit_request_info_t *req, const void *start, + size_t size) { + ssize_t res; - nxt_unit_req_debug(req, "write: %d", (int) size); + res = nxt_unit_response_write_nb(req, start, size, size); - req_impl = nxt_container_of(req, nxt_unit_request_info_impl_t, req); + return res < 0 ? -res : NXT_UNIT_OK; +} - part_start = start; - sent = 0; +ssize_t nxt_unit_response_write_nb(nxt_unit_request_info_t *req, + const void *start, size_t size, + size_t min_size) { + int rc; + ssize_t sent; + uint32_t part_size, min_part_size, buf_size; + const char *part_start; + nxt_unit_mmap_buf_t mmap_buf; + nxt_unit_request_info_impl_t *req_impl; + char local_buf[NXT_UNIT_LOCAL_BUF_SIZE]; - if (nxt_slow_path(req_impl->state < NXT_UNIT_RS_RESPONSE_INIT)) { - nxt_unit_req_alert(req, "write: response not initialized yet"); + nxt_unit_req_debug(req, "write: %d", (int)size); - return -NXT_UNIT_ERROR; - } + req_impl = nxt_container_of(req, nxt_unit_request_info_impl_t, req); - /* Check if response is not send yet. */ - if (nxt_slow_path(req->response_buf != NULL)) { - part_size = req->response_buf->end - req->response_buf->free; - part_size = nxt_min(size, part_size); + part_start = start; + sent = 0; - rc = nxt_unit_response_add_content(req, part_start, part_size); - if (nxt_slow_path(rc != NXT_UNIT_OK)) { - return -rc; - } + if (nxt_slow_path(req_impl->state < NXT_UNIT_RS_RESPONSE_INIT)) { + nxt_unit_req_alert(req, "write: response not initialized yet"); - rc = nxt_unit_response_send(req); - if (nxt_slow_path(rc != NXT_UNIT_OK)) { - return -rc; - } + return -NXT_UNIT_ERROR; + } - size -= part_size; - part_start += part_size; - sent += part_size; + /* Check if response is not send yet. */ + if (nxt_slow_path(req->response_buf != NULL)) { + part_size = req->response_buf->end - req->response_buf->free; + part_size = nxt_min(size, part_size); - min_size -= nxt_min(min_size, part_size); + rc = nxt_unit_response_add_content(req, part_start, part_size); + if (nxt_slow_path(rc != NXT_UNIT_OK)) { + return -rc; } - while (size > 0) { - part_size = nxt_min(size, PORT_MMAP_DATA_SIZE); - min_part_size = nxt_min(min_size, part_size); - min_part_size = nxt_min(min_part_size, PORT_MMAP_CHUNK_SIZE); - - rc = nxt_unit_get_outgoing_buf(req->ctx, req->response_port, part_size, - min_part_size, &mmap_buf, local_buf); - if (nxt_slow_path(rc != NXT_UNIT_OK)) { - return -rc; - } - - buf_size = mmap_buf.buf.end - mmap_buf.buf.free; - if (nxt_slow_path(buf_size == 0)) { - return sent; - } - part_size = nxt_min(buf_size, part_size); - - mmap_buf.buf.free = nxt_cpymem(mmap_buf.buf.free, - part_start, part_size); - - rc = nxt_unit_mmap_buf_send(req, &mmap_buf, 0); - if (nxt_slow_path(rc != NXT_UNIT_OK)) { - return -rc; - } - - size -= part_size; - part_start += part_size; - sent += part_size; - - min_size -= nxt_min(min_size, part_size); + rc = nxt_unit_response_send(req); + if (nxt_slow_path(rc != NXT_UNIT_OK)) { + return -rc; } - return sent; -} - - -int -nxt_unit_response_write_cb(nxt_unit_request_info_t *req, - nxt_unit_read_info_t *read_info) -{ - int rc; - ssize_t n; - uint32_t buf_size; - nxt_unit_buf_t *buf; - nxt_unit_mmap_buf_t mmap_buf; - nxt_unit_request_info_impl_t *req_impl; - char local_buf[NXT_UNIT_LOCAL_BUF_SIZE]; + size -= part_size; + part_start += part_size; + sent += part_size; - req_impl = nxt_container_of(req, nxt_unit_request_info_impl_t, req); + min_size -= nxt_min(min_size, part_size); + } - if (nxt_slow_path(req_impl->state < NXT_UNIT_RS_RESPONSE_INIT)) { - nxt_unit_req_alert(req, "write: response not initialized yet"); + while (size > 0) { + part_size = nxt_min(size, PORT_MMAP_DATA_SIZE); + min_part_size = nxt_min(min_size, part_size); + min_part_size = nxt_min(min_part_size, PORT_MMAP_CHUNK_SIZE); - return NXT_UNIT_ERROR; + rc = nxt_unit_get_outgoing_buf(req->ctx, req->response_port, part_size, + min_part_size, &mmap_buf, local_buf); + if (nxt_slow_path(rc != NXT_UNIT_OK)) { + return -rc; } - /* Check if response is not send yet. */ - if (nxt_slow_path(req->response_buf != NULL)) { - - /* Enable content in headers buf. */ - rc = nxt_unit_response_add_content(req, "", 0); - if (nxt_slow_path(rc != NXT_UNIT_OK)) { - nxt_unit_req_error(req, "Failed to add piggyback content"); - - return rc; - } - - buf = req->response_buf; - - while (buf->end - buf->free > 0) { - n = read_info->read(read_info, buf->free, buf->end - buf->free); - if (nxt_slow_path(n < 0)) { - nxt_unit_req_error(req, "Read error"); - - return NXT_UNIT_ERROR; - } - - /* Manually increase sizes. */ - buf->free += n; - req->response->piggyback_content_length += n; - - if (read_info->eof) { - break; - } - } + buf_size = mmap_buf.buf.end - mmap_buf.buf.free; + if (nxt_slow_path(buf_size == 0)) { + return sent; + } + part_size = nxt_min(buf_size, part_size); - rc = nxt_unit_response_send(req); - if (nxt_slow_path(rc != NXT_UNIT_OK)) { - nxt_unit_req_error(req, "Failed to send headers with content"); + mmap_buf.buf.free = nxt_cpymem(mmap_buf.buf.free, part_start, part_size); - return rc; - } - - if (read_info->eof) { - return NXT_UNIT_OK; - } + rc = nxt_unit_mmap_buf_send(req, &mmap_buf, 0); + if (nxt_slow_path(rc != NXT_UNIT_OK)) { + return -rc; } - while (!read_info->eof) { - nxt_unit_req_debug(req, "write_cb, alloc %"PRIu32"", - read_info->buf_size); + size -= part_size; + part_start += part_size; + sent += part_size; - buf_size = nxt_min(read_info->buf_size, PORT_MMAP_DATA_SIZE); + min_size -= nxt_min(min_size, part_size); + } - rc = nxt_unit_get_outgoing_buf(req->ctx, req->response_port, - buf_size, buf_size, - &mmap_buf, local_buf); - if (nxt_slow_path(rc != NXT_UNIT_OK)) { - return rc; - } + return sent; +} - buf = &mmap_buf.buf; +int nxt_unit_response_write_cb(nxt_unit_request_info_t *req, + nxt_unit_read_info_t *read_info) { + int rc; + ssize_t n; + uint32_t buf_size; + nxt_unit_buf_t *buf; + nxt_unit_mmap_buf_t mmap_buf; + nxt_unit_request_info_impl_t *req_impl; + char local_buf[NXT_UNIT_LOCAL_BUF_SIZE]; - while (!read_info->eof && buf->end > buf->free) { - n = read_info->read(read_info, buf->free, buf->end - buf->free); - if (nxt_slow_path(n < 0)) { - nxt_unit_req_error(req, "Read error"); + req_impl = nxt_container_of(req, nxt_unit_request_info_impl_t, req); - nxt_unit_free_outgoing_buf(&mmap_buf); + if (nxt_slow_path(req_impl->state < NXT_UNIT_RS_RESPONSE_INIT)) { + nxt_unit_req_alert(req, "write: response not initialized yet"); - return NXT_UNIT_ERROR; - } + return NXT_UNIT_ERROR; + } - buf->free += n; - } + /* Check if response is not send yet. */ + if (nxt_slow_path(req->response_buf != NULL)) { - rc = nxt_unit_mmap_buf_send(req, &mmap_buf, 0); - if (nxt_slow_path(rc != NXT_UNIT_OK)) { - nxt_unit_req_error(req, "Failed to send content"); + /* Enable content in headers buf. */ + rc = nxt_unit_response_add_content(req, "", 0); + if (nxt_slow_path(rc != NXT_UNIT_OK)) { + nxt_unit_req_error(req, "Failed to add piggyback content"); - return rc; - } + return rc; } - return NXT_UNIT_OK; -} - - -ssize_t -nxt_unit_request_read(nxt_unit_request_info_t *req, void *dst, size_t size) -{ - ssize_t buf_res, res; - - buf_res = nxt_unit_buf_read(&req->content_buf, &req->content_length, - dst, size); - - if (buf_res < (ssize_t) size && req->content_fd != -1) { - res = read(req->content_fd, dst, size); - if (nxt_slow_path(res < 0)) { - nxt_unit_req_alert(req, "failed to read content: %s (%d)", - strerror(errno), errno); - - return res; - } - - if (res < (ssize_t) size) { - nxt_unit_close(req->content_fd); + buf = req->response_buf; - req->content_fd = -1; - } + while (buf->end - buf->free > 0) { + n = read_info->read(read_info, buf->free, buf->end - buf->free); + if (nxt_slow_path(n < 0)) { + nxt_unit_req_error(req, "Read error"); - req->content_length -= res; + return NXT_UNIT_ERROR; + } - dst = nxt_pointer_to(dst, res); + /* Manually increase sizes. */ + buf->free += n; + req->response->piggyback_content_length += n; - } else { - res = 0; + if (read_info->eof) { + break; + } } - return buf_res + res; -} - - -ssize_t -nxt_unit_request_readline_size(nxt_unit_request_info_t *req, size_t max_size) -{ - char *p; - size_t l_size, b_size; - nxt_unit_buf_t *b; - nxt_unit_mmap_buf_t *mmap_buf, *preread_buf; + rc = nxt_unit_response_send(req); + if (nxt_slow_path(rc != NXT_UNIT_OK)) { + nxt_unit_req_error(req, "Failed to send headers with content"); - if (req->content_length == 0) { - return 0; + return rc; } - l_size = 0; - - b = req->content_buf; - - while (b != NULL) { - b_size = b->end - b->free; - p = memchr(b->free, '\n', b_size); - - if (p != NULL) { - p++; - l_size += p - b->free; - break; - } - - l_size += b_size; - - if (max_size <= l_size) { - break; - } - - mmap_buf = nxt_container_of(b, nxt_unit_mmap_buf_t, buf); - if (mmap_buf->next == NULL - && req->content_fd != -1 - && l_size < req->content_length) - { - preread_buf = nxt_unit_request_preread(req, 16384); - if (nxt_slow_path(preread_buf == NULL)) { - return -1; - } - - nxt_unit_mmap_buf_insert(&mmap_buf->next, preread_buf); - } - - b = nxt_unit_buf_next(b); + if (read_info->eof) { + return NXT_UNIT_OK; } + } - return nxt_min(max_size, l_size); -} - + while (!read_info->eof) { + nxt_unit_req_debug(req, "write_cb, alloc %" PRIu32 "", read_info->buf_size); -static nxt_unit_mmap_buf_t * -nxt_unit_request_preread(nxt_unit_request_info_t *req, size_t size) -{ - ssize_t res; - nxt_unit_mmap_buf_t *mmap_buf; + buf_size = nxt_min(read_info->buf_size, PORT_MMAP_DATA_SIZE); - if (req->content_fd == -1) { - nxt_unit_req_alert(req, "preread: content_fd == -1"); - return NULL; - } - - mmap_buf = nxt_unit_mmap_buf_get(req->ctx); - if (nxt_slow_path(mmap_buf == NULL)) { - nxt_unit_req_alert(req, "preread: failed to allocate buf"); - return NULL; + rc = nxt_unit_get_outgoing_buf(req->ctx, req->response_port, buf_size, + buf_size, &mmap_buf, local_buf); + if (nxt_slow_path(rc != NXT_UNIT_OK)) { + return rc; } - mmap_buf->free_ptr = nxt_unit_malloc(req->ctx, size); - if (nxt_slow_path(mmap_buf->free_ptr == NULL)) { - nxt_unit_req_alert(req, "preread: failed to allocate buf memory"); - nxt_unit_mmap_buf_release(mmap_buf); - return NULL; - } + buf = &mmap_buf.buf; - mmap_buf->plain_ptr = mmap_buf->free_ptr; + while (!read_info->eof && buf->end > buf->free) { + n = read_info->read(read_info, buf->free, buf->end - buf->free); + if (nxt_slow_path(n < 0)) { + nxt_unit_req_error(req, "Read error"); - mmap_buf->hdr = NULL; - mmap_buf->buf.start = mmap_buf->free_ptr; - mmap_buf->buf.free = mmap_buf->buf.start; - mmap_buf->buf.end = mmap_buf->buf.start + size; - - res = read(req->content_fd, mmap_buf->free_ptr, size); - if (res < 0) { - nxt_unit_req_alert(req, "failed to read content: %s (%d)", - strerror(errno), errno); + nxt_unit_free_outgoing_buf(&mmap_buf); - nxt_unit_mmap_buf_free(mmap_buf); + return NXT_UNIT_ERROR; + } - return NULL; + buf->free += n; } - if (res < (ssize_t) size) { - nxt_unit_close(req->content_fd); + rc = nxt_unit_mmap_buf_send(req, &mmap_buf, 0); + if (nxt_slow_path(rc != NXT_UNIT_OK)) { + nxt_unit_req_error(req, "Failed to send content"); - req->content_fd = -1; + return rc; } + } - nxt_unit_req_debug(req, "preread: read %d", (int) res); - - mmap_buf->buf.end = mmap_buf->buf.free + res; - - return mmap_buf; + return NXT_UNIT_OK; } +ssize_t nxt_unit_request_read(nxt_unit_request_info_t *req, void *dst, + size_t size) { + ssize_t buf_res, res; -static ssize_t -nxt_unit_buf_read(nxt_unit_buf_t **b, uint64_t *len, void *dst, size_t size) -{ - u_char *p; - size_t rest, copy, read; - nxt_unit_buf_t *buf, *last_buf; + buf_res = + nxt_unit_buf_read(&req->content_buf, &req->content_length, dst, size); - p = dst; - rest = size; + if (buf_res < (ssize_t)size && req->content_fd != -1) { + res = read(req->content_fd, dst, size); + if (nxt_slow_path(res < 0)) { + nxt_unit_req_alert(req, "failed to read content: %s (%d)", + strerror(errno), errno); - buf = *b; - last_buf = buf; - - while (buf != NULL) { - last_buf = buf; - - copy = buf->end - buf->free; - copy = nxt_min(rest, copy); - - p = nxt_cpymem(p, buf->free, copy); - - buf->free += copy; - rest -= copy; - - if (rest == 0) { - if (buf->end == buf->free) { - buf = nxt_unit_buf_next(buf); - } + return res; + } - break; - } + if (res < (ssize_t)size) { + nxt_unit_close(req->content_fd); - buf = nxt_unit_buf_next(buf); + req->content_fd = -1; } - *b = last_buf; + req->content_length -= res; - read = size - rest; + dst = nxt_pointer_to(dst, res); - *len -= read; + } else { + res = 0; + } - return read; + return buf_res + res; } +ssize_t nxt_unit_request_readline_size(nxt_unit_request_info_t *req, + size_t max_size) { + char *p; + size_t l_size, b_size; + nxt_unit_buf_t *b; + nxt_unit_mmap_buf_t *mmap_buf, *preread_buf; -void -nxt_unit_request_done(nxt_unit_request_info_t *req, int rc) -{ - uint32_t size; - nxt_port_msg_t msg; - nxt_unit_impl_t *lib; - nxt_unit_request_info_impl_t *req_impl; - - req_impl = nxt_container_of(req, nxt_unit_request_info_impl_t, req); - - nxt_unit_req_debug(req, "done: %d", rc); - - if (nxt_slow_path(rc != NXT_UNIT_OK)) { - goto skip_response_send; - } + if (req->content_length == 0) { + return 0; + } - if (nxt_slow_path(req_impl->state < NXT_UNIT_RS_RESPONSE_INIT)) { + l_size = 0; - size = nxt_length("Content-Type") + nxt_length("text/plain"); + b = req->content_buf; - rc = nxt_unit_response_init(req, 200, 1, size); - if (nxt_slow_path(rc != NXT_UNIT_OK)) { - goto skip_response_send; - } + while (b != NULL) { + b_size = b->end - b->free; + p = memchr(b->free, '\n', b_size); - rc = nxt_unit_response_add_field(req, "Content-Type", - nxt_length("Content-Type"), - "text/plain", nxt_length("text/plain")); - if (nxt_slow_path(rc != NXT_UNIT_OK)) { - goto skip_response_send; - } + if (p != NULL) { + p++; + l_size += p - b->free; + break; } - if (nxt_slow_path(req_impl->state < NXT_UNIT_RS_RESPONSE_SENT)) { - - req_impl->state = NXT_UNIT_RS_RESPONSE_SENT; + l_size += b_size; - nxt_unit_buf_send_done(req->response_buf); - - return; + if (max_size <= l_size) { + break; } -skip_response_send: - - lib = nxt_container_of(req->unit, nxt_unit_impl_t, unit); + mmap_buf = nxt_container_of(b, nxt_unit_mmap_buf_t, buf); + if (mmap_buf->next == NULL && req->content_fd != -1 && + l_size < req->content_length) { + preread_buf = nxt_unit_request_preread(req, 16384); + if (nxt_slow_path(preread_buf == NULL)) { + return -1; + } - msg.stream = req_impl->stream; - msg.pid = lib->pid; - msg.reply_port = 0; - msg.type = (rc == NXT_UNIT_OK) ? _NXT_PORT_MSG_DATA - : _NXT_PORT_MSG_RPC_ERROR; - msg.last = 1; - msg.mmap = 0; - msg.nf = 0; - msg.mf = 0; + nxt_unit_mmap_buf_insert(&mmap_buf->next, preread_buf); + } - (void) nxt_unit_port_send(req->ctx, req->response_port, - &msg, sizeof(msg), NULL); + b = nxt_unit_buf_next(b); + } - nxt_unit_request_info_release(req); + return nxt_min(max_size, l_size); } +static nxt_unit_mmap_buf_t * +nxt_unit_request_preread(nxt_unit_request_info_t *req, size_t size) { + ssize_t res; + nxt_unit_mmap_buf_t *mmap_buf; -int -nxt_unit_websocket_send(nxt_unit_request_info_t *req, uint8_t opcode, - uint8_t last, const void *start, size_t size) -{ - const struct iovec iov = { (void *) start, size }; + if (req->content_fd == -1) { + nxt_unit_req_alert(req, "preread: content_fd == -1"); + return NULL; + } - return nxt_unit_websocket_sendv(req, opcode, last, &iov, 1); -} + mmap_buf = nxt_unit_mmap_buf_get(req->ctx); + if (nxt_slow_path(mmap_buf == NULL)) { + nxt_unit_req_alert(req, "preread: failed to allocate buf"); + return NULL; + } + mmap_buf->free_ptr = nxt_unit_malloc(req->ctx, size); + if (nxt_slow_path(mmap_buf->free_ptr == NULL)) { + nxt_unit_req_alert(req, "preread: failed to allocate buf memory"); + nxt_unit_mmap_buf_release(mmap_buf); + return NULL; + } -int -nxt_unit_websocket_sendv(nxt_unit_request_info_t *req, uint8_t opcode, - uint8_t last, const struct iovec *iov, int iovcnt) -{ - int i, rc; - size_t l, copy; - uint32_t payload_len, buf_size, alloc_size; - const uint8_t *b; - nxt_unit_buf_t *buf; - nxt_unit_mmap_buf_t mmap_buf; - nxt_websocket_header_t *wh; - char local_buf[NXT_UNIT_LOCAL_BUF_SIZE]; + mmap_buf->plain_ptr = mmap_buf->free_ptr; - payload_len = 0; + mmap_buf->hdr = NULL; + mmap_buf->buf.start = mmap_buf->free_ptr; + mmap_buf->buf.free = mmap_buf->buf.start; + mmap_buf->buf.end = mmap_buf->buf.start + size; - for (i = 0; i < iovcnt; i++) { - payload_len += iov[i].iov_len; - } + res = read(req->content_fd, mmap_buf->free_ptr, size); + if (res < 0) { + nxt_unit_req_alert(req, "failed to read content: %s (%d)", strerror(errno), + errno); - buf_size = 10 + payload_len; - alloc_size = nxt_min(buf_size, PORT_MMAP_DATA_SIZE); + nxt_unit_mmap_buf_free(mmap_buf); - rc = nxt_unit_get_outgoing_buf(req->ctx, req->response_port, - alloc_size, alloc_size, - &mmap_buf, local_buf); - if (nxt_slow_path(rc != NXT_UNIT_OK)) { - return rc; - } + return NULL; + } - buf = &mmap_buf.buf; + if (res < (ssize_t)size) { + nxt_unit_close(req->content_fd); - buf->start[0] = 0; - buf->start[1] = 0; + req->content_fd = -1; + } - buf_size -= buf->end - buf->start; + nxt_unit_req_debug(req, "preread: read %d", (int)res); - wh = (void *) buf->free; + mmap_buf->buf.end = mmap_buf->buf.free + res; - buf->free = nxt_websocket_frame_init(wh, payload_len); - wh->fin = last; - wh->opcode = opcode; + return mmap_buf; +} - for (i = 0; i < iovcnt; i++) { - b = iov[i].iov_base; - l = iov[i].iov_len; +static ssize_t nxt_unit_buf_read(nxt_unit_buf_t **b, uint64_t *len, void *dst, + size_t size) { + u_char *p; + size_t rest, copy, read; + nxt_unit_buf_t *buf, *last_buf; - while (l > 0) { - copy = buf->end - buf->free; - copy = nxt_min(l, copy); + p = dst; + rest = size; - buf->free = nxt_cpymem(buf->free, b, copy); - b += copy; - l -= copy; + buf = *b; + last_buf = buf; - if (l > 0) { - if (nxt_fast_path(buf->free > buf->start)) { - rc = nxt_unit_mmap_buf_send(req, &mmap_buf, 0); + while (buf != NULL) { + last_buf = buf; - if (nxt_slow_path(rc != NXT_UNIT_OK)) { - return rc; - } - } + copy = buf->end - buf->free; + copy = nxt_min(rest, copy); - alloc_size = nxt_min(buf_size, PORT_MMAP_DATA_SIZE); + p = nxt_cpymem(p, buf->free, copy); - rc = nxt_unit_get_outgoing_buf(req->ctx, req->response_port, - alloc_size, alloc_size, - &mmap_buf, local_buf); - if (nxt_slow_path(rc != NXT_UNIT_OK)) { - return rc; - } + buf->free += copy; + rest -= copy; - buf_size -= buf->end - buf->start; - } - } - } + if (rest == 0) { + if (buf->end == buf->free) { + buf = nxt_unit_buf_next(buf); + } - if (buf->free > buf->start) { - rc = nxt_unit_mmap_buf_send(req, &mmap_buf, 0); + break; } - return rc; -} + buf = nxt_unit_buf_next(buf); + } + *b = last_buf; -ssize_t -nxt_unit_websocket_read(nxt_unit_websocket_frame_t *ws, void *dst, - size_t size) -{ - ssize_t res; - uint8_t *b; - uint64_t i, d; + read = size - rest; - res = nxt_unit_buf_read(&ws->content_buf, &ws->content_length, - dst, size); + *len -= read; - if (ws->mask == NULL) { - return res; - } + return read; +} - b = dst; - d = (ws->payload_len - ws->content_length - res) % 4; +void nxt_unit_request_done(nxt_unit_request_info_t *req, int rc) { + uint32_t size; + nxt_port_msg_t msg; + nxt_unit_impl_t *lib; + nxt_unit_request_info_impl_t *req_impl; - for (i = 0; i < (uint64_t) res; i++) { - b[i] ^= ws->mask[ (i + d) % 4 ]; - } + req_impl = nxt_container_of(req, nxt_unit_request_info_impl_t, req); - return res; -} + nxt_unit_req_debug(req, "done: %d", rc); + if (nxt_slow_path(rc != NXT_UNIT_OK)) { + goto skip_response_send; + } -int -nxt_unit_websocket_retain(nxt_unit_websocket_frame_t *ws) -{ - char *b; - size_t size, hsize; - nxt_unit_websocket_frame_impl_t *ws_impl; + if (nxt_slow_path(req_impl->state < NXT_UNIT_RS_RESPONSE_INIT)) { - ws_impl = nxt_container_of(ws, nxt_unit_websocket_frame_impl_t, ws); + size = nxt_length("Content-Type") + nxt_length("text/plain"); - if (ws_impl->buf->free_ptr != NULL || ws_impl->buf->hdr != NULL) { - return NXT_UNIT_OK; + rc = nxt_unit_response_init(req, 200, 1, size); + if (nxt_slow_path(rc != NXT_UNIT_OK)) { + goto skip_response_send; } - size = ws_impl->buf->buf.end - ws_impl->buf->buf.start; - - b = nxt_unit_malloc(ws->req->ctx, size); - if (nxt_slow_path(b == NULL)) { - return NXT_UNIT_ERROR; + rc = nxt_unit_response_add_field(req, "Content-Type", + nxt_length("Content-Type"), "text/plain", + nxt_length("text/plain")); + if (nxt_slow_path(rc != NXT_UNIT_OK)) { + goto skip_response_send; } + } - memcpy(b, ws_impl->buf->buf.start, size); + if (nxt_slow_path(req_impl->state < NXT_UNIT_RS_RESPONSE_SENT)) { - hsize = nxt_websocket_frame_header_size(b); + req_impl->state = NXT_UNIT_RS_RESPONSE_SENT; - ws_impl->buf->buf.start = b; - ws_impl->buf->buf.free = b + hsize; - ws_impl->buf->buf.end = b + size; + nxt_unit_buf_send_done(req->response_buf); - ws_impl->buf->free_ptr = b; + return; + } - ws_impl->ws.header = (nxt_websocket_header_t *) b; +skip_response_send: - if (ws_impl->ws.header->mask) { - ws_impl->ws.mask = (uint8_t *) b + hsize - 4; + lib = nxt_container_of(req->unit, nxt_unit_impl_t, unit); - } else { - ws_impl->ws.mask = NULL; - } - - return NXT_UNIT_OK; -} + msg.stream = req_impl->stream; + msg.pid = lib->pid; + msg.reply_port = 0; + msg.type = (rc == NXT_UNIT_OK) ? _NXT_PORT_MSG_DATA : _NXT_PORT_MSG_RPC_ERROR; + msg.last = 1; + msg.mmap = 0; + msg.nf = 0; + msg.mf = 0; + (void)nxt_unit_port_send(req->ctx, req->response_port, &msg, sizeof(msg), + NULL); -void -nxt_unit_websocket_done(nxt_unit_websocket_frame_t *ws) -{ - nxt_unit_websocket_frame_release(ws); + nxt_unit_request_info_release(req); } +int nxt_unit_websocket_send(nxt_unit_request_info_t *req, uint8_t opcode, + uint8_t last, const void *start, size_t size) { + const struct iovec iov = {(void *)start, size}; -static nxt_port_mmap_header_t * -nxt_unit_mmap_get(nxt_unit_ctx_t *ctx, nxt_unit_port_t *port, - nxt_chunk_id_t *c, int *n, int min_n) -{ - int res, nchunks, i; - uint32_t outgoing_size; - nxt_unit_mmap_t *mm, *mm_end; - nxt_unit_impl_t *lib; - nxt_port_mmap_header_t *hdr; - - lib = nxt_container_of(ctx->unit, nxt_unit_impl_t, unit); - - pthread_mutex_lock(&lib->outgoing.mutex); - - if (nxt_slow_path(lib->outgoing.elts == NULL)) { - goto skip; - } - -retry: - - outgoing_size = lib->outgoing.size; - - mm_end = lib->outgoing.elts + outgoing_size; - - for (mm = lib->outgoing.elts; mm < mm_end; mm++) { - hdr = mm->hdr; - - if (hdr->sent_over != 0xFFFFu - && (hdr->sent_over != port->id.id - || mm->src_thread != pthread_self())) - { - continue; - } - - *c = 0; - - while (nxt_port_mmap_get_free_chunk(hdr->free_map, c)) { - nchunks = 1; - - while (nchunks < *n) { - res = nxt_port_mmap_chk_set_chunk_busy(hdr->free_map, - *c + nchunks); + return nxt_unit_websocket_sendv(req, opcode, last, &iov, 1); +} - if (res == 0) { - if (nchunks >= min_n) { - *n = nchunks; +int nxt_unit_websocket_sendv(nxt_unit_request_info_t *req, uint8_t opcode, + uint8_t last, const struct iovec *iov, + int iovcnt) { + int i, rc; + size_t l, copy; + uint32_t payload_len, buf_size, alloc_size; + const uint8_t *b; + nxt_unit_buf_t *buf; + nxt_unit_mmap_buf_t mmap_buf; + nxt_websocket_header_t *wh; + char local_buf[NXT_UNIT_LOCAL_BUF_SIZE]; - goto unlock; - } + payload_len = 0; - for (i = 0; i < nchunks; i++) { - nxt_port_mmap_set_chunk_free(hdr->free_map, *c + i); - } + for (i = 0; i < iovcnt; i++) { + payload_len += iov[i].iov_len; + } - *c += nchunks + 1; - nchunks = 0; - break; - } + buf_size = 10 + payload_len; + alloc_size = nxt_min(buf_size, PORT_MMAP_DATA_SIZE); - nchunks++; - } + rc = nxt_unit_get_outgoing_buf(req->ctx, req->response_port, alloc_size, + alloc_size, &mmap_buf, local_buf); + if (nxt_slow_path(rc != NXT_UNIT_OK)) { + return rc; + } - if (nchunks >= min_n) { - *n = nchunks; + buf = &mmap_buf.buf; - goto unlock; - } - } + buf->start[0] = 0; + buf->start[1] = 0; - hdr->oosm = 1; - } + buf_size -= buf->end - buf->start; - if (outgoing_size >= lib->shm_mmap_limit) { - /* Cannot allocate more shared memory. */ - pthread_mutex_unlock(&lib->outgoing.mutex); + wh = (void *)buf->free; - if (min_n == 0) { - *n = 0; - } + buf->free = nxt_websocket_frame_init(wh, payload_len); + wh->fin = last; + wh->opcode = opcode; - if (nxt_slow_path(lib->outgoing.allocated_chunks + min_n - >= lib->shm_mmap_limit * PORT_MMAP_CHUNK_COUNT)) - { - /* Memory allocated by application, but not send to router. */ - return NULL; - } + for (i = 0; i < iovcnt; i++) { + b = iov[i].iov_base; + l = iov[i].iov_len; - /* Notify router about OOSM condition. */ + while (l > 0) { + copy = buf->end - buf->free; + copy = nxt_min(l, copy); - res = nxt_unit_send_oosm(ctx, port); - if (nxt_slow_path(res != NXT_UNIT_OK)) { - return NULL; - } + buf->free = nxt_cpymem(buf->free, b, copy); + b += copy; + l -= copy; - /* Return if caller can handle OOSM condition. Non-blocking mode. */ + if (l > 0) { + if (nxt_fast_path(buf->free > buf->start)) { + rc = nxt_unit_mmap_buf_send(req, &mmap_buf, 0); - if (min_n == 0) { - return NULL; + if (nxt_slow_path(rc != NXT_UNIT_OK)) { + return rc; + } } - nxt_unit_debug(ctx, "oosm: waiting for ACK"); + alloc_size = nxt_min(buf_size, PORT_MMAP_DATA_SIZE); - res = nxt_unit_wait_shm_ack(ctx); - if (nxt_slow_path(res != NXT_UNIT_OK)) { - return NULL; + rc = nxt_unit_get_outgoing_buf(req->ctx, req->response_port, alloc_size, + alloc_size, &mmap_buf, local_buf); + if (nxt_slow_path(rc != NXT_UNIT_OK)) { + return rc; } - nxt_unit_debug(ctx, "oosm: retry"); - - pthread_mutex_lock(&lib->outgoing.mutex); - - goto retry; + buf_size -= buf->end - buf->start; + } } + } -skip: - - *c = 0; - hdr = nxt_unit_new_mmap(ctx, port, *n); - -unlock: + if (buf->free > buf->start) { + rc = nxt_unit_mmap_buf_send(req, &mmap_buf, 0); + } - nxt_atomic_fetch_add(&lib->outgoing.allocated_chunks, *n); - - nxt_unit_debug(ctx, "allocated_chunks %d", - (int) lib->outgoing.allocated_chunks); - - pthread_mutex_unlock(&lib->outgoing.mutex); - - return hdr; + return rc; } +ssize_t nxt_unit_websocket_read(nxt_unit_websocket_frame_t *ws, void *dst, + size_t size) { + ssize_t res; + uint8_t *b; + uint64_t i, d; -static int -nxt_unit_send_oosm(nxt_unit_ctx_t *ctx, nxt_unit_port_t *port) -{ - ssize_t res; - nxt_port_msg_t msg; - nxt_unit_impl_t *lib; + res = nxt_unit_buf_read(&ws->content_buf, &ws->content_length, dst, size); - lib = nxt_container_of(ctx->unit, nxt_unit_impl_t, unit); - - msg.stream = 0; - msg.pid = lib->pid; - msg.reply_port = 0; - msg.type = _NXT_PORT_MSG_OOSM; - msg.last = 0; - msg.mmap = 0; - msg.nf = 0; - msg.mf = 0; - - res = nxt_unit_port_send(ctx, lib->router_port, &msg, sizeof(msg), NULL); - if (nxt_slow_path(res != sizeof(msg))) { - return NXT_UNIT_ERROR; - } - - return NXT_UNIT_OK; -} - - -static int -nxt_unit_wait_shm_ack(nxt_unit_ctx_t *ctx) -{ - int res; - nxt_unit_ctx_impl_t *ctx_impl; - nxt_unit_read_buf_t *rbuf; - - ctx_impl = nxt_container_of(ctx, nxt_unit_ctx_impl_t, ctx); - - while (1) { - rbuf = nxt_unit_read_buf_get(ctx); - if (nxt_slow_path(rbuf == NULL)) { - return NXT_UNIT_ERROR; - } - - do { - res = nxt_unit_ctx_port_recv(ctx, ctx_impl->read_port, rbuf); - } while (res == NXT_UNIT_AGAIN); - - if (res == NXT_UNIT_ERROR) { - nxt_unit_read_buf_release(ctx, rbuf); - - return NXT_UNIT_ERROR; - } - - if (nxt_unit_is_shm_ack(rbuf)) { - nxt_unit_read_buf_release(ctx, rbuf); - break; - } + if (ws->mask == NULL) { + return res; + } - pthread_mutex_lock(&ctx_impl->mutex); + b = dst; + d = (ws->payload_len - ws->content_length - res) % 4; - nxt_queue_insert_tail(&ctx_impl->pending_rbuf, &rbuf->link); + for (i = 0; i < (uint64_t)res; i++) { + b[i] ^= ws->mask[(i + d) % 4]; + } - pthread_mutex_unlock(&ctx_impl->mutex); + return res; +} - if (nxt_unit_is_quit(rbuf)) { - nxt_unit_debug(ctx, "oosm: quit received"); +int nxt_unit_websocket_retain(nxt_unit_websocket_frame_t *ws) { + char *b; + size_t size, hsize; + nxt_unit_websocket_frame_impl_t *ws_impl; - return NXT_UNIT_ERROR; - } - } + ws_impl = nxt_container_of(ws, nxt_unit_websocket_frame_impl_t, ws); + if (ws_impl->buf->free_ptr != NULL || ws_impl->buf->hdr != NULL) { return NXT_UNIT_OK; -} - + } -static nxt_unit_mmap_t * -nxt_unit_mmap_at(nxt_unit_mmaps_t *mmaps, uint32_t i) -{ - uint32_t cap, n; - nxt_unit_mmap_t *e; + size = ws_impl->buf->buf.end - ws_impl->buf->buf.start; - if (nxt_fast_path(mmaps->size > i)) { - return mmaps->elts + i; - } - - cap = mmaps->cap; + b = nxt_unit_malloc(ws->req->ctx, size); + if (nxt_slow_path(b == NULL)) { + return NXT_UNIT_ERROR; + } - if (cap == 0) { - cap = i + 1; - } + memcpy(b, ws_impl->buf->buf.start, size); - while (i + 1 > cap) { + hsize = nxt_websocket_frame_header_size(b); - if (cap < 16) { - cap = cap * 2; + ws_impl->buf->buf.start = b; + ws_impl->buf->buf.free = b + hsize; + ws_impl->buf->buf.end = b + size; - } else { - cap = cap + cap / 2; - } - } + ws_impl->buf->free_ptr = b; - if (cap != mmaps->cap) { + ws_impl->ws.header = (nxt_websocket_header_t *)b; - e = realloc(mmaps->elts, cap * sizeof(nxt_unit_mmap_t)); - if (nxt_slow_path(e == NULL)) { - return NULL; - } + if (ws_impl->ws.header->mask) { + ws_impl->ws.mask = (uint8_t *)b + hsize - 4; - mmaps->elts = e; + } else { + ws_impl->ws.mask = NULL; + } - for (n = mmaps->cap; n < cap; n++) { - e = mmaps->elts + n; + return NXT_UNIT_OK; +} - e->hdr = NULL; - nxt_queue_init(&e->awaiting_rbuf); - } +void nxt_unit_websocket_done(nxt_unit_websocket_frame_t *ws) { + nxt_unit_websocket_frame_release(ws); +} - mmaps->cap = cap; - } +static nxt_port_mmap_header_t *nxt_unit_mmap_get(nxt_unit_ctx_t *ctx, + nxt_unit_port_t *port, + nxt_chunk_id_t *c, int *n, + int min_n) { + int res, nchunks, i; + uint32_t outgoing_size; + nxt_unit_mmap_t *mm, *mm_end; + nxt_unit_impl_t *lib; + nxt_port_mmap_header_t *hdr; - if (i + 1 > mmaps->size) { - mmaps->size = i + 1; - } + lib = nxt_container_of(ctx->unit, nxt_unit_impl_t, unit); - return mmaps->elts + i; -} + pthread_mutex_lock(&lib->outgoing.mutex); + if (nxt_slow_path(lib->outgoing.elts == NULL)) { + goto skip; + } -static nxt_port_mmap_header_t * -nxt_unit_new_mmap(nxt_unit_ctx_t *ctx, nxt_unit_port_t *port, int n) -{ - int i, fd, rc; - void *mem; - nxt_unit_mmap_t *mm; - nxt_unit_impl_t *lib; - nxt_port_mmap_header_t *hdr; +retry: - lib = nxt_container_of(ctx->unit, nxt_unit_impl_t, unit); + outgoing_size = lib->outgoing.size; - mm = nxt_unit_mmap_at(&lib->outgoing, lib->outgoing.size); - if (nxt_slow_path(mm == NULL)) { - nxt_unit_alert(ctx, "failed to add mmap to outgoing array"); + mm_end = lib->outgoing.elts + outgoing_size; - return NULL; - } + for (mm = lib->outgoing.elts; mm < mm_end; mm++) { + hdr = mm->hdr; - fd = nxt_unit_shm_open(ctx, PORT_MMAP_SIZE); - if (nxt_slow_path(fd == -1)) { - goto remove_fail; + if (hdr->sent_over != 0xFFFFu && + (hdr->sent_over != port->id.id || mm->src_thread != pthread_self())) { + continue; } - mem = mmap(NULL, PORT_MMAP_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); - if (nxt_slow_path(mem == MAP_FAILED)) { - nxt_unit_alert(ctx, "mmap(%d) failed: %s (%d)", fd, - strerror(errno), errno); + *c = 0; - nxt_unit_close(fd); + while (nxt_port_mmap_get_free_chunk(hdr->free_map, c)) { + nchunks = 1; - goto remove_fail; - } + while (nchunks < *n) { + res = nxt_port_mmap_chk_set_chunk_busy(hdr->free_map, *c + nchunks); + + if (res == 0) { + if (nchunks >= min_n) { + *n = nchunks; + + goto unlock; + } - mm->hdr = mem; - hdr = mem; + for (i = 0; i < nchunks; i++) { + nxt_port_mmap_set_chunk_free(hdr->free_map, *c + i); + } - memset(hdr->free_map, 0xFFU, sizeof(hdr->free_map)); - memset(hdr->free_tracking_map, 0xFFU, sizeof(hdr->free_tracking_map)); + *c += nchunks + 1; + nchunks = 0; + break; + } + + nchunks++; + } - hdr->id = lib->outgoing.size - 1; - hdr->src_pid = lib->pid; - hdr->dst_pid = port->id.pid; - hdr->sent_over = port->id.id; - mm->src_thread = pthread_self(); + if (nchunks >= min_n) { + *n = nchunks; - /* Mark first n chunk(s) as busy */ - for (i = 0; i < n; i++) { - nxt_port_mmap_set_chunk_busy(hdr->free_map, i); + goto unlock; + } } - /* Mark as busy chunk followed the last available chunk. */ - nxt_port_mmap_set_chunk_busy(hdr->free_map, PORT_MMAP_CHUNK_COUNT); - nxt_port_mmap_set_chunk_busy(hdr->free_tracking_map, PORT_MMAP_CHUNK_COUNT); + hdr->oosm = 1; + } + if (outgoing_size >= lib->shm_mmap_limit) { + /* Cannot allocate more shared memory. */ pthread_mutex_unlock(&lib->outgoing.mutex); - rc = nxt_unit_send_mmap(ctx, port, fd); - if (nxt_slow_path(rc != NXT_UNIT_OK)) { - munmap(mem, PORT_MMAP_SIZE); - hdr = NULL; - - } else { - nxt_unit_debug(ctx, "new mmap #%"PRIu32" created for %d -> %d", - hdr->id, (int) lib->pid, (int) port->id.pid); + if (min_n == 0) { + *n = 0; } - nxt_unit_close(fd); + if (nxt_slow_path(lib->outgoing.allocated_chunks + min_n >= + lib->shm_mmap_limit * PORT_MMAP_CHUNK_COUNT)) { + /* Memory allocated by application, but not send to router. */ + return NULL; + } - pthread_mutex_lock(&lib->outgoing.mutex); + /* Notify router about OOSM condition. */ - if (nxt_fast_path(hdr != NULL)) { - return hdr; + res = nxt_unit_send_oosm(ctx, port); + if (nxt_slow_path(res != NXT_UNIT_OK)) { + return NULL; } -remove_fail: + /* Return if caller can handle OOSM condition. Non-blocking mode. */ - lib->outgoing.size--; + if (min_n == 0) { + return NULL; + } - return NULL; -} + nxt_unit_debug(ctx, "oosm: waiting for ACK"); + res = nxt_unit_wait_shm_ack(ctx); + if (nxt_slow_path(res != NXT_UNIT_OK)) { + return NULL; + } -static int -nxt_unit_shm_open(nxt_unit_ctx_t *ctx, size_t size) -{ - int fd; + nxt_unit_debug(ctx, "oosm: retry"); -#if (NXT_HAVE_MEMFD_CREATE || NXT_HAVE_SHM_OPEN) - char name[64]; - nxt_unit_impl_t *lib; + pthread_mutex_lock(&lib->outgoing.mutex); - lib = nxt_container_of(ctx->unit, nxt_unit_impl_t, unit); - snprintf(name, sizeof(name), NXT_SHM_PREFIX "unit.%d.%p", - lib->pid, (void *) (uintptr_t) pthread_self()); -#endif + goto retry; + } -#if (NXT_HAVE_MEMFD_CREATE) +skip: - fd = syscall(SYS_memfd_create, name, MFD_CLOEXEC); - if (nxt_slow_path(fd == -1)) { - nxt_unit_alert(ctx, "memfd_create(%s) failed: %s (%d)", name, - strerror(errno), errno); + *c = 0; + hdr = nxt_unit_new_mmap(ctx, port, *n); - return -1; - } +unlock: - nxt_unit_debug(ctx, "memfd_create(%s): %d", name, fd); + nxt_atomic_fetch_add(&lib->outgoing.allocated_chunks, *n); -#elif (NXT_HAVE_SHM_OPEN_ANON) + nxt_unit_debug(ctx, "allocated_chunks %d", + (int)lib->outgoing.allocated_chunks); - fd = shm_open(SHM_ANON, O_RDWR, 0600); - if (nxt_slow_path(fd == -1)) { - nxt_unit_alert(ctx, "shm_open(SHM_ANON) failed: %s (%d)", - strerror(errno), errno); + pthread_mutex_unlock(&lib->outgoing.mutex); - return -1; - } + return hdr; +} -#elif (NXT_HAVE_SHM_OPEN) +static int nxt_unit_send_oosm(nxt_unit_ctx_t *ctx, nxt_unit_port_t *port) { + ssize_t res; + nxt_port_msg_t msg; + nxt_unit_impl_t *lib; - /* Just in case. */ - shm_unlink(name); + lib = nxt_container_of(ctx->unit, nxt_unit_impl_t, unit); - fd = shm_open(name, O_CREAT | O_EXCL | O_RDWR, 0600); - if (nxt_slow_path(fd == -1)) { - nxt_unit_alert(ctx, "shm_open(%s) failed: %s (%d)", name, - strerror(errno), errno); + msg.stream = 0; + msg.pid = lib->pid; + msg.reply_port = 0; + msg.type = _NXT_PORT_MSG_OOSM; + msg.last = 0; + msg.mmap = 0; + msg.nf = 0; + msg.mf = 0; - return -1; - } + res = nxt_unit_port_send(ctx, lib->router_port, &msg, sizeof(msg), NULL); + if (nxt_slow_path(res != sizeof(msg))) { + return NXT_UNIT_ERROR; + } - if (nxt_slow_path(shm_unlink(name) == -1)) { - nxt_unit_alert(ctx, "shm_unlink(%s) failed: %s (%d)", name, - strerror(errno), errno); - } + return NXT_UNIT_OK; +} -#else +static int nxt_unit_wait_shm_ack(nxt_unit_ctx_t *ctx) { + int res; + nxt_unit_ctx_impl_t *ctx_impl; + nxt_unit_read_buf_t *rbuf; -#error No working shared memory implementation. + ctx_impl = nxt_container_of(ctx, nxt_unit_ctx_impl_t, ctx); -#endif + while (1) { + rbuf = nxt_unit_read_buf_get(ctx); + if (nxt_slow_path(rbuf == NULL)) { + return NXT_UNIT_ERROR; + } - if (nxt_slow_path(ftruncate(fd, size) == -1)) { - nxt_unit_alert(ctx, "ftruncate(%d) failed: %s (%d)", fd, - strerror(errno), errno); + do { + res = nxt_unit_ctx_port_recv(ctx, ctx_impl->read_port, rbuf); + } while (res == NXT_UNIT_AGAIN); - nxt_unit_close(fd); + if (res == NXT_UNIT_ERROR) { + nxt_unit_read_buf_release(ctx, rbuf); - return -1; + return NXT_UNIT_ERROR; } - return fd; -} - + if (nxt_unit_is_shm_ack(rbuf)) { + nxt_unit_read_buf_release(ctx, rbuf); + break; + } -static int -nxt_unit_send_mmap(nxt_unit_ctx_t *ctx, nxt_unit_port_t *port, int fd) -{ - ssize_t res; - nxt_send_oob_t oob; - nxt_port_msg_t msg; - nxt_unit_impl_t *lib; - int fds[2] = {fd, -1}; + pthread_mutex_lock(&ctx_impl->mutex); - lib = nxt_container_of(ctx->unit, nxt_unit_impl_t, unit); + nxt_queue_insert_tail(&ctx_impl->pending_rbuf, &rbuf->link); - msg.stream = 0; - msg.pid = lib->pid; - msg.reply_port = 0; - msg.type = _NXT_PORT_MSG_MMAP; - msg.last = 0; - msg.mmap = 0; - msg.nf = 0; - msg.mf = 0; + pthread_mutex_unlock(&ctx_impl->mutex); - nxt_socket_msg_oob_init(&oob, fds); + if (nxt_unit_is_quit(rbuf)) { + nxt_unit_debug(ctx, "oosm: quit received"); - res = nxt_unit_port_send(ctx, port, &msg, sizeof(msg), &oob); - if (nxt_slow_path(res != sizeof(msg))) { - return NXT_UNIT_ERROR; + return NXT_UNIT_ERROR; } + } - return NXT_UNIT_OK; + return NXT_UNIT_OK; } +static nxt_unit_mmap_t *nxt_unit_mmap_at(nxt_unit_mmaps_t *mmaps, uint32_t i) { + uint32_t cap, n; + nxt_unit_mmap_t *e; -static int -nxt_unit_get_outgoing_buf(nxt_unit_ctx_t *ctx, nxt_unit_port_t *port, - uint32_t size, uint32_t min_size, - nxt_unit_mmap_buf_t *mmap_buf, char *local_buf) -{ - int nchunks, min_nchunks; - nxt_chunk_id_t c; - nxt_port_mmap_header_t *hdr; - - if (size <= NXT_UNIT_MAX_PLAIN_SIZE) { - if (local_buf != NULL) { - mmap_buf->free_ptr = NULL; - mmap_buf->plain_ptr = local_buf; + if (nxt_fast_path(mmaps->size > i)) { + return mmaps->elts + i; + } - } else { - mmap_buf->free_ptr = nxt_unit_malloc(ctx, - size + sizeof(nxt_port_msg_t)); - if (nxt_slow_path(mmap_buf->free_ptr == NULL)) { - return NXT_UNIT_ERROR; - } + cap = mmaps->cap; - mmap_buf->plain_ptr = mmap_buf->free_ptr; - } + if (cap == 0) { + cap = i + 1; + } - mmap_buf->hdr = NULL; - mmap_buf->buf.start = mmap_buf->plain_ptr + sizeof(nxt_port_msg_t); - mmap_buf->buf.free = mmap_buf->buf.start; - mmap_buf->buf.end = mmap_buf->buf.start + size; + while (i + 1 > cap) { - nxt_unit_debug(ctx, "outgoing plain buffer allocation: (%p, %d)", - mmap_buf->buf.start, (int) size); + if (cap < 16) { + cap = cap * 2; - return NXT_UNIT_OK; + } else { + cap = cap + cap / 2; } + } - nchunks = (size + PORT_MMAP_CHUNK_SIZE - 1) / PORT_MMAP_CHUNK_SIZE; - min_nchunks = (min_size + PORT_MMAP_CHUNK_SIZE - 1) / PORT_MMAP_CHUNK_SIZE; + if (cap != mmaps->cap) { - hdr = nxt_unit_mmap_get(ctx, port, &c, &nchunks, min_nchunks); - if (nxt_slow_path(hdr == NULL)) { - if (nxt_fast_path(min_nchunks == 0 && nchunks == 0)) { - mmap_buf->hdr = NULL; - mmap_buf->buf.start = NULL; - mmap_buf->buf.free = NULL; - mmap_buf->buf.end = NULL; - mmap_buf->free_ptr = NULL; + e = realloc(mmaps->elts, cap * sizeof(nxt_unit_mmap_t)); + if (nxt_slow_path(e == NULL)) { + return NULL; + } - return NXT_UNIT_OK; - } + mmaps->elts = e; - return NXT_UNIT_ERROR; + for (n = mmaps->cap; n < cap; n++) { + e = mmaps->elts + n; + + e->hdr = NULL; + nxt_queue_init(&e->awaiting_rbuf); } - mmap_buf->hdr = hdr; - mmap_buf->buf.start = (char *) nxt_port_mmap_chunk_start(hdr, c); - mmap_buf->buf.free = mmap_buf->buf.start; - mmap_buf->buf.end = mmap_buf->buf.start + nchunks * PORT_MMAP_CHUNK_SIZE; - mmap_buf->free_ptr = NULL; - mmap_buf->ctx_impl = nxt_container_of(ctx, nxt_unit_ctx_impl_t, ctx); + mmaps->cap = cap; + } - nxt_unit_debug(ctx, "outgoing mmap allocation: (%d,%d,%d)", - (int) hdr->id, (int) c, - (int) (nchunks * PORT_MMAP_CHUNK_SIZE)); + if (i + 1 > mmaps->size) { + mmaps->size = i + 1; + } - return NXT_UNIT_OK; + return mmaps->elts + i; } +static nxt_port_mmap_header_t *nxt_unit_new_mmap(nxt_unit_ctx_t *ctx, + nxt_unit_port_t *port, int n) { + int i, fd, rc; + void *mem; + nxt_unit_mmap_t *mm; + nxt_unit_impl_t *lib; + nxt_port_mmap_header_t *hdr; + + lib = nxt_container_of(ctx->unit, nxt_unit_impl_t, unit); -static int -nxt_unit_incoming_mmap(nxt_unit_ctx_t *ctx, pid_t pid, int fd) -{ - int rc; - void *mem; - nxt_queue_t awaiting_rbuf; - struct stat mmap_stat; - nxt_unit_mmap_t *mm; - nxt_unit_impl_t *lib; - nxt_unit_ctx_impl_t *ctx_impl; - nxt_unit_read_buf_t *rbuf; - nxt_port_mmap_header_t *hdr; + mm = nxt_unit_mmap_at(&lib->outgoing, lib->outgoing.size); + if (nxt_slow_path(mm == NULL)) { + nxt_unit_alert(ctx, "failed to add mmap to outgoing array"); - lib = nxt_container_of(ctx->unit, nxt_unit_impl_t, unit); + return NULL; + } - nxt_unit_debug(ctx, "incoming_mmap: fd %d from process %d", fd, (int) pid); + fd = nxt_unit_shm_open(ctx, PORT_MMAP_SIZE); + if (nxt_slow_path(fd == -1)) { + goto remove_fail; + } - if (fstat(fd, &mmap_stat) == -1) { - nxt_unit_alert(ctx, "incoming_mmap: fstat(%d) failed: %s (%d)", fd, - strerror(errno), errno); + mem = mmap(NULL, PORT_MMAP_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); + if (nxt_slow_path(mem == MAP_FAILED)) { + nxt_unit_alert(ctx, "mmap(%d) failed: %s (%d)", fd, strerror(errno), errno); - return NXT_UNIT_ERROR; - } + nxt_unit_close(fd); - mem = mmap(NULL, mmap_stat.st_size, PROT_READ | PROT_WRITE, - MAP_SHARED, fd, 0); - if (nxt_slow_path(mem == MAP_FAILED)) { - nxt_unit_alert(ctx, "incoming_mmap: mmap() failed: %s (%d)", - strerror(errno), errno); + goto remove_fail; + } - return NXT_UNIT_ERROR; - } + mm->hdr = mem; + hdr = mem; - hdr = mem; + memset(hdr->free_map, 0xFFU, sizeof(hdr->free_map)); + memset(hdr->free_tracking_map, 0xFFU, sizeof(hdr->free_tracking_map)); - if (nxt_slow_path(hdr->src_pid != pid)) { + hdr->id = lib->outgoing.size - 1; + hdr->src_pid = lib->pid; + hdr->dst_pid = port->id.pid; + hdr->sent_over = port->id.id; + mm->src_thread = pthread_self(); - nxt_unit_alert(ctx, "incoming_mmap: unexpected pid in mmap header " - "detected: %d != %d or %d != %d", (int) hdr->src_pid, - (int) pid, (int) hdr->dst_pid, (int) lib->pid); + /* Mark first n chunk(s) as busy */ + for (i = 0; i < n; i++) { + nxt_port_mmap_set_chunk_busy(hdr->free_map, i); + } - munmap(mem, PORT_MMAP_SIZE); + /* Mark as busy chunk followed the last available chunk. */ + nxt_port_mmap_set_chunk_busy(hdr->free_map, PORT_MMAP_CHUNK_COUNT); + nxt_port_mmap_set_chunk_busy(hdr->free_tracking_map, PORT_MMAP_CHUNK_COUNT); - return NXT_UNIT_ERROR; - } + pthread_mutex_unlock(&lib->outgoing.mutex); - nxt_queue_init(&awaiting_rbuf); + rc = nxt_unit_send_mmap(ctx, port, fd); + if (nxt_slow_path(rc != NXT_UNIT_OK)) { + munmap(mem, PORT_MMAP_SIZE); + hdr = NULL; - pthread_mutex_lock(&lib->incoming.mutex); + } else { + nxt_unit_debug(ctx, "new mmap #%" PRIu32 " created for %d -> %d", hdr->id, + (int)lib->pid, (int)port->id.pid); + } - mm = nxt_unit_mmap_at(&lib->incoming, hdr->id); - if (nxt_slow_path(mm == NULL)) { - nxt_unit_alert(ctx, "incoming_mmap: failed to add to incoming array"); + nxt_unit_close(fd); - munmap(mem, PORT_MMAP_SIZE); + pthread_mutex_lock(&lib->outgoing.mutex); - rc = NXT_UNIT_ERROR; + if (nxt_fast_path(hdr != NULL)) { + return hdr; + } - } else { - mm->hdr = hdr; +remove_fail: - hdr->sent_over = 0xFFFFu; + lib->outgoing.size--; - nxt_queue_add(&awaiting_rbuf, &mm->awaiting_rbuf); - nxt_queue_init(&mm->awaiting_rbuf); + return NULL; +} - rc = NXT_UNIT_OK; - } +static int nxt_unit_shm_open(nxt_unit_ctx_t *ctx, size_t size) { + int fd; - pthread_mutex_unlock(&lib->incoming.mutex); +#if (NXT_HAVE_MEMFD_CREATE || NXT_HAVE_SHM_OPEN) + char name[64]; + nxt_unit_impl_t *lib; - nxt_queue_each(rbuf, &awaiting_rbuf, nxt_unit_read_buf_t, link) { + lib = nxt_container_of(ctx->unit, nxt_unit_impl_t, unit); + snprintf(name, sizeof(name), NXT_SHM_PREFIX "unit.%d.%p", lib->pid, + (void *)(uintptr_t)pthread_self()); +#endif - ctx_impl = rbuf->ctx_impl; +#if (NXT_HAVE_MEMFD_CREATE) - pthread_mutex_lock(&ctx_impl->mutex); + fd = syscall(SYS_memfd_create, name, MFD_CLOEXEC); + if (nxt_slow_path(fd == -1)) { + nxt_unit_alert(ctx, "memfd_create(%s) failed: %s (%d)", name, + strerror(errno), errno); - nxt_queue_insert_head(&ctx_impl->pending_rbuf, &rbuf->link); + return -1; + } - pthread_mutex_unlock(&ctx_impl->mutex); + nxt_unit_debug(ctx, "memfd_create(%s): %d", name, fd); - nxt_atomic_fetch_add(&ctx_impl->wait_items, -1); +#elif (NXT_HAVE_SHM_OPEN_ANON) - nxt_unit_awake_ctx(ctx, ctx_impl); + fd = shm_open(SHM_ANON, O_RDWR, 0600); + if (nxt_slow_path(fd == -1)) { + nxt_unit_alert(ctx, "shm_open(SHM_ANON) failed: %s (%d)", strerror(errno), + errno); - } nxt_queue_loop; + return -1; + } - return rc; -} +#elif (NXT_HAVE_SHM_OPEN) + /* Just in case. */ + shm_unlink(name); -static void -nxt_unit_awake_ctx(nxt_unit_ctx_t *ctx, nxt_unit_ctx_impl_t *ctx_impl) -{ - nxt_port_msg_t msg; + fd = shm_open(name, O_CREAT | O_EXCL | O_RDWR, 0600); + if (nxt_slow_path(fd == -1)) { + nxt_unit_alert(ctx, "shm_open(%s) failed: %s (%d)", name, strerror(errno), + errno); - if (nxt_fast_path(ctx == &ctx_impl->ctx)) { - return; - } + return -1; + } - if (nxt_slow_path(ctx_impl->read_port == NULL - || ctx_impl->read_port->out_fd == -1)) - { - nxt_unit_alert(ctx, "target context read_port is NULL or not writable"); + if (nxt_slow_path(shm_unlink(name) == -1)) { + nxt_unit_alert(ctx, "shm_unlink(%s) failed: %s (%d)", name, strerror(errno), + errno); + } - return; - } +#else - memset(&msg, 0, sizeof(nxt_port_msg_t)); +#error No working shared memory implementation. - msg.type = _NXT_PORT_MSG_RPC_READY; +#endif - (void) nxt_unit_port_send(ctx, ctx_impl->read_port, - &msg, sizeof(msg), NULL); -} + if (nxt_slow_path(ftruncate(fd, size) == -1)) { + nxt_unit_alert(ctx, "ftruncate(%d) failed: %s (%d)", fd, strerror(errno), + errno); + nxt_unit_close(fd); -static int -nxt_unit_mmaps_init(nxt_unit_mmaps_t *mmaps) -{ - mmaps->size = 0; - mmaps->cap = 0; - mmaps->elts = NULL; - mmaps->allocated_chunks = 0; + return -1; + } - return pthread_mutex_init(&mmaps->mutex, NULL); + return fd; } +static int nxt_unit_send_mmap(nxt_unit_ctx_t *ctx, nxt_unit_port_t *port, + int fd) { + ssize_t res; + nxt_send_oob_t oob; + nxt_port_msg_t msg; + nxt_unit_impl_t *lib; + int fds[2] = {fd, -1}; + + lib = nxt_container_of(ctx->unit, nxt_unit_impl_t, unit); + + msg.stream = 0; + msg.pid = lib->pid; + msg.reply_port = 0; + msg.type = _NXT_PORT_MSG_MMAP; + msg.last = 0; + msg.mmap = 0; + msg.nf = 0; + msg.mf = 0; + + nxt_socket_msg_oob_init(&oob, fds); + + res = nxt_unit_port_send(ctx, port, &msg, sizeof(msg), &oob); + if (nxt_slow_path(res != sizeof(msg))) { + return NXT_UNIT_ERROR; + } -nxt_inline void -nxt_unit_process_use(nxt_unit_process_t *process) -{ - nxt_atomic_fetch_add(&process->use_count, 1); + return NXT_UNIT_OK; } +static int nxt_unit_get_outgoing_buf(nxt_unit_ctx_t *ctx, nxt_unit_port_t *port, + uint32_t size, uint32_t min_size, + nxt_unit_mmap_buf_t *mmap_buf, + char *local_buf) { + int nchunks, min_nchunks; + nxt_chunk_id_t c; + nxt_port_mmap_header_t *hdr; -nxt_inline void -nxt_unit_process_release(nxt_unit_process_t *process) -{ - long c; + if (size <= NXT_UNIT_MAX_PLAIN_SIZE) { + if (local_buf != NULL) { + mmap_buf->free_ptr = NULL; + mmap_buf->plain_ptr = local_buf; - c = nxt_atomic_fetch_add(&process->use_count, -1); - - if (c == 1) { - nxt_unit_debug(NULL, "destroy process #%d", (int) process->pid); + } else { + mmap_buf->free_ptr = nxt_unit_malloc(ctx, size + sizeof(nxt_port_msg_t)); + if (nxt_slow_path(mmap_buf->free_ptr == NULL)) { + return NXT_UNIT_ERROR; + } - nxt_unit_free(NULL, process); + mmap_buf->plain_ptr = mmap_buf->free_ptr; } -} + mmap_buf->hdr = NULL; + mmap_buf->buf.start = mmap_buf->plain_ptr + sizeof(nxt_port_msg_t); + mmap_buf->buf.free = mmap_buf->buf.start; + mmap_buf->buf.end = mmap_buf->buf.start + size; -static void -nxt_unit_mmaps_destroy(nxt_unit_mmaps_t *mmaps) -{ - nxt_unit_mmap_t *mm, *end; + nxt_unit_debug(ctx, "outgoing plain buffer allocation: (%p, %d)", + mmap_buf->buf.start, (int)size); - if (mmaps->elts != NULL) { - end = mmaps->elts + mmaps->size; + return NXT_UNIT_OK; + } - for (mm = mmaps->elts; mm < end; mm++) { - munmap(mm->hdr, PORT_MMAP_SIZE); - } + nchunks = (size + PORT_MMAP_CHUNK_SIZE - 1) / PORT_MMAP_CHUNK_SIZE; + min_nchunks = (min_size + PORT_MMAP_CHUNK_SIZE - 1) / PORT_MMAP_CHUNK_SIZE; - nxt_unit_free(NULL, mmaps->elts); + hdr = nxt_unit_mmap_get(ctx, port, &c, &nchunks, min_nchunks); + if (nxt_slow_path(hdr == NULL)) { + if (nxt_fast_path(min_nchunks == 0 && nchunks == 0)) { + mmap_buf->hdr = NULL; + mmap_buf->buf.start = NULL; + mmap_buf->buf.free = NULL; + mmap_buf->buf.end = NULL; + mmap_buf->free_ptr = NULL; + + return NXT_UNIT_OK; } - pthread_mutex_destroy(&mmaps->mutex); -} + return NXT_UNIT_ERROR; + } + mmap_buf->hdr = hdr; + mmap_buf->buf.start = (char *)nxt_port_mmap_chunk_start(hdr, c); + mmap_buf->buf.free = mmap_buf->buf.start; + mmap_buf->buf.end = mmap_buf->buf.start + nchunks * PORT_MMAP_CHUNK_SIZE; + mmap_buf->free_ptr = NULL; + mmap_buf->ctx_impl = nxt_container_of(ctx, nxt_unit_ctx_impl_t, ctx); -static int -nxt_unit_check_rbuf_mmap(nxt_unit_ctx_t *ctx, nxt_unit_mmaps_t *mmaps, - pid_t pid, uint32_t id, nxt_port_mmap_header_t **hdr, - nxt_unit_read_buf_t *rbuf) -{ - int res, need_rbuf; - nxt_unit_mmap_t *mm; - nxt_unit_ctx_impl_t *ctx_impl; + nxt_unit_debug(ctx, "outgoing mmap allocation: (%d,%d,%d)", (int)hdr->id, + (int)c, (int)(nchunks * PORT_MMAP_CHUNK_SIZE)); - mm = nxt_unit_mmap_at(mmaps, id); - if (nxt_slow_path(mm == NULL)) { - nxt_unit_alert(ctx, "failed to allocate mmap"); + return NXT_UNIT_OK; +} - pthread_mutex_unlock(&mmaps->mutex); +static int nxt_unit_incoming_mmap(nxt_unit_ctx_t *ctx, pid_t pid, int fd) { + int rc; + void *mem; + nxt_queue_t awaiting_rbuf; + struct stat mmap_stat; + nxt_unit_mmap_t *mm; + nxt_unit_impl_t *lib; + nxt_unit_ctx_impl_t *ctx_impl; + nxt_unit_read_buf_t *rbuf; + nxt_port_mmap_header_t *hdr; - *hdr = NULL; + lib = nxt_container_of(ctx->unit, nxt_unit_impl_t, unit); - return NXT_UNIT_ERROR; - } + nxt_unit_debug(ctx, "incoming_mmap: fd %d from process %d", fd, (int)pid); - *hdr = mm->hdr; + if (fstat(fd, &mmap_stat) == -1) { + nxt_unit_alert(ctx, "incoming_mmap: fstat(%d) failed: %s (%d)", fd, + strerror(errno), errno); - if (nxt_fast_path(*hdr != NULL)) { - return NXT_UNIT_OK; - } + return NXT_UNIT_ERROR; + } - need_rbuf = nxt_queue_is_empty(&mm->awaiting_rbuf); + mem = + mmap(NULL, mmap_stat.st_size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); + if (nxt_slow_path(mem == MAP_FAILED)) { + nxt_unit_alert(ctx, "incoming_mmap: mmap() failed: %s (%d)", + strerror(errno), errno); - nxt_queue_insert_tail(&mm->awaiting_rbuf, &rbuf->link); + return NXT_UNIT_ERROR; + } - pthread_mutex_unlock(&mmaps->mutex); + hdr = mem; - ctx_impl = nxt_container_of(ctx, nxt_unit_ctx_impl_t, ctx); + if (nxt_slow_path(hdr->src_pid != pid)) { - nxt_atomic_fetch_add(&ctx_impl->wait_items, 1); + nxt_unit_alert(ctx, + "incoming_mmap: unexpected pid in mmap header " + "detected: %d != %d or %d != %d", + (int)hdr->src_pid, (int)pid, (int)hdr->dst_pid, + (int)lib->pid); - if (need_rbuf) { - res = nxt_unit_get_mmap(ctx, pid, id); - if (nxt_slow_path(res == NXT_UNIT_ERROR)) { - return NXT_UNIT_ERROR; - } - } + munmap(mem, PORT_MMAP_SIZE); - return NXT_UNIT_AGAIN; -} + return NXT_UNIT_ERROR; + } + nxt_queue_init(&awaiting_rbuf); -static int -nxt_unit_mmap_read(nxt_unit_ctx_t *ctx, nxt_unit_recv_msg_t *recv_msg, - nxt_unit_read_buf_t *rbuf) -{ - int res; - void *start; - uint32_t size; - nxt_unit_impl_t *lib; - nxt_unit_mmaps_t *mmaps; - nxt_unit_mmap_buf_t *b, **incoming_tail; - nxt_port_mmap_msg_t *mmap_msg, *end; - nxt_port_mmap_header_t *hdr; + pthread_mutex_lock(&lib->incoming.mutex); - if (nxt_slow_path(recv_msg->size < sizeof(nxt_port_mmap_msg_t))) { - nxt_unit_warn(ctx, "#%"PRIu32": mmap_read: too small message (%d)", - recv_msg->stream, (int) recv_msg->size); + mm = nxt_unit_mmap_at(&lib->incoming, hdr->id); + if (nxt_slow_path(mm == NULL)) { + nxt_unit_alert(ctx, "incoming_mmap: failed to add to incoming array"); - return NXT_UNIT_ERROR; - } + munmap(mem, PORT_MMAP_SIZE); - mmap_msg = recv_msg->start; - end = nxt_pointer_to(recv_msg->start, recv_msg->size); + rc = NXT_UNIT_ERROR; - incoming_tail = &recv_msg->incoming_buf; + } else { + mm->hdr = hdr; - /* Allocating buffer structures. */ - for (; mmap_msg < end; mmap_msg++) { - b = nxt_unit_mmap_buf_get(ctx); - if (nxt_slow_path(b == NULL)) { - nxt_unit_warn(ctx, "#%"PRIu32": mmap_read: failed to allocate buf", - recv_msg->stream); + hdr->sent_over = 0xFFFFu; - while (recv_msg->incoming_buf != NULL) { - nxt_unit_mmap_buf_release(recv_msg->incoming_buf); - } + nxt_queue_add(&awaiting_rbuf, &mm->awaiting_rbuf); + nxt_queue_init(&mm->awaiting_rbuf); - return NXT_UNIT_ERROR; - } + rc = NXT_UNIT_OK; + } - nxt_unit_mmap_buf_insert(incoming_tail, b); - incoming_tail = &b->next; - } + pthread_mutex_unlock(&lib->incoming.mutex); - b = recv_msg->incoming_buf; - mmap_msg = recv_msg->start; + nxt_queue_each(rbuf, &awaiting_rbuf, nxt_unit_read_buf_t, link) { - lib = nxt_container_of(ctx->unit, nxt_unit_impl_t, unit); + ctx_impl = rbuf->ctx_impl; - mmaps = &lib->incoming; + pthread_mutex_lock(&ctx_impl->mutex); - pthread_mutex_lock(&mmaps->mutex); + nxt_queue_insert_head(&ctx_impl->pending_rbuf, &rbuf->link); - for (; mmap_msg < end; mmap_msg++) { - res = nxt_unit_check_rbuf_mmap(ctx, mmaps, - recv_msg->pid, mmap_msg->mmap_id, - &hdr, rbuf); + pthread_mutex_unlock(&ctx_impl->mutex); - if (nxt_slow_path(res != NXT_UNIT_OK)) { - while (recv_msg->incoming_buf != NULL) { - nxt_unit_mmap_buf_release(recv_msg->incoming_buf); - } + nxt_atomic_fetch_add(&ctx_impl->wait_items, -1); - return res; - } + nxt_unit_awake_ctx(ctx, ctx_impl); + } + nxt_queue_loop; - start = nxt_port_mmap_chunk_start(hdr, mmap_msg->chunk_id); - size = mmap_msg->size; + return rc; +} - if (recv_msg->start == mmap_msg) { - recv_msg->start = start; - recv_msg->size = size; - } +static void nxt_unit_awake_ctx(nxt_unit_ctx_t *ctx, + nxt_unit_ctx_impl_t *ctx_impl) { + nxt_port_msg_t msg; - b->buf.start = start; - b->buf.free = start; - b->buf.end = b->buf.start + size; - b->hdr = hdr; + if (nxt_fast_path(ctx == &ctx_impl->ctx)) { + return; + } - b = b->next; + if (nxt_slow_path(ctx_impl->read_port == NULL || + ctx_impl->read_port->out_fd == -1)) { + nxt_unit_alert(ctx, "target context read_port is NULL or not writable"); - nxt_unit_debug(ctx, "#%"PRIu32": mmap_read: [%p,%d] %d->%d,(%d,%d,%d)", - recv_msg->stream, - start, (int) size, - (int) hdr->src_pid, (int) hdr->dst_pid, - (int) hdr->id, (int) mmap_msg->chunk_id, - (int) mmap_msg->size); - } + return; + } - pthread_mutex_unlock(&mmaps->mutex); + memset(&msg, 0, sizeof(nxt_port_msg_t)); - return NXT_UNIT_OK; + msg.type = _NXT_PORT_MSG_RPC_READY; + + (void)nxt_unit_port_send(ctx, ctx_impl->read_port, &msg, sizeof(msg), NULL); } +static int nxt_unit_mmaps_init(nxt_unit_mmaps_t *mmaps) { + mmaps->size = 0; + mmaps->cap = 0; + mmaps->elts = NULL; + mmaps->allocated_chunks = 0; -static int -nxt_unit_get_mmap(nxt_unit_ctx_t *ctx, pid_t pid, uint32_t id) -{ - ssize_t res; - nxt_unit_impl_t *lib; - nxt_unit_ctx_impl_t *ctx_impl; + return pthread_mutex_init(&mmaps->mutex, NULL); +} + +nxt_inline void nxt_unit_process_use(nxt_unit_process_t *process) { + nxt_atomic_fetch_add(&process->use_count, 1); +} - struct { - nxt_port_msg_t msg; - nxt_port_msg_get_mmap_t get_mmap; - } m; +nxt_inline void nxt_unit_process_release(nxt_unit_process_t *process) { + long c; - lib = nxt_container_of(ctx->unit, nxt_unit_impl_t, unit); - ctx_impl = nxt_container_of(ctx, nxt_unit_ctx_impl_t, ctx); + c = nxt_atomic_fetch_add(&process->use_count, -1); - memset(&m.msg, 0, sizeof(nxt_port_msg_t)); + if (c == 1) { + nxt_unit_debug(NULL, "destroy process #%d", (int)process->pid); - m.msg.pid = lib->pid; - m.msg.reply_port = ctx_impl->read_port->id.id; - m.msg.type = _NXT_PORT_MSG_GET_MMAP; + nxt_unit_free(NULL, process); + } +} - m.get_mmap.id = id; +static void nxt_unit_mmaps_destroy(nxt_unit_mmaps_t *mmaps) { + nxt_unit_mmap_t *mm, *end; - nxt_unit_debug(ctx, "get_mmap: %d %d", (int) pid, (int) id); + if (mmaps->elts != NULL) { + end = mmaps->elts + mmaps->size; - res = nxt_unit_port_send(ctx, lib->router_port, &m, sizeof(m), NULL); - if (nxt_slow_path(res != sizeof(m))) { - return NXT_UNIT_ERROR; + for (mm = mmaps->elts; mm < end; mm++) { + munmap(mm->hdr, PORT_MMAP_SIZE); } - return NXT_UNIT_OK; -} + nxt_unit_free(NULL, mmaps->elts); + } + pthread_mutex_destroy(&mmaps->mutex); +} -static void -nxt_unit_mmap_release(nxt_unit_ctx_t *ctx, nxt_port_mmap_header_t *hdr, - void *start, uint32_t size) -{ - int freed_chunks; - u_char *p, *end; - nxt_chunk_id_t c; - nxt_unit_impl_t *lib; +static int nxt_unit_check_rbuf_mmap(nxt_unit_ctx_t *ctx, + nxt_unit_mmaps_t *mmaps, pid_t pid, + uint32_t id, nxt_port_mmap_header_t **hdr, + nxt_unit_read_buf_t *rbuf) { + int res, need_rbuf; + nxt_unit_mmap_t *mm; + nxt_unit_ctx_impl_t *ctx_impl; - memset(start, 0xA5, size); + mm = nxt_unit_mmap_at(mmaps, id); + if (nxt_slow_path(mm == NULL)) { + nxt_unit_alert(ctx, "failed to allocate mmap"); - p = start; - end = p + size; - c = nxt_port_mmap_chunk_id(hdr, p); - freed_chunks = 0; + pthread_mutex_unlock(&mmaps->mutex); - while (p < end) { - nxt_port_mmap_set_chunk_free(hdr->free_map, c); + *hdr = NULL; - p += PORT_MMAP_CHUNK_SIZE; - c++; - freed_chunks++; - } + return NXT_UNIT_ERROR; + } - lib = nxt_container_of(ctx->unit, nxt_unit_impl_t, unit); + *hdr = mm->hdr; - if (hdr->src_pid == lib->pid && freed_chunks != 0) { - nxt_atomic_fetch_add(&lib->outgoing.allocated_chunks, -freed_chunks); + if (nxt_fast_path(*hdr != NULL)) { + return NXT_UNIT_OK; + } - nxt_unit_debug(ctx, "allocated_chunks %d", - (int) lib->outgoing.allocated_chunks); - } + need_rbuf = nxt_queue_is_empty(&mm->awaiting_rbuf); - if (hdr->dst_pid == lib->pid - && freed_chunks != 0 - && nxt_atomic_cmp_set(&hdr->oosm, 1, 0)) - { - nxt_unit_send_shm_ack(ctx, hdr->src_pid); - } -} + nxt_queue_insert_tail(&mm->awaiting_rbuf, &rbuf->link); + pthread_mutex_unlock(&mmaps->mutex); -static int -nxt_unit_send_shm_ack(nxt_unit_ctx_t *ctx, pid_t pid) -{ - ssize_t res; - nxt_port_msg_t msg; - nxt_unit_impl_t *lib; + ctx_impl = nxt_container_of(ctx, nxt_unit_ctx_impl_t, ctx); - lib = nxt_container_of(ctx->unit, nxt_unit_impl_t, unit); + nxt_atomic_fetch_add(&ctx_impl->wait_items, 1); - msg.stream = 0; - msg.pid = lib->pid; - msg.reply_port = 0; - msg.type = _NXT_PORT_MSG_SHM_ACK; - msg.last = 0; - msg.mmap = 0; - msg.nf = 0; - msg.mf = 0; - - res = nxt_unit_port_send(ctx, lib->router_port, &msg, sizeof(msg), NULL); - if (nxt_slow_path(res != sizeof(msg))) { - return NXT_UNIT_ERROR; + if (need_rbuf) { + res = nxt_unit_get_mmap(ctx, pid, id); + if (nxt_slow_path(res == NXT_UNIT_ERROR)) { + return NXT_UNIT_ERROR; } + } - return NXT_UNIT_OK; + return NXT_UNIT_AGAIN; } +static int nxt_unit_mmap_read(nxt_unit_ctx_t *ctx, + nxt_unit_recv_msg_t *recv_msg, + nxt_unit_read_buf_t *rbuf) { + int res; + void *start; + uint32_t size; + nxt_unit_impl_t *lib; + nxt_unit_mmaps_t *mmaps; + nxt_unit_mmap_buf_t *b, **incoming_tail; + nxt_port_mmap_msg_t *mmap_msg, *end; + nxt_port_mmap_header_t *hdr; + + if (nxt_slow_path(recv_msg->size < sizeof(nxt_port_mmap_msg_t))) { + nxt_unit_warn(ctx, "#%" PRIu32 ": mmap_read: too small message (%d)", + recv_msg->stream, (int)recv_msg->size); -static nxt_int_t -nxt_unit_lvlhsh_pid_test(nxt_lvlhsh_query_t *lhq, void *data) -{ - nxt_process_t *process; + return NXT_UNIT_ERROR; + } - process = data; + mmap_msg = recv_msg->start; + end = nxt_pointer_to(recv_msg->start, recv_msg->size); - if (lhq->key.length == sizeof(pid_t) - && *(pid_t *) lhq->key.start == process->pid) - { - return NXT_OK; - } + incoming_tail = &recv_msg->incoming_buf; - return NXT_DECLINED; -} + /* Allocating buffer structures. */ + for (; mmap_msg < end; mmap_msg++) { + b = nxt_unit_mmap_buf_get(ctx); + if (nxt_slow_path(b == NULL)) { + nxt_unit_warn(ctx, "#%" PRIu32 ": mmap_read: failed to allocate buf", + recv_msg->stream); + while (recv_msg->incoming_buf != NULL) { + nxt_unit_mmap_buf_release(recv_msg->incoming_buf); + } -static const nxt_lvlhsh_proto_t lvlhsh_processes_proto nxt_aligned(64) = { - NXT_LVLHSH_DEFAULT, - nxt_unit_lvlhsh_pid_test, - nxt_unit_lvlhsh_alloc, - nxt_unit_lvlhsh_free, -}; + return NXT_UNIT_ERROR; + } + nxt_unit_mmap_buf_insert(incoming_tail, b); + incoming_tail = &b->next; + } -static inline void -nxt_unit_process_lhq_pid(nxt_lvlhsh_query_t *lhq, pid_t *pid) -{ - lhq->key_hash = nxt_murmur_hash2(pid, sizeof(*pid)); - lhq->key.length = sizeof(*pid); - lhq->key.start = (u_char *) pid; - lhq->proto = &lvlhsh_processes_proto; -} + b = recv_msg->incoming_buf; + mmap_msg = recv_msg->start; + lib = nxt_container_of(ctx->unit, nxt_unit_impl_t, unit); -static nxt_unit_process_t * -nxt_unit_process_get(nxt_unit_ctx_t *ctx, pid_t pid) -{ - nxt_unit_impl_t *lib; - nxt_unit_process_t *process; - nxt_lvlhsh_query_t lhq; + mmaps = &lib->incoming; - lib = nxt_container_of(ctx->unit, nxt_unit_impl_t, unit); + pthread_mutex_lock(&mmaps->mutex); - nxt_unit_process_lhq_pid(&lhq, &pid); + for (; mmap_msg < end; mmap_msg++) { + res = nxt_unit_check_rbuf_mmap(ctx, mmaps, recv_msg->pid, mmap_msg->mmap_id, + &hdr, rbuf); - if (nxt_lvlhsh_find(&lib->processes, &lhq) == NXT_OK) { - process = lhq.value; - nxt_unit_process_use(process); + if (nxt_slow_path(res != NXT_UNIT_OK)) { + while (recv_msg->incoming_buf != NULL) { + nxt_unit_mmap_buf_release(recv_msg->incoming_buf); + } - return process; + return res; } - process = nxt_unit_malloc(ctx, sizeof(nxt_unit_process_t)); - if (nxt_slow_path(process == NULL)) { - nxt_unit_alert(ctx, "failed to allocate process for #%d", (int) pid); + start = nxt_port_mmap_chunk_start(hdr, mmap_msg->chunk_id); + size = mmap_msg->size; - return NULL; + if (recv_msg->start == mmap_msg) { + recv_msg->start = start; + recv_msg->size = size; } - process->pid = pid; - process->use_count = 2; - process->next_port_id = 0; - process->lib = lib; + b->buf.start = start; + b->buf.free = start; + b->buf.end = b->buf.start + size; + b->hdr = hdr; - nxt_queue_init(&process->ports); + b = b->next; - lhq.replace = 0; - lhq.value = process; + nxt_unit_debug(ctx, "#%" PRIu32 ": mmap_read: [%p,%d] %d->%d,(%d,%d,%d)", + recv_msg->stream, start, (int)size, (int)hdr->src_pid, + (int)hdr->dst_pid, (int)hdr->id, (int)mmap_msg->chunk_id, + (int)mmap_msg->size); + } - switch (nxt_lvlhsh_insert(&lib->processes, &lhq)) { + pthread_mutex_unlock(&mmaps->mutex); - case NXT_OK: - break; + return NXT_UNIT_OK; +} - default: - nxt_unit_alert(ctx, "process %d insert failed", (int) pid); +static int nxt_unit_get_mmap(nxt_unit_ctx_t *ctx, pid_t pid, uint32_t id) { + ssize_t res; + nxt_unit_impl_t *lib; + nxt_unit_ctx_impl_t *ctx_impl; - nxt_unit_free(ctx, process); - process = NULL; - break; - } + struct { + nxt_port_msg_t msg; + nxt_port_msg_get_mmap_t get_mmap; + } m; - return process; -} + lib = nxt_container_of(ctx->unit, nxt_unit_impl_t, unit); + ctx_impl = nxt_container_of(ctx, nxt_unit_ctx_impl_t, ctx); + memset(&m.msg, 0, sizeof(nxt_port_msg_t)); -static nxt_unit_process_t * -nxt_unit_process_find(nxt_unit_impl_t *lib, pid_t pid, int remove) -{ - int rc; - nxt_lvlhsh_query_t lhq; + m.msg.pid = lib->pid; + m.msg.reply_port = ctx_impl->read_port->id.id; + m.msg.type = _NXT_PORT_MSG_GET_MMAP; - nxt_unit_process_lhq_pid(&lhq, &pid); + m.get_mmap.id = id; - if (remove) { - rc = nxt_lvlhsh_delete(&lib->processes, &lhq); + nxt_unit_debug(ctx, "get_mmap: %d %d", (int)pid, (int)id); - } else { - rc = nxt_lvlhsh_find(&lib->processes, &lhq); - } + res = nxt_unit_port_send(ctx, lib->router_port, &m, sizeof(m), NULL); + if (nxt_slow_path(res != sizeof(m))) { + return NXT_UNIT_ERROR; + } - if (rc == NXT_OK) { - if (!remove) { - nxt_unit_process_use(lhq.value); - } + return NXT_UNIT_OK; +} - return lhq.value; - } +static void nxt_unit_mmap_release(nxt_unit_ctx_t *ctx, + nxt_port_mmap_header_t *hdr, void *start, + uint32_t size) { + int freed_chunks; + u_char *p, *end; + nxt_chunk_id_t c; + nxt_unit_impl_t *lib; - return NULL; -} + memset(start, 0xA5, size); + p = start; + end = p + size; + c = nxt_port_mmap_chunk_id(hdr, p); + freed_chunks = 0; -static nxt_unit_process_t * -nxt_unit_process_pop_first(nxt_unit_impl_t *lib) -{ - return nxt_lvlhsh_retrieve(&lib->processes, &lvlhsh_processes_proto, NULL); -} + while (p < end) { + nxt_port_mmap_set_chunk_free(hdr->free_map, c); + p += PORT_MMAP_CHUNK_SIZE; + c++; + freed_chunks++; + } -int -nxt_unit_run(nxt_unit_ctx_t *ctx) -{ - int rc; - nxt_unit_ctx_impl_t *ctx_impl; + lib = nxt_container_of(ctx->unit, nxt_unit_impl_t, unit); - nxt_unit_ctx_use(ctx); + if (hdr->src_pid == lib->pid && freed_chunks != 0) { + nxt_atomic_fetch_add(&lib->outgoing.allocated_chunks, -freed_chunks); - ctx_impl = nxt_container_of(ctx, nxt_unit_ctx_impl_t, ctx); + nxt_unit_debug(ctx, "allocated_chunks %d", + (int)lib->outgoing.allocated_chunks); + } - rc = NXT_UNIT_OK; + if (hdr->dst_pid == lib->pid && freed_chunks != 0 && + nxt_atomic_cmp_set(&hdr->oosm, 1, 0)) { + nxt_unit_send_shm_ack(ctx, hdr->src_pid); + } +} - while (nxt_fast_path(ctx_impl->online)) { - rc = nxt_unit_run_once_impl(ctx); +static int nxt_unit_send_shm_ack(nxt_unit_ctx_t *ctx, pid_t pid) { + ssize_t res; + nxt_port_msg_t msg; + nxt_unit_impl_t *lib; - if (nxt_slow_path(rc == NXT_UNIT_ERROR)) { - nxt_unit_quit(ctx, NXT_QUIT_NORMAL); - break; - } - } + lib = nxt_container_of(ctx->unit, nxt_unit_impl_t, unit); - nxt_unit_ctx_release(ctx); + msg.stream = 0; + msg.pid = lib->pid; + msg.reply_port = 0; + msg.type = _NXT_PORT_MSG_SHM_ACK; + msg.last = 0; + msg.mmap = 0; + msg.nf = 0; + msg.mf = 0; - return rc; + res = nxt_unit_port_send(ctx, lib->router_port, &msg, sizeof(msg), NULL); + if (nxt_slow_path(res != sizeof(msg))) { + return NXT_UNIT_ERROR; + } + + return NXT_UNIT_OK; } +static nxt_int_t nxt_unit_lvlhsh_pid_test(nxt_lvlhsh_query_t *lhq, void *data) { + nxt_process_t *process; -int -nxt_unit_run_once(nxt_unit_ctx_t *ctx) -{ - int rc; + process = data; - nxt_unit_ctx_use(ctx); + if (lhq->key.length == sizeof(pid_t) && + *(pid_t *)lhq->key.start == process->pid) { + return NXT_OK; + } - rc = nxt_unit_run_once_impl(ctx); + return NXT_DECLINED; +} - nxt_unit_ctx_release(ctx); +static const nxt_lvlhsh_proto_t lvlhsh_processes_proto nxt_aligned(64) = { + NXT_LVLHSH_DEFAULT, + nxt_unit_lvlhsh_pid_test, + nxt_unit_lvlhsh_alloc, + nxt_unit_lvlhsh_free, +}; - return rc; +static inline void nxt_unit_process_lhq_pid(nxt_lvlhsh_query_t *lhq, + pid_t *pid) { + lhq->key_hash = nxt_murmur_hash2(pid, sizeof(*pid)); + lhq->key.length = sizeof(*pid); + lhq->key.start = (u_char *)pid; + lhq->proto = &lvlhsh_processes_proto; } +static nxt_unit_process_t *nxt_unit_process_get(nxt_unit_ctx_t *ctx, + pid_t pid) { + nxt_unit_impl_t *lib; + nxt_unit_process_t *process; + nxt_lvlhsh_query_t lhq; -static int -nxt_unit_run_once_impl(nxt_unit_ctx_t *ctx) -{ - int rc; - nxt_unit_read_buf_t *rbuf; - - rbuf = nxt_unit_read_buf_get(ctx); - if (nxt_slow_path(rbuf == NULL)) { - return NXT_UNIT_ERROR; - } + lib = nxt_container_of(ctx->unit, nxt_unit_impl_t, unit); - rc = nxt_unit_read_buf(ctx, rbuf); - if (nxt_slow_path(rc != NXT_UNIT_OK)) { - nxt_unit_read_buf_release(ctx, rbuf); + nxt_unit_process_lhq_pid(&lhq, &pid); - return rc; - } + if (nxt_lvlhsh_find(&lib->processes, &lhq) == NXT_OK) { + process = lhq.value; + nxt_unit_process_use(process); - rc = nxt_unit_process_msg(ctx, rbuf, NULL); - if (nxt_slow_path(rc == NXT_UNIT_ERROR)) { - return NXT_UNIT_ERROR; - } + return process; + } - rc = nxt_unit_process_pending_rbuf(ctx); - if (nxt_slow_path(rc == NXT_UNIT_ERROR)) { - return NXT_UNIT_ERROR; - } + process = nxt_unit_malloc(ctx, sizeof(nxt_unit_process_t)); + if (nxt_slow_path(process == NULL)) { + nxt_unit_alert(ctx, "failed to allocate process for #%d", (int)pid); - nxt_unit_process_ready_req(ctx); + return NULL; + } - return rc; -} + process->pid = pid; + process->use_count = 2; + process->next_port_id = 0; + process->lib = lib; + nxt_queue_init(&process->ports); -static int -nxt_unit_read_buf(nxt_unit_ctx_t *ctx, nxt_unit_read_buf_t *rbuf) -{ - int nevents, res, err; - nxt_uint_t nfds; - nxt_unit_impl_t *lib; - nxt_unit_ctx_impl_t *ctx_impl; - nxt_unit_port_impl_t *port_impl; - struct pollfd fds[2]; + lhq.replace = 0; + lhq.value = process; - ctx_impl = nxt_container_of(ctx, nxt_unit_ctx_impl_t, ctx); + switch (nxt_lvlhsh_insert(&lib->processes, &lhq)) { - if (ctx_impl->wait_items > 0 || !nxt_unit_chk_ready(ctx)) { - return nxt_unit_ctx_port_recv(ctx, ctx_impl->read_port, rbuf); - } + case NXT_OK: + break; - port_impl = nxt_container_of(ctx_impl->read_port, nxt_unit_port_impl_t, - port); + default: + nxt_unit_alert(ctx, "process %d insert failed", (int)pid); - lib = nxt_container_of(ctx->unit, nxt_unit_impl_t, unit); + nxt_unit_free(ctx, process); + process = NULL; + break; + } -retry: + return process; +} - if (port_impl->from_socket == 0) { - res = nxt_unit_port_queue_recv(ctx_impl->read_port, rbuf); - if (res == NXT_UNIT_OK) { - if (nxt_unit_is_read_socket(rbuf)) { - port_impl->from_socket++; - - nxt_unit_debug(ctx, "port{%d,%d} dequeue 1 read_socket %d", - (int) ctx_impl->read_port->id.pid, - (int) ctx_impl->read_port->id.id, - port_impl->from_socket); - - } else { - nxt_unit_debug(ctx, "port{%d,%d} dequeue %d", - (int) ctx_impl->read_port->id.pid, - (int) ctx_impl->read_port->id.id, - (int) rbuf->size); - - return NXT_UNIT_OK; - } - } - } +static nxt_unit_process_t *nxt_unit_process_find(nxt_unit_impl_t *lib, + pid_t pid, int remove) { + int rc; + nxt_lvlhsh_query_t lhq; - if (nxt_fast_path(nxt_unit_chk_ready(ctx))) { - res = nxt_unit_app_queue_recv(ctx, lib->shared_port, rbuf); - if (res == NXT_UNIT_OK) { - return NXT_UNIT_OK; - } + nxt_unit_process_lhq_pid(&lhq, &pid); - fds[1].fd = lib->shared_port->in_fd; - fds[1].events = POLLIN; + if (remove) { + rc = nxt_lvlhsh_delete(&lib->processes, &lhq); - nfds = 2; + } else { + rc = nxt_lvlhsh_find(&lib->processes, &lhq); + } - } else { - nfds = 1; + if (rc == NXT_OK) { + if (!remove) { + nxt_unit_process_use(lhq.value); } - fds[0].fd = ctx_impl->read_port->in_fd; - fds[0].events = POLLIN; - fds[0].revents = 0; + return lhq.value; + } + + return NULL; +} + +static nxt_unit_process_t *nxt_unit_process_pop_first(nxt_unit_impl_t *lib) { + return nxt_lvlhsh_retrieve(&lib->processes, &lvlhsh_processes_proto, NULL); +} - fds[1].revents = 0; +int nxt_unit_run(nxt_unit_ctx_t *ctx) { + int rc; + nxt_unit_ctx_impl_t *ctx_impl; - nevents = poll(fds, nfds, -1); - if (nxt_slow_path(nevents == -1)) { - err = errno; + nxt_unit_ctx_use(ctx); - if (err == EINTR) { - goto retry; - } + ctx_impl = nxt_container_of(ctx, nxt_unit_ctx_impl_t, ctx); - nxt_unit_alert(ctx, "poll(%d,%d) failed: %s (%d)", - fds[0].fd, fds[1].fd, strerror(err), err); + rc = NXT_UNIT_OK; - rbuf->size = -1; + while (nxt_fast_path(ctx_impl->online)) { + rc = nxt_unit_run_once_impl(ctx); - return (err == EAGAIN) ? NXT_UNIT_AGAIN : NXT_UNIT_ERROR; + if (nxt_slow_path(rc == NXT_UNIT_ERROR)) { + nxt_unit_quit(ctx, NXT_QUIT_NORMAL); + break; } + } - nxt_unit_debug(ctx, "poll(%d,%d): %d, revents [%04X, %04X]", - fds[0].fd, fds[1].fd, nevents, fds[0].revents, - fds[1].revents); + nxt_unit_ctx_release(ctx); - if ((fds[0].revents & POLLIN) != 0) { - res = nxt_unit_ctx_port_recv(ctx, ctx_impl->read_port, rbuf); - if (res == NXT_UNIT_AGAIN) { - goto retry; - } + return rc; +} - return res; - } +int nxt_unit_run_once(nxt_unit_ctx_t *ctx) { + int rc; - if ((fds[1].revents & POLLIN) != 0) { - res = nxt_unit_shared_port_recv(ctx, lib->shared_port, rbuf); - if (res == NXT_UNIT_AGAIN) { - goto retry; - } + nxt_unit_ctx_use(ctx); - return res; - } + rc = nxt_unit_run_once_impl(ctx); - nxt_unit_alert(ctx, "poll(%d,%d): %d unexpected revents [%04uXi, %04uXi]", - fds[0].fd, fds[1].fd, nevents, fds[0].revents, - fds[1].revents); + nxt_unit_ctx_release(ctx); - return NXT_UNIT_ERROR; + return rc; } +static int nxt_unit_run_once_impl(nxt_unit_ctx_t *ctx) { + int rc; + nxt_unit_read_buf_t *rbuf; -static int -nxt_unit_chk_ready(nxt_unit_ctx_t *ctx) -{ - nxt_unit_impl_t *lib; - nxt_unit_ctx_impl_t *ctx_impl; + rbuf = nxt_unit_read_buf_get(ctx); + if (nxt_slow_path(rbuf == NULL)) { + return NXT_UNIT_ERROR; + } - ctx_impl = nxt_container_of(ctx, nxt_unit_ctx_impl_t, ctx); - lib = nxt_container_of(ctx->unit, nxt_unit_impl_t, unit); + rc = nxt_unit_read_buf(ctx, rbuf); + if (nxt_slow_path(rc != NXT_UNIT_OK)) { + nxt_unit_read_buf_release(ctx, rbuf); - return (ctx_impl->ready - && (lib->request_limit == 0 - || lib->request_count < lib->request_limit)); -} + return rc; + } + rc = nxt_unit_process_msg(ctx, rbuf, NULL); + if (nxt_slow_path(rc == NXT_UNIT_ERROR)) { + return NXT_UNIT_ERROR; + } -static int -nxt_unit_process_pending_rbuf(nxt_unit_ctx_t *ctx) -{ - int rc; - nxt_queue_t pending_rbuf; - nxt_unit_ctx_impl_t *ctx_impl; - nxt_unit_read_buf_t *rbuf; + rc = nxt_unit_process_pending_rbuf(ctx); + if (nxt_slow_path(rc == NXT_UNIT_ERROR)) { + return NXT_UNIT_ERROR; + } - ctx_impl = nxt_container_of(ctx, nxt_unit_ctx_impl_t, ctx); + nxt_unit_process_ready_req(ctx); - pthread_mutex_lock(&ctx_impl->mutex); + return rc; +} - if (nxt_queue_is_empty(&ctx_impl->pending_rbuf)) { - pthread_mutex_unlock(&ctx_impl->mutex); +static int nxt_unit_read_buf(nxt_unit_ctx_t *ctx, nxt_unit_read_buf_t *rbuf) { + int nevents, res, err; + nxt_uint_t nfds; + nxt_unit_impl_t *lib; + nxt_unit_ctx_impl_t *ctx_impl; + nxt_unit_port_impl_t *port_impl; + struct pollfd fds[2]; - return NXT_UNIT_OK; - } + ctx_impl = nxt_container_of(ctx, nxt_unit_ctx_impl_t, ctx); - nxt_queue_init(&pending_rbuf); + if (ctx_impl->wait_items > 0 || !nxt_unit_chk_ready(ctx)) { + return nxt_unit_ctx_port_recv(ctx, ctx_impl->read_port, rbuf); + } - nxt_queue_add(&pending_rbuf, &ctx_impl->pending_rbuf); - nxt_queue_init(&ctx_impl->pending_rbuf); + port_impl = nxt_container_of(ctx_impl->read_port, nxt_unit_port_impl_t, port); - pthread_mutex_unlock(&ctx_impl->mutex); + lib = nxt_container_of(ctx->unit, nxt_unit_impl_t, unit); - rc = NXT_UNIT_OK; +retry: - nxt_queue_each(rbuf, &pending_rbuf, nxt_unit_read_buf_t, link) { + if (port_impl->from_socket == 0) { + res = nxt_unit_port_queue_recv(ctx_impl->read_port, rbuf); + if (res == NXT_UNIT_OK) { + if (nxt_unit_is_read_socket(rbuf)) { + port_impl->from_socket++; - if (nxt_fast_path(rc != NXT_UNIT_ERROR)) { - rc = nxt_unit_process_msg(&ctx_impl->ctx, rbuf, NULL); + nxt_unit_debug(ctx, "port{%d,%d} dequeue 1 read_socket %d", + (int)ctx_impl->read_port->id.pid, + (int)ctx_impl->read_port->id.id, port_impl->from_socket); - } else { - nxt_unit_read_buf_release(ctx, rbuf); - } + } else { + nxt_unit_debug(ctx, "port{%d,%d} dequeue %d", + (int)ctx_impl->read_port->id.pid, + (int)ctx_impl->read_port->id.id, (int)rbuf->size); - } nxt_queue_loop; + return NXT_UNIT_OK; + } + } + } - if (!ctx_impl->ready) { - nxt_unit_quit(ctx, NXT_QUIT_GRACEFUL); + if (nxt_fast_path(nxt_unit_chk_ready(ctx))) { + res = nxt_unit_app_queue_recv(ctx, lib->shared_port, rbuf); + if (res == NXT_UNIT_OK) { + return NXT_UNIT_OK; } - return rc; -} + fds[1].fd = lib->shared_port->in_fd; + fds[1].events = POLLIN; + nfds = 2; -static void -nxt_unit_process_ready_req(nxt_unit_ctx_t *ctx) -{ - int res; - nxt_queue_t ready_req; - nxt_unit_impl_t *lib; - nxt_unit_ctx_impl_t *ctx_impl; - nxt_unit_request_info_t *req; - nxt_unit_request_info_impl_t *req_impl; + } else { + nfds = 1; + } - ctx_impl = nxt_container_of(ctx, nxt_unit_ctx_impl_t, ctx); + fds[0].fd = ctx_impl->read_port->in_fd; + fds[0].events = POLLIN; + fds[0].revents = 0; - pthread_mutex_lock(&ctx_impl->mutex); + fds[1].revents = 0; - if (nxt_queue_is_empty(&ctx_impl->ready_req)) { - pthread_mutex_unlock(&ctx_impl->mutex); + nevents = poll(fds, nfds, -1); + if (nxt_slow_path(nevents == -1)) { + err = errno; - return; + if (err == EINTR) { + goto retry; } - nxt_queue_init(&ready_req); + nxt_unit_alert(ctx, "poll(%d,%d) failed: %s (%d)", fds[0].fd, fds[1].fd, + strerror(err), err); - nxt_queue_add(&ready_req, &ctx_impl->ready_req); - nxt_queue_init(&ctx_impl->ready_req); + rbuf->size = -1; - pthread_mutex_unlock(&ctx_impl->mutex); + return (err == EAGAIN) ? NXT_UNIT_AGAIN : NXT_UNIT_ERROR; + } - nxt_queue_each(req_impl, &ready_req, - nxt_unit_request_info_impl_t, port_wait_link) - { - lib = nxt_container_of(ctx_impl->ctx.unit, nxt_unit_impl_t, unit); + nxt_unit_debug(ctx, "poll(%d,%d): %d, revents [%04X, %04X]", fds[0].fd, + fds[1].fd, nevents, fds[0].revents, fds[1].revents); - req = &req_impl->req; + if ((fds[0].revents & POLLIN) != 0) { + res = nxt_unit_ctx_port_recv(ctx, ctx_impl->read_port, rbuf); + if (res == NXT_UNIT_AGAIN) { + goto retry; + } - res = nxt_unit_send_req_headers_ack(req); - if (nxt_slow_path(res != NXT_UNIT_OK)) { - nxt_unit_request_done(req, NXT_UNIT_ERROR); + return res; + } - continue; - } + if ((fds[1].revents & POLLIN) != 0) { + res = nxt_unit_shared_port_recv(ctx, lib->shared_port, rbuf); + if (res == NXT_UNIT_AGAIN) { + goto retry; + } - if (req->content_length - > (uint64_t) (req->content_buf->end - req->content_buf->free)) - { - res = nxt_unit_request_hash_add(ctx, req); - if (nxt_slow_path(res != NXT_UNIT_OK)) { - nxt_unit_req_warn(req, "failed to add request to hash"); - - nxt_unit_request_done(req, NXT_UNIT_ERROR); - - continue; - } - - /* - * If application have separate data handler, we may start - * request processing and process data when it is arrived. - */ - if (lib->callbacks.data_handler == NULL) { - continue; - } - } + return res; + } - lib->callbacks.request_handler(&req_impl->req); + nxt_unit_alert(ctx, "poll(%d,%d): %d unexpected revents [%04uXi, %04uXi]", + fds[0].fd, fds[1].fd, nevents, fds[0].revents, fds[1].revents); - } nxt_queue_loop; + return NXT_UNIT_ERROR; } +static int nxt_unit_chk_ready(nxt_unit_ctx_t *ctx) { + nxt_unit_impl_t *lib; + nxt_unit_ctx_impl_t *ctx_impl; -int -nxt_unit_run_ctx(nxt_unit_ctx_t *ctx) -{ - int rc; - nxt_unit_read_buf_t *rbuf; - nxt_unit_ctx_impl_t *ctx_impl; + ctx_impl = nxt_container_of(ctx, nxt_unit_ctx_impl_t, ctx); + lib = nxt_container_of(ctx->unit, nxt_unit_impl_t, unit); - nxt_unit_ctx_use(ctx); + return (ctx_impl->ready && + (lib->request_limit == 0 || lib->request_count < lib->request_limit)); +} - ctx_impl = nxt_container_of(ctx, nxt_unit_ctx_impl_t, ctx); +static int nxt_unit_process_pending_rbuf(nxt_unit_ctx_t *ctx) { + int rc; + nxt_queue_t pending_rbuf; + nxt_unit_ctx_impl_t *ctx_impl; + nxt_unit_read_buf_t *rbuf; - rc = NXT_UNIT_OK; + ctx_impl = nxt_container_of(ctx, nxt_unit_ctx_impl_t, ctx); - while (nxt_fast_path(ctx_impl->online)) { - rbuf = nxt_unit_read_buf_get(ctx); - if (nxt_slow_path(rbuf == NULL)) { - rc = NXT_UNIT_ERROR; - break; - } + pthread_mutex_lock(&ctx_impl->mutex); - retry: + if (nxt_queue_is_empty(&ctx_impl->pending_rbuf)) { + pthread_mutex_unlock(&ctx_impl->mutex); - rc = nxt_unit_ctx_port_recv(ctx, ctx_impl->read_port, rbuf); - if (rc == NXT_UNIT_AGAIN) { - goto retry; - } + return NXT_UNIT_OK; + } - rc = nxt_unit_process_msg(ctx, rbuf, NULL); - if (nxt_slow_path(rc == NXT_UNIT_ERROR)) { - break; - } + nxt_queue_init(&pending_rbuf); - rc = nxt_unit_process_pending_rbuf(ctx); - if (nxt_slow_path(rc == NXT_UNIT_ERROR)) { - break; - } + nxt_queue_add(&pending_rbuf, &ctx_impl->pending_rbuf); + nxt_queue_init(&ctx_impl->pending_rbuf); + + pthread_mutex_unlock(&ctx_impl->mutex); + + rc = NXT_UNIT_OK; - nxt_unit_process_ready_req(ctx); + nxt_queue_each(rbuf, &pending_rbuf, nxt_unit_read_buf_t, link) { + + if (nxt_fast_path(rc != NXT_UNIT_ERROR)) { + rc = nxt_unit_process_msg(&ctx_impl->ctx, rbuf, NULL); + + } else { + nxt_unit_read_buf_release(ctx, rbuf); } + } + nxt_queue_loop; - nxt_unit_ctx_release(ctx); + if (!ctx_impl->ready) { + nxt_unit_quit(ctx, NXT_QUIT_GRACEFUL); + } - return rc; + return rc; } +static void nxt_unit_process_ready_req(nxt_unit_ctx_t *ctx) { + int res; + nxt_queue_t ready_req; + nxt_unit_impl_t *lib; + nxt_unit_ctx_impl_t *ctx_impl; + nxt_unit_request_info_t *req; + nxt_unit_request_info_impl_t *req_impl; -nxt_inline int -nxt_unit_is_read_queue(nxt_unit_read_buf_t *rbuf) -{ - nxt_port_msg_t *port_msg; + ctx_impl = nxt_container_of(ctx, nxt_unit_ctx_impl_t, ctx); - if (nxt_fast_path(rbuf->size == (ssize_t) sizeof(nxt_port_msg_t))) { - port_msg = (nxt_port_msg_t *) rbuf->buf; + pthread_mutex_lock(&ctx_impl->mutex); - return port_msg->type == _NXT_PORT_MSG_READ_QUEUE; - } + if (nxt_queue_is_empty(&ctx_impl->ready_req)) { + pthread_mutex_unlock(&ctx_impl->mutex); - return 0; -} + return; + } + nxt_queue_init(&ready_req); -nxt_inline int -nxt_unit_is_read_socket(nxt_unit_read_buf_t *rbuf) -{ - if (nxt_fast_path(rbuf->size == 1)) { - return rbuf->buf[0] == _NXT_PORT_MSG_READ_SOCKET; - } + nxt_queue_add(&ready_req, &ctx_impl->ready_req); + nxt_queue_init(&ctx_impl->ready_req); - return 0; -} + pthread_mutex_unlock(&ctx_impl->mutex); + nxt_queue_each(req_impl, &ready_req, nxt_unit_request_info_impl_t, + port_wait_link) { + lib = nxt_container_of(ctx_impl->ctx.unit, nxt_unit_impl_t, unit); -nxt_inline int -nxt_unit_is_shm_ack(nxt_unit_read_buf_t *rbuf) -{ - nxt_port_msg_t *port_msg; + req = &req_impl->req; - if (nxt_fast_path(rbuf->size == (ssize_t) sizeof(nxt_port_msg_t))) { - port_msg = (nxt_port_msg_t *) rbuf->buf; + res = nxt_unit_send_req_headers_ack(req); + if (nxt_slow_path(res != NXT_UNIT_OK)) { + nxt_unit_request_done(req, NXT_UNIT_ERROR); - return port_msg->type == _NXT_PORT_MSG_SHM_ACK; + continue; } - return 0; -} - + if (req->content_length > + (uint64_t)(req->content_buf->end - req->content_buf->free)) { + res = nxt_unit_request_hash_add(ctx, req); + if (nxt_slow_path(res != NXT_UNIT_OK)) { + nxt_unit_req_warn(req, "failed to add request to hash"); -nxt_inline int -nxt_unit_is_quit(nxt_unit_read_buf_t *rbuf) -{ - nxt_port_msg_t *port_msg; + nxt_unit_request_done(req, NXT_UNIT_ERROR); - if (nxt_fast_path(rbuf->size == (ssize_t) sizeof(nxt_port_msg_t))) { - port_msg = (nxt_port_msg_t *) rbuf->buf; + continue; + } - return port_msg->type == _NXT_PORT_MSG_QUIT; + /* + * If application have separate data handler, we may start + * request processing and process data when it is arrived. + */ + if (lib->callbacks.data_handler == NULL) { + continue; + } } - return 0; + lib->callbacks.request_handler(&req_impl->req); + } + nxt_queue_loop; } +int nxt_unit_run_ctx(nxt_unit_ctx_t *ctx) { + int rc; + nxt_unit_read_buf_t *rbuf; + nxt_unit_ctx_impl_t *ctx_impl; -int -nxt_unit_run_shared(nxt_unit_ctx_t *ctx) -{ - int rc; - nxt_unit_impl_t *lib; - nxt_unit_read_buf_t *rbuf; - - nxt_unit_ctx_use(ctx); - - lib = nxt_container_of(ctx->unit, nxt_unit_impl_t, unit); + nxt_unit_ctx_use(ctx); - rc = NXT_UNIT_OK; + ctx_impl = nxt_container_of(ctx, nxt_unit_ctx_impl_t, ctx); - while (nxt_fast_path(nxt_unit_chk_ready(ctx))) { - rbuf = nxt_unit_read_buf_get(ctx); - if (nxt_slow_path(rbuf == NULL)) { - rc = NXT_UNIT_ERROR; - break; - } + rc = NXT_UNIT_OK; - retry: + while (nxt_fast_path(ctx_impl->online)) { + rbuf = nxt_unit_read_buf_get(ctx); + if (nxt_slow_path(rbuf == NULL)) { + rc = NXT_UNIT_ERROR; + break; + } - rc = nxt_unit_shared_port_recv(ctx, lib->shared_port, rbuf); - if (rc == NXT_UNIT_AGAIN) { - goto retry; - } + retry: - if (nxt_slow_path(rc == NXT_UNIT_ERROR)) { - nxt_unit_read_buf_release(ctx, rbuf); - break; - } + rc = nxt_unit_ctx_port_recv(ctx, ctx_impl->read_port, rbuf); + if (rc == NXT_UNIT_AGAIN) { + goto retry; + } - rc = nxt_unit_process_msg(ctx, rbuf, NULL); - if (nxt_slow_path(rc == NXT_UNIT_ERROR)) { - break; - } + rc = nxt_unit_process_msg(ctx, rbuf, NULL); + if (nxt_slow_path(rc == NXT_UNIT_ERROR)) { + break; } - nxt_unit_ctx_release(ctx); + rc = nxt_unit_process_pending_rbuf(ctx); + if (nxt_slow_path(rc == NXT_UNIT_ERROR)) { + break; + } - return rc; -} + nxt_unit_process_ready_req(ctx); + } + nxt_unit_ctx_release(ctx); -nxt_unit_request_info_t * -nxt_unit_dequeue_request(nxt_unit_ctx_t *ctx) -{ - int rc; - nxt_unit_impl_t *lib; - nxt_unit_read_buf_t *rbuf; - nxt_unit_request_info_t *req; + return rc; +} - nxt_unit_ctx_use(ctx); +nxt_inline int nxt_unit_is_read_queue(nxt_unit_read_buf_t *rbuf) { + nxt_port_msg_t *port_msg; - lib = nxt_container_of(ctx->unit, nxt_unit_impl_t, unit); + if (nxt_fast_path(rbuf->size == (ssize_t)sizeof(nxt_port_msg_t))) { + port_msg = (nxt_port_msg_t *)rbuf->buf; - req = NULL; + return port_msg->type == _NXT_PORT_MSG_READ_QUEUE; + } - if (nxt_slow_path(!nxt_unit_chk_ready(ctx))) { - goto done; - } + return 0; +} - rbuf = nxt_unit_read_buf_get(ctx); - if (nxt_slow_path(rbuf == NULL)) { - goto done; - } +nxt_inline int nxt_unit_is_read_socket(nxt_unit_read_buf_t *rbuf) { + if (nxt_fast_path(rbuf->size == 1)) { + return rbuf->buf[0] == _NXT_PORT_MSG_READ_SOCKET; + } - rc = nxt_unit_app_queue_recv(ctx, lib->shared_port, rbuf); - if (rc != NXT_UNIT_OK) { - nxt_unit_read_buf_release(ctx, rbuf); - goto done; - } + return 0; +} - (void) nxt_unit_process_msg(ctx, rbuf, &req); +nxt_inline int nxt_unit_is_shm_ack(nxt_unit_read_buf_t *rbuf) { + nxt_port_msg_t *port_msg; -done: + if (nxt_fast_path(rbuf->size == (ssize_t)sizeof(nxt_port_msg_t))) { + port_msg = (nxt_port_msg_t *)rbuf->buf; - nxt_unit_ctx_release(ctx); + return port_msg->type == _NXT_PORT_MSG_SHM_ACK; + } - return req; + return 0; } +nxt_inline int nxt_unit_is_quit(nxt_unit_read_buf_t *rbuf) { + nxt_port_msg_t *port_msg; -int -nxt_unit_process_port_msg(nxt_unit_ctx_t *ctx, nxt_unit_port_t *port) -{ - int rc; + if (nxt_fast_path(rbuf->size == (ssize_t)sizeof(nxt_port_msg_t))) { + port_msg = (nxt_port_msg_t *)rbuf->buf; - nxt_unit_ctx_use(ctx); + return port_msg->type == _NXT_PORT_MSG_QUIT; + } - rc = nxt_unit_process_port_msg_impl(ctx, port); - - nxt_unit_ctx_release(ctx); - - return rc; + return 0; } +int nxt_unit_run_shared(nxt_unit_ctx_t *ctx) { + int rc; + nxt_unit_impl_t *lib; + nxt_unit_read_buf_t *rbuf; -static int -nxt_unit_process_port_msg_impl(nxt_unit_ctx_t *ctx, nxt_unit_port_t *port) -{ - int rc; - nxt_unit_impl_t *lib; - nxt_unit_read_buf_t *rbuf; + nxt_unit_ctx_use(ctx); - lib = nxt_container_of(ctx->unit, nxt_unit_impl_t, unit); + lib = nxt_container_of(ctx->unit, nxt_unit_impl_t, unit); - if (port == lib->shared_port && !nxt_unit_chk_ready(ctx)) { - return NXT_UNIT_AGAIN; - } + rc = NXT_UNIT_OK; + while (nxt_fast_path(nxt_unit_chk_ready(ctx))) { rbuf = nxt_unit_read_buf_get(ctx); if (nxt_slow_path(rbuf == NULL)) { - return NXT_UNIT_ERROR; + rc = NXT_UNIT_ERROR; + break; } - if (port == lib->shared_port) { - rc = nxt_unit_shared_port_recv(ctx, port, rbuf); - - } else { - rc = nxt_unit_ctx_port_recv(ctx, port, rbuf); - } + retry: - if (rc != NXT_UNIT_OK) { - nxt_unit_read_buf_release(ctx, rbuf); - return rc; + rc = nxt_unit_shared_port_recv(ctx, lib->shared_port, rbuf); + if (rc == NXT_UNIT_AGAIN) { + goto retry; } - rc = nxt_unit_process_msg(ctx, rbuf, NULL); if (nxt_slow_path(rc == NXT_UNIT_ERROR)) { - return NXT_UNIT_ERROR; + nxt_unit_read_buf_release(ctx, rbuf); + break; } - rc = nxt_unit_process_pending_rbuf(ctx); + rc = nxt_unit_process_msg(ctx, rbuf, NULL); if (nxt_slow_path(rc == NXT_UNIT_ERROR)) { - return NXT_UNIT_ERROR; + break; } + } - nxt_unit_process_ready_req(ctx); + nxt_unit_ctx_release(ctx); - return rc; + return rc; } +nxt_unit_request_info_t *nxt_unit_dequeue_request(nxt_unit_ctx_t *ctx) { + int rc; + nxt_unit_impl_t *lib; + nxt_unit_read_buf_t *rbuf; + nxt_unit_request_info_t *req; -void -nxt_unit_done(nxt_unit_ctx_t *ctx) -{ - nxt_unit_ctx_release(ctx); -} - + nxt_unit_ctx_use(ctx); -nxt_unit_ctx_t * -nxt_unit_ctx_alloc(nxt_unit_ctx_t *ctx, void *data) -{ - int rc, queue_fd; - void *mem; - nxt_unit_impl_t *lib; - nxt_unit_port_t *port; - nxt_unit_ctx_impl_t *new_ctx; - nxt_unit_port_impl_t *port_impl; + lib = nxt_container_of(ctx->unit, nxt_unit_impl_t, unit); - lib = nxt_container_of(ctx->unit, nxt_unit_impl_t, unit); + req = NULL; - new_ctx = nxt_unit_malloc(ctx, sizeof(nxt_unit_ctx_impl_t) - + lib->request_data_size); - if (nxt_slow_path(new_ctx == NULL)) { - nxt_unit_alert(ctx, "failed to allocate context"); + if (nxt_slow_path(!nxt_unit_chk_ready(ctx))) { + goto done; + } - return NULL; - } + rbuf = nxt_unit_read_buf_get(ctx); + if (nxt_slow_path(rbuf == NULL)) { + goto done; + } - rc = nxt_unit_ctx_init(lib, new_ctx, data); - if (nxt_slow_path(rc != NXT_UNIT_OK)) { - nxt_unit_free(ctx, new_ctx); + rc = nxt_unit_app_queue_recv(ctx, lib->shared_port, rbuf); + if (rc != NXT_UNIT_OK) { + nxt_unit_read_buf_release(ctx, rbuf); + goto done; + } - return NULL; - } + (void)nxt_unit_process_msg(ctx, rbuf, &req); - queue_fd = -1; +done: - port = nxt_unit_create_port(&new_ctx->ctx); - if (nxt_slow_path(port == NULL)) { - goto fail; - } + nxt_unit_ctx_release(ctx); - new_ctx->read_port = port; + return req; +} - queue_fd = nxt_unit_shm_open(&new_ctx->ctx, sizeof(nxt_port_queue_t)); - if (nxt_slow_path(queue_fd == -1)) { - goto fail; - } +int nxt_unit_process_port_msg(nxt_unit_ctx_t *ctx, nxt_unit_port_t *port) { + int rc; - mem = mmap(NULL, sizeof(nxt_port_queue_t), - PROT_READ | PROT_WRITE, MAP_SHARED, queue_fd, 0); - if (nxt_slow_path(mem == MAP_FAILED)) { - nxt_unit_alert(ctx, "mmap(%d) failed: %s (%d)", queue_fd, - strerror(errno), errno); + nxt_unit_ctx_use(ctx); - goto fail; - } + rc = nxt_unit_process_port_msg_impl(ctx, port); - nxt_port_queue_init(mem); + nxt_unit_ctx_release(ctx); - port_impl = nxt_container_of(port, nxt_unit_port_impl_t, port); - port_impl->queue = mem; + return rc; +} - rc = nxt_unit_send_port(&new_ctx->ctx, lib->router_port, port, queue_fd); - if (nxt_slow_path(rc != NXT_UNIT_OK)) { - goto fail; - } +static int nxt_unit_process_port_msg_impl(nxt_unit_ctx_t *ctx, + nxt_unit_port_t *port) { + int rc; + nxt_unit_impl_t *lib; + nxt_unit_read_buf_t *rbuf; - nxt_unit_close(queue_fd); + lib = nxt_container_of(ctx->unit, nxt_unit_impl_t, unit); - return &new_ctx->ctx; + if (port == lib->shared_port && !nxt_unit_chk_ready(ctx)) { + return NXT_UNIT_AGAIN; + } -fail: + rbuf = nxt_unit_read_buf_get(ctx); + if (nxt_slow_path(rbuf == NULL)) { + return NXT_UNIT_ERROR; + } - if (queue_fd != -1) { - nxt_unit_close(queue_fd); - } + if (port == lib->shared_port) { + rc = nxt_unit_shared_port_recv(ctx, port, rbuf); - nxt_unit_ctx_release(&new_ctx->ctx); + } else { + rc = nxt_unit_ctx_port_recv(ctx, port, rbuf); + } - return NULL; -} + if (rc != NXT_UNIT_OK) { + nxt_unit_read_buf_release(ctx, rbuf); + return rc; + } + rc = nxt_unit_process_msg(ctx, rbuf, NULL); + if (nxt_slow_path(rc == NXT_UNIT_ERROR)) { + return NXT_UNIT_ERROR; + } -static void -nxt_unit_ctx_free(nxt_unit_ctx_impl_t *ctx_impl) -{ - nxt_unit_impl_t *lib; - nxt_unit_mmap_buf_t *mmap_buf; - nxt_unit_read_buf_t *rbuf; - nxt_unit_request_info_impl_t *req_impl; - nxt_unit_websocket_frame_impl_t *ws_impl; + rc = nxt_unit_process_pending_rbuf(ctx); + if (nxt_slow_path(rc == NXT_UNIT_ERROR)) { + return NXT_UNIT_ERROR; + } - lib = nxt_container_of(ctx_impl->ctx.unit, nxt_unit_impl_t, unit); + nxt_unit_process_ready_req(ctx); - nxt_queue_each(req_impl, &ctx_impl->active_req, - nxt_unit_request_info_impl_t, link) - { - nxt_unit_req_warn(&req_impl->req, "active request on ctx free"); + return rc; +} - nxt_unit_request_done(&req_impl->req, NXT_UNIT_ERROR); +void nxt_unit_done(nxt_unit_ctx_t *ctx) { nxt_unit_ctx_release(ctx); } - } nxt_queue_loop; +nxt_unit_ctx_t *nxt_unit_ctx_alloc(nxt_unit_ctx_t *ctx, void *data) { + int rc, queue_fd; + void *mem; + nxt_unit_impl_t *lib; + nxt_unit_port_t *port; + nxt_unit_ctx_impl_t *new_ctx; + nxt_unit_port_impl_t *port_impl; - nxt_unit_mmap_buf_unlink(&ctx_impl->ctx_buf[0]); - nxt_unit_mmap_buf_unlink(&ctx_impl->ctx_buf[1]); + lib = nxt_container_of(ctx->unit, nxt_unit_impl_t, unit); - while (ctx_impl->free_buf != NULL) { - mmap_buf = ctx_impl->free_buf; - nxt_unit_mmap_buf_unlink(mmap_buf); - nxt_unit_free(&ctx_impl->ctx, mmap_buf); - } + new_ctx = nxt_unit_malloc(ctx, sizeof(nxt_unit_ctx_impl_t) + + lib->request_data_size); + if (nxt_slow_path(new_ctx == NULL)) { + nxt_unit_alert(ctx, "failed to allocate context"); - nxt_queue_each(req_impl, &ctx_impl->free_req, - nxt_unit_request_info_impl_t, link) - { - nxt_unit_request_info_free(req_impl); + return NULL; + } - } nxt_queue_loop; + rc = nxt_unit_ctx_init(lib, new_ctx, data); + if (nxt_slow_path(rc != NXT_UNIT_OK)) { + nxt_unit_free(ctx, new_ctx); - nxt_queue_each(ws_impl, &ctx_impl->free_ws, - nxt_unit_websocket_frame_impl_t, link) - { - nxt_unit_websocket_frame_free(&ctx_impl->ctx, ws_impl); + return NULL; + } - } nxt_queue_loop; + queue_fd = -1; - nxt_queue_each(rbuf, &ctx_impl->free_rbuf, nxt_unit_read_buf_t, link) - { - if (rbuf != &ctx_impl->ctx_read_buf) { - nxt_unit_free(&ctx_impl->ctx, rbuf); - } - } nxt_queue_loop; + port = nxt_unit_create_port(&new_ctx->ctx); + if (nxt_slow_path(port == NULL)) { + goto fail; + } - pthread_mutex_destroy(&ctx_impl->mutex); + new_ctx->read_port = port; - pthread_mutex_lock(&lib->mutex); + queue_fd = nxt_unit_shm_open(&new_ctx->ctx, sizeof(nxt_port_queue_t)); + if (nxt_slow_path(queue_fd == -1)) { + goto fail; + } - nxt_queue_remove(&ctx_impl->link); + mem = mmap(NULL, sizeof(nxt_port_queue_t), PROT_READ | PROT_WRITE, MAP_SHARED, + queue_fd, 0); + if (nxt_slow_path(mem == MAP_FAILED)) { + nxt_unit_alert(ctx, "mmap(%d) failed: %s (%d)", queue_fd, strerror(errno), + errno); - pthread_mutex_unlock(&lib->mutex); + goto fail; + } - if (nxt_fast_path(ctx_impl->read_port != NULL)) { - nxt_unit_remove_port(lib, NULL, &ctx_impl->read_port->id); - nxt_unit_port_release(ctx_impl->read_port); - } + nxt_port_queue_init(mem); - if (ctx_impl != &lib->main_ctx) { - nxt_unit_free(&lib->main_ctx.ctx, ctx_impl); - } + port_impl = nxt_container_of(port, nxt_unit_port_impl_t, port); + port_impl->queue = mem; - nxt_unit_lib_release(lib); -} + rc = nxt_unit_send_port(&new_ctx->ctx, lib->router_port, port, queue_fd); + if (nxt_slow_path(rc != NXT_UNIT_OK)) { + goto fail; + } + nxt_unit_close(queue_fd); -/* SOCK_SEQPACKET is disabled to test SOCK_DGRAM on all platforms. */ -#if (0 || NXT_HAVE_AF_UNIX_SOCK_SEQPACKET) -#define NXT_UNIX_SOCKET SOCK_SEQPACKET -#else -#define NXT_UNIX_SOCKET SOCK_DGRAM -#endif + return &new_ctx->ctx; +fail: -void -nxt_unit_port_id_init(nxt_unit_port_id_t *port_id, pid_t pid, uint16_t id) -{ - nxt_unit_port_hash_id_t port_hash_id; + if (queue_fd != -1) { + nxt_unit_close(queue_fd); + } - port_hash_id.pid = pid; - port_hash_id.id = id; + nxt_unit_ctx_release(&new_ctx->ctx); - port_id->pid = pid; - port_id->hash = nxt_murmur_hash2(&port_hash_id, sizeof(port_hash_id)); - port_id->id = id; + return NULL; } +static void nxt_unit_ctx_free(nxt_unit_ctx_impl_t *ctx_impl) { + nxt_unit_impl_t *lib; + nxt_unit_mmap_buf_t *mmap_buf; + nxt_unit_read_buf_t *rbuf; + nxt_unit_request_info_impl_t *req_impl; + nxt_unit_websocket_frame_impl_t *ws_impl; -static nxt_unit_port_t * -nxt_unit_create_port(nxt_unit_ctx_t *ctx) -{ - int rc, port_sockets[2]; - nxt_unit_impl_t *lib; - nxt_unit_port_t new_port, *port; - nxt_unit_process_t *process; - - lib = nxt_container_of(ctx->unit, nxt_unit_impl_t, unit); - - rc = socketpair(AF_UNIX, NXT_UNIX_SOCKET, 0, port_sockets); - if (nxt_slow_path(rc != 0)) { - nxt_unit_warn(ctx, "create_port: socketpair() failed: %s (%d)", - strerror(errno), errno); - - return NULL; - } - -#if (NXT_HAVE_SOCKOPT_SO_PASSCRED) - int enable_creds = 1; + lib = nxt_container_of(ctx_impl->ctx.unit, nxt_unit_impl_t, unit); - if (nxt_slow_path(setsockopt(port_sockets[0], SOL_SOCKET, SO_PASSCRED, - &enable_creds, sizeof(enable_creds)) == -1)) - { - nxt_unit_warn(ctx, "failed to set SO_PASSCRED %s", strerror(errno)); - return NULL; - } + nxt_queue_each(req_impl, &ctx_impl->active_req, nxt_unit_request_info_impl_t, + link) { + nxt_unit_req_warn(&req_impl->req, "active request on ctx free"); - if (nxt_slow_path(setsockopt(port_sockets[1], SOL_SOCKET, SO_PASSCRED, - &enable_creds, sizeof(enable_creds)) == -1)) - { - nxt_unit_warn(ctx, "failed to set SO_PASSCRED %s", strerror(errno)); - return NULL; - } -#endif + nxt_unit_request_done(&req_impl->req, NXT_UNIT_ERROR); + } + nxt_queue_loop; - nxt_unit_debug(ctx, "create_port: new socketpair: %d->%d", - port_sockets[0], port_sockets[1]); + nxt_unit_mmap_buf_unlink(&ctx_impl->ctx_buf[0]); + nxt_unit_mmap_buf_unlink(&ctx_impl->ctx_buf[1]); - pthread_mutex_lock(&lib->mutex); + while (ctx_impl->free_buf != NULL) { + mmap_buf = ctx_impl->free_buf; + nxt_unit_mmap_buf_unlink(mmap_buf); + nxt_unit_free(&ctx_impl->ctx, mmap_buf); + } - process = nxt_unit_process_get(ctx, lib->pid); - if (nxt_slow_path(process == NULL)) { - pthread_mutex_unlock(&lib->mutex); + nxt_queue_each(req_impl, &ctx_impl->free_req, nxt_unit_request_info_impl_t, + link) { + nxt_unit_request_info_free(req_impl); + } + nxt_queue_loop; - nxt_unit_close(port_sockets[0]); - nxt_unit_close(port_sockets[1]); + nxt_queue_each(ws_impl, &ctx_impl->free_ws, nxt_unit_websocket_frame_impl_t, + link) { + nxt_unit_websocket_frame_free(&ctx_impl->ctx, ws_impl); + } + nxt_queue_loop; - return NULL; + nxt_queue_each(rbuf, &ctx_impl->free_rbuf, nxt_unit_read_buf_t, link) { + if (rbuf != &ctx_impl->ctx_read_buf) { + nxt_unit_free(&ctx_impl->ctx, rbuf); } + } + nxt_queue_loop; - nxt_unit_port_id_init(&new_port.id, lib->pid, process->next_port_id++); + pthread_mutex_destroy(&ctx_impl->mutex); - new_port.in_fd = port_sockets[0]; - new_port.out_fd = port_sockets[1]; - new_port.data = NULL; + pthread_mutex_lock(&lib->mutex); - pthread_mutex_unlock(&lib->mutex); + nxt_queue_remove(&ctx_impl->link); - nxt_unit_process_release(process); + pthread_mutex_unlock(&lib->mutex); - port = nxt_unit_add_port(ctx, &new_port, NULL); - if (nxt_slow_path(port == NULL)) { - nxt_unit_close(port_sockets[0]); - nxt_unit_close(port_sockets[1]); - } + if (nxt_fast_path(ctx_impl->read_port != NULL)) { + nxt_unit_remove_port(lib, NULL, &ctx_impl->read_port->id); + nxt_unit_port_release(ctx_impl->read_port); + } - return port; -} + if (ctx_impl != &lib->main_ctx) { + nxt_unit_free(&lib->main_ctx.ctx, ctx_impl); + } + nxt_unit_lib_release(lib); +} -static int -nxt_unit_send_port(nxt_unit_ctx_t *ctx, nxt_unit_port_t *dst, - nxt_unit_port_t *port, int queue_fd) -{ - ssize_t res; - nxt_send_oob_t oob; - nxt_unit_impl_t *lib; - int fds[2] = { port->out_fd, queue_fd }; +/* SOCK_SEQPACKET is disabled to test SOCK_DGRAM on all platforms. */ +#if (0 || NXT_HAVE_AF_UNIX_SOCK_SEQPACKET) +#define NXT_UNIX_SOCKET SOCK_SEQPACKET +#else +#define NXT_UNIX_SOCKET SOCK_DGRAM +#endif - struct { - nxt_port_msg_t msg; - nxt_port_msg_new_port_t new_port; - } m; +void nxt_unit_port_id_init(nxt_unit_port_id_t *port_id, pid_t pid, + uint16_t id) { + nxt_unit_port_hash_id_t port_hash_id; - lib = nxt_container_of(ctx->unit, nxt_unit_impl_t, unit); + port_hash_id.pid = pid; + port_hash_id.id = id; - m.msg.stream = 0; - m.msg.pid = lib->pid; - m.msg.reply_port = 0; - m.msg.type = _NXT_PORT_MSG_NEW_PORT; - m.msg.last = 0; - m.msg.mmap = 0; - m.msg.nf = 0; - m.msg.mf = 0; + port_id->pid = pid; + port_id->hash = nxt_murmur_hash2(&port_hash_id, sizeof(port_hash_id)); + port_id->id = id; +} - m.new_port.id = port->id.id; - m.new_port.pid = port->id.pid; - m.new_port.type = NXT_PROCESS_APP; - m.new_port.max_size = 16 * 1024; - m.new_port.max_share = 64 * 1024; +static nxt_unit_port_t *nxt_unit_create_port(nxt_unit_ctx_t *ctx) { + int rc, port_sockets[2]; + nxt_unit_impl_t *lib; + nxt_unit_port_t new_port, *port; + nxt_unit_process_t *process; - nxt_socket_msg_oob_init(&oob, fds); + lib = nxt_container_of(ctx->unit, nxt_unit_impl_t, unit); - res = nxt_unit_port_send(ctx, dst, &m, sizeof(m), &oob); + rc = socketpair(AF_UNIX, NXT_UNIX_SOCKET, 0, port_sockets); + if (nxt_slow_path(rc != 0)) { + nxt_unit_warn(ctx, "create_port: socketpair() failed: %s (%d)", + strerror(errno), errno); - return (res == sizeof(m)) ? NXT_UNIT_OK : NXT_UNIT_ERROR; -} + return NULL; + } +#if (NXT_HAVE_SOCKOPT_SO_PASSCRED) + int enable_creds = 1; -nxt_inline void nxt_unit_port_use(nxt_unit_port_t *port) -{ - nxt_unit_port_impl_t *port_impl; + if (nxt_slow_path(setsockopt(port_sockets[0], SOL_SOCKET, SO_PASSCRED, + &enable_creds, sizeof(enable_creds)) == -1)) { + nxt_unit_warn(ctx, "failed to set SO_PASSCRED %s", strerror(errno)); + return NULL; + } - port_impl = nxt_container_of(port, nxt_unit_port_impl_t, port); + if (nxt_slow_path(setsockopt(port_sockets[1], SOL_SOCKET, SO_PASSCRED, + &enable_creds, sizeof(enable_creds)) == -1)) { + nxt_unit_warn(ctx, "failed to set SO_PASSCRED %s", strerror(errno)); + return NULL; + } +#endif - nxt_atomic_fetch_add(&port_impl->use_count, 1); -} + nxt_unit_debug(ctx, "create_port: new socketpair: %d->%d", port_sockets[0], + port_sockets[1]); + pthread_mutex_lock(&lib->mutex); -nxt_inline void nxt_unit_port_release(nxt_unit_port_t *port) -{ - long c; - nxt_unit_port_impl_t *port_impl; + process = nxt_unit_process_get(ctx, lib->pid); + if (nxt_slow_path(process == NULL)) { + pthread_mutex_unlock(&lib->mutex); - port_impl = nxt_container_of(port, nxt_unit_port_impl_t, port); + nxt_unit_close(port_sockets[0]); + nxt_unit_close(port_sockets[1]); - c = nxt_atomic_fetch_add(&port_impl->use_count, -1); + return NULL; + } - if (c == 1) { - nxt_unit_debug(NULL, "destroy port{%d,%d} in_fd %d out_fd %d", - (int) port->id.pid, (int) port->id.id, - port->in_fd, port->out_fd); + nxt_unit_port_id_init(&new_port.id, lib->pid, process->next_port_id++); - nxt_unit_process_release(port_impl->process); + new_port.in_fd = port_sockets[0]; + new_port.out_fd = port_sockets[1]; + new_port.data = NULL; - if (port->in_fd != -1) { - nxt_unit_close(port->in_fd); + pthread_mutex_unlock(&lib->mutex); - port->in_fd = -1; - } + nxt_unit_process_release(process); - if (port->out_fd != -1) { - nxt_unit_close(port->out_fd); + port = nxt_unit_add_port(ctx, &new_port, NULL); + if (nxt_slow_path(port == NULL)) { + nxt_unit_close(port_sockets[0]); + nxt_unit_close(port_sockets[1]); + } - port->out_fd = -1; - } + return port; +} - if (port_impl->queue != NULL) { - munmap(port_impl->queue, (port->id.id == NXT_UNIT_SHARED_PORT_ID) - ? sizeof(nxt_app_queue_t) - : sizeof(nxt_port_queue_t)); - } +static int nxt_unit_send_port(nxt_unit_ctx_t *ctx, nxt_unit_port_t *dst, + nxt_unit_port_t *port, int queue_fd) { + ssize_t res; + nxt_send_oob_t oob; + nxt_unit_impl_t *lib; + int fds[2] = {port->out_fd, queue_fd}; - nxt_unit_free(NULL, port_impl); - } -} + struct { + nxt_port_msg_t msg; + nxt_port_msg_new_port_t new_port; + } m; + lib = nxt_container_of(ctx->unit, nxt_unit_impl_t, unit); -static nxt_unit_port_t * -nxt_unit_add_port(nxt_unit_ctx_t *ctx, nxt_unit_port_t *port, void *queue) -{ - int rc, ready; - nxt_queue_t awaiting_req; - nxt_unit_impl_t *lib; - nxt_unit_port_t *old_port; - nxt_unit_process_t *process; - nxt_unit_port_impl_t *new_port, *old_port_impl; + m.msg.stream = 0; + m.msg.pid = lib->pid; + m.msg.reply_port = 0; + m.msg.type = _NXT_PORT_MSG_NEW_PORT; + m.msg.last = 0; + m.msg.mmap = 0; + m.msg.nf = 0; + m.msg.mf = 0; - lib = nxt_container_of(ctx->unit, nxt_unit_impl_t, unit); + m.new_port.id = port->id.id; + m.new_port.pid = port->id.pid; + m.new_port.type = NXT_PROCESS_APP; + m.new_port.max_size = 16 * 1024; + m.new_port.max_share = 64 * 1024; - pthread_mutex_lock(&lib->mutex); + nxt_socket_msg_oob_init(&oob, fds); - old_port = nxt_unit_port_hash_find(&lib->ports, &port->id, 0); + res = nxt_unit_port_send(ctx, dst, &m, sizeof(m), &oob); - if (nxt_slow_path(old_port != NULL)) { - nxt_unit_debug(ctx, "add_port: duplicate port{%d,%d} " - "in_fd %d out_fd %d queue %p", - port->id.pid, port->id.id, - port->in_fd, port->out_fd, queue); + return (res == sizeof(m)) ? NXT_UNIT_OK : NXT_UNIT_ERROR; +} - if (old_port->data == NULL) { - old_port->data = port->data; - port->data = NULL; - } +nxt_inline void nxt_unit_port_use(nxt_unit_port_t *port) { + nxt_unit_port_impl_t *port_impl; - if (old_port->in_fd == -1) { - old_port->in_fd = port->in_fd; - port->in_fd = -1; - } + port_impl = nxt_container_of(port, nxt_unit_port_impl_t, port); - if (port->in_fd != -1) { - nxt_unit_close(port->in_fd); - port->in_fd = -1; - } + nxt_atomic_fetch_add(&port_impl->use_count, 1); +} - if (old_port->out_fd == -1) { - old_port->out_fd = port->out_fd; - port->out_fd = -1; - } +nxt_inline void nxt_unit_port_release(nxt_unit_port_t *port) { + long c; + nxt_unit_port_impl_t *port_impl; - if (port->out_fd != -1) { - nxt_unit_close(port->out_fd); - port->out_fd = -1; - } + port_impl = nxt_container_of(port, nxt_unit_port_impl_t, port); - *port = *old_port; + c = nxt_atomic_fetch_add(&port_impl->use_count, -1); - nxt_queue_init(&awaiting_req); + if (c == 1) { + nxt_unit_debug(NULL, "destroy port{%d,%d} in_fd %d out_fd %d", + (int)port->id.pid, (int)port->id.id, port->in_fd, + port->out_fd); - old_port_impl = nxt_container_of(old_port, nxt_unit_port_impl_t, port); + nxt_unit_process_release(port_impl->process); - if (old_port_impl->queue == NULL) { - old_port_impl->queue = queue; - } + if (port->in_fd != -1) { + nxt_unit_close(port->in_fd); - ready = (port->in_fd != -1 || port->out_fd != -1); + port->in_fd = -1; + } - /* - * Port can be market as 'ready' only after callbacks.add_port() call. - * Otherwise, request may try to use the port before callback. - */ - if (lib->callbacks.add_port == NULL && ready) { - old_port_impl->ready = ready; + if (port->out_fd != -1) { + nxt_unit_close(port->out_fd); - if (!nxt_queue_is_empty(&old_port_impl->awaiting_req)) { - nxt_queue_add(&awaiting_req, &old_port_impl->awaiting_req); - nxt_queue_init(&old_port_impl->awaiting_req); - } - } + port->out_fd = -1; + } - pthread_mutex_unlock(&lib->mutex); + if (port_impl->queue != NULL) { + munmap(port_impl->queue, (port->id.id == NXT_UNIT_SHARED_PORT_ID) + ? sizeof(nxt_app_queue_t) + : sizeof(nxt_port_queue_t)); + } - if (lib->callbacks.add_port != NULL && ready) { - lib->callbacks.add_port(ctx, old_port); + nxt_unit_free(NULL, port_impl); + } +} - pthread_mutex_lock(&lib->mutex); +static nxt_unit_port_t *nxt_unit_add_port(nxt_unit_ctx_t *ctx, + nxt_unit_port_t *port, void *queue) { + int rc, ready; + nxt_queue_t awaiting_req; + nxt_unit_impl_t *lib; + nxt_unit_port_t *old_port; + nxt_unit_process_t *process; + nxt_unit_port_impl_t *new_port, *old_port_impl; - old_port_impl->ready = ready; + lib = nxt_container_of(ctx->unit, nxt_unit_impl_t, unit); - if (!nxt_queue_is_empty(&old_port_impl->awaiting_req)) { - nxt_queue_add(&awaiting_req, &old_port_impl->awaiting_req); - nxt_queue_init(&old_port_impl->awaiting_req); - } + pthread_mutex_lock(&lib->mutex); - pthread_mutex_unlock(&lib->mutex); - } + old_port = nxt_unit_port_hash_find(&lib->ports, &port->id, 0); - nxt_unit_process_awaiting_req(ctx, &awaiting_req); + if (nxt_slow_path(old_port != NULL)) { + nxt_unit_debug(ctx, + "add_port: duplicate port{%d,%d} " + "in_fd %d out_fd %d queue %p", + port->id.pid, port->id.id, port->in_fd, port->out_fd, queue); - return old_port; + if (old_port->data == NULL) { + old_port->data = port->data; + port->data = NULL; } - new_port = NULL; - ready = 0; + if (old_port->in_fd == -1) { + old_port->in_fd = port->in_fd; + port->in_fd = -1; + } - nxt_unit_debug(ctx, "add_port: port{%d,%d} in_fd %d out_fd %d queue %p", - port->id.pid, port->id.id, - port->in_fd, port->out_fd, queue); + if (port->in_fd != -1) { + nxt_unit_close(port->in_fd); + port->in_fd = -1; + } - process = nxt_unit_process_get(ctx, port->id.pid); - if (nxt_slow_path(process == NULL)) { - goto unlock; + if (old_port->out_fd == -1) { + old_port->out_fd = port->out_fd; + port->out_fd = -1; } - if (port->id.id != NXT_UNIT_SHARED_PORT_ID - && port->id.id >= process->next_port_id) - { - process->next_port_id = port->id.id + 1; + if (port->out_fd != -1) { + nxt_unit_close(port->out_fd); + port->out_fd = -1; } - new_port = nxt_unit_malloc(ctx, sizeof(nxt_unit_port_impl_t)); - if (nxt_slow_path(new_port == NULL)) { - nxt_unit_alert(ctx, "add_port: %d,%d malloc() failed", - port->id.pid, port->id.id); + *port = *old_port; - goto unlock; - } + nxt_queue_init(&awaiting_req); - new_port->port = *port; + old_port_impl = nxt_container_of(old_port, nxt_unit_port_impl_t, port); - rc = nxt_unit_port_hash_add(&lib->ports, &new_port->port); - if (nxt_slow_path(rc != NXT_UNIT_OK)) { - nxt_unit_alert(ctx, "add_port: %d,%d hash_add failed", - port->id.pid, port->id.id); + if (old_port_impl->queue == NULL) { + old_port_impl->queue = queue; + } - nxt_unit_free(ctx, new_port); + ready = (port->in_fd != -1 || port->out_fd != -1); - new_port = NULL; + /* + * Port can be market as 'ready' only after callbacks.add_port() call. + * Otherwise, request may try to use the port before callback. + */ + if (lib->callbacks.add_port == NULL && ready) { + old_port_impl->ready = ready; - goto unlock; + if (!nxt_queue_is_empty(&old_port_impl->awaiting_req)) { + nxt_queue_add(&awaiting_req, &old_port_impl->awaiting_req); + nxt_queue_init(&old_port_impl->awaiting_req); + } } - nxt_queue_insert_tail(&process->ports, &new_port->link); + pthread_mutex_unlock(&lib->mutex); - new_port->use_count = 2; - new_port->process = process; - new_port->queue = queue; - new_port->from_socket = 0; - new_port->socket_rbuf = NULL; + if (lib->callbacks.add_port != NULL && ready) { + lib->callbacks.add_port(ctx, old_port); - nxt_queue_init(&new_port->awaiting_req); + pthread_mutex_lock(&lib->mutex); - ready = (port->in_fd != -1 || port->out_fd != -1); + old_port_impl->ready = ready; - if (lib->callbacks.add_port == NULL) { - new_port->ready = ready; + if (!nxt_queue_is_empty(&old_port_impl->awaiting_req)) { + nxt_queue_add(&awaiting_req, &old_port_impl->awaiting_req); + nxt_queue_init(&old_port_impl->awaiting_req); + } - } else { - new_port->ready = 0; + pthread_mutex_unlock(&lib->mutex); } - process = NULL; + nxt_unit_process_awaiting_req(ctx, &awaiting_req); -unlock: + return old_port; + } - pthread_mutex_unlock(&lib->mutex); + new_port = NULL; + ready = 0; - if (nxt_slow_path(process != NULL)) { - nxt_unit_process_release(process); - } + nxt_unit_debug(ctx, "add_port: port{%d,%d} in_fd %d out_fd %d queue %p", + port->id.pid, port->id.id, port->in_fd, port->out_fd, queue); - if (lib->callbacks.add_port != NULL && new_port != NULL && ready) { - lib->callbacks.add_port(ctx, &new_port->port); + process = nxt_unit_process_get(ctx, port->id.pid); + if (nxt_slow_path(process == NULL)) { + goto unlock; + } - nxt_queue_init(&awaiting_req); + if (port->id.id != NXT_UNIT_SHARED_PORT_ID && + port->id.id >= process->next_port_id) { + process->next_port_id = port->id.id + 1; + } - pthread_mutex_lock(&lib->mutex); + new_port = nxt_unit_malloc(ctx, sizeof(nxt_unit_port_impl_t)); + if (nxt_slow_path(new_port == NULL)) { + nxt_unit_alert(ctx, "add_port: %d,%d malloc() failed", port->id.pid, + port->id.id); - new_port->ready = 1; + goto unlock; + } - if (!nxt_queue_is_empty(&new_port->awaiting_req)) { - nxt_queue_add(&awaiting_req, &new_port->awaiting_req); - nxt_queue_init(&new_port->awaiting_req); - } + new_port->port = *port; - pthread_mutex_unlock(&lib->mutex); + rc = nxt_unit_port_hash_add(&lib->ports, &new_port->port); + if (nxt_slow_path(rc != NXT_UNIT_OK)) { + nxt_unit_alert(ctx, "add_port: %d,%d hash_add failed", port->id.pid, + port->id.id); - nxt_unit_process_awaiting_req(ctx, &awaiting_req); - } + nxt_unit_free(ctx, new_port); - return (new_port == NULL) ? NULL : &new_port->port; -} + new_port = NULL; + goto unlock; + } -static void -nxt_unit_process_awaiting_req(nxt_unit_ctx_t *ctx, nxt_queue_t *awaiting_req) -{ - nxt_unit_ctx_impl_t *ctx_impl; - nxt_unit_request_info_impl_t *req_impl; + nxt_queue_insert_tail(&process->ports, &new_port->link); - nxt_queue_each(req_impl, awaiting_req, - nxt_unit_request_info_impl_t, port_wait_link) - { - nxt_queue_remove(&req_impl->port_wait_link); + new_port->use_count = 2; + new_port->process = process; + new_port->queue = queue; + new_port->from_socket = 0; + new_port->socket_rbuf = NULL; - ctx_impl = nxt_container_of(req_impl->req.ctx, nxt_unit_ctx_impl_t, - ctx); + nxt_queue_init(&new_port->awaiting_req); - pthread_mutex_lock(&ctx_impl->mutex); + ready = (port->in_fd != -1 || port->out_fd != -1); - nxt_queue_insert_tail(&ctx_impl->ready_req, - &req_impl->port_wait_link); + if (lib->callbacks.add_port == NULL) { + new_port->ready = ready; - pthread_mutex_unlock(&ctx_impl->mutex); + } else { + new_port->ready = 0; + } - nxt_atomic_fetch_add(&ctx_impl->wait_items, -1); + process = NULL; + +unlock: - nxt_unit_awake_ctx(ctx, ctx_impl); + pthread_mutex_unlock(&lib->mutex); - } nxt_queue_loop; -} + if (nxt_slow_path(process != NULL)) { + nxt_unit_process_release(process); + } + if (lib->callbacks.add_port != NULL && new_port != NULL && ready) { + lib->callbacks.add_port(ctx, &new_port->port); -static void -nxt_unit_remove_port(nxt_unit_impl_t *lib, nxt_unit_ctx_t *ctx, - nxt_unit_port_id_t *port_id) -{ - nxt_unit_port_t *port; - nxt_unit_port_impl_t *port_impl; + nxt_queue_init(&awaiting_req); pthread_mutex_lock(&lib->mutex); - port = nxt_unit_remove_port_unsafe(lib, port_id); - - if (nxt_fast_path(port != NULL)) { - port_impl = nxt_container_of(port, nxt_unit_port_impl_t, port); + new_port->ready = 1; - nxt_queue_remove(&port_impl->link); + if (!nxt_queue_is_empty(&new_port->awaiting_req)) { + nxt_queue_add(&awaiting_req, &new_port->awaiting_req); + nxt_queue_init(&new_port->awaiting_req); } pthread_mutex_unlock(&lib->mutex); - if (lib->callbacks.remove_port != NULL && port != NULL) { - lib->callbacks.remove_port(&lib->unit, ctx, port); - } + nxt_unit_process_awaiting_req(ctx, &awaiting_req); + } - if (nxt_fast_path(port != NULL)) { - nxt_unit_port_release(port); - } + return (new_port == NULL) ? NULL : &new_port->port; } +static void nxt_unit_process_awaiting_req(nxt_unit_ctx_t *ctx, + nxt_queue_t *awaiting_req) { + nxt_unit_ctx_impl_t *ctx_impl; + nxt_unit_request_info_impl_t *req_impl; -static nxt_unit_port_t * -nxt_unit_remove_port_unsafe(nxt_unit_impl_t *lib, nxt_unit_port_id_t *port_id) -{ - nxt_unit_port_t *port; + nxt_queue_each(req_impl, awaiting_req, nxt_unit_request_info_impl_t, + port_wait_link) { + nxt_queue_remove(&req_impl->port_wait_link); - port = nxt_unit_port_hash_find(&lib->ports, port_id, 1); - if (nxt_slow_path(port == NULL)) { - nxt_unit_debug(NULL, "remove_port: port{%d,%d} not found", - (int) port_id->pid, (int) port_id->id); + ctx_impl = nxt_container_of(req_impl->req.ctx, nxt_unit_ctx_impl_t, ctx); - return NULL; - } + pthread_mutex_lock(&ctx_impl->mutex); + + nxt_queue_insert_tail(&ctx_impl->ready_req, &req_impl->port_wait_link); - nxt_unit_debug(NULL, "remove_port: port{%d,%d}, fds %d,%d, data %p", - (int) port_id->pid, (int) port_id->id, - port->in_fd, port->out_fd, port->data); + pthread_mutex_unlock(&ctx_impl->mutex); + + nxt_atomic_fetch_add(&ctx_impl->wait_items, -1); - return port; + nxt_unit_awake_ctx(ctx, ctx_impl); + } + nxt_queue_loop; } +static void nxt_unit_remove_port(nxt_unit_impl_t *lib, nxt_unit_ctx_t *ctx, + nxt_unit_port_id_t *port_id) { + nxt_unit_port_t *port; + nxt_unit_port_impl_t *port_impl; -static void -nxt_unit_remove_pid(nxt_unit_impl_t *lib, pid_t pid) -{ - nxt_unit_process_t *process; + pthread_mutex_lock(&lib->mutex); - pthread_mutex_lock(&lib->mutex); + port = nxt_unit_remove_port_unsafe(lib, port_id); - process = nxt_unit_process_find(lib, pid, 1); - if (nxt_slow_path(process == NULL)) { - nxt_unit_debug(NULL, "remove_pid: process %d not found", (int) pid); + if (nxt_fast_path(port != NULL)) { + port_impl = nxt_container_of(port, nxt_unit_port_impl_t, port); - pthread_mutex_unlock(&lib->mutex); + nxt_queue_remove(&port_impl->link); + } - return; - } + pthread_mutex_unlock(&lib->mutex); - nxt_unit_remove_process(lib, process); + if (lib->callbacks.remove_port != NULL && port != NULL) { + lib->callbacks.remove_port(&lib->unit, ctx, port); + } - if (lib->callbacks.remove_pid != NULL) { - lib->callbacks.remove_pid(&lib->unit, pid); - } + if (nxt_fast_path(port != NULL)) { + nxt_unit_port_release(port); + } } +static nxt_unit_port_t * +nxt_unit_remove_port_unsafe(nxt_unit_impl_t *lib, nxt_unit_port_id_t *port_id) { + nxt_unit_port_t *port; -static void -nxt_unit_remove_process(nxt_unit_impl_t *lib, nxt_unit_process_t *process) -{ - nxt_queue_t ports; - nxt_unit_port_impl_t *port; + port = nxt_unit_port_hash_find(&lib->ports, port_id, 1); + if (nxt_slow_path(port == NULL)) { + nxt_unit_debug(NULL, "remove_port: port{%d,%d} not found", + (int)port_id->pid, (int)port_id->id); - nxt_queue_init(&ports); + return NULL; + } + + nxt_unit_debug(NULL, "remove_port: port{%d,%d}, fds %d,%d, data %p", + (int)port_id->pid, (int)port_id->id, port->in_fd, port->out_fd, + port->data); - nxt_queue_add(&ports, &process->ports); + return port; +} - nxt_queue_each(port, &ports, nxt_unit_port_impl_t, link) { +static void nxt_unit_remove_pid(nxt_unit_impl_t *lib, pid_t pid) { + nxt_unit_process_t *process; - nxt_unit_remove_port_unsafe(lib, &port->port.id); + pthread_mutex_lock(&lib->mutex); - } nxt_queue_loop; + process = nxt_unit_process_find(lib, pid, 1); + if (nxt_slow_path(process == NULL)) { + nxt_unit_debug(NULL, "remove_pid: process %d not found", (int)pid); pthread_mutex_unlock(&lib->mutex); - nxt_queue_each(port, &ports, nxt_unit_port_impl_t, link) { + return; + } - nxt_queue_remove(&port->link); + nxt_unit_remove_process(lib, process); - if (lib->callbacks.remove_port != NULL) { - lib->callbacks.remove_port(&lib->unit, NULL, &port->port); - } + if (lib->callbacks.remove_pid != NULL) { + lib->callbacks.remove_pid(&lib->unit, pid); + } +} - nxt_unit_port_release(&port->port); +static void nxt_unit_remove_process(nxt_unit_impl_t *lib, + nxt_unit_process_t *process) { + nxt_queue_t ports; + nxt_unit_port_impl_t *port; - } nxt_queue_loop; + nxt_queue_init(&ports); - nxt_unit_process_release(process); -} + nxt_queue_add(&ports, &process->ports); + nxt_queue_each(port, &ports, nxt_unit_port_impl_t, link) { -static void -nxt_unit_quit(nxt_unit_ctx_t *ctx, uint8_t quit_param) -{ - nxt_bool_t skip_graceful_broadcast, quit; - nxt_unit_impl_t *lib; - nxt_unit_ctx_impl_t *ctx_impl; - nxt_unit_callbacks_t *cb; - nxt_unit_request_info_t *req; - nxt_unit_request_info_impl_t *req_impl; - - struct { - nxt_port_msg_t msg; - uint8_t quit_param; - } nxt_packed m; + nxt_unit_remove_port_unsafe(lib, &port->port.id); + } + nxt_queue_loop; - lib = nxt_container_of(ctx->unit, nxt_unit_impl_t, unit); - ctx_impl = nxt_container_of(ctx, nxt_unit_ctx_impl_t, ctx); + pthread_mutex_unlock(&lib->mutex); - nxt_unit_debug(ctx, "quit: %d/%d/%d", (int) quit_param, ctx_impl->ready, - ctx_impl->online); + nxt_queue_each(port, &ports, nxt_unit_port_impl_t, link) { - if (nxt_slow_path(!ctx_impl->online)) { - return; + nxt_queue_remove(&port->link); + + if (lib->callbacks.remove_port != NULL) { + lib->callbacks.remove_port(&lib->unit, NULL, &port->port); } - skip_graceful_broadcast = quit_param == NXT_QUIT_GRACEFUL - && !ctx_impl->ready; + nxt_unit_port_release(&port->port); + } + nxt_queue_loop; + + nxt_unit_process_release(process); +} - cb = &lib->callbacks; +static void nxt_unit_quit(nxt_unit_ctx_t *ctx, uint8_t quit_param) { + nxt_bool_t skip_graceful_broadcast, quit; + nxt_unit_impl_t *lib; + nxt_unit_ctx_impl_t *ctx_impl; + nxt_unit_callbacks_t *cb; + nxt_unit_request_info_t *req; + nxt_unit_request_info_impl_t *req_impl; - if (nxt_fast_path(ctx_impl->ready)) { - ctx_impl->ready = 0; + struct { + nxt_port_msg_t msg; + uint8_t quit_param; + } nxt_packed m; - if (cb->remove_port != NULL) { - cb->remove_port(&lib->unit, ctx, lib->shared_port); - } - } + lib = nxt_container_of(ctx->unit, nxt_unit_impl_t, unit); + ctx_impl = nxt_container_of(ctx, nxt_unit_ctx_impl_t, ctx); - if (quit_param == NXT_QUIT_GRACEFUL) { - pthread_mutex_lock(&ctx_impl->mutex); + nxt_unit_debug(ctx, "quit: %d/%d/%d", (int)quit_param, ctx_impl->ready, + ctx_impl->online); - quit = nxt_queue_is_empty(&ctx_impl->active_req) - && nxt_queue_is_empty(&ctx_impl->pending_rbuf) - && ctx_impl->wait_items == 0; + if (nxt_slow_path(!ctx_impl->online)) { + return; + } - pthread_mutex_unlock(&ctx_impl->mutex); + skip_graceful_broadcast = quit_param == NXT_QUIT_GRACEFUL && !ctx_impl->ready; - } else { - quit = 1; - ctx_impl->quit_param = NXT_QUIT_GRACEFUL; + cb = &lib->callbacks; + + if (nxt_fast_path(ctx_impl->ready)) { + ctx_impl->ready = 0; + + if (cb->remove_port != NULL) { + cb->remove_port(&lib->unit, ctx, lib->shared_port); } + } + + if (quit_param == NXT_QUIT_GRACEFUL) { + pthread_mutex_lock(&ctx_impl->mutex); - if (quit) { - ctx_impl->online = 0; + quit = nxt_queue_is_empty(&ctx_impl->active_req) && + nxt_queue_is_empty(&ctx_impl->pending_rbuf) && + ctx_impl->wait_items == 0; - if (cb->quit != NULL) { - cb->quit(ctx); - } + pthread_mutex_unlock(&ctx_impl->mutex); + + } else { + quit = 1; + ctx_impl->quit_param = NXT_QUIT_GRACEFUL; + } - nxt_queue_each(req_impl, &ctx_impl->active_req, - nxt_unit_request_info_impl_t, link) - { - req = &req_impl->req; + if (quit) { + ctx_impl->online = 0; - nxt_unit_req_warn(req, "active request on ctx quit"); + if (cb->quit != NULL) { + cb->quit(ctx); + } - if (cb->close_handler) { - nxt_unit_req_debug(req, "close_handler"); + nxt_queue_each(req_impl, &ctx_impl->active_req, + nxt_unit_request_info_impl_t, link) { + req = &req_impl->req; - cb->close_handler(req); + nxt_unit_req_warn(req, "active request on ctx quit"); - } else { - nxt_unit_request_done(req, NXT_UNIT_ERROR); - } + if (cb->close_handler) { + nxt_unit_req_debug(req, "close_handler"); - } nxt_queue_loop; + cb->close_handler(req); - if (nxt_fast_path(ctx_impl->read_port != NULL)) { - nxt_unit_remove_port(lib, ctx, &ctx_impl->read_port->id); - } + } else { + nxt_unit_request_done(req, NXT_UNIT_ERROR); + } } + nxt_queue_loop; - if (ctx != &lib->main_ctx.ctx || skip_graceful_broadcast) { - return; + if (nxt_fast_path(ctx_impl->read_port != NULL)) { + nxt_unit_remove_port(lib, ctx, &ctx_impl->read_port->id); } + } - memset(&m.msg, 0, sizeof(nxt_port_msg_t)); + if (ctx != &lib->main_ctx.ctx || skip_graceful_broadcast) { + return; + } - m.msg.pid = lib->pid; - m.msg.type = _NXT_PORT_MSG_QUIT; - m.quit_param = quit_param; + memset(&m.msg, 0, sizeof(nxt_port_msg_t)); - pthread_mutex_lock(&lib->mutex); + m.msg.pid = lib->pid; + m.msg.type = _NXT_PORT_MSG_QUIT; + m.quit_param = quit_param; - nxt_queue_each(ctx_impl, &lib->contexts, nxt_unit_ctx_impl_t, link) { + pthread_mutex_lock(&lib->mutex); - if (ctx == &ctx_impl->ctx - || ctx_impl->read_port == NULL - || ctx_impl->read_port->out_fd == -1) - { - continue; - } + nxt_queue_each(ctx_impl, &lib->contexts, nxt_unit_ctx_impl_t, link) { - (void) nxt_unit_port_send(ctx, ctx_impl->read_port, - &m, sizeof(m), NULL); + if (ctx == &ctx_impl->ctx || ctx_impl->read_port == NULL || + ctx_impl->read_port->out_fd == -1) { + continue; + } - } nxt_queue_loop; + (void)nxt_unit_port_send(ctx, ctx_impl->read_port, &m, sizeof(m), NULL); + } + nxt_queue_loop; - pthread_mutex_unlock(&lib->mutex); + pthread_mutex_unlock(&lib->mutex); } +static int nxt_unit_get_port(nxt_unit_ctx_t *ctx, nxt_unit_port_id_t *port_id) { + ssize_t res; + nxt_unit_impl_t *lib; + nxt_unit_ctx_impl_t *ctx_impl; -static int -nxt_unit_get_port(nxt_unit_ctx_t *ctx, nxt_unit_port_id_t *port_id) -{ - ssize_t res; - nxt_unit_impl_t *lib; - nxt_unit_ctx_impl_t *ctx_impl; - - struct { - nxt_port_msg_t msg; - nxt_port_msg_get_port_t get_port; - } m; + struct { + nxt_port_msg_t msg; + nxt_port_msg_get_port_t get_port; + } m; - lib = nxt_container_of(ctx->unit, nxt_unit_impl_t, unit); - ctx_impl = nxt_container_of(ctx, nxt_unit_ctx_impl_t, ctx); + lib = nxt_container_of(ctx->unit, nxt_unit_impl_t, unit); + ctx_impl = nxt_container_of(ctx, nxt_unit_ctx_impl_t, ctx); - memset(&m.msg, 0, sizeof(nxt_port_msg_t)); + memset(&m.msg, 0, sizeof(nxt_port_msg_t)); - m.msg.pid = lib->pid; - m.msg.reply_port = ctx_impl->read_port->id.id; - m.msg.type = _NXT_PORT_MSG_GET_PORT; + m.msg.pid = lib->pid; + m.msg.reply_port = ctx_impl->read_port->id.id; + m.msg.type = _NXT_PORT_MSG_GET_PORT; - m.get_port.id = port_id->id; - m.get_port.pid = port_id->pid; + m.get_port.id = port_id->id; + m.get_port.pid = port_id->pid; - nxt_unit_debug(ctx, "get_port: %d %d", (int) port_id->pid, - (int) port_id->id); + nxt_unit_debug(ctx, "get_port: %d %d", (int)port_id->pid, (int)port_id->id); - res = nxt_unit_port_send(ctx, lib->router_port, &m, sizeof(m), NULL); - if (nxt_slow_path(res != sizeof(m))) { - return NXT_UNIT_ERROR; - } + res = nxt_unit_port_send(ctx, lib->router_port, &m, sizeof(m), NULL); + if (nxt_slow_path(res != sizeof(m))) { + return NXT_UNIT_ERROR; + } - return NXT_UNIT_OK; + return NXT_UNIT_OK; } +static ssize_t nxt_unit_port_send(nxt_unit_ctx_t *ctx, nxt_unit_port_t *port, + const void *buf, size_t buf_size, + const nxt_send_oob_t *oob) { + int notify; + ssize_t ret; + nxt_int_t rc; + nxt_port_msg_t msg; + nxt_unit_impl_t *lib; + nxt_unit_port_impl_t *port_impl; -static ssize_t -nxt_unit_port_send(nxt_unit_ctx_t *ctx, nxt_unit_port_t *port, - const void *buf, size_t buf_size, const nxt_send_oob_t *oob) -{ - int notify; - ssize_t ret; - nxt_int_t rc; - nxt_port_msg_t msg; - nxt_unit_impl_t *lib; - nxt_unit_port_impl_t *port_impl; + lib = nxt_container_of(ctx->unit, nxt_unit_impl_t, unit); - lib = nxt_container_of(ctx->unit, nxt_unit_impl_t, unit); - - port_impl = nxt_container_of(port, nxt_unit_port_impl_t, port); - if (port_impl->queue != NULL && (oob == NULL || oob->size == 0) - && buf_size <= NXT_PORT_QUEUE_MSG_SIZE) - { - rc = nxt_port_queue_send(port_impl->queue, buf, buf_size, ¬ify); - if (nxt_slow_path(rc != NXT_OK)) { - nxt_unit_alert(ctx, "port_send: port %d,%d queue overflow", - (int) port->id.pid, (int) port->id.id); - - return -1; - } - - nxt_unit_debug(ctx, "port{%d,%d} enqueue %d notify %d", - (int) port->id.pid, (int) port->id.id, - (int) buf_size, notify); + port_impl = nxt_container_of(port, nxt_unit_port_impl_t, port); + if (port_impl->queue != NULL && (oob == NULL || oob->size == 0) && + buf_size <= NXT_PORT_QUEUE_MSG_SIZE) { + rc = nxt_port_queue_send(port_impl->queue, buf, buf_size, ¬ify); + if (nxt_slow_path(rc != NXT_OK)) { + nxt_unit_alert(ctx, "port_send: port %d,%d queue overflow", + (int)port->id.pid, (int)port->id.id); - if (notify) { - memcpy(&msg, buf, sizeof(nxt_port_msg_t)); + return -1; + } - msg.type = _NXT_PORT_MSG_READ_QUEUE; + nxt_unit_debug(ctx, "port{%d,%d} enqueue %d notify %d", (int)port->id.pid, + (int)port->id.id, (int)buf_size, notify); - if (lib->callbacks.port_send == NULL) { - ret = nxt_unit_sendmsg(ctx, port->out_fd, &msg, - sizeof(nxt_port_msg_t), NULL); + if (notify) { + memcpy(&msg, buf, sizeof(nxt_port_msg_t)); - nxt_unit_debug(ctx, "port{%d,%d} send %d read_queue", - (int) port->id.pid, (int) port->id.id, - (int) ret); + msg.type = _NXT_PORT_MSG_READ_QUEUE; - } else { - ret = lib->callbacks.port_send(ctx, port, &msg, - sizeof(nxt_port_msg_t), NULL, 0); + if (lib->callbacks.port_send == NULL) { + ret = nxt_unit_sendmsg(ctx, port->out_fd, &msg, sizeof(nxt_port_msg_t), + NULL); - nxt_unit_debug(ctx, "port{%d,%d} sendcb %d read_queue", - (int) port->id.pid, (int) port->id.id, - (int) ret); - } + nxt_unit_debug(ctx, "port{%d,%d} send %d read_queue", (int)port->id.pid, + (int)port->id.id, (int)ret); - } + } else { + ret = lib->callbacks.port_send(ctx, port, &msg, sizeof(nxt_port_msg_t), + NULL, 0); - return buf_size; + nxt_unit_debug(ctx, "port{%d,%d} sendcb %d read_queue", + (int)port->id.pid, (int)port->id.id, (int)ret); + } } - if (port_impl->queue != NULL) { - msg.type = _NXT_PORT_MSG_READ_SOCKET; + return buf_size; + } - rc = nxt_port_queue_send(port_impl->queue, &msg.type, 1, ¬ify); - if (nxt_slow_path(rc != NXT_OK)) { - nxt_unit_alert(ctx, "port_send: port %d,%d queue overflow", - (int) port->id.pid, (int) port->id.id); + if (port_impl->queue != NULL) { + msg.type = _NXT_PORT_MSG_READ_SOCKET; - return -1; - } + rc = nxt_port_queue_send(port_impl->queue, &msg.type, 1, ¬ify); + if (nxt_slow_path(rc != NXT_OK)) { + nxt_unit_alert(ctx, "port_send: port %d,%d queue overflow", + (int)port->id.pid, (int)port->id.id); - nxt_unit_debug(ctx, "port{%d,%d} enqueue 1 read_socket notify %d", - (int) port->id.pid, (int) port->id.id, notify); + return -1; } - if (lib->callbacks.port_send != NULL) { - ret = lib->callbacks.port_send(ctx, port, buf, buf_size, - oob != NULL ? oob->buf : NULL, - oob != NULL ? oob->size : 0); + nxt_unit_debug(ctx, "port{%d,%d} enqueue 1 read_socket notify %d", + (int)port->id.pid, (int)port->id.id, notify); + } - nxt_unit_debug(ctx, "port{%d,%d} sendcb %d", - (int) port->id.pid, (int) port->id.id, - (int) ret); + if (lib->callbacks.port_send != NULL) { + ret = lib->callbacks.port_send(ctx, port, buf, buf_size, + oob != NULL ? oob->buf : NULL, + oob != NULL ? oob->size : 0); - } else { - ret = nxt_unit_sendmsg(ctx, port->out_fd, buf, buf_size, oob); + nxt_unit_debug(ctx, "port{%d,%d} sendcb %d", (int)port->id.pid, + (int)port->id.id, (int)ret); - nxt_unit_debug(ctx, "port{%d,%d} sendmsg %d", - (int) port->id.pid, (int) port->id.id, - (int) ret); - } + } else { + ret = nxt_unit_sendmsg(ctx, port->out_fd, buf, buf_size, oob); - return ret; -} + nxt_unit_debug(ctx, "port{%d,%d} sendmsg %d", (int)port->id.pid, + (int)port->id.id, (int)ret); + } + return ret; +} -static ssize_t -nxt_unit_sendmsg(nxt_unit_ctx_t *ctx, int fd, - const void *buf, size_t buf_size, const nxt_send_oob_t *oob) -{ - int err; - ssize_t n; - struct iovec iov[1]; +static ssize_t nxt_unit_sendmsg(nxt_unit_ctx_t *ctx, int fd, const void *buf, + size_t buf_size, const nxt_send_oob_t *oob) { + int err; + ssize_t n; + struct iovec iov[1]; - iov[0].iov_base = (void *) buf; - iov[0].iov_len = buf_size; + iov[0].iov_base = (void *)buf; + iov[0].iov_len = buf_size; retry: - n = nxt_sendmsg(fd, iov, 1, oob); + n = nxt_sendmsg(fd, iov, 1, oob); - if (nxt_slow_path(n == -1)) { - err = errno; + if (nxt_slow_path(n == -1)) { + err = errno; - if (err == EINTR) { - goto retry; - } + if (err == EINTR) { + goto retry; + } - /* - * FIXME: This should be "alert" after router graceful shutdown - * implementation. - */ - nxt_unit_warn(ctx, "sendmsg(%d, %d) failed: %s (%d)", - fd, (int) buf_size, strerror(err), err); + /* + * FIXME: This should be "alert" after router graceful shutdown + * implementation. + */ + nxt_unit_warn(ctx, "sendmsg(%d, %d) failed: %s (%d)", fd, (int)buf_size, + strerror(err), err); - } else { - nxt_unit_debug(ctx, "sendmsg(%d, %d, %d): %d", fd, (int) buf_size, - (oob != NULL ? (int) oob->size : 0), (int) n); - } + } else { + nxt_unit_debug(ctx, "sendmsg(%d, %d, %d): %d", fd, (int)buf_size, + (oob != NULL ? (int)oob->size : 0), (int)n); + } - return n; + return n; } +static int nxt_unit_ctx_port_recv(nxt_unit_ctx_t *ctx, nxt_unit_port_t *port, + nxt_unit_read_buf_t *rbuf) { + int res, read; + nxt_unit_port_impl_t *port_impl; -static int -nxt_unit_ctx_port_recv(nxt_unit_ctx_t *ctx, nxt_unit_port_t *port, - nxt_unit_read_buf_t *rbuf) -{ - int res, read; - nxt_unit_port_impl_t *port_impl; - - port_impl = nxt_container_of(port, nxt_unit_port_impl_t, port); + port_impl = nxt_container_of(port, nxt_unit_port_impl_t, port); - read = 0; + read = 0; retry: - if (port_impl->from_socket > 0) { - if (port_impl->socket_rbuf != NULL - && port_impl->socket_rbuf->size > 0) - { - port_impl->from_socket--; + if (port_impl->from_socket > 0) { + if (port_impl->socket_rbuf != NULL && port_impl->socket_rbuf->size > 0) { + port_impl->from_socket--; - nxt_unit_rbuf_cpy(rbuf, port_impl->socket_rbuf); - port_impl->socket_rbuf->size = 0; + nxt_unit_rbuf_cpy(rbuf, port_impl->socket_rbuf); + port_impl->socket_rbuf->size = 0; - nxt_unit_debug(ctx, "port{%d,%d} use suspended message %d", - (int) port->id.pid, (int) port->id.id, - (int) rbuf->size); + nxt_unit_debug(ctx, "port{%d,%d} use suspended message %d", + (int)port->id.pid, (int)port->id.id, (int)rbuf->size); - return NXT_UNIT_OK; - } - - } else { - res = nxt_unit_port_queue_recv(port, rbuf); + return NXT_UNIT_OK; + } - if (res == NXT_UNIT_OK) { - if (nxt_unit_is_read_socket(rbuf)) { - port_impl->from_socket++; + } else { + res = nxt_unit_port_queue_recv(port, rbuf); - nxt_unit_debug(ctx, "port{%d,%d} dequeue 1 read_socket %d", - (int) port->id.pid, (int) port->id.id, - port_impl->from_socket); + if (res == NXT_UNIT_OK) { + if (nxt_unit_is_read_socket(rbuf)) { + port_impl->from_socket++; - goto retry; - } + nxt_unit_debug(ctx, "port{%d,%d} dequeue 1 read_socket %d", + (int)port->id.pid, (int)port->id.id, + port_impl->from_socket); - nxt_unit_debug(ctx, "port{%d,%d} dequeue %d", - (int) port->id.pid, (int) port->id.id, - (int) rbuf->size); + goto retry; + } - return NXT_UNIT_OK; - } - } + nxt_unit_debug(ctx, "port{%d,%d} dequeue %d", (int)port->id.pid, + (int)port->id.id, (int)rbuf->size); - if (read) { - return NXT_UNIT_AGAIN; + return NXT_UNIT_OK; } + } - res = nxt_unit_port_recv(ctx, port, rbuf); - if (nxt_slow_path(res == NXT_UNIT_ERROR)) { - return NXT_UNIT_ERROR; - } + if (read) { + return NXT_UNIT_AGAIN; + } - read = 1; + res = nxt_unit_port_recv(ctx, port, rbuf); + if (nxt_slow_path(res == NXT_UNIT_ERROR)) { + return NXT_UNIT_ERROR; + } - if (nxt_unit_is_read_queue(rbuf)) { - nxt_unit_debug(ctx, "port{%d,%d} recv %d read_queue", - (int) port->id.pid, (int) port->id.id, (int) rbuf->size); + read = 1; - goto retry; - } + if (nxt_unit_is_read_queue(rbuf)) { + nxt_unit_debug(ctx, "port{%d,%d} recv %d read_queue", (int)port->id.pid, + (int)port->id.id, (int)rbuf->size); - nxt_unit_debug(ctx, "port{%d,%d} recvmsg %d", - (int) port->id.pid, (int) port->id.id, - (int) rbuf->size); + goto retry; + } - if (res == NXT_UNIT_AGAIN) { - return NXT_UNIT_AGAIN; - } + nxt_unit_debug(ctx, "port{%d,%d} recvmsg %d", (int)port->id.pid, + (int)port->id.id, (int)rbuf->size); - if (port_impl->from_socket > 0) { - port_impl->from_socket--; + if (res == NXT_UNIT_AGAIN) { + return NXT_UNIT_AGAIN; + } - return NXT_UNIT_OK; - } + if (port_impl->from_socket > 0) { + port_impl->from_socket--; - nxt_unit_debug(ctx, "port{%d,%d} suspend message %d", - (int) port->id.pid, (int) port->id.id, - (int) rbuf->size); + return NXT_UNIT_OK; + } - if (port_impl->socket_rbuf == NULL) { - port_impl->socket_rbuf = nxt_unit_read_buf_get(ctx); + nxt_unit_debug(ctx, "port{%d,%d} suspend message %d", (int)port->id.pid, + (int)port->id.id, (int)rbuf->size); - if (nxt_slow_path(port_impl->socket_rbuf == NULL)) { - return NXT_UNIT_ERROR; - } + if (port_impl->socket_rbuf == NULL) { + port_impl->socket_rbuf = nxt_unit_read_buf_get(ctx); - port_impl->socket_rbuf->size = 0; + if (nxt_slow_path(port_impl->socket_rbuf == NULL)) { + return NXT_UNIT_ERROR; } - if (port_impl->socket_rbuf->size > 0) { - nxt_unit_alert(ctx, "too many port socket messages"); - - return NXT_UNIT_ERROR; - } + port_impl->socket_rbuf->size = 0; + } - nxt_unit_rbuf_cpy(port_impl->socket_rbuf, rbuf); + if (port_impl->socket_rbuf->size > 0) { + nxt_unit_alert(ctx, "too many port socket messages"); - rbuf->oob.size = 0; + return NXT_UNIT_ERROR; + } - goto retry; -} + nxt_unit_rbuf_cpy(port_impl->socket_rbuf, rbuf); + rbuf->oob.size = 0; -nxt_inline void -nxt_unit_rbuf_cpy(nxt_unit_read_buf_t *dst, nxt_unit_read_buf_t *src) -{ - memcpy(dst->buf, src->buf, src->size); - dst->size = src->size; - dst->oob.size = src->oob.size; - memcpy(dst->oob.buf, src->oob.buf, src->oob.size); + goto retry; } +nxt_inline void nxt_unit_rbuf_cpy(nxt_unit_read_buf_t *dst, + nxt_unit_read_buf_t *src) { + memcpy(dst->buf, src->buf, src->size); + dst->size = src->size; + dst->oob.size = src->oob.size; + memcpy(dst->oob.buf, src->oob.buf, src->oob.size); +} -static int -nxt_unit_shared_port_recv(nxt_unit_ctx_t *ctx, nxt_unit_port_t *port, - nxt_unit_read_buf_t *rbuf) -{ - int res; - nxt_unit_port_impl_t *port_impl; +static int nxt_unit_shared_port_recv(nxt_unit_ctx_t *ctx, nxt_unit_port_t *port, + nxt_unit_read_buf_t *rbuf) { + int res; + nxt_unit_port_impl_t *port_impl; - port_impl = nxt_container_of(port, nxt_unit_port_impl_t, port); + port_impl = nxt_container_of(port, nxt_unit_port_impl_t, port); retry: - res = nxt_unit_app_queue_recv(ctx, port, rbuf); + res = nxt_unit_app_queue_recv(ctx, port, rbuf); - if (res == NXT_UNIT_OK) { - return NXT_UNIT_OK; - } + if (res == NXT_UNIT_OK) { + return NXT_UNIT_OK; + } - if (res == NXT_UNIT_AGAIN) { - res = nxt_unit_port_recv(ctx, port, rbuf); - if (nxt_slow_path(res == NXT_UNIT_ERROR)) { - return NXT_UNIT_ERROR; - } + if (res == NXT_UNIT_AGAIN) { + res = nxt_unit_port_recv(ctx, port, rbuf); + if (nxt_slow_path(res == NXT_UNIT_ERROR)) { + return NXT_UNIT_ERROR; + } - if (nxt_unit_is_read_queue(rbuf)) { - nxt_app_queue_notification_received(port_impl->queue); + if (nxt_unit_is_read_queue(rbuf)) { + nxt_app_queue_notification_received(port_impl->queue); - nxt_unit_debug(ctx, "port{%d,%d} recv %d read_queue", - (int) port->id.pid, (int) port->id.id, (int) rbuf->size); + nxt_unit_debug(ctx, "port{%d,%d} recv %d read_queue", (int)port->id.pid, + (int)port->id.id, (int)rbuf->size); - goto retry; - } + goto retry; } + } - return res; + return res; } +static int nxt_unit_port_recv(nxt_unit_ctx_t *ctx, nxt_unit_port_t *port, + nxt_unit_read_buf_t *rbuf) { + int fd, err; + size_t oob_size; + struct iovec iov[1]; + nxt_unit_impl_t *lib; -static int -nxt_unit_port_recv(nxt_unit_ctx_t *ctx, nxt_unit_port_t *port, - nxt_unit_read_buf_t *rbuf) -{ - int fd, err; - size_t oob_size; - struct iovec iov[1]; - nxt_unit_impl_t *lib; - - lib = nxt_container_of(ctx->unit, nxt_unit_impl_t, unit); - - if (lib->callbacks.port_recv != NULL) { - oob_size = sizeof(rbuf->oob.buf); + lib = nxt_container_of(ctx->unit, nxt_unit_impl_t, unit); - rbuf->size = lib->callbacks.port_recv(ctx, port, - rbuf->buf, sizeof(rbuf->buf), - rbuf->oob.buf, &oob_size); + if (lib->callbacks.port_recv != NULL) { + oob_size = sizeof(rbuf->oob.buf); - nxt_unit_debug(ctx, "port{%d,%d} recvcb %d", - (int) port->id.pid, (int) port->id.id, (int) rbuf->size); + rbuf->size = lib->callbacks.port_recv( + ctx, port, rbuf->buf, sizeof(rbuf->buf), rbuf->oob.buf, &oob_size); - if (nxt_slow_path(rbuf->size < 0)) { - return NXT_UNIT_ERROR; - } + nxt_unit_debug(ctx, "port{%d,%d} recvcb %d", (int)port->id.pid, + (int)port->id.id, (int)rbuf->size); - rbuf->oob.size = oob_size; - return NXT_UNIT_OK; + if (nxt_slow_path(rbuf->size < 0)) { + return NXT_UNIT_ERROR; } - iov[0].iov_base = rbuf->buf; - iov[0].iov_len = sizeof(rbuf->buf); + rbuf->oob.size = oob_size; + return NXT_UNIT_OK; + } + + iov[0].iov_base = rbuf->buf; + iov[0].iov_len = sizeof(rbuf->buf); - fd = port->in_fd; + fd = port->in_fd; retry: - rbuf->size = nxt_recvmsg(fd, iov, 1, &rbuf->oob); + rbuf->size = nxt_recvmsg(fd, iov, 1, &rbuf->oob); - if (nxt_slow_path(rbuf->size == -1)) { - err = errno; + if (nxt_slow_path(rbuf->size == -1)) { + err = errno; - if (err == EINTR) { - goto retry; - } + if (err == EINTR) { + goto retry; + } - if (err == EAGAIN) { - nxt_unit_debug(ctx, "recvmsg(%d) failed: %s (%d)", - fd, strerror(err), err); + if (err == EAGAIN) { + nxt_unit_debug(ctx, "recvmsg(%d) failed: %s (%d)", fd, strerror(err), + err); - return NXT_UNIT_AGAIN; - } + return NXT_UNIT_AGAIN; + } - nxt_unit_alert(ctx, "recvmsg(%d) failed: %s (%d)", - fd, strerror(err), err); + nxt_unit_alert(ctx, "recvmsg(%d) failed: %s (%d)", fd, strerror(err), err); - return NXT_UNIT_ERROR; - } + return NXT_UNIT_ERROR; + } - nxt_unit_debug(ctx, "recvmsg(%d): %d", fd, (int) rbuf->size); + nxt_unit_debug(ctx, "recvmsg(%d): %d", fd, (int)rbuf->size); - return NXT_UNIT_OK; + return NXT_UNIT_OK; } +static int nxt_unit_port_queue_recv(nxt_unit_port_t *port, + nxt_unit_read_buf_t *rbuf) { + nxt_unit_port_impl_t *port_impl; -static int -nxt_unit_port_queue_recv(nxt_unit_port_t *port, nxt_unit_read_buf_t *rbuf) -{ - nxt_unit_port_impl_t *port_impl; - - port_impl = nxt_container_of(port, nxt_unit_port_impl_t, port); + port_impl = nxt_container_of(port, nxt_unit_port_impl_t, port); - rbuf->size = nxt_port_queue_recv(port_impl->queue, rbuf->buf); + rbuf->size = nxt_port_queue_recv(port_impl->queue, rbuf->buf); - return (rbuf->size == -1) ? NXT_UNIT_AGAIN : NXT_UNIT_OK; + return (rbuf->size == -1) ? NXT_UNIT_AGAIN : NXT_UNIT_OK; } +static int nxt_unit_app_queue_recv(nxt_unit_ctx_t *ctx, nxt_unit_port_t *port, + nxt_unit_read_buf_t *rbuf) { + uint32_t cookie; + nxt_port_msg_t *port_msg; + nxt_app_queue_t *queue; + nxt_unit_impl_t *lib; + nxt_unit_port_impl_t *port_impl; -static int -nxt_unit_app_queue_recv(nxt_unit_ctx_t *ctx, nxt_unit_port_t *port, - nxt_unit_read_buf_t *rbuf) -{ - uint32_t cookie; - nxt_port_msg_t *port_msg; - nxt_app_queue_t *queue; - nxt_unit_impl_t *lib; - nxt_unit_port_impl_t *port_impl; - - struct { - nxt_port_msg_t msg; - uint8_t quit_param; - } nxt_packed m; + struct { + nxt_port_msg_t msg; + uint8_t quit_param; + } nxt_packed m; - port_impl = nxt_container_of(port, nxt_unit_port_impl_t, port); - queue = port_impl->queue; + port_impl = nxt_container_of(port, nxt_unit_port_impl_t, port); + queue = port_impl->queue; retry: - rbuf->size = nxt_app_queue_recv(queue, rbuf->buf, &cookie); - - nxt_unit_debug(NULL, "app_queue_recv: %d", (int) rbuf->size); + rbuf->size = nxt_app_queue_recv(queue, rbuf->buf, &cookie); - if (rbuf->size >= (ssize_t) sizeof(nxt_port_msg_t)) { - port_msg = (nxt_port_msg_t *) rbuf->buf; + nxt_unit_debug(NULL, "app_queue_recv: %d", (int)rbuf->size); - if (nxt_app_queue_cancel(queue, cookie, port_msg->stream)) { - lib = nxt_container_of(ctx->unit, nxt_unit_impl_t, unit); + if (rbuf->size >= (ssize_t)sizeof(nxt_port_msg_t)) { + port_msg = (nxt_port_msg_t *)rbuf->buf; - if (lib->request_limit != 0) { - nxt_atomic_fetch_add(&lib->request_count, 1); + if (nxt_app_queue_cancel(queue, cookie, port_msg->stream)) { + lib = nxt_container_of(ctx->unit, nxt_unit_impl_t, unit); - if (nxt_slow_path(lib->request_count >= lib->request_limit)) { - nxt_unit_debug(ctx, "request limit reached"); + if (lib->request_limit != 0) { + nxt_atomic_fetch_add(&lib->request_count, 1); - memset(&m.msg, 0, sizeof(nxt_port_msg_t)); + if (nxt_slow_path(lib->request_count >= lib->request_limit)) { + nxt_unit_debug(ctx, "request limit reached"); - m.msg.pid = lib->pid; - m.msg.type = _NXT_PORT_MSG_QUIT; - m.quit_param = NXT_QUIT_GRACEFUL; + memset(&m.msg, 0, sizeof(nxt_port_msg_t)); - (void) nxt_unit_port_send(ctx, lib->main_ctx.read_port, - &m, sizeof(m), NULL); - } - } + m.msg.pid = lib->pid; + m.msg.type = _NXT_PORT_MSG_QUIT; + m.quit_param = NXT_QUIT_GRACEFUL; - return NXT_UNIT_OK; + (void)nxt_unit_port_send(ctx, lib->main_ctx.read_port, &m, sizeof(m), + NULL); } + } - nxt_unit_debug(NULL, "app_queue_recv: message cancelled"); - - goto retry; + return NXT_UNIT_OK; } - return (rbuf->size == -1) ? NXT_UNIT_AGAIN : NXT_UNIT_OK; -} + nxt_unit_debug(NULL, "app_queue_recv: message cancelled"); + goto retry; + } -nxt_inline int -nxt_unit_close(int fd) -{ - int res; + return (rbuf->size == -1) ? NXT_UNIT_AGAIN : NXT_UNIT_OK; +} - res = close(fd); +nxt_inline int nxt_unit_close(int fd) { + int res; - if (nxt_slow_path(res == -1)) { - nxt_unit_alert(NULL, "close(%d) failed: %s (%d)", - fd, strerror(errno), errno); + res = close(fd); - } else { - nxt_unit_debug(NULL, "close(%d): %d", fd, res); - } + if (nxt_slow_path(res == -1)) { + nxt_unit_alert(NULL, "close(%d) failed: %s (%d)", fd, strerror(errno), + errno); - return res; -} + } else { + nxt_unit_debug(NULL, "close(%d): %d", fd, res); + } + return res; +} -static int -nxt_unit_fd_blocking(int fd) -{ - int nb; +static int nxt_unit_fd_blocking(int fd) { + int nb; - nb = 0; + nb = 0; - if (nxt_slow_path(ioctl(fd, FIONBIO, &nb) == -1)) { - nxt_unit_alert(NULL, "ioctl(%d, FIONBIO, 0) failed: %s (%d)", - fd, strerror(errno), errno); + if (nxt_slow_path(ioctl(fd, FIONBIO, &nb) == -1)) { + nxt_unit_alert(NULL, "ioctl(%d, FIONBIO, 0) failed: %s (%d)", fd, + strerror(errno), errno); - return NXT_UNIT_ERROR; - } + return NXT_UNIT_ERROR; + } - return NXT_UNIT_OK; + return NXT_UNIT_OK; } +static nxt_int_t nxt_unit_port_hash_test(nxt_lvlhsh_query_t *lhq, void *data) { + nxt_unit_port_t *port; + nxt_unit_port_hash_id_t *port_id; -static nxt_int_t -nxt_unit_port_hash_test(nxt_lvlhsh_query_t *lhq, void *data) -{ - nxt_unit_port_t *port; - nxt_unit_port_hash_id_t *port_id; - - port = data; - port_id = (nxt_unit_port_hash_id_t *) lhq->key.start; + port = data; + port_id = (nxt_unit_port_hash_id_t *)lhq->key.start; - if (lhq->key.length == sizeof(nxt_unit_port_hash_id_t) - && port_id->pid == port->id.pid - && port_id->id == port->id.id) - { - return NXT_OK; - } + if (lhq->key.length == sizeof(nxt_unit_port_hash_id_t) && + port_id->pid == port->id.pid && port_id->id == port->id.id) { + return NXT_OK; + } - return NXT_DECLINED; + return NXT_DECLINED; } - -static const nxt_lvlhsh_proto_t lvlhsh_ports_proto nxt_aligned(64) = { +static const nxt_lvlhsh_proto_t lvlhsh_ports_proto nxt_aligned(64) = { NXT_LVLHSH_DEFAULT, nxt_unit_port_hash_test, nxt_unit_lvlhsh_alloc, nxt_unit_lvlhsh_free, }; +static inline void nxt_unit_port_hash_lhq(nxt_lvlhsh_query_t *lhq, + nxt_unit_port_hash_id_t *port_hash_id, + nxt_unit_port_id_t *port_id) { + port_hash_id->pid = port_id->pid; + port_hash_id->id = port_id->id; -static inline void -nxt_unit_port_hash_lhq(nxt_lvlhsh_query_t *lhq, - nxt_unit_port_hash_id_t *port_hash_id, - nxt_unit_port_id_t *port_id) -{ - port_hash_id->pid = port_id->pid; - port_hash_id->id = port_id->id; - - if (nxt_fast_path(port_id->hash != 0)) { - lhq->key_hash = port_id->hash; + if (nxt_fast_path(port_id->hash != 0)) { + lhq->key_hash = port_id->hash; - } else { - lhq->key_hash = nxt_murmur_hash2(port_hash_id, sizeof(*port_hash_id)); + } else { + lhq->key_hash = nxt_murmur_hash2(port_hash_id, sizeof(*port_hash_id)); - port_id->hash = lhq->key_hash; + port_id->hash = lhq->key_hash; - nxt_unit_debug(NULL, "calculate hash for port_id (%d, %d): %04X", - (int) port_id->pid, (int) port_id->id, - (int) port_id->hash); - } + nxt_unit_debug(NULL, "calculate hash for port_id (%d, %d): %04X", + (int)port_id->pid, (int)port_id->id, (int)port_id->hash); + } - lhq->key.length = sizeof(nxt_unit_port_hash_id_t); - lhq->key.start = (u_char *) port_hash_id; - lhq->proto = &lvlhsh_ports_proto; - lhq->pool = NULL; + lhq->key.length = sizeof(nxt_unit_port_hash_id_t); + lhq->key.start = (u_char *)port_hash_id; + lhq->proto = &lvlhsh_ports_proto; + lhq->pool = NULL; } +static int nxt_unit_port_hash_add(nxt_lvlhsh_t *port_hash, + nxt_unit_port_t *port) { + nxt_int_t res; + nxt_lvlhsh_query_t lhq; + nxt_unit_port_hash_id_t port_hash_id; -static int -nxt_unit_port_hash_add(nxt_lvlhsh_t *port_hash, nxt_unit_port_t *port) -{ - nxt_int_t res; - nxt_lvlhsh_query_t lhq; - nxt_unit_port_hash_id_t port_hash_id; - - nxt_unit_port_hash_lhq(&lhq, &port_hash_id, &port->id); - lhq.replace = 0; - lhq.value = port; + nxt_unit_port_hash_lhq(&lhq, &port_hash_id, &port->id); + lhq.replace = 0; + lhq.value = port; - res = nxt_lvlhsh_insert(port_hash, &lhq); + res = nxt_lvlhsh_insert(port_hash, &lhq); - switch (res) { + switch (res) { - case NXT_OK: - return NXT_UNIT_OK; + case NXT_OK: + return NXT_UNIT_OK; - default: - return NXT_UNIT_ERROR; - } + default: + return NXT_UNIT_ERROR; + } } +static nxt_unit_port_t *nxt_unit_port_hash_find(nxt_lvlhsh_t *port_hash, + nxt_unit_port_id_t *port_id, + int remove) { + nxt_int_t res; + nxt_lvlhsh_query_t lhq; + nxt_unit_port_hash_id_t port_hash_id; -static nxt_unit_port_t * -nxt_unit_port_hash_find(nxt_lvlhsh_t *port_hash, nxt_unit_port_id_t *port_id, - int remove) -{ - nxt_int_t res; - nxt_lvlhsh_query_t lhq; - nxt_unit_port_hash_id_t port_hash_id; - - nxt_unit_port_hash_lhq(&lhq, &port_hash_id, port_id); - - if (remove) { - res = nxt_lvlhsh_delete(port_hash, &lhq); - - } else { - res = nxt_lvlhsh_find(port_hash, &lhq); - } + nxt_unit_port_hash_lhq(&lhq, &port_hash_id, port_id); - switch (res) { + if (remove) { + res = nxt_lvlhsh_delete(port_hash, &lhq); - case NXT_OK: - if (!remove) { - nxt_unit_port_use(lhq.value); - } + } else { + res = nxt_lvlhsh_find(port_hash, &lhq); + } - return lhq.value; + switch (res) { - default: - return NULL; + case NXT_OK: + if (!remove) { + nxt_unit_port_use(lhq.value); } -} + return lhq.value; -static nxt_int_t -nxt_unit_request_hash_test(nxt_lvlhsh_query_t *lhq, void *data) -{ - return NXT_OK; + default: + return NULL; + } } +static nxt_int_t nxt_unit_request_hash_test(nxt_lvlhsh_query_t *lhq, + void *data) { + return NXT_OK; +} -static const nxt_lvlhsh_proto_t lvlhsh_requests_proto nxt_aligned(64) = { +static const nxt_lvlhsh_proto_t lvlhsh_requests_proto nxt_aligned(64) = { NXT_LVLHSH_DEFAULT, nxt_unit_request_hash_test, nxt_unit_lvlhsh_alloc, nxt_unit_lvlhsh_free, }; +static int nxt_unit_request_hash_add(nxt_unit_ctx_t *ctx, + nxt_unit_request_info_t *req) { + uint32_t *stream; + nxt_int_t res; + nxt_lvlhsh_query_t lhq; + nxt_unit_ctx_impl_t *ctx_impl; + nxt_unit_request_info_impl_t *req_impl; + + req_impl = nxt_container_of(req, nxt_unit_request_info_impl_t, req); + if (req_impl->in_hash) { + return NXT_UNIT_OK; + } -static int -nxt_unit_request_hash_add(nxt_unit_ctx_t *ctx, - nxt_unit_request_info_t *req) -{ - uint32_t *stream; - nxt_int_t res; - nxt_lvlhsh_query_t lhq; - nxt_unit_ctx_impl_t *ctx_impl; - nxt_unit_request_info_impl_t *req_impl; - - req_impl = nxt_container_of(req, nxt_unit_request_info_impl_t, req); - if (req_impl->in_hash) { - return NXT_UNIT_OK; - } - - stream = &req_impl->stream; + stream = &req_impl->stream; - lhq.key_hash = nxt_murmur_hash2(stream, sizeof(*stream)); - lhq.key.length = sizeof(*stream); - lhq.key.start = (u_char *) stream; - lhq.proto = &lvlhsh_requests_proto; - lhq.pool = NULL; - lhq.replace = 0; - lhq.value = req_impl; + lhq.key_hash = nxt_murmur_hash2(stream, sizeof(*stream)); + lhq.key.length = sizeof(*stream); + lhq.key.start = (u_char *)stream; + lhq.proto = &lvlhsh_requests_proto; + lhq.pool = NULL; + lhq.replace = 0; + lhq.value = req_impl; - ctx_impl = nxt_container_of(ctx, nxt_unit_ctx_impl_t, ctx); + ctx_impl = nxt_container_of(ctx, nxt_unit_ctx_impl_t, ctx); - pthread_mutex_lock(&ctx_impl->mutex); + pthread_mutex_lock(&ctx_impl->mutex); - res = nxt_lvlhsh_insert(&ctx_impl->requests, &lhq); + res = nxt_lvlhsh_insert(&ctx_impl->requests, &lhq); - pthread_mutex_unlock(&ctx_impl->mutex); + pthread_mutex_unlock(&ctx_impl->mutex); - switch (res) { + switch (res) { - case NXT_OK: - req_impl->in_hash = 1; - return NXT_UNIT_OK; + case NXT_OK: + req_impl->in_hash = 1; + return NXT_UNIT_OK; - default: - return NXT_UNIT_ERROR; - } + default: + return NXT_UNIT_ERROR; + } } - static nxt_unit_request_info_t * -nxt_unit_request_hash_find(nxt_unit_ctx_t *ctx, uint32_t stream, int remove) -{ - nxt_int_t res; - nxt_lvlhsh_query_t lhq; - nxt_unit_ctx_impl_t *ctx_impl; - nxt_unit_request_info_impl_t *req_impl; +nxt_unit_request_hash_find(nxt_unit_ctx_t *ctx, uint32_t stream, int remove) { + nxt_int_t res; + nxt_lvlhsh_query_t lhq; + nxt_unit_ctx_impl_t *ctx_impl; + nxt_unit_request_info_impl_t *req_impl; - lhq.key_hash = nxt_murmur_hash2(&stream, sizeof(stream)); - lhq.key.length = sizeof(stream); - lhq.key.start = (u_char *) &stream; - lhq.proto = &lvlhsh_requests_proto; - lhq.pool = NULL; + lhq.key_hash = nxt_murmur_hash2(&stream, sizeof(stream)); + lhq.key.length = sizeof(stream); + lhq.key.start = (u_char *)&stream; + lhq.proto = &lvlhsh_requests_proto; + lhq.pool = NULL; - ctx_impl = nxt_container_of(ctx, nxt_unit_ctx_impl_t, ctx); + ctx_impl = nxt_container_of(ctx, nxt_unit_ctx_impl_t, ctx); - pthread_mutex_lock(&ctx_impl->mutex); + pthread_mutex_lock(&ctx_impl->mutex); - if (remove) { - res = nxt_lvlhsh_delete(&ctx_impl->requests, &lhq); + if (remove) { + res = nxt_lvlhsh_delete(&ctx_impl->requests, &lhq); - } else { - res = nxt_lvlhsh_find(&ctx_impl->requests, &lhq); - } + } else { + res = nxt_lvlhsh_find(&ctx_impl->requests, &lhq); + } - pthread_mutex_unlock(&ctx_impl->mutex); + pthread_mutex_unlock(&ctx_impl->mutex); - switch (res) { + switch (res) { - case NXT_OK: - req_impl = nxt_container_of(lhq.value, nxt_unit_request_info_impl_t, - req); - if (remove) { - req_impl->in_hash = 0; - } + case NXT_OK: + req_impl = nxt_container_of(lhq.value, nxt_unit_request_info_impl_t, req); + if (remove) { + req_impl->in_hash = 0; + } - return lhq.value; + return lhq.value; - default: - return NULL; - } + default: + return NULL; + } } +void nxt_unit_log(nxt_unit_ctx_t *ctx, int level, const char *fmt, ...) { + int log_fd, n; + char msg[NXT_MAX_ERROR_STR], *p, *end; + pid_t pid; + va_list ap; + nxt_unit_impl_t *lib; -void -nxt_unit_log(nxt_unit_ctx_t *ctx, int level, const char *fmt, ...) -{ - int log_fd, n; - char msg[NXT_MAX_ERROR_STR], *p, *end; - pid_t pid; - va_list ap; - nxt_unit_impl_t *lib; - - if (nxt_fast_path(ctx != NULL)) { - lib = nxt_container_of(ctx->unit, nxt_unit_impl_t, unit); + if (nxt_fast_path(ctx != NULL)) { + lib = nxt_container_of(ctx->unit, nxt_unit_impl_t, unit); - pid = lib->pid; - log_fd = lib->log_fd; + pid = lib->pid; + log_fd = lib->log_fd; - } else { - pid = nxt_unit_pid; - log_fd = STDERR_FILENO; - } + } else { + pid = nxt_unit_pid; + log_fd = STDERR_FILENO; + } - p = msg; - end = p + sizeof(msg) - 1; + p = msg; + end = p + sizeof(msg) - 1; - p = nxt_unit_snprint_prefix(p, end, pid, level); + p = nxt_unit_snprint_prefix(p, end, pid, level); - va_start(ap, fmt); - p += vsnprintf(p, end - p, fmt, ap); - va_end(ap); + va_start(ap, fmt); + p += vsnprintf(p, end - p, fmt, ap); + va_end(ap); - if (nxt_slow_path(p > end)) { - memcpy(end - 5, "[...]", 5); - p = end; - } + if (nxt_slow_path(p > end)) { + memcpy(end - 5, "[...]", 5); + p = end; + } - *p++ = '\n'; + *p++ = '\n'; - n = write(log_fd, msg, p - msg); - if (nxt_slow_path(n < 0)) { - fprintf(stderr, "Failed to write log: %.*s", (int) (p - msg), msg); - } + n = write(log_fd, msg, p - msg); + if (nxt_slow_path(n < 0)) { + fprintf(stderr, "Failed to write log: %.*s", (int)(p - msg), msg); + } } +void nxt_unit_req_log(nxt_unit_request_info_t *req, int level, const char *fmt, + ...) { + int log_fd, n; + char msg[NXT_MAX_ERROR_STR], *p, *end; + pid_t pid; + va_list ap; + nxt_unit_impl_t *lib; + nxt_unit_request_info_impl_t *req_impl; -void -nxt_unit_req_log(nxt_unit_request_info_t *req, int level, const char *fmt, ...) -{ - int log_fd, n; - char msg[NXT_MAX_ERROR_STR], *p, *end; - pid_t pid; - va_list ap; - nxt_unit_impl_t *lib; - nxt_unit_request_info_impl_t *req_impl; - - if (nxt_fast_path(req != NULL)) { - lib = nxt_container_of(req->ctx->unit, nxt_unit_impl_t, unit); + if (nxt_fast_path(req != NULL)) { + lib = nxt_container_of(req->ctx->unit, nxt_unit_impl_t, unit); - pid = lib->pid; - log_fd = lib->log_fd; + pid = lib->pid; + log_fd = lib->log_fd; - } else { - pid = nxt_unit_pid; - log_fd = STDERR_FILENO; - } + } else { + pid = nxt_unit_pid; + log_fd = STDERR_FILENO; + } - p = msg; - end = p + sizeof(msg) - 1; + p = msg; + end = p + sizeof(msg) - 1; - p = nxt_unit_snprint_prefix(p, end, pid, level); + p = nxt_unit_snprint_prefix(p, end, pid, level); - if (nxt_fast_path(req != NULL)) { - req_impl = nxt_container_of(req, nxt_unit_request_info_impl_t, req); + if (nxt_fast_path(req != NULL)) { + req_impl = nxt_container_of(req, nxt_unit_request_info_impl_t, req); - p += snprintf(p, end - p, "#%"PRIu32": ", req_impl->stream); - } + p += snprintf(p, end - p, "#%" PRIu32 ": ", req_impl->stream); + } - va_start(ap, fmt); - p += vsnprintf(p, end - p, fmt, ap); - va_end(ap); + va_start(ap, fmt); + p += vsnprintf(p, end - p, fmt, ap); + va_end(ap); - if (nxt_slow_path(p > end)) { - memcpy(end - 5, "[...]", 5); - p = end; - } + if (nxt_slow_path(p > end)) { + memcpy(end - 5, "[...]", 5); + p = end; + } - *p++ = '\n'; + *p++ = '\n'; - n = write(log_fd, msg, p - msg); - if (nxt_slow_path(n < 0)) { - fprintf(stderr, "Failed to write log: %.*s", (int) (p - msg), msg); - } + n = write(log_fd, msg, p - msg); + if (nxt_slow_path(n < 0)) { + fprintf(stderr, "Failed to write log: %.*s", (int)(p - msg), msg); + } } - -static const char * nxt_unit_log_levels[] = { - "alert", - "error", - "warn", - "notice", - "info", - "debug", +static const char *nxt_unit_log_levels[] = { + "alert", "error", "warn", "notice", "info", "debug", }; +static char *nxt_unit_snprint_prefix(char *p, char *end, pid_t pid, int level) { + struct tm tm; + struct timespec ts; -static char * -nxt_unit_snprint_prefix(char *p, char *end, pid_t pid, int level) -{ - struct tm tm; - struct timespec ts; - - (void) clock_gettime(CLOCK_REALTIME, &ts); + (void)clock_gettime(CLOCK_REALTIME, &ts); #if (NXT_HAVE_LOCALTIME_R) - (void) localtime_r(&ts.tv_sec, &tm); + (void)localtime_r(&ts.tv_sec, &tm); #else - tm = *localtime(&ts.tv_sec); + tm = *localtime(&ts.tv_sec); #endif #if (NXT_DEBUG) - p += snprintf(p, end - p, - "%4d/%02d/%02d %02d:%02d:%02d.%03d ", - tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday, - tm.tm_hour, tm.tm_min, tm.tm_sec, - (int) ts.tv_nsec / 1000000); + p += snprintf(p, end - p, "%4d/%02d/%02d %02d:%02d:%02d.%03d ", + tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday, tm.tm_hour, + tm.tm_min, tm.tm_sec, (int)ts.tv_nsec / 1000000); #else - p += snprintf(p, end - p, - "%4d/%02d/%02d %02d:%02d:%02d ", - tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday, - tm.tm_hour, tm.tm_min, tm.tm_sec); + p += snprintf(p, end - p, "%4d/%02d/%02d %02d:%02d:%02d ", tm.tm_year + 1900, + tm.tm_mon + 1, tm.tm_mday, tm.tm_hour, tm.tm_min, tm.tm_sec); #endif - p += snprintf(p, end - p, - "[%s] %d#%"PRIu64" [unit] ", nxt_unit_log_levels[level], - (int) pid, - (uint64_t) (uintptr_t) nxt_thread_get_tid()); + p += snprintf(p, end - p, "[%s] %d#%" PRIu64 " [unit] ", + nxt_unit_log_levels[level], (int)pid, + (uint64_t)(uintptr_t)nxt_thread_get_tid()); - return p; + return p; } +static void *nxt_unit_lvlhsh_alloc(void *data, size_t size) { + int err; + void *p; -static void * -nxt_unit_lvlhsh_alloc(void *data, size_t size) -{ - int err; - void *p; + err = posix_memalign(&p, size, size); - err = posix_memalign(&p, size, size); - - if (nxt_fast_path(err == 0)) { - nxt_unit_debug(NULL, "posix_memalign(%d, %d): %p", - (int) size, (int) size, p); - return p; - } + if (nxt_fast_path(err == 0)) { + nxt_unit_debug(NULL, "posix_memalign(%d, %d): %p", (int)size, (int)size, p); + return p; + } - nxt_unit_alert(NULL, "posix_memalign(%d, %d) failed: %s (%d)", - (int) size, (int) size, strerror(err), err); - return NULL; + nxt_unit_alert(NULL, "posix_memalign(%d, %d) failed: %s (%d)", (int)size, + (int)size, strerror(err), err); + return NULL; } - -static void -nxt_unit_lvlhsh_free(void *data, void *p) -{ - nxt_unit_free(NULL, p); +static void nxt_unit_lvlhsh_free(void *data, void *p) { + nxt_unit_free(NULL, p); } +void *nxt_unit_malloc(nxt_unit_ctx_t *ctx, size_t size) { + void *p; -void * -nxt_unit_malloc(nxt_unit_ctx_t *ctx, size_t size) -{ - void *p; + p = malloc(size); - p = malloc(size); - - if (nxt_fast_path(p != NULL)) { + if (nxt_fast_path(p != NULL)) { #if (NXT_DEBUG_ALLOC) - nxt_unit_debug(ctx, "malloc(%d): %p", (int) size, p); + nxt_unit_debug(ctx, "malloc(%d): %p", (int)size, p); #endif - } else { - nxt_unit_alert(ctx, "malloc(%d) failed: %s (%d)", - (int) size, strerror(errno), errno); - } + } else { + nxt_unit_alert(ctx, "malloc(%d) failed: %s (%d)", (int)size, + strerror(errno), errno); + } - return p; + return p; } - -void -nxt_unit_free(nxt_unit_ctx_t *ctx, void *p) -{ +void nxt_unit_free(nxt_unit_ctx_t *ctx, void *p) { #if (NXT_DEBUG_ALLOC) - nxt_unit_debug(ctx, "free(%p)", p); + nxt_unit_debug(ctx, "free(%p)", p); #endif - free(p); + free(p); } +static int nxt_unit_memcasecmp(const void *p1, const void *p2, size_t length) { + u_char c1, c2; + nxt_int_t n; + const u_char *s1, *s2; -static int -nxt_unit_memcasecmp(const void *p1, const void *p2, size_t length) -{ - u_char c1, c2; - nxt_int_t n; - const u_char *s1, *s2; - - s1 = p1; - s2 = p2; + s1 = p1; + s2 = p2; - while (length-- != 0) { - c1 = *s1++; - c2 = *s2++; + while (length-- != 0) { + c1 = *s1++; + c2 = *s2++; - c1 = nxt_lowcase(c1); - c2 = nxt_lowcase(c2); + c1 = nxt_lowcase(c1); + c2 = nxt_lowcase(c2); - n = c1 - c2; + n = c1 - c2; - if (n != 0) { - return n; - } + if (n != 0) { + return n; } + } - return 0; + return 0; } diff --git a/src/nxt_unit.h b/src/nxt_unit.h index a50046a52..d37048076 100644 --- a/src/nxt_unit.h +++ b/src/nxt_unit.h @@ -6,7 +6,6 @@ #ifndef _NXT_UNIT_H_INCLUDED_ #define _NXT_UNIT_H_INCLUDED_ - #include #include #include @@ -16,26 +15,25 @@ #include "nxt_version.h" #include "nxt_unit_typedefs.h" - enum { - NXT_UNIT_OK = 0, - NXT_UNIT_ERROR = 1, - NXT_UNIT_AGAIN = 2, - NXT_UNIT_CANCELLED = 3, + NXT_UNIT_OK = 0, + NXT_UNIT_ERROR = 1, + NXT_UNIT_AGAIN = 2, + NXT_UNIT_CANCELLED = 3, }; enum { - NXT_UNIT_LOG_ALERT = 0, - NXT_UNIT_LOG_ERR = 1, - NXT_UNIT_LOG_WARN = 2, - NXT_UNIT_LOG_NOTICE = 3, - NXT_UNIT_LOG_INFO = 4, - NXT_UNIT_LOG_DEBUG = 5, + NXT_UNIT_LOG_ALERT = 0, + NXT_UNIT_LOG_ERR = 1, + NXT_UNIT_LOG_WARN = 2, + NXT_UNIT_LOG_NOTICE = 3, + NXT_UNIT_LOG_INFO = 4, + NXT_UNIT_LOG_DEBUG = 5, }; -#define NXT_UNIT_INIT_ENV "NXT_UNIT_INIT" +#define NXT_UNIT_INIT_ENV "NXT_UNIT_INIT" -#define NXT_UNIT_SHARED_PORT_ID ((uint16_t) 0xFFFFu) +#define NXT_UNIT_SHARED_PORT_ID ((uint16_t)0xFFFFu) /* * Mostly opaque structure with library state. @@ -44,7 +42,7 @@ enum { * implementation specific and hidden. */ struct nxt_unit_s { - void *data; /* User defined data. */ + void *data; /* User defined data. */ }; /* @@ -55,8 +53,8 @@ struct nxt_unit_s { * further in that thread. */ struct nxt_unit_ctx_s { - void *data; /* User context-specific data. */ - nxt_unit_t *unit; + void *data; /* User context-specific data. */ + nxt_unit_t *unit; }; /* @@ -66,9 +64,9 @@ struct nxt_unit_ctx_s { * This identification is required to refer the port from different process. */ struct nxt_unit_port_id_s { - pid_t pid; - uint32_t hash; - uint16_t id; + pid_t pid; + uint32_t hash; + uint16_t id; }; /* @@ -76,124 +74,115 @@ struct nxt_unit_port_id_s { * data structures. */ struct nxt_unit_port_s { - nxt_unit_port_id_t id; + nxt_unit_port_id_t id; - int in_fd; - int out_fd; + int in_fd; + int out_fd; - void *data; + void *data; }; - struct nxt_unit_buf_s { - char *start; - char *free; - char *end; + char *start; + char *free; + char *end; }; - struct nxt_unit_request_info_s { - nxt_unit_t *unit; - nxt_unit_ctx_t *ctx; + nxt_unit_t *unit; + nxt_unit_ctx_t *ctx; - nxt_unit_port_t *response_port; + nxt_unit_port_t *response_port; - nxt_unit_request_t *request; - nxt_unit_buf_t *request_buf; + nxt_unit_request_t *request; + nxt_unit_buf_t *request_buf; - nxt_unit_response_t *response; - nxt_unit_buf_t *response_buf; - uint32_t response_max_fields; + nxt_unit_response_t *response; + nxt_unit_buf_t *response_buf; + uint32_t response_max_fields; - nxt_unit_buf_t *content_buf; - uint64_t content_length; - int content_fd; + nxt_unit_buf_t *content_buf; + uint64_t content_length; + int content_fd; - void *data; + void *data; }; - /* * Set of application-specific callbacks. The application may leave all * optional callbacks as NULL. */ struct nxt_unit_callbacks_s { - /* - * Process request. Unlike all other callbacks, this callback is required - * and needs to be defined by the application. - */ - void (*request_handler)(nxt_unit_request_info_t *req); + /* + * Process request. Unlike all other callbacks, this callback is required + * and needs to be defined by the application. + */ + void (*request_handler)(nxt_unit_request_info_t *req); - void (*data_handler)(nxt_unit_request_info_t *req); + void (*data_handler)(nxt_unit_request_info_t *req); - /* Process websocket frame. */ - void (*websocket_handler)(nxt_unit_websocket_frame_t *ws); + /* Process websocket frame. */ + void (*websocket_handler)(nxt_unit_websocket_frame_t *ws); - /* Connection closed. */ - void (*close_handler)(nxt_unit_request_info_t *req); + /* Connection closed. */ + void (*close_handler)(nxt_unit_request_info_t *req); - /* Add new Unit port to communicate with process pid. Optional. */ - int (*add_port)(nxt_unit_ctx_t *, nxt_unit_port_t *port); + /* Add new Unit port to communicate with process pid. Optional. */ + int (*add_port)(nxt_unit_ctx_t *, nxt_unit_port_t *port); - /* Remove previously added port. Optional. */ - void (*remove_port)(nxt_unit_t *, nxt_unit_ctx_t *, - nxt_unit_port_t *port); + /* Remove previously added port. Optional. */ + void (*remove_port)(nxt_unit_t *, nxt_unit_ctx_t *, nxt_unit_port_t *port); - /* Remove all data associated with process pid including ports. Optional. */ - void (*remove_pid)(nxt_unit_t *, pid_t pid); + /* Remove all data associated with process pid including ports. Optional. */ + void (*remove_pid)(nxt_unit_t *, pid_t pid); - /* Gracefully quit the application. Optional. */ - void (*quit)(nxt_unit_ctx_t *); + /* Gracefully quit the application. Optional. */ + void (*quit)(nxt_unit_ctx_t *); - /* Shared memory release acknowledgement. Optional. */ - void (*shm_ack_handler)(nxt_unit_ctx_t *); + /* Shared memory release acknowledgement. Optional. */ + void (*shm_ack_handler)(nxt_unit_ctx_t *); - /* Send data and control to process pid using port id. Optional. */ - ssize_t (*port_send)(nxt_unit_ctx_t *, nxt_unit_port_t *port, - const void *buf, size_t buf_size, - const void *oob, size_t oob_size); + /* Send data and control to process pid using port id. Optional. */ + ssize_t (*port_send)(nxt_unit_ctx_t *, nxt_unit_port_t *port, const void *buf, + size_t buf_size, const void *oob, size_t oob_size); - /* Receive data on port id. Optional. */ - ssize_t (*port_recv)(nxt_unit_ctx_t *, nxt_unit_port_t *port, - void *buf, size_t buf_size, void *oob, size_t *oob_size); + /* Receive data on port id. Optional. */ + ssize_t (*port_recv)(nxt_unit_ctx_t *, nxt_unit_port_t *port, void *buf, + size_t buf_size, void *oob, size_t *oob_size); - int (*ready_handler)(nxt_unit_ctx_t *); + int (*ready_handler)(nxt_unit_ctx_t *); }; - struct nxt_unit_init_s { - void *data; /* Opaque pointer to user-defined data. */ - void *ctx_data; /* Opaque pointer to user-defined data. */ - int max_pending_requests; - - uint32_t request_data_size; - uint32_t shm_limit; - uint32_t request_limit; - - nxt_unit_callbacks_t callbacks; - - nxt_unit_port_t ready_port; - uint32_t ready_stream; - nxt_unit_port_t router_port; - nxt_unit_port_t read_port; - int shared_port_fd; - int shared_queue_fd; - int log_fd; + void *data; /* Opaque pointer to user-defined data. */ + void *ctx_data; /* Opaque pointer to user-defined data. */ + int max_pending_requests; + + uint32_t request_data_size; + uint32_t shm_limit; + uint32_t request_limit; + + nxt_unit_callbacks_t callbacks; + + nxt_unit_port_t ready_port; + uint32_t ready_stream; + nxt_unit_port_t router_port; + nxt_unit_port_t read_port; + int shared_port_fd; + int shared_queue_fd; + int log_fd; }; - typedef ssize_t (*nxt_unit_read_func_t)(nxt_unit_read_info_t *read_info, - void *dst, size_t size); - + void *dst, size_t size); struct nxt_unit_read_info_s { - nxt_unit_read_func_t read; - int eof; - uint32_t buf_size; - void *data; + nxt_unit_read_func_t read; + int eof; + uint32_t buf_size; + void *data; }; - /* * Initialize Unit application library with necessary callbacks and * ready/reply port parameters, send 'READY' response to main. @@ -243,11 +232,12 @@ nxt_unit_ctx_t *nxt_unit_ctx_alloc(nxt_unit_ctx_t *, void *); void nxt_unit_port_id_init(nxt_unit_port_id_t *port_id, pid_t pid, uint16_t id); /* Calculates hash for given field name. */ -uint16_t nxt_unit_field_hash(const char* name, size_t name_length); +uint16_t nxt_unit_field_hash(const char *name, size_t name_length); /* Split host for server name and port. */ -void nxt_unit_split_host(char *host_start, uint32_t host_length, - char **name, uint32_t *name_length, char **port, uint32_t *port_length); +void nxt_unit_split_host(char *host_start, uint32_t host_length, char **name, + uint32_t *name_length, char **port, + uint32_t *port_length); /* Group duplicate fields for easy enumeration. */ void nxt_unit_request_group_dup_fields(nxt_unit_request_info_t *req); @@ -257,20 +247,21 @@ void nxt_unit_request_group_dup_fields(nxt_unit_request_info_t *req); * The structure may be accessed directly via req->response pointer or * filled step-by-step using functions add_field and add_content. */ -int nxt_unit_response_init(nxt_unit_request_info_t *req, - uint16_t status, uint32_t max_fields_count, uint32_t max_fields_size); +int nxt_unit_response_init(nxt_unit_request_info_t *req, uint16_t status, + uint32_t max_fields_count, uint32_t max_fields_size); int nxt_unit_response_realloc(nxt_unit_request_info_t *req, - uint32_t max_fields_count, uint32_t max_fields_size); + uint32_t max_fields_count, + uint32_t max_fields_size); int nxt_unit_response_is_init(nxt_unit_request_info_t *req); -int nxt_unit_response_add_field(nxt_unit_request_info_t *req, - const char* name, uint8_t name_length, - const char* value, uint32_t value_length); +int nxt_unit_response_add_field(nxt_unit_request_info_t *req, const char *name, + uint8_t name_length, const char *value, + uint32_t value_length); -int nxt_unit_response_add_content(nxt_unit_request_info_t *req, - const void* src, uint32_t size); +int nxt_unit_response_add_content(nxt_unit_request_info_t *req, const void *src, + uint32_t size); /* * Send the prepared response to the Unit server. The Response structure is @@ -281,7 +272,7 @@ int nxt_unit_response_send(nxt_unit_request_info_t *req); int nxt_unit_response_is_sent(nxt_unit_request_info_t *req); nxt_unit_buf_t *nxt_unit_response_buf_alloc(nxt_unit_request_info_t *req, - uint32_t size); + uint32_t size); int nxt_unit_request_is_websocket_handshake(nxt_unit_request_info_t *req); @@ -302,37 +293,36 @@ uint32_t nxt_unit_buf_max(void); uint32_t nxt_unit_buf_min(void); int nxt_unit_response_write(nxt_unit_request_info_t *req, const void *start, - size_t size); + size_t size); ssize_t nxt_unit_response_write_nb(nxt_unit_request_info_t *req, - const void *start, size_t size, size_t min_size); + const void *start, size_t size, + size_t min_size); int nxt_unit_response_write_cb(nxt_unit_request_info_t *req, - nxt_unit_read_info_t *read_info); + nxt_unit_read_info_t *read_info); ssize_t nxt_unit_request_read(nxt_unit_request_info_t *req, void *dst, - size_t size); + size_t size); ssize_t nxt_unit_request_readline_size(nxt_unit_request_info_t *req, - size_t max_size); + size_t max_size); void nxt_unit_request_done(nxt_unit_request_info_t *req, int rc); - int nxt_unit_websocket_send(nxt_unit_request_info_t *req, uint8_t opcode, - uint8_t last, const void *start, size_t size); + uint8_t last, const void *start, size_t size); int nxt_unit_websocket_sendv(nxt_unit_request_info_t *req, uint8_t opcode, - uint8_t last, const struct iovec *iov, int iovcnt); + uint8_t last, const struct iovec *iov, int iovcnt); ssize_t nxt_unit_websocket_read(nxt_unit_websocket_frame_t *ws, void *dst, - size_t size); + size_t size); int nxt_unit_websocket_retain(nxt_unit_websocket_frame_t *ws); void nxt_unit_websocket_done(nxt_unit_websocket_frame_t *ws); - void *nxt_unit_malloc(nxt_unit_ctx_t *ctx, size_t size); void nxt_unit_free(nxt_unit_ctx_t *ctx, void *p); @@ -341,33 +331,31 @@ void nxt_unit_free(nxt_unit_ctx_t *ctx, void *p); #if __has_attribute(format) -#define NXT_ATTR_FORMAT __attribute__((format(printf, 3, 4))) +#define NXT_ATTR_FORMAT __attribute__((format(printf, 3, 4))) #endif #endif - #if !defined(NXT_ATTR_FORMAT) #define NXT_ATTR_FORMAT #endif +void nxt_unit_log(nxt_unit_ctx_t *ctx, int level, const char *fmt, + ...) NXT_ATTR_FORMAT; -void nxt_unit_log(nxt_unit_ctx_t *ctx, int level, const char* fmt, ...) - NXT_ATTR_FORMAT; - -void nxt_unit_req_log(nxt_unit_request_info_t *req, int level, - const char* fmt, ...) NXT_ATTR_FORMAT; +void nxt_unit_req_log(nxt_unit_request_info_t *req, int level, const char *fmt, + ...) NXT_ATTR_FORMAT; #if (NXT_DEBUG) -#define nxt_unit_debug(ctx, fmt, ARGS...) \ - nxt_unit_log(ctx, NXT_UNIT_LOG_DEBUG, fmt, ##ARGS) +#define nxt_unit_debug(ctx, fmt, ARGS...) \ + nxt_unit_log(ctx, NXT_UNIT_LOG_DEBUG, fmt, ##ARGS) -#define nxt_unit_req_debug(req, fmt, ARGS...) \ - nxt_unit_req_log(req, NXT_UNIT_LOG_DEBUG, fmt, ##ARGS) +#define nxt_unit_req_debug(req, fmt, ARGS...) \ + nxt_unit_req_log(req, NXT_UNIT_LOG_DEBUG, fmt, ##ARGS) #else @@ -377,24 +365,22 @@ void nxt_unit_req_log(nxt_unit_request_info_t *req, int level, #endif +#define nxt_unit_warn(ctx, fmt, ARGS...) \ + nxt_unit_log(ctx, NXT_UNIT_LOG_WARN, fmt, ##ARGS) -#define nxt_unit_warn(ctx, fmt, ARGS...) \ - nxt_unit_log(ctx, NXT_UNIT_LOG_WARN, fmt, ##ARGS) - -#define nxt_unit_req_warn(req, fmt, ARGS...) \ - nxt_unit_req_log(req, NXT_UNIT_LOG_WARN, fmt, ##ARGS) - -#define nxt_unit_error(ctx, fmt, ARGS...) \ - nxt_unit_log(ctx, NXT_UNIT_LOG_ERR, fmt, ##ARGS) +#define nxt_unit_req_warn(req, fmt, ARGS...) \ + nxt_unit_req_log(req, NXT_UNIT_LOG_WARN, fmt, ##ARGS) -#define nxt_unit_req_error(req, fmt, ARGS...) \ - nxt_unit_req_log(req, NXT_UNIT_LOG_ERR, fmt, ##ARGS) +#define nxt_unit_error(ctx, fmt, ARGS...) \ + nxt_unit_log(ctx, NXT_UNIT_LOG_ERR, fmt, ##ARGS) -#define nxt_unit_alert(ctx, fmt, ARGS...) \ - nxt_unit_log(ctx, NXT_UNIT_LOG_ALERT, fmt, ##ARGS) +#define nxt_unit_req_error(req, fmt, ARGS...) \ + nxt_unit_req_log(req, NXT_UNIT_LOG_ERR, fmt, ##ARGS) -#define nxt_unit_req_alert(req, fmt, ARGS...) \ - nxt_unit_req_log(req, NXT_UNIT_LOG_ALERT, fmt, ##ARGS) +#define nxt_unit_alert(ctx, fmt, ARGS...) \ + nxt_unit_log(ctx, NXT_UNIT_LOG_ALERT, fmt, ##ARGS) +#define nxt_unit_req_alert(req, fmt, ARGS...) \ + nxt_unit_req_log(req, NXT_UNIT_LOG_ALERT, fmt, ##ARGS) #endif /* _NXT_UNIT_H_INCLUDED_ */ diff --git a/src/nxt_unit_field.h b/src/nxt_unit_field.h index b07d3046b..f4fc97525 100644 --- a/src/nxt_unit_field.h +++ b/src/nxt_unit_field.h @@ -6,29 +6,26 @@ #ifndef _NXT_UNIT_FIELD_H_INCLUDED_ #define _NXT_UNIT_FIELD_H_INCLUDED_ - #include #include "nxt_unit_sptr.h" enum { - NXT_UNIT_HASH_CONTENT_LENGTH = 0x1EA0, - NXT_UNIT_HASH_CONTENT_TYPE = 0x5F7D, - NXT_UNIT_HASH_COOKIE = 0x23F2, + NXT_UNIT_HASH_CONTENT_LENGTH = 0x1EA0, + NXT_UNIT_HASH_CONTENT_TYPE = 0x5F7D, + NXT_UNIT_HASH_COOKIE = 0x23F2, }; - /* Name and Value field aka HTTP header. */ struct nxt_unit_field_s { - uint16_t hash; - uint8_t skip:1; - uint8_t hopbyhop:1; - uint8_t name_length; - uint32_t value_length; - - nxt_unit_sptr_t name; - nxt_unit_sptr_t value; + uint16_t hash; + uint8_t skip : 1; + uint8_t hopbyhop : 1; + uint8_t name_length; + uint32_t value_length; + + nxt_unit_sptr_t name; + nxt_unit_sptr_t value; }; - #endif /* _NXT_UNIT_FIELD_H_INCLUDED_ */ diff --git a/src/nxt_unit_request.h b/src/nxt_unit_request.h index a6ebf0b63..2933d3be7 100644 --- a/src/nxt_unit_request.h +++ b/src/nxt_unit_request.h @@ -6,50 +6,47 @@ #ifndef _NXT_UNIT_REQUEST_H_INCLUDED_ #define _NXT_UNIT_REQUEST_H_INCLUDED_ - #include #include "nxt_unit_sptr.h" #include "nxt_unit_field.h" -#define NXT_UNIT_NONE_FIELD 0xFFFFFFFFU +#define NXT_UNIT_NONE_FIELD 0xFFFFFFFFU struct nxt_unit_request_s { - uint8_t method_length; - uint8_t version_length; - uint8_t remote_length; - uint8_t local_addr_length; - uint8_t local_port_length; - uint8_t tls; - uint8_t websocket_handshake; - uint8_t app_target; - uint32_t server_name_length; - uint32_t target_length; - uint32_t path_length; - uint32_t query_length; - uint32_t fields_count; - - uint32_t content_length_field; - uint32_t content_type_field; - uint32_t cookie_field; - uint32_t authorization_field; - - uint64_t content_length; - - nxt_unit_sptr_t method; - nxt_unit_sptr_t version; - nxt_unit_sptr_t remote; - nxt_unit_sptr_t local_addr; - nxt_unit_sptr_t local_port; - nxt_unit_sptr_t server_name; - nxt_unit_sptr_t target; - nxt_unit_sptr_t path; - nxt_unit_sptr_t query; - nxt_unit_sptr_t preread_content; - - nxt_unit_field_t fields[]; + uint8_t method_length; + uint8_t version_length; + uint8_t remote_length; + uint8_t local_addr_length; + uint8_t local_port_length; + uint8_t tls; + uint8_t websocket_handshake; + uint8_t app_target; + uint32_t server_name_length; + uint32_t target_length; + uint32_t path_length; + uint32_t query_length; + uint32_t fields_count; + + uint32_t content_length_field; + uint32_t content_type_field; + uint32_t cookie_field; + uint32_t authorization_field; + + uint64_t content_length; + + nxt_unit_sptr_t method; + nxt_unit_sptr_t version; + nxt_unit_sptr_t remote; + nxt_unit_sptr_t local_addr; + nxt_unit_sptr_t local_port; + nxt_unit_sptr_t server_name; + nxt_unit_sptr_t target; + nxt_unit_sptr_t path; + nxt_unit_sptr_t query; + nxt_unit_sptr_t preread_content; + + nxt_unit_field_t fields[]; }; - #endif /* _NXT_UNIT_REQUEST_H_INCLUDED_ */ - diff --git a/src/nxt_unit_response.h b/src/nxt_unit_response.h index 481ed701c..9a77bbbd5 100644 --- a/src/nxt_unit_response.h +++ b/src/nxt_unit_response.h @@ -6,22 +6,20 @@ #ifndef _NXT_UNIT_RESPONSE_H_INCLUDED_ #define _NXT_UNIT_RESPONSE_H_INCLUDED_ - #include #include "nxt_unit_sptr.h" #include "nxt_unit_field.h" struct nxt_unit_response_s { - uint64_t content_length; - uint32_t fields_count; - uint32_t piggyback_content_length; - uint16_t status; + uint64_t content_length; + uint32_t fields_count; + uint32_t piggyback_content_length; + uint16_t status; - nxt_unit_sptr_t piggyback_content; + nxt_unit_sptr_t piggyback_content; - nxt_unit_field_t fields[]; + nxt_unit_field_t fields[]; }; - #endif /* _NXT_UNIT_RESPONSE_H_INCLUDED_ */ diff --git a/src/nxt_unit_sptr.h b/src/nxt_unit_sptr.h index 314416e4e..e77fb9c30 100644 --- a/src/nxt_unit_sptr.h +++ b/src/nxt_unit_sptr.h @@ -6,33 +6,24 @@ #ifndef _NXT_UNIT_SPTR_H_INCLUDED_ #define _NXT_UNIT_SPTR_H_INCLUDED_ - #include #include #include #include "nxt_unit_typedefs.h" - /* Serialized pointer. */ union nxt_unit_sptr_u { - uint8_t base[1]; - uint32_t offset; + uint8_t base[1]; + uint32_t offset; }; - -static inline void -nxt_unit_sptr_set(nxt_unit_sptr_t *sptr, void *ptr) -{ - sptr->offset = (uint8_t *) ptr - sptr->base; +static inline void nxt_unit_sptr_set(nxt_unit_sptr_t *sptr, void *ptr) { + sptr->offset = (uint8_t *)ptr - sptr->base; } - -static inline void * -nxt_unit_sptr_get(nxt_unit_sptr_t *sptr) -{ - return sptr->base + sptr->offset; +static inline void *nxt_unit_sptr_get(nxt_unit_sptr_t *sptr) { + return sptr->base + sptr->offset; } - #endif /* _NXT_UNIT_SPTR_H_INCLUDED_ */ diff --git a/src/nxt_unit_typedefs.h b/src/nxt_unit_typedefs.h index 26e54f913..b89c1b6aa 100644 --- a/src/nxt_unit_typedefs.h +++ b/src/nxt_unit_typedefs.h @@ -6,21 +6,19 @@ #ifndef _NXT_UNIT_TYPEDEFS_H_INCLUDED_ #define _NXT_UNIT_TYPEDEFS_H_INCLUDED_ - -typedef struct nxt_unit_s nxt_unit_t; -typedef struct nxt_unit_ctx_s nxt_unit_ctx_t; -typedef struct nxt_unit_port_id_s nxt_unit_port_id_t; -typedef struct nxt_unit_port_s nxt_unit_port_t; -typedef struct nxt_unit_buf_s nxt_unit_buf_t; -typedef struct nxt_unit_request_info_s nxt_unit_request_info_t; -typedef struct nxt_unit_callbacks_s nxt_unit_callbacks_t; -typedef struct nxt_unit_init_s nxt_unit_init_t; -typedef union nxt_unit_sptr_u nxt_unit_sptr_t; -typedef struct nxt_unit_field_s nxt_unit_field_t; -typedef struct nxt_unit_request_s nxt_unit_request_t; -typedef struct nxt_unit_response_s nxt_unit_response_t; -typedef struct nxt_unit_read_info_s nxt_unit_read_info_t; -typedef struct nxt_unit_websocket_frame_s nxt_unit_websocket_frame_t; - +typedef struct nxt_unit_s nxt_unit_t; +typedef struct nxt_unit_ctx_s nxt_unit_ctx_t; +typedef struct nxt_unit_port_id_s nxt_unit_port_id_t; +typedef struct nxt_unit_port_s nxt_unit_port_t; +typedef struct nxt_unit_buf_s nxt_unit_buf_t; +typedef struct nxt_unit_request_info_s nxt_unit_request_info_t; +typedef struct nxt_unit_callbacks_s nxt_unit_callbacks_t; +typedef struct nxt_unit_init_s nxt_unit_init_t; +typedef union nxt_unit_sptr_u nxt_unit_sptr_t; +typedef struct nxt_unit_field_s nxt_unit_field_t; +typedef struct nxt_unit_request_s nxt_unit_request_t; +typedef struct nxt_unit_response_s nxt_unit_response_t; +typedef struct nxt_unit_read_info_s nxt_unit_read_info_t; +typedef struct nxt_unit_websocket_frame_s nxt_unit_websocket_frame_t; #endif /* _NXT_UNIT_TYPEDEFS_H_INCLUDED_ */ diff --git a/src/nxt_unit_websocket.h b/src/nxt_unit_websocket.h index beb2536ef..faafc6bc9 100644 --- a/src/nxt_unit_websocket.h +++ b/src/nxt_unit_websocket.h @@ -11,17 +11,15 @@ #include "nxt_unit_typedefs.h" #include "nxt_websocket_header.h" - struct nxt_unit_websocket_frame_s { - nxt_unit_request_info_t *req; + nxt_unit_request_info_t *req; - uint64_t payload_len; - nxt_websocket_header_t *header; - uint8_t *mask; + uint64_t payload_len; + nxt_websocket_header_t *header; + uint8_t *mask; - nxt_unit_buf_t *content_buf; - uint64_t content_length; + nxt_unit_buf_t *content_buf; + uint64_t content_length; }; - #endif /* _NXT_UNIT_WEBSOCKET_H_INCLUDED_ */ diff --git a/src/nxt_unix.h b/src/nxt_unix.h index 6bc6be5ee..a46c36d1b 100644 --- a/src/nxt_unix.h +++ b/src/nxt_unix.h @@ -4,11 +4,9 @@ * Copyright (C) NGINX, Inc. */ - #ifndef _NXT_UNIX_H_INCLUDED_ #define _NXT_UNIX_H_INCLUDED_ - #if (NXT_LINUX) #ifdef _FORTIFY_SOURCE @@ -24,51 +22,49 @@ #endif #ifndef _GNU_SOURCE -#define _GNU_SOURCE /* pread(), pwrite(), gethostname(). */ +#define _GNU_SOURCE /* pread(), pwrite(), gethostname(). */ #endif -#define _FILE_OFFSET_BITS 64 +#define _FILE_OFFSET_BITS 64 -#include /* malloc_usable_size(). */ -#include /* syscall(SYS_gettid). */ +#include /* malloc_usable_size(). */ +#include /* syscall(SYS_gettid). */ #if (__GLIBC__ >= 2 && __GLIBC_MINOR__ >= 4) /* * POSIX semaphores using NPTL atomic/futex operations * were introduced during glibc 2.3 development time. */ -#define NXT_HAVE_SEM_TRYWAIT_FAST 1 +#define NXT_HAVE_SEM_TRYWAIT_FAST 1 #endif #endif /* NXT_LINUX */ - #if (NXT_FREEBSD) #if (NXT_HAVE_MALLOC_USABLE_SIZE) -#include /* malloc_usable_size(). */ +#include /* malloc_usable_size(). */ #endif #if (__FreeBSD_version >= 900007) /* POSIX semaphores using atomic/umtx. */ -#define NXT_HAVE_SEM_TRYWAIT_FAST 1 +#define NXT_HAVE_SEM_TRYWAIT_FAST 1 #endif #endif /* NXT_FREEBSD */ - #if (NXT_SOLARIS) #ifndef _FILE_OFFSET_BITS -#define _FILE_OFFSET_BITS 64 /* Must be before . */ +#define _FILE_OFFSET_BITS 64 /* Must be before . */ #endif -#ifndef _REENTRANT /* May be set by "-mt" options. */ -#define _REENTRANT /* Thread safe errno. */ +#ifndef _REENTRANT /* May be set by "-mt" options. */ +#define _REENTRANT /* Thread safe errno. */ #endif #ifndef _POSIX_PTHREAD_SEMANTICS -#define _POSIX_PTHREAD_SEMANTICS /* 2 arguments in sigwait(). */ +#define _POSIX_PTHREAD_SEMANTICS /* 2 arguments in sigwait(). */ #endif /* @@ -82,7 +78,7 @@ /* Enable X/Open sockets API. */ #define _XOPEN_SOURCE -#define _XOPEN_SOURCE_EXTENDED 1 +#define _XOPEN_SOURCE_EXTENDED 1 /* Enable Solaris extensions disabled by _XOPEN_SOURCE. */ #ifndef __EXTENSIONS__ #define __EXTENSIONS__ @@ -90,29 +86,26 @@ #endif /* NXT_SOLARIS */ - #if (NXT_MACOSX) #ifndef _DARWIN_C_SOURCE -#define _DARWIN_C_SOURCE /* pthread_threadid_np(), mach_port_t. */ +#define _DARWIN_C_SOURCE /* pthread_threadid_np(), mach_port_t. */ #endif -#include /* mach_absolute_time(). */ -#include /* malloc_size(). */ +#include /* mach_absolute_time(). */ +#include /* malloc_size(). */ #endif /* NXT_MACOSX */ - #if (NXT_AIX) -#define _THREAD_SAFE /* Must before any include. */ +#define _THREAD_SAFE /* Must before any include. */ #endif /* NXT_AIX */ - #if (NXT_HPUX) -#define _FILE_OFFSET_BITS 64 +#define _FILE_OFFSET_BITS 64 /* * HP-UX provides three sockets API: @@ -138,7 +131,6 @@ #endif /* NXT_HPUX */ - #if (NXT_HAVE_ALLOCA_H) #include #endif @@ -158,18 +150,18 @@ #include #include #include -#include /* offsetof() */ +#include /* offsetof() */ #include #include #include #include #include #if (NXT_HAVE_SYS_FILIO_H) -#include /* FIONBIO */ +#include /* FIONBIO */ #endif #include #include -#include /* MAXPATHLEN */ +#include /* MAXPATHLEN */ #include #include #include @@ -191,7 +183,7 @@ /* * Epoll edge-tiggered mode is pretty much useless without EPOLLRDHUP support. */ -#define NXT_HAVE_EPOLL_EDGE 1 +#define NXT_HAVE_EPOLL_EDGE 1 #endif #endif @@ -229,11 +221,11 @@ #endif #if (NXT_HAVE_GETRANDOM) -#include /* getrandom(). */ +#include /* getrandom(). */ #elif (NXT_HAVE_LINUX_SYS_GETRANDOM) -#include /* SYS_getrandom. */ +#include /* SYS_getrandom. */ #elif (NXT_HAVE_GETENTROPY_SYS_RANDOM) -#include /* getentropy(). */ +#include /* getentropy(). */ #endif #if (NXT_HAVE_ISOLATION_ROOTFS) @@ -248,7 +240,6 @@ #include #endif - /* * On Linux IOV_MAX is 1024. Linux uses kernel stack for 8 iovec's * to avoid kernel allocation/deallocation. @@ -268,25 +259,20 @@ * * On AIX and HP-UX IOV_MAX is 16. */ -#define NXT_IOBUF_MAX 8 - - -typedef struct iovec nxt_iobuf_t; +#define NXT_IOBUF_MAX 8 -#define nxt_iobuf_data(iob) \ - (iob)->iov_base +typedef struct iovec nxt_iobuf_t; -#define nxt_iobuf_size(iob) \ - (iob)->iov_len +#define nxt_iobuf_data(iob) (iob)->iov_base -#define nxt_iobuf_set(iob, p, size) \ - do { \ - (iob)->iov_base = (void *) p; \ - (iob)->iov_len = size; \ - } while (0) +#define nxt_iobuf_size(iob) (iob)->iov_len -#define nxt_iobuf_add(iob, size) \ - (iob)->iov_len += size +#define nxt_iobuf_set(iob, p, size) \ + do { \ + (iob)->iov_base = (void *)p; \ + (iob)->iov_len = size; \ + } while (0) +#define nxt_iobuf_add(iob, size) (iob)->iov_len += size #endif /* _NXT_UNIX_H_INCLUDED_ */ diff --git a/src/nxt_upstream.c b/src/nxt_upstream.c index c92d4a50b..739cbd7ca 100644 --- a/src/nxt_upstream.c +++ b/src/nxt_upstream.c @@ -8,144 +8,133 @@ #include #include - static nxt_http_action_t *nxt_upstream_handler(nxt_task_t *task, - nxt_http_request_t *r, nxt_http_action_t *action); - + nxt_http_request_t *r, + nxt_http_action_t *action); -nxt_int_t -nxt_upstreams_create(nxt_task_t *task, nxt_router_temp_conf_t *tmcf, - nxt_conf_value_t *conf) -{ - size_t size; - uint32_t i, n, next; - nxt_mp_t *mp; - nxt_int_t ret; - nxt_str_t name, *string; - nxt_upstreams_t *upstreams; - nxt_conf_value_t *upstreams_conf, *upcf; +nxt_int_t nxt_upstreams_create(nxt_task_t *task, nxt_router_temp_conf_t *tmcf, + nxt_conf_value_t *conf) { + size_t size; + uint32_t i, n, next; + nxt_mp_t *mp; + nxt_int_t ret; + nxt_str_t name, *string; + nxt_upstreams_t *upstreams; + nxt_conf_value_t *upstreams_conf, *upcf; - static const nxt_str_t upstreams_name = nxt_string("upstreams"); + static const nxt_str_t upstreams_name = nxt_string("upstreams"); - upstreams_conf = nxt_conf_get_object_member(conf, &upstreams_name, NULL); + upstreams_conf = nxt_conf_get_object_member(conf, &upstreams_name, NULL); - if (upstreams_conf == NULL) { - return NXT_OK; - } + if (upstreams_conf == NULL) { + return NXT_OK; + } - n = nxt_conf_object_members_count(upstreams_conf); + n = nxt_conf_object_members_count(upstreams_conf); - if (n == 0) { - return NXT_OK; - } + if (n == 0) { + return NXT_OK; + } - mp = tmcf->router_conf->mem_pool; - size = sizeof(nxt_upstreams_t) + n * sizeof(nxt_upstream_t); + mp = tmcf->router_conf->mem_pool; + size = sizeof(nxt_upstreams_t) + n * sizeof(nxt_upstream_t); - upstreams = nxt_mp_zalloc(mp, size); - if (nxt_slow_path(upstreams == NULL)) { - return NXT_ERROR; - } + upstreams = nxt_mp_zalloc(mp, size); + if (nxt_slow_path(upstreams == NULL)) { + return NXT_ERROR; + } - upstreams->items = n; - next = 0; + upstreams->items = n; + next = 0; - for (i = 0; i < n; i++) { - upcf = nxt_conf_next_object_member(upstreams_conf, &name, &next); + for (i = 0; i < n; i++) { + upcf = nxt_conf_next_object_member(upstreams_conf, &name, &next); - string = nxt_str_dup(mp, &upstreams->upstream[i].name, &name); - if (nxt_slow_path(string == NULL)) { - return NXT_ERROR; - } + string = nxt_str_dup(mp, &upstreams->upstream[i].name, &name); + if (nxt_slow_path(string == NULL)) { + return NXT_ERROR; + } - ret = nxt_upstream_round_robin_create(task, tmcf, upcf, - &upstreams->upstream[i]); - if (nxt_slow_path(ret != NXT_OK)) { - return NXT_ERROR; - } + ret = nxt_upstream_round_robin_create(task, tmcf, upcf, + &upstreams->upstream[i]); + if (nxt_slow_path(ret != NXT_OK)) { + return NXT_ERROR; } + } - tmcf->router_conf->upstreams = upstreams; + tmcf->router_conf->upstreams = upstreams; - return NXT_OK; + return NXT_OK; } +nxt_int_t nxt_upstream_find(nxt_upstreams_t *upstreams, nxt_str_t *name, + nxt_http_action_t *action) { + uint32_t i, n; + nxt_upstream_t *upstream; -nxt_int_t -nxt_upstream_find(nxt_upstreams_t *upstreams, nxt_str_t *name, - nxt_http_action_t *action) -{ - uint32_t i, n; - nxt_upstream_t *upstream; - - if (upstreams == NULL) { - return NXT_DECLINED; - } + if (upstreams == NULL) { + return NXT_DECLINED; + } - upstream = &upstreams->upstream[0]; - n = upstreams->items; + upstream = &upstreams->upstream[0]; + n = upstreams->items; - for (i = 0; i < n; i++) { - if (nxt_strstr_eq(&upstream[i].name, name)) { - action->u.upstream_number = i; - action->handler = nxt_upstream_handler; + for (i = 0; i < n; i++) { + if (nxt_strstr_eq(&upstream[i].name, name)) { + action->u.upstream_number = i; + action->handler = nxt_upstream_handler; - return NXT_OK; - } + return NXT_OK; } + } - return NXT_DECLINED; + return NXT_DECLINED; } +nxt_int_t nxt_upstreams_joint_create(nxt_router_temp_conf_t *tmcf, + nxt_upstream_t ***upstream_joint) { + uint32_t i, n; + nxt_upstream_t *u, **up; + nxt_upstreams_t *upstreams; + nxt_router_conf_t *router_conf; -nxt_int_t -nxt_upstreams_joint_create(nxt_router_temp_conf_t *tmcf, - nxt_upstream_t ***upstream_joint) -{ - uint32_t i, n; - nxt_upstream_t *u, **up; - nxt_upstreams_t *upstreams; - nxt_router_conf_t *router_conf; + router_conf = tmcf->router_conf; + upstreams = router_conf->upstreams; - router_conf = tmcf->router_conf; - upstreams = router_conf->upstreams; - - if (upstreams == NULL) { - *upstream_joint = NULL; - return NXT_OK; - } + if (upstreams == NULL) { + *upstream_joint = NULL; + return NXT_OK; + } - n = upstreams->items; + n = upstreams->items; - up = nxt_mp_zalloc(router_conf->mem_pool, n * sizeof(nxt_upstream_t *)); - if (nxt_slow_path(up == NULL)) { - return NXT_ERROR; - } + up = nxt_mp_zalloc(router_conf->mem_pool, n * sizeof(nxt_upstream_t *)); + if (nxt_slow_path(up == NULL)) { + return NXT_ERROR; + } - u = &upstreams->upstream[0]; + u = &upstreams->upstream[0]; - for (i = 0; i < n; i++) { - up[i] = u[i].proto->joint_create(tmcf, &u[i]); - if (nxt_slow_path(up[i] == NULL)) { - return NXT_ERROR; - } + for (i = 0; i < n; i++) { + up[i] = u[i].proto->joint_create(tmcf, &u[i]); + if (nxt_slow_path(up[i] == NULL)) { + return NXT_ERROR; } + } - *upstream_joint = up; + *upstream_joint = up; - return NXT_OK; + return NXT_OK; } +static nxt_http_action_t *nxt_upstream_handler(nxt_task_t *task, + nxt_http_request_t *r, + nxt_http_action_t *action) { + nxt_upstream_t *u; -static nxt_http_action_t * -nxt_upstream_handler(nxt_task_t *task, nxt_http_request_t *r, - nxt_http_action_t *action) -{ - nxt_upstream_t *u; - - u = r->conf->upstreams[action->u.upstream_number]; + u = r->conf->upstreams[action->u.upstream_number]; - nxt_debug(task, "upstream handler: \"%V\"", &u->name); + nxt_debug(task, "upstream handler: \"%V\"", &u->name); - return nxt_upstream_proxy_handler(task, r, u); + return nxt_upstream_proxy_handler(task, r, u); } diff --git a/src/nxt_upstream.h b/src/nxt_upstream.h index 0c3b4c8b1..99baf0e7b 100644 --- a/src/nxt_upstream.h +++ b/src/nxt_upstream.h @@ -7,75 +7,66 @@ #ifndef _NXT_UPSTREAM_H_INCLUDED_ #define _NXT_UPSTREAM_H_INCLUDED_ - -typedef struct nxt_upstream_proxy_s nxt_upstream_proxy_t; -typedef struct nxt_upstream_round_robin_s nxt_upstream_round_robin_t; +typedef struct nxt_upstream_proxy_s nxt_upstream_proxy_t; +typedef struct nxt_upstream_round_robin_s nxt_upstream_round_robin_t; typedef struct nxt_upstream_round_robin_server_s nxt_upstream_round_robin_server_t; - typedef void (*nxt_upstream_peer_ready_t)(nxt_task_t *task, - nxt_upstream_server_t *us); + nxt_upstream_server_t *us); typedef void (*nxt_upstream_peer_error_t)(nxt_task_t *task, - nxt_upstream_server_t *us); - + nxt_upstream_server_t *us); typedef struct { - nxt_upstream_peer_ready_t ready; - nxt_upstream_peer_error_t error; + nxt_upstream_peer_ready_t ready; + nxt_upstream_peer_error_t error; } nxt_upstream_peer_state_t; - typedef nxt_upstream_t *(*nxt_upstream_joint_create_t)( nxt_router_temp_conf_t *tmcf, nxt_upstream_t *upstream); typedef void (*nxt_upstream_server_get_t)(nxt_task_t *task, - nxt_upstream_server_t *us); - + nxt_upstream_server_t *us); typedef struct { - nxt_upstream_joint_create_t joint_create; - nxt_upstream_server_get_t get; + nxt_upstream_joint_create_t joint_create; + nxt_upstream_server_get_t get; } nxt_upstream_server_proto_t; - struct nxt_upstream_s { - const nxt_upstream_server_proto_t *proto; + const nxt_upstream_server_proto_t *proto; - union { - nxt_upstream_proxy_t *proxy; - nxt_upstream_round_robin_t *round_robin; - } type; + union { + nxt_upstream_proxy_t *proxy; + nxt_upstream_round_robin_t *round_robin; + } type; - nxt_str_t name; + nxt_str_t name; }; - struct nxt_upstreams_s { - uint32_t items; - nxt_upstream_t upstream[]; + uint32_t items; + nxt_upstream_t upstream[]; }; - struct nxt_upstream_server_s { - nxt_sockaddr_t *sockaddr; - const nxt_upstream_peer_state_t *state; - nxt_upstream_t *upstream; + nxt_sockaddr_t *sockaddr; + const nxt_upstream_peer_state_t *state; + nxt_upstream_t *upstream; - uint8_t protocol; + uint8_t protocol; - union { - nxt_upstream_round_robin_server_t *round_robin; - } server; + union { + nxt_upstream_round_robin_server_t *round_robin; + } server; - union { - nxt_http_peer_t *http; - } peer; + union { + nxt_http_peer_t *http; + } peer; }; - nxt_int_t nxt_upstream_round_robin_create(nxt_task_t *task, - nxt_router_temp_conf_t *tmcf, nxt_conf_value_t *upstream_conf, - nxt_upstream_t *upstream); - + nxt_router_temp_conf_t *tmcf, + nxt_conf_value_t *upstream_conf, + nxt_upstream_t *upstream); #endif /* _NXT_UPSTREAM_H_INCLUDED_ */ diff --git a/src/nxt_upstream_round_robin.c b/src/nxt_upstream_round_robin.c index 96c3e44e1..f3933f41a 100644 --- a/src/nxt_upstream_round_robin.c +++ b/src/nxt_upstream_round_robin.c @@ -9,197 +9,189 @@ #include #include - struct nxt_upstream_round_robin_server_s { - nxt_sockaddr_t *sockaddr; + nxt_sockaddr_t *sockaddr; - int32_t current_weight; - int32_t effective_weight; - int32_t weight; + int32_t current_weight; + int32_t effective_weight; + int32_t weight; - uint8_t protocol; + uint8_t protocol; }; - struct nxt_upstream_round_robin_s { - uint32_t items; - nxt_upstream_round_robin_server_t server[]; + uint32_t items; + nxt_upstream_round_robin_server_t server[]; }; - -static nxt_upstream_t *nxt_upstream_round_robin_joint_create( - nxt_router_temp_conf_t *tmcf, nxt_upstream_t *upstream); +static nxt_upstream_t * +nxt_upstream_round_robin_joint_create(nxt_router_temp_conf_t *tmcf, + nxt_upstream_t *upstream); static void nxt_upstream_round_robin_server_get(nxt_task_t *task, - nxt_upstream_server_t *us); - + nxt_upstream_server_t *us); -static const nxt_upstream_server_proto_t nxt_upstream_round_robin_proto = { +static const nxt_upstream_server_proto_t nxt_upstream_round_robin_proto = { .joint_create = nxt_upstream_round_robin_joint_create, - .get = nxt_upstream_round_robin_server_get, + .get = nxt_upstream_round_robin_server_get, }; - -nxt_int_t -nxt_upstream_round_robin_create(nxt_task_t *task, nxt_router_temp_conf_t *tmcf, - nxt_conf_value_t *upstream_conf, nxt_upstream_t *upstream) -{ - double total, k, w; - size_t size; - uint32_t i, n, next, wt; - nxt_mp_t *mp; - nxt_str_t name; - nxt_sockaddr_t *sa; - nxt_conf_value_t *servers_conf, *srvcf, *wtcf; - nxt_upstream_round_robin_t *urr; - - static const nxt_str_t servers = nxt_string("servers"); - static const nxt_str_t weight = nxt_string("weight"); - - mp = tmcf->router_conf->mem_pool; - - servers_conf = nxt_conf_get_object_member(upstream_conf, &servers, NULL); - n = nxt_conf_object_members_count(servers_conf); - - total = 0.0; - next = 0; - - for (i = 0; i < n; i++) { - srvcf = nxt_conf_next_object_member(servers_conf, &name, &next); - wtcf = nxt_conf_get_object_member(srvcf, &weight, NULL); - w = (wtcf != NULL) ? nxt_conf_get_number(wtcf) : 1; - total += w; - } - - /* - * This prevents overflow of int32_t - * in nxt_upstream_round_robin_server_get(). - */ - k = (total == 0) ? 0 : (NXT_INT32_T_MAX / 2) / total; - - if (isinf(k)) { - k = 1; +nxt_int_t nxt_upstream_round_robin_create(nxt_task_t *task, + nxt_router_temp_conf_t *tmcf, + nxt_conf_value_t *upstream_conf, + nxt_upstream_t *upstream) { + double total, k, w; + size_t size; + uint32_t i, n, next, wt; + nxt_mp_t *mp; + nxt_str_t name; + nxt_sockaddr_t *sa; + nxt_conf_value_t *servers_conf, *srvcf, *wtcf; + nxt_upstream_round_robin_t *urr; + + static const nxt_str_t servers = nxt_string("servers"); + static const nxt_str_t weight = nxt_string("weight"); + + mp = tmcf->router_conf->mem_pool; + + servers_conf = nxt_conf_get_object_member(upstream_conf, &servers, NULL); + n = nxt_conf_object_members_count(servers_conf); + + total = 0.0; + next = 0; + + for (i = 0; i < n; i++) { + srvcf = nxt_conf_next_object_member(servers_conf, &name, &next); + wtcf = nxt_conf_get_object_member(srvcf, &weight, NULL); + w = (wtcf != NULL) ? nxt_conf_get_number(wtcf) : 1; + total += w; + } + + /* + * This prevents overflow of int32_t + * in nxt_upstream_round_robin_server_get(). + */ + k = (total == 0) ? 0 : (NXT_INT32_T_MAX / 2) / total; + + if (isinf(k)) { + k = 1; + } + + size = sizeof(nxt_upstream_round_robin_t) + + n * sizeof(nxt_upstream_round_robin_server_t); + + urr = nxt_mp_zalloc(mp, size); + if (nxt_slow_path(urr == NULL)) { + return NXT_ERROR; + } + + urr->items = n; + next = 0; + + for (i = 0; i < n; i++) { + srvcf = nxt_conf_next_object_member(servers_conf, &name, &next); + + sa = nxt_sockaddr_parse(mp, &name); + if (nxt_slow_path(sa == NULL)) { + return NXT_ERROR; } - size = sizeof(nxt_upstream_round_robin_t) - + n * sizeof(nxt_upstream_round_robin_server_t); + sa->type = SOCK_STREAM; - urr = nxt_mp_zalloc(mp, size); - if (nxt_slow_path(urr == NULL)) { - return NXT_ERROR; - } - - urr->items = n; - next = 0; - - for (i = 0; i < n; i++) { - srvcf = nxt_conf_next_object_member(servers_conf, &name, &next); - - sa = nxt_sockaddr_parse(mp, &name); - if (nxt_slow_path(sa == NULL)) { - return NXT_ERROR; - } + urr->server[i].sockaddr = sa; + urr->server[i].protocol = NXT_HTTP_PROTO_H1; - sa->type = SOCK_STREAM; + wtcf = nxt_conf_get_object_member(srvcf, &weight, NULL); + w = (wtcf != NULL) ? k * nxt_conf_get_number(wtcf) : k; + wt = (w > 1 || w == 0) ? round(w) : 1; - urr->server[i].sockaddr = sa; - urr->server[i].protocol = NXT_HTTP_PROTO_H1; + urr->server[i].weight = wt; + urr->server[i].effective_weight = wt; + } - wtcf = nxt_conf_get_object_member(srvcf, &weight, NULL); - w = (wtcf != NULL) ? k * nxt_conf_get_number(wtcf) : k; - wt = (w > 1 || w == 0) ? round(w) : 1; + upstream->proto = &nxt_upstream_round_robin_proto; + upstream->type.round_robin = urr; - urr->server[i].weight = wt; - urr->server[i].effective_weight = wt; - } - - upstream->proto = &nxt_upstream_round_robin_proto; - upstream->type.round_robin = urr; - - return NXT_OK; + return NXT_OK; } - static nxt_upstream_t * nxt_upstream_round_robin_joint_create(nxt_router_temp_conf_t *tmcf, - nxt_upstream_t *upstream) -{ - size_t size; - uint32_t i, n; - nxt_mp_t *mp; - nxt_upstream_t *u; - nxt_upstream_round_robin_t *urr, *urrcf; - - mp = tmcf->router_conf->mem_pool; - - u = nxt_mp_alloc(mp, sizeof(nxt_upstream_t)); - if (nxt_slow_path(u == NULL)) { - return NULL; - } + nxt_upstream_t *upstream) { + size_t size; + uint32_t i, n; + nxt_mp_t *mp; + nxt_upstream_t *u; + nxt_upstream_round_robin_t *urr, *urrcf; - *u = *upstream; + mp = tmcf->router_conf->mem_pool; - urrcf = upstream->type.round_robin; + u = nxt_mp_alloc(mp, sizeof(nxt_upstream_t)); + if (nxt_slow_path(u == NULL)) { + return NULL; + } - size = sizeof(nxt_upstream_round_robin_t) - + urrcf->items * sizeof(nxt_upstream_round_robin_server_t); + *u = *upstream; - urr = nxt_mp_alloc(mp, size); - if (nxt_slow_path(urr == NULL)) { - return NULL; - } + urrcf = upstream->type.round_robin; - u->type.round_robin = urr; + size = sizeof(nxt_upstream_round_robin_t) + + urrcf->items * sizeof(nxt_upstream_round_robin_server_t); - n = urrcf->items; - urr->items = n; + urr = nxt_mp_alloc(mp, size); + if (nxt_slow_path(urr == NULL)) { + return NULL; + } - for (i = 0; i < n; i++) { - urr->server[i] = urrcf->server[i]; - } + u->type.round_robin = urr; - return u; -} + n = urrcf->items; + urr->items = n; + for (i = 0; i < n; i++) { + urr->server[i] = urrcf->server[i]; + } -static void -nxt_upstream_round_robin_server_get(nxt_task_t *task, nxt_upstream_server_t *us) -{ - int32_t total; - uint32_t i, n; - nxt_upstream_round_robin_t *round_robin; - nxt_upstream_round_robin_server_t *s, *best; + return u; +} - best = NULL; - total = 0; +static void nxt_upstream_round_robin_server_get(nxt_task_t *task, + nxt_upstream_server_t *us) { + int32_t total; + uint32_t i, n; + nxt_upstream_round_robin_t *round_robin; + nxt_upstream_round_robin_server_t *s, *best; - round_robin = us->upstream->type.round_robin; + best = NULL; + total = 0; - s = round_robin->server; - n = round_robin->items; + round_robin = us->upstream->type.round_robin; - for (i = 0; i < n; i++) { + s = round_robin->server; + n = round_robin->items; - s[i].current_weight += s[i].effective_weight; - total += s[i].effective_weight; + for (i = 0; i < n; i++) { - if (s[i].effective_weight < s[i].weight) { - s[i].effective_weight++; - } + s[i].current_weight += s[i].effective_weight; + total += s[i].effective_weight; - if (best == NULL || s[i].current_weight > best->current_weight) { - best = &s[i]; - } + if (s[i].effective_weight < s[i].weight) { + s[i].effective_weight++; } - if (best == NULL || total == 0) { - us->state->error(task, us); - return; + if (best == NULL || s[i].current_weight > best->current_weight) { + best = &s[i]; } + } + + if (best == NULL || total == 0) { + us->state->error(task, us); + return; + } - best->current_weight -= total; - us->sockaddr = best->sockaddr; - us->protocol = best->protocol; - us->server.round_robin = best; + best->current_weight -= total; + us->sockaddr = best->sockaddr; + us->protocol = best->protocol; + us->server.round_robin = best; - us->state->ready(task, us); + us->state->ready(task, us); } diff --git a/src/nxt_utf8.c b/src/nxt_utf8.c index d983be841..a9005e63d 100644 --- a/src/nxt_utf8.c +++ b/src/nxt_utf8.c @@ -29,245 +29,224 @@ #include #endif - -u_char * -nxt_utf8_encode(u_char *p, uint32_t u) -{ - if (u < 0x80) { - *p++ = (u_char) (u & 0xFF); - return p; - } - - if (u < 0x0800) { - *p++ = (u_char) (( u >> 6) | 0xC0); - *p++ = (u_char) (( u & 0x3F) | 0x80); - return p; - } - - if (u < 0x10000) { - *p++ = (u_char) ( (u >> 12) | 0xE0); - *p++ = (u_char) (((u >> 6) & 0x3F) | 0x80); - *p++ = (u_char) (( u & 0x3F) | 0x80); - return p; - } - - if (u < 0x110000) { - *p++ = (u_char) ( (u >> 18) | 0xF0); - *p++ = (u_char) (((u >> 12) & 0x3F) | 0x80); - *p++ = (u_char) (((u >> 6) & 0x3F) | 0x80); - *p++ = (u_char) (( u & 0x3F) | 0x80); - return p; - } - - return NULL; +u_char *nxt_utf8_encode(u_char *p, uint32_t u) { + if (u < 0x80) { + *p++ = (u_char)(u & 0xFF); + return p; + } + + if (u < 0x0800) { + *p++ = (u_char)((u >> 6) | 0xC0); + *p++ = (u_char)((u & 0x3F) | 0x80); + return p; + } + + if (u < 0x10000) { + *p++ = (u_char)((u >> 12) | 0xE0); + *p++ = (u_char)(((u >> 6) & 0x3F) | 0x80); + *p++ = (u_char)((u & 0x3F) | 0x80); + return p; + } + + if (u < 0x110000) { + *p++ = (u_char)((u >> 18) | 0xF0); + *p++ = (u_char)(((u >> 12) & 0x3F) | 0x80); + *p++ = (u_char)(((u >> 6) & 0x3F) | 0x80); + *p++ = (u_char)((u & 0x3F) | 0x80); + return p; + } + + return NULL; } - /* * nxt_utf8_decode() decodes UTF-8 sequences and returns a valid * character 0x00 - 0x10FFFF, or 0xFFFFFFFF for invalid or overlong * UTF-8 sequence. */ -uint32_t -nxt_utf8_decode(const u_char **start, const u_char *end) -{ - uint32_t u; +uint32_t nxt_utf8_decode(const u_char **start, const u_char *end) { + uint32_t u; - u = (uint32_t) **start; + u = (uint32_t)**start; - if (u < 0x80) { - (*start)++; - return u; - } + if (u < 0x80) { + (*start)++; + return u; + } - return nxt_utf8_decode2(start, end); + return nxt_utf8_decode2(start, end); } - /* * nxt_utf8_decode2() decodes two and more bytes UTF-8 sequences only * and returns a valid character 0x80 - 0x10FFFF, or 0xFFFFFFFF for * invalid or overlong UTF-8 sequence. */ -uint32_t -nxt_utf8_decode2(const u_char **start, const u_char *end) -{ - u_char c; - size_t n; - uint32_t u, overlong; - const u_char *p; +uint32_t nxt_utf8_decode2(const u_char **start, const u_char *end) { + u_char c; + size_t n; + uint32_t u, overlong; + const u_char *p; - p = *start; - u = (uint32_t) *p; + p = *start; + u = (uint32_t)*p; - if (u >= 0xE0) { + if (u >= 0xE0) { - if (u >= 0xF0) { + if (u >= 0xF0) { - if (nxt_slow_path(u > 0xF4)) { - /* - * The maximum valid Unicode character is 0x10FFFF - * which is encoded as 0xF4 0x8F 0xBF 0xBF. - */ - return 0xFFFFFFFF; - } + if (nxt_slow_path(u > 0xF4)) { + /* + * The maximum valid Unicode character is 0x10FFFF + * which is encoded as 0xF4 0x8F 0xBF 0xBF. + */ + return 0xFFFFFFFF; + } - u &= 0x07; - overlong = 0x00FFFF; - n = 3; + u &= 0x07; + overlong = 0x00FFFF; + n = 3; - } else { - u &= 0x0F; - overlong = 0x07FF; - n = 2; - } + } else { + u &= 0x0F; + overlong = 0x07FF; + n = 2; + } - } else if (u >= 0xC2) { + } else if (u >= 0xC2) { - /* 0x80 is encoded as 0xC2 0x80. */ + /* 0x80 is encoded as 0xC2 0x80. */ - u &= 0x1F; - overlong = 0x007F; - n = 1; + u &= 0x1F; + overlong = 0x007F; + n = 1; - } else { - /* u <= 0xC2 */ - return 0xFFFFFFFF; - } + } else { + /* u <= 0xC2 */ + return 0xFFFFFFFF; + } - p++; + p++; - if (nxt_fast_path(p + n <= end)) { + if (nxt_fast_path(p + n <= end)) { - do { - c = *p++; - /* - * The byte must in the 0x80 - 0xBF range. - * Values below 0x80 become >= 0x80. - */ - c = c - 0x80; + do { + c = *p++; + /* + * The byte must in the 0x80 - 0xBF range. + * Values below 0x80 become >= 0x80. + */ + c = c - 0x80; - if (nxt_slow_path(c > 0x3F)) { - return 0xFFFFFFFF; - } + if (nxt_slow_path(c > 0x3F)) { + return 0xFFFFFFFF; + } - u = (u << 6) | c; - n--; + u = (u << 6) | c; + n--; - } while (n != 0); + } while (n != 0); - if (overlong < u && u < 0x110000) { - *start = p; - return u; - } + if (overlong < u && u < 0x110000) { + *start = p; + return u; } + } - return 0xFFFFFFFF; + return 0xFFFFFFFF; } - /* * nxt_utf8_casecmp() tests only up to the minimum of given lengths, but * requires lengths of both strings because otherwise nxt_utf8_decode2() * may fail due to incomplete sequence. */ -nxt_int_t -nxt_utf8_casecmp(const u_char *start1, const u_char *start2, size_t len1, - size_t len2) -{ - int32_t n; - uint32_t u1, u2; - const u_char *end1, *end2; +nxt_int_t nxt_utf8_casecmp(const u_char *start1, const u_char *start2, + size_t len1, size_t len2) { + int32_t n; + uint32_t u1, u2; + const u_char *end1, *end2; - end1 = start1 + len1; - end2 = start2 + len2; + end1 = start1 + len1; + end2 = start2 + len2; - while (start1 < end1 && start2 < end2) { + while (start1 < end1 && start2 < end2) { - u1 = nxt_utf8_lowcase(&start1, end1); + u1 = nxt_utf8_lowcase(&start1, end1); - u2 = nxt_utf8_lowcase(&start2, end2); + u2 = nxt_utf8_lowcase(&start2, end2); - if (nxt_slow_path((u1 | u2) == 0xFFFFFFFF)) { - return NXT_UTF8_SORT_INVALID; - } + if (nxt_slow_path((u1 | u2) == 0xFFFFFFFF)) { + return NXT_UTF8_SORT_INVALID; + } - n = u1 - u2; + n = u1 - u2; - if (n != 0) { - return (nxt_int_t) n; - } + if (n != 0) { + return (nxt_int_t)n; } + } - return 0; + return 0; } +uint32_t nxt_utf8_lowcase(const u_char **start, const u_char *end) { + uint32_t u; + const uint32_t *block; -uint32_t -nxt_utf8_lowcase(const u_char **start, const u_char *end) -{ - uint32_t u; - const uint32_t *block; + u = (uint32_t)**start; - u = (uint32_t) **start; + if (nxt_fast_path(u < 0x80)) { + (*start)++; - if (nxt_fast_path(u < 0x80)) { - (*start)++; + return nxt_unicode_block_000[u]; + } - return nxt_unicode_block_000[u]; - } - - u = nxt_utf8_decode2(start, end); + u = nxt_utf8_decode2(start, end); - if (u <= NXT_UNICODE_MAX_LOWCASE) { - block = nxt_unicode_blocks[u / NXT_UNICODE_BLOCK_SIZE]; + if (u <= NXT_UNICODE_MAX_LOWCASE) { + block = nxt_unicode_blocks[u / NXT_UNICODE_BLOCK_SIZE]; - if (block != NULL) { - return block[u % NXT_UNICODE_BLOCK_SIZE]; - } + if (block != NULL) { + return block[u % NXT_UNICODE_BLOCK_SIZE]; } + } - return u; + return u; } +ssize_t nxt_utf8_length(const u_char *p, size_t len) { + ssize_t length; + const u_char *end; -ssize_t -nxt_utf8_length(const u_char *p, size_t len) -{ - ssize_t length; - const u_char *end; - - length = 0; + length = 0; - end = p + len; + end = p + len; - while (p < end) { - if (nxt_slow_path(nxt_utf8_decode(&p, end) == 0xFFFFFFFF)) { - return -1; - } - - length++; + while (p < end) { + if (nxt_slow_path(nxt_utf8_decode(&p, end) == 0xFFFFFFFF)) { + return -1; } - return length; -} + length++; + } + return length; +} -nxt_bool_t -nxt_utf8_is_valid(const u_char *p, size_t len) -{ - const u_char *end; +nxt_bool_t nxt_utf8_is_valid(const u_char *p, size_t len) { + const u_char *end; - end = p + len; + end = p + len; - while (p < end) { - if (nxt_slow_path(nxt_utf8_decode(&p, end) == 0xFFFFFFFF)) { - return 0; - } + while (p < end) { + if (nxt_slow_path(nxt_utf8_decode(&p, end) == 0xFFFFFFFF)) { + return 0; } + } - return 1; + return 1; } diff --git a/src/nxt_utf8.h b/src/nxt_utf8.h index 13f42e16a..f44ad6873 100644 --- a/src/nxt_utf8.h +++ b/src/nxt_utf8.h @@ -7,54 +7,49 @@ #ifndef _NXT_UTF8_H_INCLUDED_ #define _NXT_UTF8_H_INCLUDED_ - /* * Since the maximum valid Unicode character is 0x0010FFFF, the maximum * difference between Unicode characters is lesser 0x0010FFFF and * 0x0EEE0EEE can be used as value to indicate UTF-8 encoding error. */ -#define NXT_UTF8_SORT_INVALID 0x0EEE0EEE - +#define NXT_UTF8_SORT_INVALID 0x0EEE0EEE NXT_EXPORT u_char *nxt_utf8_encode(u_char *p, uint32_t u); NXT_EXPORT uint32_t nxt_utf8_decode(const u_char **start, const u_char *end); NXT_EXPORT uint32_t nxt_utf8_decode2(const u_char **start, const u_char *end); NXT_EXPORT nxt_int_t nxt_utf8_casecmp(const u_char *start1, - const u_char *start2, size_t len1, size_t len2); + const u_char *start2, size_t len1, + size_t len2); NXT_EXPORT uint32_t nxt_utf8_lowcase(const u_char **start, const u_char *end); NXT_EXPORT ssize_t nxt_utf8_length(const u_char *p, size_t len); NXT_EXPORT nxt_bool_t nxt_utf8_is_valid(const u_char *p, size_t len); - /* nxt_utf8_next() expects a valid UTF-8 string. */ -nxt_inline const u_char * -nxt_utf8_next(const u_char *p, const u_char *end) -{ - u_char c; +nxt_inline const u_char *nxt_utf8_next(const u_char *p, const u_char *end) { + u_char c; - c = *p++; + c = *p++; - if ((c & 0x80) != 0) { + if ((c & 0x80) != 0) { - do { - /* - * The first UTF-8 byte is either 0xxxxxxx or 11xxxxxx. - * The next UTF-8 bytes are 10xxxxxx. - */ - c = *p; + do { + /* + * The first UTF-8 byte is either 0xxxxxxx or 11xxxxxx. + * The next UTF-8 bytes are 10xxxxxx. + */ + c = *p; - if ((c & 0xC0) != 0x80) { - return p; - } + if ((c & 0xC0) != 0x80) { + return p; + } - p++; + p++; - } while (p < end); - } + } while (p < end); + } - return p; + return p; } - #endif /* _NXT_UTF8_H_INCLUDED_ */ diff --git a/src/nxt_var.c b/src/nxt_var.c index 16aa1c7ed..364aad3b4 100644 --- a/src/nxt_var.c +++ b/src/nxt_var.c @@ -5,578 +5,533 @@ #include - struct nxt_var_s { - size_t length; - nxt_uint_t vars; - u_char data[]; - -/* - nxt_var_sub_t subs[vars]; - u_char raw[length]; -*/ + size_t length; + nxt_uint_t vars; + u_char data[]; + + /* + nxt_var_sub_t subs[vars]; + u_char raw[length]; + */ }; - typedef struct { - uint32_t index; - uint32_t length; - uint32_t position; + uint32_t index; + uint32_t length; + uint32_t position; } nxt_var_sub_t; - struct nxt_var_query_s { - nxt_mp_t *pool; + nxt_mp_t *pool; - nxt_var_cache_t cache; + nxt_var_cache_t cache; - void *ctx; - void *data; + void *ctx; + void *data; }; +#define nxt_var_subs(var) ((nxt_var_sub_t *)(var)->data) -#define nxt_var_subs(var) ((nxt_var_sub_t *) (var)->data) - -#define nxt_var_raw_start(var) \ - ((var)->data + (var)->vars * sizeof(nxt_var_sub_t)) - +#define nxt_var_raw_start(var) \ + ((var)->data + (var)->vars * sizeof(nxt_var_sub_t)) static nxt_int_t nxt_var_hash_test(nxt_lvlhsh_query_t *lhq, void *data); static nxt_var_decl_t *nxt_var_hash_find(nxt_str_t *name); static nxt_var_ref_t *nxt_var_ref_get(nxt_tstr_state_t *state, nxt_str_t *name, - nxt_mp_t *mp); + nxt_mp_t *mp); static nxt_int_t nxt_var_cache_test(nxt_lvlhsh_query_t *lhq, void *data); static nxt_str_t *nxt_var_cache_value(nxt_task_t *task, nxt_tstr_state_t *state, - nxt_var_cache_t *cache, nxt_var_ref_t *ref, void *ctx); + nxt_var_cache_t *cache, + nxt_var_ref_t *ref, void *ctx); static u_char *nxt_var_next_part(u_char *start, u_char *end, nxt_str_t *part); - -static const nxt_lvlhsh_proto_t nxt_var_hash_proto nxt_aligned(64) = { +static const nxt_lvlhsh_proto_t nxt_var_hash_proto nxt_aligned(64) = { NXT_LVLHSH_DEFAULT, nxt_var_hash_test, nxt_lvlhsh_alloc, nxt_lvlhsh_free, }; -static const nxt_lvlhsh_proto_t nxt_var_cache_proto nxt_aligned(64) = { +static const nxt_lvlhsh_proto_t nxt_var_cache_proto nxt_aligned(64) = { NXT_LVLHSH_DEFAULT, nxt_var_cache_test, nxt_mp_lvlhsh_alloc, nxt_mp_lvlhsh_free, }; +static nxt_lvlhsh_t nxt_var_hash; +static uint32_t nxt_var_count; -static nxt_lvlhsh_t nxt_var_hash; -static uint32_t nxt_var_count; - -static nxt_var_decl_t **nxt_vars; +static nxt_var_decl_t **nxt_vars; +static nxt_int_t nxt_var_hash_test(nxt_lvlhsh_query_t *lhq, void *data) { + nxt_var_decl_t *decl; -static nxt_int_t -nxt_var_hash_test(nxt_lvlhsh_query_t *lhq, void *data) -{ - nxt_var_decl_t *decl; + decl = data; - decl = data; - - return nxt_strstr_eq(&lhq->key, &decl->name) ? NXT_OK : NXT_DECLINED; + return nxt_strstr_eq(&lhq->key, &decl->name) ? NXT_OK : NXT_DECLINED; } +static nxt_var_decl_t *nxt_var_hash_find(nxt_str_t *name) { + nxt_lvlhsh_query_t lhq; -static nxt_var_decl_t * -nxt_var_hash_find(nxt_str_t *name) -{ - nxt_lvlhsh_query_t lhq; - - lhq.key_hash = nxt_djb_hash(name->start, name->length); - lhq.key = *name; - lhq.proto = &nxt_var_hash_proto; + lhq.key_hash = nxt_djb_hash(name->start, name->length); + lhq.key = *name; + lhq.proto = &nxt_var_hash_proto; - if (nxt_lvlhsh_find(&nxt_var_hash, &lhq) != NXT_OK) { - return NULL; - } + if (nxt_lvlhsh_find(&nxt_var_hash, &lhq) != NXT_OK) { + return NULL; + } - return lhq.value; + return lhq.value; } +static nxt_var_ref_t *nxt_var_ref_get(nxt_tstr_state_t *state, nxt_str_t *name, + nxt_mp_t *mp) { + nxt_int_t ret; + nxt_uint_t i; + nxt_var_ref_t *ref; + nxt_var_decl_t *decl; -static nxt_var_ref_t * -nxt_var_ref_get(nxt_tstr_state_t *state, nxt_str_t *name, nxt_mp_t *mp) -{ - nxt_int_t ret; - nxt_uint_t i; - nxt_var_ref_t *ref; - nxt_var_decl_t *decl; - - ref = state->var_refs->elts; + ref = state->var_refs->elts; - for (i = 0; i < state->var_refs->nelts; i++) { + for (i = 0; i < state->var_refs->nelts; i++) { - if (nxt_strstr_eq(ref[i].name, name)) { - return &ref[i]; - } + if (nxt_strstr_eq(ref[i].name, name)) { + return &ref[i]; } + } - if (mp != NULL) { - ref = nxt_mp_alloc(mp, sizeof(nxt_var_ref_t)); - if (nxt_slow_path(ref == NULL)) { - return NULL; - } + if (mp != NULL) { + ref = nxt_mp_alloc(mp, sizeof(nxt_var_ref_t)); + if (nxt_slow_path(ref == NULL)) { + return NULL; + } - } else { - ref = nxt_array_add(state->var_refs); - if (nxt_slow_path(ref == NULL)) { - return NULL; - } + } else { + ref = nxt_array_add(state->var_refs); + if (nxt_slow_path(ref == NULL)) { + return NULL; + } - ref->index = state->var_refs->nelts - 1; + ref->index = state->var_refs->nelts - 1; - mp = state->pool; - } + mp = state->pool; + } - decl = nxt_var_hash_find(name); + decl = nxt_var_hash_find(name); - if (decl != NULL) { - ref->handler = decl->handler; - ref->cacheable = (mp == state->pool) ? decl->cacheable : 0; + if (decl != NULL) { + ref->handler = decl->handler; + ref->cacheable = (mp == state->pool) ? decl->cacheable : 0; - goto done; - } + goto done; + } - ret = nxt_http_unknown_var_ref(mp, ref, name); - if (nxt_slow_path(ret != NXT_OK)) { - return NULL; - } + ret = nxt_http_unknown_var_ref(mp, ref, name); + if (nxt_slow_path(ret != NXT_OK)) { + return NULL; + } done: - ref->name = nxt_str_dup(mp, NULL, name); - if (nxt_slow_path(ref->name == NULL)) { - return NULL; - } + ref->name = nxt_str_dup(mp, NULL, name); + if (nxt_slow_path(ref->name == NULL)) { + return NULL; + } - return ref; + return ref; } +nxt_var_field_t *nxt_var_field_new(nxt_mp_t *mp, nxt_str_t *name, + uint32_t hash) { + nxt_str_t *str; + nxt_var_field_t *field; -nxt_var_field_t * -nxt_var_field_new(nxt_mp_t *mp, nxt_str_t *name, uint32_t hash) -{ - nxt_str_t *str; - nxt_var_field_t *field; - - field = nxt_mp_alloc(mp, sizeof(nxt_var_field_t)); - if (nxt_slow_path(field == NULL)) { - return NULL; - } + field = nxt_mp_alloc(mp, sizeof(nxt_var_field_t)); + if (nxt_slow_path(field == NULL)) { + return NULL; + } - str = nxt_str_dup(mp, &field->name, name); - if (nxt_slow_path(str == NULL)) { - return NULL; - } + str = nxt_str_dup(mp, &field->name, name); + if (nxt_slow_path(str == NULL)) { + return NULL; + } - field->hash = hash; + field->hash = hash; - return field; + return field; } +nxt_var_field_t *nxt_var_field_get(nxt_array_t *fields, uint16_t index) { + nxt_uint_t nfields; + nxt_var_field_t *field; -nxt_var_field_t * -nxt_var_field_get(nxt_array_t *fields, uint16_t index) -{ - nxt_uint_t nfields; - nxt_var_field_t *field; + field = fields->elts; + nfields = fields->nelts; - field = fields->elts; - nfields = fields->nelts; - - if (nfields > 0 && index <= nfields) { - return &field[index]; - } + if (nfields > 0 && index <= nfields) { + return &field[index]; + } - return NULL; + return NULL; } - -static nxt_int_t -nxt_var_cache_test(nxt_lvlhsh_query_t *lhq, void *data) -{ - return NXT_OK; +static nxt_int_t nxt_var_cache_test(nxt_lvlhsh_query_t *lhq, void *data) { + return NXT_OK; } - -static nxt_str_t * -nxt_var_cache_value(nxt_task_t *task, nxt_tstr_state_t *state, - nxt_var_cache_t *cache, nxt_var_ref_t *ref, void *ctx) -{ - nxt_int_t ret; - nxt_str_t *value; - nxt_lvlhsh_query_t lhq; - - value = cache->spare; - - if (value == NULL) { - value = nxt_mp_zget(cache->pool, sizeof(nxt_str_t)); - if (nxt_slow_path(value == NULL)) { - return NULL; - } - - cache->spare = value; +static nxt_str_t *nxt_var_cache_value(nxt_task_t *task, nxt_tstr_state_t *state, + nxt_var_cache_t *cache, + nxt_var_ref_t *ref, void *ctx) { + nxt_int_t ret; + nxt_str_t *value; + nxt_lvlhsh_query_t lhq; + + value = cache->spare; + + if (value == NULL) { + value = nxt_mp_zget(cache->pool, sizeof(nxt_str_t)); + if (nxt_slow_path(value == NULL)) { + return NULL; } - if (!ref->cacheable) { - goto not_cached; - } + cache->spare = value; + } - lhq.key_hash = nxt_murmur_hash2_uint32(&ref->index); - lhq.replace = 0; - lhq.key.length = sizeof(uint32_t); - lhq.key.start = (u_char *) &ref->index; - lhq.value = value; - lhq.proto = &nxt_var_cache_proto; - lhq.pool = cache->pool; + if (!ref->cacheable) { + goto not_cached; + } - ret = nxt_lvlhsh_insert(&cache->hash, &lhq); - if (nxt_slow_path(ret == NXT_ERROR)) { - return NULL; - } + lhq.key_hash = nxt_murmur_hash2_uint32(&ref->index); + lhq.replace = 0; + lhq.key.length = sizeof(uint32_t); + lhq.key.start = (u_char *)&ref->index; + lhq.value = value; + lhq.proto = &nxt_var_cache_proto; + lhq.pool = cache->pool; - if (ret == NXT_DECLINED) { - return lhq.value; - } + ret = nxt_lvlhsh_insert(&cache->hash, &lhq); + if (nxt_slow_path(ret == NXT_ERROR)) { + return NULL; + } + + if (ret == NXT_DECLINED) { + return lhq.value; + } not_cached: - ret = ref->handler(task, value, ctx, ref->data); - if (nxt_slow_path(ret != NXT_OK)) { - return NULL; - } + ret = ref->handler(task, value, ctx, ref->data); + if (nxt_slow_path(ret != NXT_OK)) { + return NULL; + } - cache->spare = NULL; + cache->spare = NULL; - return value; + return value; } +nxt_int_t nxt_var_register(nxt_var_decl_t *decl, size_t n) { + nxt_uint_t i; + nxt_lvlhsh_query_t lhq; -nxt_int_t -nxt_var_register(nxt_var_decl_t *decl, size_t n) -{ - nxt_uint_t i; - nxt_lvlhsh_query_t lhq; - - lhq.replace = 0; - lhq.proto = &nxt_var_hash_proto; + lhq.replace = 0; + lhq.proto = &nxt_var_hash_proto; - for (i = 0; i < n; i++) { - lhq.key = decl[i].name; - lhq.key_hash = nxt_djb_hash(lhq.key.start, lhq.key.length); - lhq.value = &decl[i]; + for (i = 0; i < n; i++) { + lhq.key = decl[i].name; + lhq.key_hash = nxt_djb_hash(lhq.key.start, lhq.key.length); + lhq.value = &decl[i]; - if (nxt_slow_path(nxt_lvlhsh_insert(&nxt_var_hash, &lhq) != NXT_OK)) { - return NXT_ERROR; - } + if (nxt_slow_path(nxt_lvlhsh_insert(&nxt_var_hash, &lhq) != NXT_OK)) { + return NXT_ERROR; } + } - nxt_var_count += n; + nxt_var_count += n; - return NXT_OK; + return NXT_OK; } +nxt_int_t nxt_var_index_init(void) { + nxt_uint_t i; + nxt_var_decl_t *decl, **vars; + nxt_lvlhsh_each_t lhe; -nxt_int_t -nxt_var_index_init(void) -{ - nxt_uint_t i; - nxt_var_decl_t *decl, **vars; - nxt_lvlhsh_each_t lhe; + vars = nxt_memalign(64, nxt_var_count * sizeof(nxt_var_decl_t *)); + if (vars == NULL) { + return NXT_ERROR; + } - vars = nxt_memalign(64, nxt_var_count * sizeof(nxt_var_decl_t *)); - if (vars == NULL) { - return NXT_ERROR; - } + nxt_lvlhsh_each_init(&lhe, &nxt_var_hash_proto); - nxt_lvlhsh_each_init(&lhe, &nxt_var_hash_proto); + for (i = 0; i < nxt_var_count; i++) { + decl = nxt_lvlhsh_each(&nxt_var_hash, &lhe); + vars[i] = decl; + } - for (i = 0; i < nxt_var_count; i++) { - decl = nxt_lvlhsh_each(&nxt_var_hash, &lhe); - vars[i] = decl; - } - - nxt_vars = vars; + nxt_vars = vars; - return NXT_OK; + return NXT_OK; } +nxt_var_t *nxt_var_compile(nxt_tstr_state_t *state, nxt_str_t *str) { + u_char *p, *end, *next, *src; + size_t size; + nxt_var_t *var; + nxt_str_t part; + nxt_uint_t n; + nxt_var_sub_t *subs; + nxt_var_ref_t *ref; -nxt_var_t * -nxt_var_compile(nxt_tstr_state_t *state, nxt_str_t *str) -{ - u_char *p, *end, *next, *src; - size_t size; - nxt_var_t *var; - nxt_str_t part; - nxt_uint_t n; - nxt_var_sub_t *subs; - nxt_var_ref_t *ref; - - n = 0; + n = 0; - p = str->start; - end = p + str->length; + p = str->start; + end = p + str->length; - while (p < end) { - p = nxt_var_next_part(p, end, &part); - if (nxt_slow_path(p == NULL)) { - return NULL; - } - - if (part.start != NULL) { - n++; - } + while (p < end) { + p = nxt_var_next_part(p, end, &part); + if (nxt_slow_path(p == NULL)) { + return NULL; } - size = sizeof(nxt_var_t) + n * sizeof(nxt_var_sub_t) + str->length; - - var = nxt_mp_get(state->pool, size); - if (nxt_slow_path(var == NULL)) { - return NULL; + if (part.start != NULL) { + n++; } + } - var->length = str->length; - var->vars = n; - - subs = nxt_var_subs(var); - src = nxt_var_raw_start(var); - - nxt_memcpy(src, str->start, str->length); - - n = 0; - p = str->start; + size = sizeof(nxt_var_t) + n * sizeof(nxt_var_sub_t) + str->length; - while (p < end) { - next = nxt_var_next_part(p, end, &part); + var = nxt_mp_get(state->pool, size); + if (nxt_slow_path(var == NULL)) { + return NULL; + } - if (part.start != NULL) { - ref = nxt_var_ref_get(state, &part, NULL); - if (nxt_slow_path(ref == NULL)) { - return NULL; - } + var->length = str->length; + var->vars = n; - subs[n].index = ref->index; - subs[n].length = next - p; - subs[n].position = p - str->start; + subs = nxt_var_subs(var); + src = nxt_var_raw_start(var); - n++; - } + nxt_memcpy(src, str->start, str->length); - p = next; - } + n = 0; + p = str->start; - return var; -} + while (p < end) { + next = nxt_var_next_part(p, end, &part); + if (part.start != NULL) { + ref = nxt_var_ref_get(state, &part, NULL); + if (nxt_slow_path(ref == NULL)) { + return NULL; + } -nxt_int_t -nxt_var_test(nxt_tstr_state_t *state, nxt_str_t *str, u_char *error) -{ - u_char *p, *end, *next; - nxt_str_t part; - nxt_var_ref_t *ref; + subs[n].index = ref->index; + subs[n].length = next - p; + subs[n].position = p - str->start; - p = str->start; - end = p + str->length; + n++; + } - while (p < end) { - next = nxt_var_next_part(p, end, &part); + p = next; + } - if (next == NULL) { - nxt_sprintf(error, error + NXT_MAX_ERROR_STR, - "Invalid variable at position %uz%Z", p - str->start); + return var; +} - return NXT_ERROR; - } +nxt_int_t nxt_var_test(nxt_tstr_state_t *state, nxt_str_t *str, u_char *error) { + u_char *p, *end, *next; + nxt_str_t part; + nxt_var_ref_t *ref; - if (part.start != NULL) { - ref = nxt_var_ref_get(state, &part, NULL); + p = str->start; + end = p + str->length; - if (ref == NULL) { - nxt_sprintf(error, error + NXT_MAX_ERROR_STR, - "Unknown variable \"%V\"%Z", &part); + while (p < end) { + next = nxt_var_next_part(p, end, &part); - return NXT_ERROR; - } - } + if (next == NULL) { + nxt_sprintf(error, error + NXT_MAX_ERROR_STR, + "Invalid variable at position %uz%Z", p - str->start); - p = next; + return NXT_ERROR; } - return NXT_OK; -} - + if (part.start != NULL) { + ref = nxt_var_ref_get(state, &part, NULL); -static u_char * -nxt_var_next_part(u_char *start, u_char *end, nxt_str_t *part) -{ - size_t length; - u_char *p, ch, c; - nxt_bool_t bracket; + if (ref == NULL) { + nxt_sprintf(error, error + NXT_MAX_ERROR_STR, + "Unknown variable \"%V\"%Z", &part); - p = memchr(start, '$', end - start); + return NXT_ERROR; + } + } - if (p == start) { - p++; + p = next; + } - if (p == end) { - return NULL; - } + return NXT_OK; +} - if (*p == '{') { - bracket = 1; +static u_char *nxt_var_next_part(u_char *start, u_char *end, nxt_str_t *part) { + size_t length; + u_char *p, ch, c; + nxt_bool_t bracket; - if (end - p < 2) { - return NULL; - } + p = memchr(start, '$', end - start); - p++; + if (p == start) { + p++; - } else { - bracket = 0; - } + if (p == end) { + return NULL; + } - length = 0; - start = p; + if (*p == '{') { + bracket = 1; - while (p < end) { - ch = *p; + if (end - p < 2) { + return NULL; + } - c = (u_char) (ch | 0x20); + p++; - if ((c >= 'a' && c <= 'z') || ch == '_') { - p++; - length++; - continue; - } + } else { + bracket = 0; + } - if (bracket && ch == '}') { - p++; - bracket = 0; - } + length = 0; + start = p; - break; - } + while (p < end) { + ch = *p; - if (bracket || length == 0) { - return NULL; - } + c = (u_char)(ch | 0x20); - part->length = length; - part->start = start; + if ((c >= 'a' && c <= 'z') || ch == '_') { + p++; + length++; + continue; + } - } else { - if (p == NULL) { - p = end; - } + if (bracket && ch == '}') { + p++; + bracket = 0; + } - nxt_str_null(part); + break; } - return p; -} - - -nxt_int_t -nxt_var_interpreter(nxt_task_t *task, nxt_tstr_state_t *state, - nxt_var_cache_t *cache, nxt_var_t *var, nxt_str_t *str, void *ctx, - nxt_bool_t logging) -{ - u_char *p, *src; - size_t length, last, next; - uint32_t index; - nxt_str_t *value, **part; - nxt_uint_t i; - nxt_array_t parts; - nxt_var_ref_t *ref; - nxt_var_sub_t *subs; + if (bracket || length == 0) { + return NULL; + } - nxt_memzero(&parts, sizeof(nxt_array_t)); - nxt_array_init(&parts, cache->pool, sizeof(nxt_str_t *)); + part->length = length; + part->start = start; - ref = state->var_refs->elts; - subs = nxt_var_subs(var); + } else { + if (p == NULL) { + p = end; + } - length = var->length; + nxt_str_null(part); + } - for (i = 0; i < var->vars; i++) { - index = subs[i].index; - value = nxt_var_cache_value(task, state, cache, &ref[index], ctx); - if (nxt_slow_path(value == NULL)) { - return NXT_ERROR; - } + return p; +} - part = nxt_array_add(&parts); - if (nxt_slow_path(part == NULL)) { - return NXT_ERROR; - } +nxt_int_t nxt_var_interpreter(nxt_task_t *task, nxt_tstr_state_t *state, + nxt_var_cache_t *cache, nxt_var_t *var, + nxt_str_t *str, void *ctx, nxt_bool_t logging) { + u_char *p, *src; + size_t length, last, next; + uint32_t index; + nxt_str_t *value, **part; + nxt_uint_t i; + nxt_array_t parts; + nxt_var_ref_t *ref; + nxt_var_sub_t *subs; + + nxt_memzero(&parts, sizeof(nxt_array_t)); + nxt_array_init(&parts, cache->pool, sizeof(nxt_str_t *)); + + ref = state->var_refs->elts; + subs = nxt_var_subs(var); + + length = var->length; + + for (i = 0; i < var->vars; i++) { + index = subs[i].index; + value = nxt_var_cache_value(task, state, cache, &ref[index], ctx); + if (nxt_slow_path(value == NULL)) { + return NXT_ERROR; + } - *part = value; + part = nxt_array_add(&parts); + if (nxt_slow_path(part == NULL)) { + return NXT_ERROR; + } - length += value->length - subs[i].length; + *part = value; - if (logging && value->start == NULL) { - length += 1; - } - } + length += value->length - subs[i].length; - p = nxt_mp_nget(cache->pool, length); - if (nxt_slow_path(p == NULL)) { - return NXT_ERROR; + if (logging && value->start == NULL) { + length += 1; } + } - str->length = length; - str->start = p; + p = nxt_mp_nget(cache->pool, length); + if (nxt_slow_path(p == NULL)) { + return NXT_ERROR; + } - part = parts.elts; - src = nxt_var_raw_start(var); + str->length = length; + str->start = p; - last = 0; + part = parts.elts; + src = nxt_var_raw_start(var); - for (i = 0; i < var->vars; i++) { - next = subs[i].position; + last = 0; - if (next != last) { - p = nxt_cpymem(p, &src[last], next - last); - } + for (i = 0; i < var->vars; i++) { + next = subs[i].position; - p = nxt_cpymem(p, part[i]->start, part[i]->length); + if (next != last) { + p = nxt_cpymem(p, &src[last], next - last); + } - if (logging && part[i]->start == NULL) { - *p++ = '-'; - } + p = nxt_cpymem(p, part[i]->start, part[i]->length); - last = next + subs[i].length; + if (logging && part[i]->start == NULL) { + *p++ = '-'; } - if (last != var->length) { - nxt_cpymem(p, &src[last], var->length - last); - } + last = next + subs[i].length; + } - return NXT_OK; -} + if (last != var->length) { + nxt_cpymem(p, &src[last], var->length - last); + } + return NXT_OK; +} -nxt_str_t * -nxt_var_get(nxt_task_t *task, nxt_tstr_state_t *state, nxt_var_cache_t *cache, - nxt_str_t *name, void *ctx) -{ - nxt_var_ref_t *ref; +nxt_str_t *nxt_var_get(nxt_task_t *task, nxt_tstr_state_t *state, + nxt_var_cache_t *cache, nxt_str_t *name, void *ctx) { + nxt_var_ref_t *ref; - ref = nxt_var_ref_get(state, name, cache->pool); - if (nxt_slow_path(ref == NULL)) { - return NULL; - } + ref = nxt_var_ref_get(state, name, cache->pool); + if (nxt_slow_path(ref == NULL)) { + return NULL; + } - return nxt_var_cache_value(task, state, cache, ref, ctx); + return nxt_var_cache_value(task, state, cache, ref, ctx); } diff --git a/src/nxt_var.h b/src/nxt_var.h index 08a92c08a..794b02c75 100644 --- a/src/nxt_var.h +++ b/src/nxt_var.h @@ -6,64 +6,56 @@ #ifndef _NXT_VAR_H_INCLUDED_ #define _NXT_VAR_H_INCLUDED_ +typedef struct nxt_var_s nxt_var_t; +typedef struct nxt_var_query_s nxt_var_query_t; -typedef struct nxt_var_s nxt_var_t; -typedef struct nxt_var_query_s nxt_var_query_t; - - -typedef nxt_int_t (*nxt_var_handler_t)(nxt_task_t *task, - nxt_str_t *str, +typedef nxt_int_t (*nxt_var_handler_t)(nxt_task_t *task, nxt_str_t *str, void *ctx, void *data); typedef int64_t (*nxt_var_field_hash_t)(nxt_mp_t *mp, nxt_str_t *str); typedef struct { - nxt_str_t name; - nxt_var_handler_t handler; - uint8_t cacheable; /* 1 bit */ + nxt_str_t name; + nxt_var_handler_t handler; + uint8_t cacheable; /* 1 bit */ } nxt_var_decl_t; - typedef struct { - nxt_str_t *name; - nxt_var_handler_t handler; - void *data; - uint32_t index; - uint8_t cacheable; /* 1 bit */ + nxt_str_t *name; + nxt_var_handler_t handler; + void *data; + uint32_t index; + uint8_t cacheable; /* 1 bit */ } nxt_var_ref_t; - typedef struct { - nxt_str_t name; - uint16_t hash; + nxt_str_t name; + uint16_t hash; } nxt_var_field_t; - typedef struct { - nxt_mp_t *pool; - nxt_lvlhsh_t hash; - nxt_str_t *spare; + nxt_mp_t *pool; + nxt_lvlhsh_t hash; + nxt_str_t *spare; } nxt_var_cache_t; - nxt_int_t nxt_var_register(nxt_var_decl_t *decl, size_t n); nxt_int_t nxt_var_index_init(void); nxt_var_field_t *nxt_var_field_get(nxt_array_t *fields, uint16_t index); nxt_var_field_t *nxt_var_field_new(nxt_mp_t *mp, nxt_str_t *name, - uint32_t hash); + uint32_t hash); nxt_var_t *nxt_var_compile(nxt_tstr_state_t *state, nxt_str_t *str); nxt_int_t nxt_var_test(nxt_tstr_state_t *state, nxt_str_t *str, u_char *error); nxt_int_t nxt_var_interpreter(nxt_task_t *task, nxt_tstr_state_t *state, - nxt_var_cache_t *cache, nxt_var_t *var, nxt_str_t *str, void *ctx, - nxt_bool_t logging); + nxt_var_cache_t *cache, nxt_var_t *var, + nxt_str_t *str, void *ctx, nxt_bool_t logging); nxt_str_t *nxt_var_get(nxt_task_t *task, nxt_tstr_state_t *state, - nxt_var_cache_t *cache, nxt_str_t *name, void *ctx); + nxt_var_cache_t *cache, nxt_str_t *name, void *ctx); nxt_int_t nxt_http_unknown_var_ref(nxt_mp_t *mp, nxt_var_ref_t *ref, - nxt_str_t *name); - + nxt_str_t *name); #endif /* _NXT_VAR_H_INCLUDED_ */ diff --git a/src/nxt_websocket.c b/src/nxt_websocket.c index 910022379..531ec710a 100644 --- a/src/nxt_websocket.c +++ b/src/nxt_websocket.c @@ -7,116 +7,91 @@ #include #include - -nxt_inline uint16_t -nxt_ntoh16(const uint8_t *b) -{ - return ((uint16_t) b[0]) << 8 | ((uint16_t) b[1]); +nxt_inline uint16_t nxt_ntoh16(const uint8_t *b) { + return ((uint16_t)b[0]) << 8 | ((uint16_t)b[1]); } - -nxt_inline void -nxt_hton16(uint8_t *b, uint16_t v) -{ - b[0] = (v >> 8); - b[1] = (v & 0xFFu); +nxt_inline void nxt_hton16(uint8_t *b, uint16_t v) { + b[0] = (v >> 8); + b[1] = (v & 0xFFu); } - -nxt_inline uint64_t -nxt_ntoh64(const uint8_t *b) -{ - return ((uint64_t) b[0]) << 56 - | ((uint64_t) b[1]) << 48 - | ((uint64_t) b[2]) << 40 - | ((uint64_t) b[3]) << 32 - | ((uint64_t) b[4]) << 24 - | ((uint64_t) b[5]) << 16 - | ((uint64_t) b[6]) << 8 - | ((uint64_t) b[7]); +nxt_inline uint64_t nxt_ntoh64(const uint8_t *b) { + return ((uint64_t)b[0]) << 56 | ((uint64_t)b[1]) << 48 | + ((uint64_t)b[2]) << 40 | ((uint64_t)b[3]) << 32 | + ((uint64_t)b[4]) << 24 | ((uint64_t)b[5]) << 16 | + ((uint64_t)b[6]) << 8 | ((uint64_t)b[7]); } - -nxt_inline void -nxt_hton64(uint8_t *b, uint64_t v) -{ - b[0] = (v >> 56); - b[1] = (v >> 48) & 0xFFu; - b[2] = (v >> 40) & 0xFFu; - b[3] = (v >> 32) & 0xFFu; - b[4] = (v >> 24) & 0xFFu; - b[5] = (v >> 16) & 0xFFu; - b[6] = (v >> 8) & 0xFFu; - b[7] = v & 0xFFu; +nxt_inline void nxt_hton64(uint8_t *b, uint64_t v) { + b[0] = (v >> 56); + b[1] = (v >> 48) & 0xFFu; + b[2] = (v >> 40) & 0xFFu; + b[3] = (v >> 32) & 0xFFu; + b[4] = (v >> 24) & 0xFFu; + b[5] = (v >> 16) & 0xFFu; + b[6] = (v >> 8) & 0xFFu; + b[7] = v & 0xFFu; } +size_t nxt_websocket_frame_header_size(const void *data) { + size_t res; + uint64_t p; + const nxt_websocket_header_t *h; -size_t -nxt_websocket_frame_header_size(const void *data) -{ - size_t res; - uint64_t p; - const nxt_websocket_header_t *h; + h = data; + p = h->payload_len; - h = data; - p = h->payload_len; + res = 2; - res = 2; + if (p == 126) { + res += 2; + } else if (p == 127) { + res += 8; + } - if (p == 126) { - res += 2; - } else if (p == 127) { - res += 8; - } + if (h->mask) { + res += 4; + } - if (h->mask) { - res += 4; - } - - return res; + return res; } +uint64_t nxt_websocket_frame_payload_len(const void *data) { + uint64_t p; + const nxt_websocket_header_t *h; -uint64_t -nxt_websocket_frame_payload_len(const void *data) -{ - uint64_t p; - const nxt_websocket_header_t *h; - - h = data; - p = h->payload_len; + h = data; + p = h->payload_len; - if (p == 126) { - p = nxt_ntoh16(h->payload_len_); - } else if (p == 127) { - p = nxt_ntoh64(h->payload_len_); - } + if (p == 126) { + p = nxt_ntoh16(h->payload_len_); + } else if (p == 127) { + p = nxt_ntoh64(h->payload_len_); + } - return p; + return p; } +void *nxt_websocket_frame_init(void *data, uint64_t payload_len) { + uint8_t *p; + nxt_websocket_header_t *h; -void * -nxt_websocket_frame_init(void *data, uint64_t payload_len) -{ - uint8_t *p; - nxt_websocket_header_t *h; - - h = data; - p = data; + h = data; + p = data; - if (payload_len < 126) { - h->payload_len = payload_len; - return p + 2; - } + if (payload_len < 126) { + h->payload_len = payload_len; + return p + 2; + } - if (payload_len < 65536) { - h->payload_len = 126; - nxt_hton16(h->payload_len_, payload_len); - return p + 4; - } + if (payload_len < 65536) { + h->payload_len = 126; + nxt_hton16(h->payload_len_, payload_len); + return p + 4; + } - h->payload_len = 127; - nxt_hton64(h->payload_len_, payload_len); - return p + 10; + h->payload_len = 127; + nxt_hton64(h->payload_len_, payload_len); + return p + 10; } diff --git a/src/nxt_websocket.h b/src/nxt_websocket.h index 499a3268c..351476d15 100644 --- a/src/nxt_websocket.h +++ b/src/nxt_websocket.h @@ -6,16 +6,13 @@ #ifndef _NXT_WEBSOCKET_H_INCLUDED_ #define _NXT_WEBSOCKET_H_INCLUDED_ - enum { - NXT_WEBSOCKET_ACCEPT_SIZE = 28, + NXT_WEBSOCKET_ACCEPT_SIZE = 28, }; - NXT_EXPORT size_t nxt_websocket_frame_header_size(const void *data); NXT_EXPORT uint64_t nxt_websocket_frame_payload_len(const void *data); NXT_EXPORT void *nxt_websocket_frame_init(void *data, uint64_t payload_len); NXT_EXPORT void nxt_websocket_accept(u_char *accept, const void *key); - -#endif /* _NXT_WEBSOCKET_H_INCLUDED_ */ +#endif /* _NXT_WEBSOCKET_H_INCLUDED_ */ diff --git a/src/nxt_websocket_accept.c b/src/nxt_websocket_accept.c index 0e2cef588..ba5d14779 100644 --- a/src/nxt_websocket_accept.c +++ b/src/nxt_websocket_accept.c @@ -7,62 +7,55 @@ #include #include - -static void -nxt_websocket_base64_encode(u_char *d, const uint8_t *s, size_t len) -{ - u_char c0, c1, c2; - static const u_char basis[] = - "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; - - while (len > 2) { - c0 = s[0]; - c1 = s[1]; - c2 = s[2]; - - *d++ = basis[c0 >> 2]; - *d++ = basis[((c0 & 0x03) << 4) | (c1 >> 4)]; - *d++ = basis[((c1 & 0x0f) << 2) | (c2 >> 6)]; - *d++ = basis[c2 & 0x3f]; - - s += 3; - len -= 3; - } - - if (len > 0) { - c0 = s[0]; - *d++ = basis[c0 >> 2]; - - if (len == 1) { - *d++ = basis[(c0 & 0x03) << 4]; - *d++ = '='; - *d++ = '='; - - } else { - c1 = s[1]; - - *d++ = basis[((c0 & 0x03) << 4) | (c1 >> 4)]; - *d++ = basis[(c1 & 0x0f) << 2]; - - *d++ = '='; - } +static void nxt_websocket_base64_encode(u_char *d, const uint8_t *s, + size_t len) { + u_char c0, c1, c2; + static const u_char basis[] = + "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; + + while (len > 2) { + c0 = s[0]; + c1 = s[1]; + c2 = s[2]; + + *d++ = basis[c0 >> 2]; + *d++ = basis[((c0 & 0x03) << 4) | (c1 >> 4)]; + *d++ = basis[((c1 & 0x0f) << 2) | (c2 >> 6)]; + *d++ = basis[c2 & 0x3f]; + + s += 3; + len -= 3; + } + + if (len > 0) { + c0 = s[0]; + *d++ = basis[c0 >> 2]; + + if (len == 1) { + *d++ = basis[(c0 & 0x03) << 4]; + *d++ = '='; + *d++ = '='; + + } else { + c1 = s[1]; + + *d++ = basis[((c0 & 0x03) << 4) | (c1 >> 4)]; + *d++ = basis[(c1 & 0x0f) << 2]; + + *d++ = '='; } + } } +void nxt_websocket_accept(u_char *accept, const void *key) { + u_char bin_accept[20]; + nxt_sha1_t ctx; + static const char accept_guid[] = "258EAFA5-E914-47DA-95CA-C5AB0DC85B11"; -void -nxt_websocket_accept(u_char *accept, const void *key) -{ - u_char bin_accept[20]; - nxt_sha1_t ctx; - static const char accept_guid[] = "258EAFA5-E914-47DA-95CA-C5AB0DC85B11"; + nxt_sha1_init(&ctx); + nxt_sha1_update(&ctx, key, 24); + nxt_sha1_update(&ctx, accept_guid, nxt_length(accept_guid)); + nxt_sha1_final(bin_accept, &ctx); - nxt_sha1_init(&ctx); - nxt_sha1_update(&ctx, key, 24); - nxt_sha1_update(&ctx, accept_guid, nxt_length(accept_guid)); - nxt_sha1_final(bin_accept, &ctx); - - nxt_websocket_base64_encode(accept, bin_accept, sizeof(bin_accept)); + nxt_websocket_base64_encode(accept, bin_accept, sizeof(bin_accept)); } - - diff --git a/src/nxt_websocket_header.h b/src/nxt_websocket_header.h index cb7431dd0..a456410c1 100644 --- a/src/nxt_websocket_header.h +++ b/src/nxt_websocket_header.h @@ -8,61 +8,57 @@ #include - typedef struct { #if (NXT_HAVE_BIG_ENDIAN) - uint8_t fin:1; - uint8_t rsv1:1; - uint8_t rsv2:1; - uint8_t rsv3:1; - uint8_t opcode:4; - - uint8_t mask:1; - uint8_t payload_len:7; + uint8_t fin : 1; + uint8_t rsv1 : 1; + uint8_t rsv2 : 1; + uint8_t rsv3 : 1; + uint8_t opcode : 4; + + uint8_t mask : 1; + uint8_t payload_len : 7; #endif #if (NXT_HAVE_LITTLE_ENDIAN) - uint8_t opcode:4; - uint8_t rsv3:1; - uint8_t rsv2:1; - uint8_t rsv1:1; - uint8_t fin:1; - - uint8_t payload_len:7; - uint8_t mask:1; + uint8_t opcode : 4; + uint8_t rsv3 : 1; + uint8_t rsv2 : 1; + uint8_t rsv1 : 1; + uint8_t fin : 1; + + uint8_t payload_len : 7; + uint8_t mask : 1; #endif - uint8_t payload_len_[8]; + uint8_t payload_len_[8]; } nxt_websocket_header_t; - enum { - NXT_WEBSOCKET_OP_CONT = 0x00, - NXT_WEBSOCKET_OP_TEXT = 0x01, - NXT_WEBSOCKET_OP_BINARY = 0x02, - NXT_WEBSOCKET_OP_CLOSE = 0x08, - NXT_WEBSOCKET_OP_PING = 0x09, - NXT_WEBSOCKET_OP_PONG = 0x0A, - - NXT_WEBSOCKET_OP_CTRL = 0x08, + NXT_WEBSOCKET_OP_CONT = 0x00, + NXT_WEBSOCKET_OP_TEXT = 0x01, + NXT_WEBSOCKET_OP_BINARY = 0x02, + NXT_WEBSOCKET_OP_CLOSE = 0x08, + NXT_WEBSOCKET_OP_PING = 0x09, + NXT_WEBSOCKET_OP_PONG = 0x0A, + + NXT_WEBSOCKET_OP_CTRL = 0x08, }; - enum { - NXT_WEBSOCKET_CR_NORMAL = 1000, - NXT_WEBSOCKET_CR_GOING_AWAY = 1001, - NXT_WEBSOCKET_CR_PROTOCOL_ERROR = 1002, - NXT_WEBSOCKET_CR_UNPROCESSABLE_INPUT = 1003, - NXT_WEBSOCKET_CR_RESERVED = 1004, - NXT_WEBSOCKET_CR_NOT_PROVIDED = 1005, - NXT_WEBSOCKET_CR_ABNORMAL = 1006, - NXT_WEBSOCKET_CR_INVALID_DATA = 1007, - NXT_WEBSOCKET_CR_POLICY_VIOLATION = 1008, - NXT_WEBSOCKET_CR_MESSAGE_TOO_BIG = 1009, - NXT_WEBSOCKET_CR_EXTENSION_REQUIRED = 1010, - NXT_WEBSOCKET_CR_INTERNAL_SERVER_ERROR = 1011, - NXT_WEBSOCKET_CR_TLS_HANDSHAKE_FAILED = 1015, + NXT_WEBSOCKET_CR_NORMAL = 1000, + NXT_WEBSOCKET_CR_GOING_AWAY = 1001, + NXT_WEBSOCKET_CR_PROTOCOL_ERROR = 1002, + NXT_WEBSOCKET_CR_UNPROCESSABLE_INPUT = 1003, + NXT_WEBSOCKET_CR_RESERVED = 1004, + NXT_WEBSOCKET_CR_NOT_PROVIDED = 1005, + NXT_WEBSOCKET_CR_ABNORMAL = 1006, + NXT_WEBSOCKET_CR_INVALID_DATA = 1007, + NXT_WEBSOCKET_CR_POLICY_VIOLATION = 1008, + NXT_WEBSOCKET_CR_MESSAGE_TOO_BIG = 1009, + NXT_WEBSOCKET_CR_EXTENSION_REQUIRED = 1010, + NXT_WEBSOCKET_CR_INTERNAL_SERVER_ERROR = 1011, + NXT_WEBSOCKET_CR_TLS_HANDSHAKE_FAILED = 1015, }; - #endif /* _NXT_WEBSOCKET_HEADER_H_INCLUDED_ */ diff --git a/src/nxt_work_queue.c b/src/nxt_work_queue.c index f38f700b0..93a90a019 100644 --- a/src/nxt_work_queue.c +++ b/src/nxt_work_queue.c @@ -6,7 +6,6 @@ #include - /* * Available work items are crucial for overall engine operation, so * the items are preallocated in two chunks: cache and spare chunks. @@ -27,55 +26,46 @@ static void nxt_work_queue_allocate(nxt_work_queue_cache_t *cache); - /* It should be adjusted with the "work_queue_bucket_items" directive. */ -static nxt_uint_t nxt_work_queue_bucket_items = 409; - +static nxt_uint_t nxt_work_queue_bucket_items = 409; #if (NXT_DEBUG) -nxt_inline void -nxt_work_queue_thread_assert(nxt_work_queue_t *wq) -{ - nxt_tid_t tid; - nxt_thread_t *thread; +nxt_inline void nxt_work_queue_thread_assert(nxt_work_queue_t *wq) { + nxt_tid_t tid; + nxt_thread_t *thread; - thread = nxt_thread(); - tid = nxt_thread_tid(thread); + thread = nxt_thread(); + tid = nxt_thread_tid(thread); - if (nxt_fast_path(wq->tid == tid)) { - return; - } + if (nxt_fast_path(wq->tid == tid)) { + return; + } - if (nxt_slow_path(nxt_pid != wq->pid)) { - wq->pid = nxt_pid; - wq->tid = tid; + if (nxt_slow_path(nxt_pid != wq->pid)) { + wq->pid = nxt_pid; + wq->tid = tid; - return; - } + return; + } - nxt_log_alert(thread->log, "work queue locked by thread %PT", wq->tid); - nxt_abort(); + nxt_log_alert(thread->log, "work queue locked by thread %PT", wq->tid); + nxt_abort(); } +void nxt_work_queue_thread_adopt(nxt_work_queue_t *wq) { + nxt_thread_t *thread; -void nxt_work_queue_thread_adopt(nxt_work_queue_t *wq) -{ - nxt_thread_t *thread; + thread = nxt_thread(); - thread = nxt_thread(); - - wq->pid = nxt_pid; - wq->tid = nxt_thread_tid(thread); + wq->pid = nxt_pid; + wq->tid = nxt_thread_tid(thread); } +void nxt_work_queue_name(nxt_work_queue_t *wq, const char *name) { + nxt_work_queue_thread_assert(wq); -void -nxt_work_queue_name(nxt_work_queue_t *wq, const char *name) -{ - nxt_work_queue_thread_assert(wq); - - wq->name = name; + wq->name = name; } #else @@ -84,228 +74,205 @@ nxt_work_queue_name(nxt_work_queue_t *wq, const char *name) #endif +void nxt_work_queue_cache_create(nxt_work_queue_cache_t *cache, + size_t chunk_size) { + nxt_memzero(cache, sizeof(nxt_work_queue_cache_t)); -void -nxt_work_queue_cache_create(nxt_work_queue_cache_t *cache, size_t chunk_size) -{ - nxt_memzero(cache, sizeof(nxt_work_queue_cache_t)); - - if (chunk_size == 0) { - chunk_size = nxt_work_queue_bucket_items; - } + if (chunk_size == 0) { + chunk_size = nxt_work_queue_bucket_items; + } - /* nxt_work_queue_chunk_t already has one work item. */ - cache->chunk_size = chunk_size - 1; + /* nxt_work_queue_chunk_t already has one work item. */ + cache->chunk_size = chunk_size - 1; - while (cache->next == NULL) { - nxt_work_queue_allocate(cache); - } + while (cache->next == NULL) { + nxt_work_queue_allocate(cache); + } } +void nxt_work_queue_cache_destroy(nxt_work_queue_cache_t *cache) { + nxt_work_queue_chunk_t *chunk, *next; -void -nxt_work_queue_cache_destroy(nxt_work_queue_cache_t *cache) -{ - nxt_work_queue_chunk_t *chunk, *next; - - for (chunk = cache->chunk; chunk; chunk = next) { - next = chunk->next; - nxt_free(chunk); - } + for (chunk = cache->chunk; chunk; chunk = next) { + next = chunk->next; + nxt_free(chunk); + } } +static void nxt_work_queue_allocate(nxt_work_queue_cache_t *cache) { + size_t size; + nxt_uint_t i, n; + nxt_work_t *work; + nxt_work_queue_chunk_t *chunk; -static void -nxt_work_queue_allocate(nxt_work_queue_cache_t *cache) -{ - size_t size; - nxt_uint_t i, n; - nxt_work_t *work; - nxt_work_queue_chunk_t *chunk; + n = cache->chunk_size; + size = sizeof(nxt_work_queue_chunk_t) + n * sizeof(nxt_work_t); - n = cache->chunk_size; - size = sizeof(nxt_work_queue_chunk_t) + n * sizeof(nxt_work_t); + chunk = nxt_malloc(size); - chunk = nxt_malloc(size); + if (nxt_fast_path(chunk != NULL)) { - if (nxt_fast_path(chunk != NULL)) { + chunk->next = cache->chunk; + cache->chunk = chunk; + work = &chunk->work; - chunk->next = cache->chunk; - cache->chunk = chunk; - work = &chunk->work; - - for (i = 0; i < n; i++) { - work[i].next = &work[i + 1]; - } + for (i = 0; i < n; i++) { + work[i].next = &work[i + 1]; + } - work[i].next = NULL; - work++; + work[i].next = NULL; + work++; - } else if (cache->spare != NULL) { + } else if (cache->spare != NULL) { - work = NULL; + work = NULL; - } else { - return; - } + } else { + return; + } - cache->next = cache->spare; - cache->spare = work; + cache->next = cache->spare; + cache->spare = work; } - /* Add a work to a work queue tail. */ -void -nxt_work_queue_add(nxt_work_queue_t *wq, nxt_work_handler_t handler, - nxt_task_t *task, void *obj, void *data) -{ - nxt_work_t *work; - - nxt_work_queue_thread_assert(wq); +void nxt_work_queue_add(nxt_work_queue_t *wq, nxt_work_handler_t handler, + nxt_task_t *task, void *obj, void *data) { + nxt_work_t *work; - for ( ;; ) { - work = wq->cache->next; + nxt_work_queue_thread_assert(wq); - if (nxt_fast_path(work != NULL)) { - wq->cache->next = work->next; - work->next = NULL; + for (;;) { + work = wq->cache->next; - work->handler = handler; - work->task = task; - work->obj = obj; - work->data = data; + if (nxt_fast_path(work != NULL)) { + wq->cache->next = work->next; + work->next = NULL; - if (wq->tail != NULL) { - wq->tail->next = work; + work->handler = handler; + work->task = task; + work->obj = obj; + work->data = data; - } else { - wq->head = work; - } + if (wq->tail != NULL) { + wq->tail->next = work; - wq->tail = work; + } else { + wq->head = work; + } - return; - } + wq->tail = work; - nxt_work_queue_allocate(wq->cache); + return; } + + nxt_work_queue_allocate(wq->cache); + } } +nxt_work_handler_t nxt_work_queue_pop(nxt_work_queue_t *wq, nxt_task_t **task, + void **obj, void **data) { + nxt_work_t *work; -nxt_work_handler_t -nxt_work_queue_pop(nxt_work_queue_t *wq, nxt_task_t **task, void **obj, - void **data) -{ - nxt_work_t *work; + nxt_work_queue_thread_assert(wq); - nxt_work_queue_thread_assert(wq); + work = wq->head; - work = wq->head; + wq->head = work->next; - wq->head = work->next; + if (work->next == NULL) { + wq->tail = NULL; + } - if (work->next == NULL) { - wq->tail = NULL; - } - - *task = work->task; + *task = work->task; - *obj = work->obj; - nxt_prefetch(*obj); + *obj = work->obj; + nxt_prefetch(*obj); - *data = work->data; - nxt_prefetch(*data); + *data = work->data; + nxt_prefetch(*data); - work->next = wq->cache->next; - wq->cache->next = work; + work->next = wq->cache->next; + wq->cache->next = work; - return work->handler; + return work->handler; } - /* Add a work to a locked work queue tail. */ -void -nxt_locked_work_queue_add(nxt_locked_work_queue_t *lwq, nxt_work_t *work) -{ - nxt_thread_spin_lock(&lwq->lock); +void nxt_locked_work_queue_add(nxt_locked_work_queue_t *lwq, nxt_work_t *work) { + nxt_thread_spin_lock(&lwq->lock); - if (lwq->tail != NULL) { - lwq->tail->next = work; + if (lwq->tail != NULL) { + lwq->tail->next = work; - } else { - lwq->head = work; - } + } else { + lwq->head = work; + } - lwq->tail = work; + lwq->tail = work; - nxt_thread_spin_unlock(&lwq->lock); + nxt_thread_spin_unlock(&lwq->lock); } - /* Pop a work from a locked work queue head. */ -nxt_work_handler_t -nxt_locked_work_queue_pop(nxt_locked_work_queue_t *lwq, nxt_task_t **task, - void **obj, void **data) -{ - nxt_work_t *work; - nxt_work_handler_t handler; +nxt_work_handler_t nxt_locked_work_queue_pop(nxt_locked_work_queue_t *lwq, + nxt_task_t **task, void **obj, + void **data) { + nxt_work_t *work; + nxt_work_handler_t handler; - handler = NULL; + handler = NULL; - nxt_thread_spin_lock(&lwq->lock); + nxt_thread_spin_lock(&lwq->lock); - work = lwq->head; + work = lwq->head; - if (work != NULL) { - *task = work->task; - - *obj = work->obj; - nxt_prefetch(*obj); + if (work != NULL) { + *task = work->task; - *data = work->data; - nxt_prefetch(*data); + *obj = work->obj; + nxt_prefetch(*obj); - lwq->head = work->next; + *data = work->data; + nxt_prefetch(*data); - if (work->next == NULL) { - lwq->tail = NULL; - } + lwq->head = work->next; - handler = work->handler; + if (work->next == NULL) { + lwq->tail = NULL; } - nxt_thread_spin_unlock(&lwq->lock); + handler = work->handler; + } - return handler; -} + nxt_thread_spin_unlock(&lwq->lock); + return handler; +} /* Move all works from a locked work queue to a usual work queue. */ -void -nxt_locked_work_queue_move(nxt_thread_t *thr, nxt_locked_work_queue_t *lwq, - nxt_work_queue_t *wq) -{ - nxt_work_t *work; +void nxt_locked_work_queue_move(nxt_thread_t *thr, nxt_locked_work_queue_t *lwq, + nxt_work_queue_t *wq) { + nxt_work_t *work; - nxt_thread_spin_lock(&lwq->lock); + nxt_thread_spin_lock(&lwq->lock); - work = lwq->head; + work = lwq->head; - lwq->head = NULL; - lwq->tail = NULL; + lwq->head = NULL; + lwq->tail = NULL; - nxt_thread_spin_unlock(&lwq->lock); + nxt_thread_spin_unlock(&lwq->lock); - while (work != NULL) { - work->task->thread = thr; + while (work != NULL) { + work->task->thread = thr; - nxt_work_queue_add(wq, work->handler, work->task, - work->obj, work->data); + nxt_work_queue_add(wq, work->handler, work->task, work->obj, work->data); - work = work->next; - } + work = work->next; + } } diff --git a/src/nxt_work_queue.h b/src/nxt_work_queue.h index b6aa4d4c8..3d8630245 100644 --- a/src/nxt_work_queue.h +++ b/src/nxt_work_queue.h @@ -7,22 +7,19 @@ #ifndef _NXT_WORK_QUEUE_H_INCLUDED_ #define _NXT_WORK_QUEUE_H_INCLUDED_ - -typedef struct nxt_work_s nxt_work_t; +typedef struct nxt_work_s nxt_work_t; struct nxt_task_s { - nxt_thread_t *thread; - nxt_log_t *log; - uint32_t ident; - nxt_work_t *next_work; + nxt_thread_t *thread; + nxt_log_t *log; + uint32_t ident; + nxt_work_t *next_work; - /* TODO: exception_handler, prev/next task, subtasks. */ + /* TODO: exception_handler, prev/next task, subtasks. */ }; - -#define nxt_task_next_ident() \ - ((uint32_t) nxt_atomic_fetch_add(&nxt_task_ident, 1) & 0x3FFFFFFF) - +#define nxt_task_next_ident() \ + ((uint32_t)nxt_atomic_fetch_add(&nxt_task_ident, 1) & 0x3FFFFFFF) /* * A work handler with just the obj and data arguments instead @@ -32,75 +29,70 @@ struct nxt_task_s { * source filters, so the data argument has been introduced and * is used where appropriate. */ -//typedef void (*nxt_work_handler_t)(nxt_task_t *task, void *obj, void *data); - +// typedef void (*nxt_work_handler_t)(nxt_task_t *task, void *obj, void *data); struct nxt_work_s { - nxt_work_t *next; - nxt_work_handler_t handler; - nxt_task_t *task; - void *obj; - void *data; + nxt_work_t *next; + nxt_work_handler_t handler; + nxt_task_t *task; + void *obj; + void *data; }; - -typedef struct nxt_work_queue_chunk_s nxt_work_queue_chunk_t; +typedef struct nxt_work_queue_chunk_s nxt_work_queue_chunk_t; struct nxt_work_queue_chunk_s { - nxt_work_queue_chunk_t *next; - nxt_work_t work; + nxt_work_queue_chunk_t *next; + nxt_work_t work; }; - typedef struct { - nxt_work_t *next; - nxt_work_t *spare; - nxt_work_queue_chunk_t *chunk; - size_t chunk_size; + nxt_work_t *next; + nxt_work_t *spare; + nxt_work_queue_chunk_t *chunk; + size_t chunk_size; } nxt_work_queue_cache_t; - -typedef struct nxt_work_queue_s nxt_work_queue_t; +typedef struct nxt_work_queue_s nxt_work_queue_t; struct nxt_work_queue_s { - nxt_work_t *head; - nxt_work_t *tail; - nxt_work_queue_cache_t *cache; + nxt_work_t *head; + nxt_work_t *tail; + nxt_work_queue_cache_t *cache; #if (NXT_DEBUG) - const char *name; - int32_t pid; - nxt_tid_t tid; + const char *name; + int32_t pid; + nxt_tid_t tid; #endif }; - typedef struct { - nxt_thread_spinlock_t lock; - nxt_work_t *head; - nxt_work_t *tail; - nxt_work_queue_cache_t cache; + nxt_thread_spinlock_t lock; + nxt_work_t *head; + nxt_work_t *tail; + nxt_work_queue_cache_t cache; } nxt_locked_work_queue_t; - NXT_EXPORT void nxt_work_queue_cache_create(nxt_work_queue_cache_t *cache, - size_t chunk_size); + size_t chunk_size); NXT_EXPORT void nxt_work_queue_cache_destroy(nxt_work_queue_cache_t *cache); NXT_EXPORT void nxt_work_queue_add(nxt_work_queue_t *wq, - nxt_work_handler_t handler, nxt_task_t *task, void *obj, void *data); + nxt_work_handler_t handler, nxt_task_t *task, + void *obj, void *data); NXT_EXPORT nxt_work_handler_t nxt_work_queue_pop(nxt_work_queue_t *wq, - nxt_task_t **task, void **obj, void **data); - - -#define nxt_work_set(_work, _handler, _task, _obj, _data) \ - do { \ - nxt_work_t *work = _work; \ - \ - work->handler = _handler; \ - work->task = _task; \ - work->obj = _obj; \ - work->data = _data; \ - } while (0) + nxt_task_t **task, void **obj, + void **data); + +#define nxt_work_set(_work, _handler, _task, _obj, _data) \ + do { \ + nxt_work_t *work = _work; \ + \ + work->handler = _handler; \ + work->task = _task; \ + work->obj = _obj; \ + work->data = _data; \ + } while (0) #if (NXT_DEBUG) @@ -115,13 +107,12 @@ NXT_EXPORT void nxt_work_queue_thread_adopt(nxt_work_queue_t *wq); #endif - NXT_EXPORT void nxt_locked_work_queue_add(nxt_locked_work_queue_t *lwq, - nxt_work_t *work); + nxt_work_t *work); NXT_EXPORT nxt_work_handler_t nxt_locked_work_queue_pop( nxt_locked_work_queue_t *lwq, nxt_task_t **task, void **obj, void **data); NXT_EXPORT void nxt_locked_work_queue_move(nxt_thread_t *thr, - nxt_locked_work_queue_t *lwq, nxt_work_queue_t *wq); - + nxt_locked_work_queue_t *lwq, + nxt_work_queue_t *wq); #endif /* _NXT_WORK_QUEUE_H_INCLUDED_ */ diff --git a/src/perl/nxt_perl_psgi.c b/src/perl/nxt_perl_psgi.c index 587656cd4..9d46c1325 100644 --- a/src/perl/nxt_perl_psgi.c +++ b/src/perl/nxt_perl_psgi.c @@ -15,28 +15,30 @@ #include #include - typedef struct { - PerlInterpreter *my_perl; - nxt_perl_psgi_io_arg_t arg_input; - nxt_perl_psgi_io_arg_t arg_error; - SV *app; - CV *cb; - nxt_unit_request_info_t *req; - pthread_t thread; - nxt_unit_ctx_t *ctx; + PerlInterpreter *my_perl; + nxt_perl_psgi_io_arg_t arg_input; + nxt_perl_psgi_io_arg_t arg_error; + SV *app; + CV *cb; + nxt_unit_request_info_t *req; + pthread_t thread; + nxt_unit_ctx_t *ctx; } nxt_perl_psgi_ctx_t; - static SSize_t nxt_perl_psgi_io_input_read(PerlInterpreter *my_perl, - nxt_perl_psgi_io_arg_t *arg, void *vbuf, size_t length); + nxt_perl_psgi_io_arg_t *arg, + void *vbuf, size_t length); static SSize_t nxt_perl_psgi_io_input_write(PerlInterpreter *my_perl, - nxt_perl_psgi_io_arg_t *arg, const void *vbuf, size_t length); + nxt_perl_psgi_io_arg_t *arg, + const void *vbuf, size_t length); static SSize_t nxt_perl_psgi_io_error_read(PerlInterpreter *my_perl, - nxt_perl_psgi_io_arg_t *arg, void *vbuf, size_t length); + nxt_perl_psgi_io_arg_t *arg, + void *vbuf, size_t length); static SSize_t nxt_perl_psgi_io_error_write(PerlInterpreter *my_perl, - nxt_perl_psgi_io_arg_t *arg, const void *vbuf, size_t length); + nxt_perl_psgi_io_arg_t *arg, + const void *vbuf, size_t length); /* static void nxt_perl_psgi_xs_core_global_changes(PerlInterpreter *my_perl, @@ -45,70 +47,77 @@ static void nxt_perl_psgi_xs_core_global_changes(PerlInterpreter *my_perl, static void nxt_perl_psgi_xs_init(pTHX); -static SV *nxt_perl_psgi_call_var_application(PerlInterpreter *my_perl, - SV *env, SV *app, nxt_unit_request_info_t *req); +static SV *nxt_perl_psgi_call_var_application(PerlInterpreter *my_perl, SV *env, + SV *app, + nxt_unit_request_info_t *req); static SV *nxt_perl_psgi_call_method(PerlInterpreter *my_perl, SV *obj, - const char *method, nxt_unit_request_info_t *req); + const char *method, + nxt_unit_request_info_t *req); /* For currect load XS modules */ EXTERN_C void boot_DynaLoader(pTHX_ CV *cv); static int nxt_perl_psgi_io_init(PerlInterpreter *my_perl, - nxt_perl_psgi_io_arg_t *arg, const char *mode, void *req); + nxt_perl_psgi_io_arg_t *arg, const char *mode, + void *req); static int nxt_perl_psgi_ctx_init(const char *script, - nxt_perl_psgi_ctx_t *pctx); + nxt_perl_psgi_ctx_t *pctx); static SV *nxt_perl_psgi_env_create(PerlInterpreter *my_perl, - nxt_unit_request_info_t *req); + nxt_unit_request_info_t *req); nxt_inline int nxt_perl_psgi_add_sptr(PerlInterpreter *my_perl, HV *hash_env, - const char *name, uint32_t name_len, nxt_unit_sptr_t *sptr, uint32_t len); + const char *name, uint32_t name_len, + nxt_unit_sptr_t *sptr, uint32_t len); nxt_inline int nxt_perl_psgi_add_str(PerlInterpreter *my_perl, HV *hash_env, - const char *name, uint32_t name_len, const char *str, uint32_t len); + const char *name, uint32_t name_len, + const char *str, uint32_t len); nxt_inline int nxt_perl_psgi_add_value(PerlInterpreter *my_perl, HV *hash_env, - const char *name, uint32_t name_len, void *value); - + const char *name, uint32_t name_len, + void *value); static char *nxt_perl_psgi_module_create(const char *script); static nxt_int_t nxt_perl_psgi_result_status(PerlInterpreter *my_perl, - SV *result); -static int nxt_perl_psgi_result_head(PerlInterpreter *my_perl, - SV *sv_head, nxt_unit_request_info_t *req, uint16_t status); -static int nxt_perl_psgi_result_body(PerlInterpreter *my_perl, - SV *result, nxt_unit_request_info_t *req); -static int nxt_perl_psgi_result_body_ref(PerlInterpreter *my_perl, - SV *sv_body, nxt_unit_request_info_t *req); + SV *result); +static int nxt_perl_psgi_result_head(PerlInterpreter *my_perl, SV *sv_head, + nxt_unit_request_info_t *req, + uint16_t status); +static int nxt_perl_psgi_result_body(PerlInterpreter *my_perl, SV *result, + nxt_unit_request_info_t *req); +static int nxt_perl_psgi_result_body_ref(PerlInterpreter *my_perl, SV *sv_body, + nxt_unit_request_info_t *req); static int nxt_perl_psgi_result_body_fh(PerlInterpreter *my_perl, SV *sv_body, - nxt_unit_request_info_t *req); + nxt_unit_request_info_t *req); static ssize_t nxt_perl_psgi_io_read(nxt_unit_read_info_t *read_info, void *dst, - size_t size); -static int nxt_perl_psgi_result_array(PerlInterpreter *my_perl, - SV *result, nxt_unit_request_info_t *req); + size_t size); +static int nxt_perl_psgi_result_array(PerlInterpreter *my_perl, SV *result, + nxt_unit_request_info_t *req); static void nxt_perl_psgi_result_cb(PerlInterpreter *my_perl, SV *result, - nxt_unit_request_info_t *req); + nxt_unit_request_info_t *req); static nxt_int_t nxt_perl_psgi_start(nxt_task_t *task, - nxt_process_data_t *data); + nxt_process_data_t *data); static void nxt_perl_psgi_request_handler(nxt_unit_request_info_t *req); static int nxt_perl_psgi_ready_handler(nxt_unit_ctx_t *ctx); static void *nxt_perl_psgi_thread_func(void *main_ctx); static int nxt_perl_psgi_init_threads(nxt_perl_app_conf_t *c); static void nxt_perl_psgi_join_threads(nxt_unit_ctx_t *ctx, - nxt_perl_app_conf_t *c); + nxt_perl_app_conf_t *c); static void nxt_perl_psgi_ctx_free(nxt_perl_psgi_ctx_t *pctx); -static CV *nxt_perl_psgi_write; -static CV *nxt_perl_psgi_close; -static CV *nxt_perl_psgi_cb; -static pthread_attr_t *nxt_perl_psgi_thread_attr; -static nxt_perl_psgi_ctx_t *nxt_perl_psgi_ctxs; +static CV *nxt_perl_psgi_write; +static CV *nxt_perl_psgi_close; +static CV *nxt_perl_psgi_cb; +static pthread_attr_t *nxt_perl_psgi_thread_attr; +static nxt_perl_psgi_ctx_t *nxt_perl_psgi_ctxs; -static uint32_t nxt_perl_psgi_compat[] = { - NXT_VERNUM, NXT_DEBUG, +static uint32_t nxt_perl_psgi_compat[] = { + NXT_VERNUM, + NXT_DEBUG, }; -NXT_EXPORT nxt_app_module_t nxt_app_module = { +NXT_EXPORT nxt_app_module_t nxt_app_module = { sizeof(nxt_perl_psgi_compat), nxt_perl_psgi_compat, nxt_string("perl"), @@ -129,41 +138,32 @@ const nxt_perl_psgi_io_tab_t nxt_perl_psgi_io_tab_error = { .write = nxt_perl_psgi_io_error_write, }; - -static SSize_t -nxt_perl_psgi_io_input_read(PerlInterpreter *my_perl, - nxt_perl_psgi_io_arg_t *arg, void *vbuf, size_t length) -{ - return nxt_unit_request_read(arg->req, vbuf, length); +static SSize_t nxt_perl_psgi_io_input_read(PerlInterpreter *my_perl, + nxt_perl_psgi_io_arg_t *arg, + void *vbuf, size_t length) { + return nxt_unit_request_read(arg->req, vbuf, length); } - -static SSize_t -nxt_perl_psgi_io_input_write(PerlInterpreter *my_perl, - nxt_perl_psgi_io_arg_t *arg, const void *vbuf, size_t length) -{ - return 0; +static SSize_t nxt_perl_psgi_io_input_write(PerlInterpreter *my_perl, + nxt_perl_psgi_io_arg_t *arg, + const void *vbuf, size_t length) { + return 0; } - -static SSize_t -nxt_perl_psgi_io_error_read(PerlInterpreter *my_perl, - nxt_perl_psgi_io_arg_t *arg, void *vbuf, size_t length) -{ - return 0; +static SSize_t nxt_perl_psgi_io_error_read(PerlInterpreter *my_perl, + nxt_perl_psgi_io_arg_t *arg, + void *vbuf, size_t length) { + return 0; } +static SSize_t nxt_perl_psgi_io_error_write(PerlInterpreter *my_perl, + nxt_perl_psgi_io_arg_t *arg, + const void *vbuf, size_t length) { + nxt_unit_req_error(arg->req, "Perl: %s", (const char *)vbuf); -static SSize_t -nxt_perl_psgi_io_error_write(PerlInterpreter *my_perl, - nxt_perl_psgi_io_arg_t *arg, const void *vbuf, size_t length) -{ - nxt_unit_req_error(arg->req, "Perl: %s", (const char*) vbuf); - - return (SSize_t) length; + return (SSize_t)length; } - /* In the future it will be necessary to change some Perl functions. */ /* static void @@ -185,1248 +185,1160 @@ nxt_perl_psgi_xs_core_global_changes(PerlInterpreter *my_perl, } */ - XS(XS_NGINX__Unit__PSGI_exit); -XS(XS_NGINX__Unit__PSGI_exit) -{ - I32 ax = POPMARK; - Perl_croak(aTHX_ (char *) NULL); - XSRETURN_EMPTY; +XS(XS_NGINX__Unit__PSGI_exit) { + I32 ax = POPMARK; + Perl_croak(aTHX_(char *) NULL); + XSRETURN_EMPTY; } - XS(XS_NGINX__Unit__Sandbox_write); -XS(XS_NGINX__Unit__Sandbox_write) -{ - int rc; - char *body; - size_t len; - nxt_perl_psgi_ctx_t *pctx; +XS(XS_NGINX__Unit__Sandbox_write) { + int rc; + char *body; + size_t len; + nxt_perl_psgi_ctx_t *pctx; - dXSARGS; + dXSARGS; - if (nxt_slow_path(items != 2)) { - Perl_croak(aTHX_ "Wrong number of arguments. Need one string"); + if (nxt_slow_path(items != 2)) { + Perl_croak(aTHX_ "Wrong number of arguments. Need one string"); - XSRETURN_EMPTY; - } + XSRETURN_EMPTY; + } - body = SvPV(ST(1), len); + body = SvPV(ST(1), len); - pctx = CvXSUBANY(cv).any_ptr; + pctx = CvXSUBANY(cv).any_ptr; - rc = nxt_unit_response_write(pctx->req, body, len); - if (nxt_slow_path(rc != NXT_UNIT_OK)) { - Perl_croak(aTHX_ "Failed to write response body"); + rc = nxt_unit_response_write(pctx->req, body, len); + if (nxt_slow_path(rc != NXT_UNIT_OK)) { + Perl_croak(aTHX_ "Failed to write response body"); - XSRETURN_EMPTY; - } + XSRETURN_EMPTY; + } - XSRETURN_IV(len); + XSRETURN_IV(len); } - -nxt_inline void -nxt_perl_psgi_cb_request_done(nxt_perl_psgi_ctx_t *pctx, int status) -{ - if (pctx->req != NULL) { - nxt_unit_request_done(pctx->req, status); - pctx->req = NULL; - } +nxt_inline void nxt_perl_psgi_cb_request_done(nxt_perl_psgi_ctx_t *pctx, + int status) { + if (pctx->req != NULL) { + nxt_unit_request_done(pctx->req, status); + pctx->req = NULL; + } } - XS(XS_NGINX__Unit__Sandbox_close); -XS(XS_NGINX__Unit__Sandbox_close) -{ - I32 ax; +XS(XS_NGINX__Unit__Sandbox_close) { + I32 ax; - ax = POPMARK; + ax = POPMARK; - nxt_perl_psgi_cb_request_done(CvXSUBANY(cv).any_ptr, NXT_UNIT_OK); + nxt_perl_psgi_cb_request_done(CvXSUBANY(cv).any_ptr, NXT_UNIT_OK); - XSRETURN_NO; + XSRETURN_NO; } - XS(XS_NGINX__Unit__Sandbox_cb); -XS(XS_NGINX__Unit__Sandbox_cb) -{ - SV *obj; - int rc; - long array_len; - nxt_perl_psgi_ctx_t *pctx; +XS(XS_NGINX__Unit__Sandbox_cb) { + SV *obj; + int rc; + long array_len; + nxt_perl_psgi_ctx_t *pctx; - dXSARGS; + dXSARGS; - if (nxt_slow_path(items != 1)) { - nxt_perl_psgi_cb_request_done(CvXSUBANY(cv).any_ptr, NXT_UNIT_ERROR); + if (nxt_slow_path(items != 1)) { + nxt_perl_psgi_cb_request_done(CvXSUBANY(cv).any_ptr, NXT_UNIT_ERROR); - Perl_croak(aTHX_ "Wrong number of arguments"); + Perl_croak(aTHX_ "Wrong number of arguments"); - XSRETURN_EMPTY; - } + XSRETURN_EMPTY; + } - pctx = CvXSUBANY(cv).any_ptr; + pctx = CvXSUBANY(cv).any_ptr; - if (nxt_slow_path(SvOK(ST(0)) == 0 || SvROK(ST(0)) == 0 - || SvTYPE(SvRV(ST(0))) != SVt_PVAV - || pctx->req == NULL)) - { - nxt_perl_psgi_cb_request_done(CvXSUBANY(cv).any_ptr, NXT_UNIT_ERROR); + if (nxt_slow_path(SvOK(ST(0)) == 0 || SvROK(ST(0)) == 0 || + SvTYPE(SvRV(ST(0))) != SVt_PVAV || pctx->req == NULL)) { + nxt_perl_psgi_cb_request_done(CvXSUBANY(cv).any_ptr, NXT_UNIT_ERROR); - Perl_croak(aTHX_ "PSGI: An unexpected response was received " - "from Perl Application"); + Perl_croak(aTHX_ "PSGI: An unexpected response was received " + "from Perl Application"); - XSRETURN_EMPTY; - } + XSRETURN_EMPTY; + } - rc = nxt_perl_psgi_result_array(PERL_GET_CONTEXT, ST(0), pctx->req); - if (nxt_slow_path(rc != NXT_UNIT_OK)) { - nxt_perl_psgi_cb_request_done(CvXSUBANY(cv).any_ptr, NXT_UNIT_ERROR); + rc = nxt_perl_psgi_result_array(PERL_GET_CONTEXT, ST(0), pctx->req); + if (nxt_slow_path(rc != NXT_UNIT_OK)) { + nxt_perl_psgi_cb_request_done(CvXSUBANY(cv).any_ptr, NXT_UNIT_ERROR); - Perl_croak(aTHX_ (char *) NULL); + Perl_croak(aTHX_(char *) NULL); - XSRETURN_EMPTY; - } + XSRETURN_EMPTY; + } - array_len = av_len((AV *) SvRV(ST(0))); + array_len = av_len((AV *)SvRV(ST(0))); - if (array_len < 2) { - obj = sv_bless(newRV_noinc((SV *) newHV()), - gv_stashpv("NGINX::Unit::Sandbox", GV_ADD)); - ST(0) = obj; + if (array_len < 2) { + obj = sv_bless(newRV_noinc((SV *)newHV()), + gv_stashpv("NGINX::Unit::Sandbox", GV_ADD)); + ST(0) = obj; - XSRETURN(1); - } + XSRETURN(1); + } - nxt_perl_psgi_cb_request_done(CvXSUBANY(cv).any_ptr, NXT_UNIT_OK); + nxt_perl_psgi_cb_request_done(CvXSUBANY(cv).any_ptr, NXT_UNIT_OK); - XSRETURN_EMPTY; + XSRETURN_EMPTY; } +static void nxt_perl_psgi_xs_init(pTHX) { + /* + nxt_perl_psgi_xs_core_global_changes(my_perl, "CORE::GLOBAL::exit", + "NGINX::Unit::PSGI::exit", + XS_NGINX__Unit__PSGI_exit); + */ + nxt_perl_psgi_layer_stream_init(aTHX); -static void -nxt_perl_psgi_xs_init(pTHX) -{ -/* - nxt_perl_psgi_xs_core_global_changes(my_perl, "CORE::GLOBAL::exit", - "NGINX::Unit::PSGI::exit", - XS_NGINX__Unit__PSGI_exit); -*/ - nxt_perl_psgi_layer_stream_init(aTHX); + /* DynaLoader for Perl modules who use XS */ + newXS("DynaLoader::boot_DynaLoader", boot_DynaLoader, __FILE__); - /* DynaLoader for Perl modules who use XS */ - newXS("DynaLoader::boot_DynaLoader", boot_DynaLoader, __FILE__); + nxt_perl_psgi_write = newXS("NGINX::Unit::Sandbox::write", + XS_NGINX__Unit__Sandbox_write, __FILE__); - nxt_perl_psgi_write = newXS("NGINX::Unit::Sandbox::write", - XS_NGINX__Unit__Sandbox_write, __FILE__); + nxt_perl_psgi_close = newXS("NGINX::Unit::Sandbox::close", + XS_NGINX__Unit__Sandbox_close, __FILE__); - nxt_perl_psgi_close = newXS("NGINX::Unit::Sandbox::close", - XS_NGINX__Unit__Sandbox_close, __FILE__); - - nxt_perl_psgi_cb = newXS("NGINX::Unit::Sandbox::cb", - XS_NGINX__Unit__Sandbox_cb, __FILE__); + nxt_perl_psgi_cb = + newXS("NGINX::Unit::Sandbox::cb", XS_NGINX__Unit__Sandbox_cb, __FILE__); } +static SV *nxt_perl_psgi_call_var_application(PerlInterpreter *my_perl, SV *env, + SV *app, + nxt_unit_request_info_t *req) { + SV *result; -static SV * -nxt_perl_psgi_call_var_application(PerlInterpreter *my_perl, - SV *env, SV *app, nxt_unit_request_info_t *req) -{ - SV *result; + dSP; - dSP; + ENTER; + SAVETMPS; - ENTER; - SAVETMPS; + PUSHMARK(sp); + XPUSHs(env); + PUTBACK; - PUSHMARK(sp); - XPUSHs(env); - PUTBACK; + call_sv(app, G_EVAL | G_SCALAR); - call_sv(app, G_EVAL|G_SCALAR); + SPAGAIN; - SPAGAIN; - - if (SvTRUE(ERRSV)) { - nxt_unit_req_error(req, "PSGI: Failed to run Perl Application: \n%s", - SvPV_nolen(ERRSV)); - } + if (SvTRUE(ERRSV)) { + nxt_unit_req_error(req, "PSGI: Failed to run Perl Application: \n%s", + SvPV_nolen(ERRSV)); + } - result = POPs; - SvREFCNT_inc(result); + result = POPs; + SvREFCNT_inc(result); - PUTBACK; - FREETMPS; - LEAVE; + PUTBACK; + FREETMPS; + LEAVE; - return result; + return result; } +static SV *nxt_perl_psgi_call_method(PerlInterpreter *my_perl, SV *obj, + const char *method, + nxt_unit_request_info_t *req) { + SV *result; -static SV * -nxt_perl_psgi_call_method(PerlInterpreter *my_perl, SV *obj, const char *method, - nxt_unit_request_info_t *req) -{ - SV *result; + dSP; - dSP; + ENTER; + SAVETMPS; - ENTER; - SAVETMPS; + PUSHMARK(sp); + XPUSHs(obj); + PUTBACK; - PUSHMARK(sp); - XPUSHs(obj); - PUTBACK; + call_method(method, G_EVAL | G_SCALAR); - call_method(method, G_EVAL|G_SCALAR); + SPAGAIN; - SPAGAIN; + if (SvTRUE(ERRSV)) { + nxt_unit_req_error(req, "PSGI: Failed to call method '%s':\n%s", method, + SvPV_nolen(ERRSV)); + result = NULL; - if (SvTRUE(ERRSV)) { - nxt_unit_req_error(req, "PSGI: Failed to call method '%s':\n%s", - method, SvPV_nolen(ERRSV)); - result = NULL; + } else { + result = SvREFCNT_inc(POPs); + } - } else { - result = SvREFCNT_inc(POPs); - } - - PUTBACK; - FREETMPS; - LEAVE; + PUTBACK; + FREETMPS; + LEAVE; - return result; + return result; } +static char *nxt_perl_psgi_module_create(const char *script) { + char *buf, *p; + size_t length; -static char * -nxt_perl_psgi_module_create(const char *script) -{ - char *buf, *p; - size_t length; - - static const nxt_str_t prefix = nxt_string( - "package NGINX::Unit::Sandbox;" - "{my $app = do \"" - ); - - static const nxt_str_t suffix = nxt_string_zero( - "\";" - "unless ($app) {" - " if($@ || $1) {die $@ || $1}" - " else {die \"File not found or compilation error.\"}" - "} " - "return $app}" - ); - - length = strlen(script); - - buf = nxt_unit_malloc(NULL, prefix.length + length + suffix.length); - if (nxt_slow_path(buf == NULL)) { - nxt_unit_alert(NULL, "PSGI: Failed to allocate memory " - "for Perl script file %s", script); - - return NULL; - } + static const nxt_str_t prefix = nxt_string("package NGINX::Unit::Sandbox;" + "{my $app = do \""); - p = nxt_cpymem(buf, prefix.start, prefix.length); - p = nxt_cpymem(p, script, length); - nxt_memcpy(p, suffix.start, suffix.length); + static const nxt_str_t suffix = + nxt_string_zero("\";" + "unless ($app) {" + " if($@ || $1) {die $@ || $1}" + " else {die \"File not found or compilation error.\"}" + "} " + "return $app}"); - return buf; -} + length = strlen(script); + buf = nxt_unit_malloc(NULL, prefix.length + length + suffix.length); + if (nxt_slow_path(buf == NULL)) { + nxt_unit_alert(NULL, + "PSGI: Failed to allocate memory " + "for Perl script file %s", + script); -static int -nxt_perl_psgi_io_init(PerlInterpreter *my_perl, - nxt_perl_psgi_io_arg_t *arg, const char *mode, void *req) -{ - SV *io; - PerlIO *fp; - - if (arg->io == NULL) { - fp = nxt_perl_psgi_layer_stream_fp_create(aTHX_ arg->rv, mode); - if (nxt_slow_path(fp == NULL)) { - return NXT_UNIT_ERROR; - } - - io = nxt_perl_psgi_layer_stream_io_create(aTHX_ fp); - if (nxt_slow_path(io == NULL)) { - nxt_perl_psgi_layer_stream_fp_destroy(aTHX_ fp); - return NXT_UNIT_ERROR; - } - - arg->io = io; - arg->fp = fp; - } + return NULL; + } - arg->req = req; + p = nxt_cpymem(buf, prefix.start, prefix.length); + p = nxt_cpymem(p, script, length); + nxt_memcpy(p, suffix.start, suffix.length); - return NXT_UNIT_OK; + return buf; } +static int nxt_perl_psgi_io_init(PerlInterpreter *my_perl, + nxt_perl_psgi_io_arg_t *arg, const char *mode, + void *req) { + SV *io; + PerlIO *fp; + + if (arg->io == NULL) { + fp = nxt_perl_psgi_layer_stream_fp_create(aTHX_ arg->rv, mode); + if (nxt_slow_path(fp == NULL)) { + return NXT_UNIT_ERROR; + } -static void -nxt_perl_psgi_io_release(PerlInterpreter *my_perl, nxt_perl_psgi_io_arg_t *arg) -{ - if (arg->io != NULL) { - SvREFCNT_dec(arg->io); - arg->io = NULL; + io = nxt_perl_psgi_layer_stream_io_create(aTHX_ fp); + if (nxt_slow_path(io == NULL)) { + nxt_perl_psgi_layer_stream_fp_destroy(aTHX_ fp); + return NXT_UNIT_ERROR; } + + arg->io = io; + arg->fp = fp; + } + + arg->req = req; + + return NXT_UNIT_OK; } +static void nxt_perl_psgi_io_release(PerlInterpreter *my_perl, + nxt_perl_psgi_io_arg_t *arg) { + if (arg->io != NULL) { + SvREFCNT_dec(arg->io); + arg->io = NULL; + } +} -static int -nxt_perl_psgi_ctx_init(const char *script, nxt_perl_psgi_ctx_t *pctx) -{ - int status, res; - char *run_module; - PerlInterpreter *my_perl; +static int nxt_perl_psgi_ctx_init(const char *script, + nxt_perl_psgi_ctx_t *pctx) { + int status, res; + char *run_module; + PerlInterpreter *my_perl; - static char argv[] = "\0""-e\0""0"; - static char *embedding[] = { &argv[0], &argv[1], &argv[4] }; + static char argv[] = "\0" + "-e\0" + "0"; + static char *embedding[] = {&argv[0], &argv[1], &argv[4]}; - my_perl = perl_alloc(); + my_perl = perl_alloc(); - if (nxt_slow_path(my_perl == NULL)) { - nxt_unit_alert(NULL, - "PSGI: Failed to allocate memory for Perl interpreter"); + if (nxt_slow_path(my_perl == NULL)) { + nxt_unit_alert(NULL, + "PSGI: Failed to allocate memory for Perl interpreter"); - return NXT_UNIT_ERROR; - } + return NXT_UNIT_ERROR; + } - pctx->my_perl = my_perl; + pctx->my_perl = my_perl; - run_module = NULL; + run_module = NULL; - perl_construct(my_perl); - PERL_SET_CONTEXT(my_perl); + perl_construct(my_perl); + PERL_SET_CONTEXT(my_perl); - status = perl_parse(my_perl, nxt_perl_psgi_xs_init, 3, embedding, NULL); + status = perl_parse(my_perl, nxt_perl_psgi_xs_init, 3, embedding, NULL); - if (nxt_slow_path(status != 0)) { - nxt_unit_alert(NULL, "PSGI: Failed to parse Perl Script"); - goto fail; - } + if (nxt_slow_path(status != 0)) { + nxt_unit_alert(NULL, "PSGI: Failed to parse Perl Script"); + goto fail; + } - CvXSUBANY(nxt_perl_psgi_write).any_ptr = pctx; - CvXSUBANY(nxt_perl_psgi_close).any_ptr = pctx; - CvXSUBANY(nxt_perl_psgi_cb).any_ptr = pctx; + CvXSUBANY(nxt_perl_psgi_write).any_ptr = pctx; + CvXSUBANY(nxt_perl_psgi_close).any_ptr = pctx; + CvXSUBANY(nxt_perl_psgi_cb).any_ptr = pctx; - pctx->cb = nxt_perl_psgi_cb; + pctx->cb = nxt_perl_psgi_cb; - PL_exit_flags |= PERL_EXIT_DESTRUCT_END; - PL_origalen = 1; + PL_exit_flags |= PERL_EXIT_DESTRUCT_END; + PL_origalen = 1; - status = perl_run(my_perl); + status = perl_run(my_perl); - if (nxt_slow_path(status != 0)) { - nxt_unit_alert(NULL, "PSGI: Failed to run Perl"); - goto fail; - } + if (nxt_slow_path(status != 0)) { + nxt_unit_alert(NULL, "PSGI: Failed to run Perl"); + goto fail; + } - sv_setsv(get_sv("0", 0), newSVpv(script, 0)); + sv_setsv(get_sv("0", 0), newSVpv(script, 0)); - run_module = nxt_perl_psgi_module_create(script); - if (nxt_slow_path(run_module == NULL)) { - goto fail; - } + run_module = nxt_perl_psgi_module_create(script); + if (nxt_slow_path(run_module == NULL)) { + goto fail; + } - pctx->arg_input.rv = newSV_type(SVt_RV); - sv_setptrref(pctx->arg_input.rv, &pctx->arg_input); - SvSETMAGIC(pctx->arg_input.rv); + pctx->arg_input.rv = newSV_type(SVt_RV); + sv_setptrref(pctx->arg_input.rv, &pctx->arg_input); + SvSETMAGIC(pctx->arg_input.rv); - pctx->arg_input.io_tab = &nxt_perl_psgi_io_tab_input; + pctx->arg_input.io_tab = &nxt_perl_psgi_io_tab_input; - res = nxt_perl_psgi_io_init(my_perl, &pctx->arg_input, "r", NULL); - if (nxt_slow_path(res != NXT_UNIT_OK)) { - nxt_unit_alert(NULL, "PSGI: Failed to init io.psgi.input"); - goto fail; - } + res = nxt_perl_psgi_io_init(my_perl, &pctx->arg_input, "r", NULL); + if (nxt_slow_path(res != NXT_UNIT_OK)) { + nxt_unit_alert(NULL, "PSGI: Failed to init io.psgi.input"); + goto fail; + } - pctx->arg_error.rv = newSV_type(SVt_RV); - sv_setptrref(pctx->arg_error.rv, &pctx->arg_error); - SvSETMAGIC(pctx->arg_error.rv); + pctx->arg_error.rv = newSV_type(SVt_RV); + sv_setptrref(pctx->arg_error.rv, &pctx->arg_error); + SvSETMAGIC(pctx->arg_error.rv); - pctx->arg_error.io_tab = &nxt_perl_psgi_io_tab_error; + pctx->arg_error.io_tab = &nxt_perl_psgi_io_tab_error; - res = nxt_perl_psgi_io_init(my_perl, &pctx->arg_error, "w", NULL); - if (nxt_slow_path(res != NXT_UNIT_OK)) { - nxt_unit_alert(NULL, "PSGI: Failed to init io.psgi.error"); - goto fail; - } + res = nxt_perl_psgi_io_init(my_perl, &pctx->arg_error, "w", NULL); + if (nxt_slow_path(res != NXT_UNIT_OK)) { + nxt_unit_alert(NULL, "PSGI: Failed to init io.psgi.error"); + goto fail; + } - pctx->app = eval_pv(run_module, FALSE); + pctx->app = eval_pv(run_module, FALSE); - if (SvTRUE(ERRSV)) { - nxt_unit_alert(NULL, "PSGI: Failed to parse script: %s\n%s", - script, SvPV_nolen(ERRSV)); - goto fail; - } + if (SvTRUE(ERRSV)) { + nxt_unit_alert(NULL, "PSGI: Failed to parse script: %s\n%s", script, + SvPV_nolen(ERRSV)); + goto fail; + } - nxt_unit_free(NULL, run_module); + nxt_unit_free(NULL, run_module); - return NXT_UNIT_OK; + return NXT_UNIT_OK; fail: - nxt_perl_psgi_io_release(my_perl, &pctx->arg_input); - nxt_perl_psgi_io_release(my_perl, &pctx->arg_error); + nxt_perl_psgi_io_release(my_perl, &pctx->arg_input); + nxt_perl_psgi_io_release(my_perl, &pctx->arg_error); - if (run_module != NULL) { - nxt_unit_free(NULL, run_module); - } + if (run_module != NULL) { + nxt_unit_free(NULL, run_module); + } - perl_destruct(my_perl); - perl_free(my_perl); + perl_destruct(my_perl); + perl_free(my_perl); - pctx->my_perl = NULL; + pctx->my_perl = NULL; - return NXT_UNIT_ERROR; + return NXT_UNIT_ERROR; } +static SV *nxt_perl_psgi_env_create(PerlInterpreter *my_perl, + nxt_unit_request_info_t *req) { + HV *hash_env; + AV *array_version; + uint32_t i; + nxt_unit_field_t *f; + nxt_unit_request_t *r; + nxt_perl_psgi_ctx_t *pctx; + + pctx = req->ctx->data; + + hash_env = newHV(); + if (nxt_slow_path(hash_env == NULL)) { + return NULL; + } -static SV * -nxt_perl_psgi_env_create(PerlInterpreter *my_perl, - nxt_unit_request_info_t *req) -{ - HV *hash_env; - AV *array_version; - uint32_t i; - nxt_unit_field_t *f; - nxt_unit_request_t *r; - nxt_perl_psgi_ctx_t *pctx; - - pctx = req->ctx->data; - - hash_env = newHV(); - if (nxt_slow_path(hash_env == NULL)) { - return NULL; - } - -#define RC(FNS) \ - do { \ - if (nxt_slow_path((FNS) != NXT_UNIT_OK)) \ - goto fail; \ - } while (0) +#define RC(FNS) \ + do { \ + if (nxt_slow_path((FNS) != NXT_UNIT_OK)) \ + goto fail; \ + } while (0) -#define NL(S) (S), sizeof(S)-1 +#define NL(S) (S), sizeof(S) - 1 - r = req->request; + r = req->request; - RC(nxt_perl_psgi_add_str(my_perl, hash_env, NL("SERVER_SOFTWARE"), - (char *) nxt_server.start, nxt_server.length)); + RC(nxt_perl_psgi_add_str(my_perl, hash_env, NL("SERVER_SOFTWARE"), + (char *)nxt_server.start, nxt_server.length)); - RC(nxt_perl_psgi_add_sptr(my_perl, hash_env, NL("REQUEST_METHOD"), - &r->method, r->method_length)); - RC(nxt_perl_psgi_add_sptr(my_perl, hash_env, NL("REQUEST_URI"), - &r->target, r->target_length)); - RC(nxt_perl_psgi_add_sptr(my_perl, hash_env, NL("PATH_INFO"), - &r->path, r->path_length)); + RC(nxt_perl_psgi_add_sptr(my_perl, hash_env, NL("REQUEST_METHOD"), &r->method, + r->method_length)); + RC(nxt_perl_psgi_add_sptr(my_perl, hash_env, NL("REQUEST_URI"), &r->target, + r->target_length)); + RC(nxt_perl_psgi_add_sptr(my_perl, hash_env, NL("PATH_INFO"), &r->path, + r->path_length)); - array_version = newAV(); + array_version = newAV(); - if (nxt_slow_path(array_version == NULL)) { - goto fail; - } + if (nxt_slow_path(array_version == NULL)) { + goto fail; + } - av_push(array_version, newSViv(1)); - av_push(array_version, newSViv(1)); + av_push(array_version, newSViv(1)); + av_push(array_version, newSViv(1)); - RC(nxt_perl_psgi_add_value(my_perl, hash_env, NL("psgi.version"), - newRV_noinc((SV *) array_version))); + RC(nxt_perl_psgi_add_value(my_perl, hash_env, NL("psgi.version"), + newRV_noinc((SV *)array_version))); - RC(nxt_perl_psgi_add_value(my_perl, hash_env, NL("psgi.url_scheme"), - r->tls ? newSVpv("https", 5) + RC(nxt_perl_psgi_add_value(my_perl, hash_env, NL("psgi.url_scheme"), + r->tls ? newSVpv("https", 5) : newSVpv("http", 4))); - RC(nxt_perl_psgi_io_init(my_perl, &pctx->arg_input, "r", req)); - RC(nxt_perl_psgi_add_value(my_perl, hash_env, NL("psgi.input"), - SvREFCNT_inc(pctx->arg_input.io))); - - RC(nxt_perl_psgi_io_init(my_perl, &pctx->arg_error, "w", req)); - RC(nxt_perl_psgi_add_value(my_perl, hash_env, NL("psgi.errors"), - SvREFCNT_inc(pctx->arg_error.io))); - - RC(nxt_perl_psgi_add_value(my_perl, hash_env, NL("psgi.multithread"), - nxt_perl_psgi_ctxs != NULL - ? &PL_sv_yes : &PL_sv_no)); - RC(nxt_perl_psgi_add_value(my_perl, hash_env, NL("psgi.multiprocess"), - &PL_sv_yes)); - RC(nxt_perl_psgi_add_value(my_perl, hash_env, NL("psgi.run_once"), - &PL_sv_no)); - RC(nxt_perl_psgi_add_value(my_perl, hash_env, NL("psgi.nonblocking"), - &PL_sv_no)); - RC(nxt_perl_psgi_add_value(my_perl, hash_env, NL("psgi.streaming"), - &PL_sv_yes)); - - RC(nxt_perl_psgi_add_sptr(my_perl, hash_env, NL("QUERY_STRING"), - &r->query, r->query_length)); - RC(nxt_perl_psgi_add_sptr(my_perl, hash_env, NL("SERVER_PROTOCOL"), - &r->version, r->version_length)); - RC(nxt_perl_psgi_add_sptr(my_perl, hash_env, NL("REMOTE_ADDR"), - &r->remote, r->remote_length)); - RC(nxt_perl_psgi_add_sptr(my_perl, hash_env, NL("SERVER_ADDR"), - &r->local_addr, r->local_addr_length)); - - RC(nxt_perl_psgi_add_sptr(my_perl, hash_env, NL("SERVER_NAME"), - &r->server_name, r->server_name_length)); - RC(nxt_perl_psgi_add_str(my_perl, hash_env, NL("SERVER_PORT"), "80", 2)); - - for (i = 0; i < r->fields_count; i++) { - f = r->fields + i; - - RC(nxt_perl_psgi_add_sptr(my_perl, hash_env, - nxt_unit_sptr_get(&f->name), f->name_length, - &f->value, f->value_length)); - } - - if (r->content_length_field != NXT_UNIT_NONE_FIELD) { - f = r->fields + r->content_length_field; - - RC(nxt_perl_psgi_add_sptr(my_perl, hash_env, NL("CONTENT_LENGTH"), - &f->value, f->value_length)); - } - - if (r->content_type_field != NXT_UNIT_NONE_FIELD) { - f = r->fields + r->content_type_field; - - RC(nxt_perl_psgi_add_sptr(my_perl, hash_env, NL("CONTENT_TYPE"), - &f->value, f->value_length)); - } + RC(nxt_perl_psgi_io_init(my_perl, &pctx->arg_input, "r", req)); + RC(nxt_perl_psgi_add_value(my_perl, hash_env, NL("psgi.input"), + SvREFCNT_inc(pctx->arg_input.io))); + + RC(nxt_perl_psgi_io_init(my_perl, &pctx->arg_error, "w", req)); + RC(nxt_perl_psgi_add_value(my_perl, hash_env, NL("psgi.errors"), + SvREFCNT_inc(pctx->arg_error.io))); + + RC(nxt_perl_psgi_add_value(my_perl, hash_env, NL("psgi.multithread"), + nxt_perl_psgi_ctxs != NULL ? &PL_sv_yes + : &PL_sv_no)); + RC(nxt_perl_psgi_add_value(my_perl, hash_env, NL("psgi.multiprocess"), + &PL_sv_yes)); + RC(nxt_perl_psgi_add_value(my_perl, hash_env, NL("psgi.run_once"), + &PL_sv_no)); + RC(nxt_perl_psgi_add_value(my_perl, hash_env, NL("psgi.nonblocking"), + &PL_sv_no)); + RC(nxt_perl_psgi_add_value(my_perl, hash_env, NL("psgi.streaming"), + &PL_sv_yes)); + + RC(nxt_perl_psgi_add_sptr(my_perl, hash_env, NL("QUERY_STRING"), &r->query, + r->query_length)); + RC(nxt_perl_psgi_add_sptr(my_perl, hash_env, NL("SERVER_PROTOCOL"), + &r->version, r->version_length)); + RC(nxt_perl_psgi_add_sptr(my_perl, hash_env, NL("REMOTE_ADDR"), &r->remote, + r->remote_length)); + RC(nxt_perl_psgi_add_sptr(my_perl, hash_env, NL("SERVER_ADDR"), + &r->local_addr, r->local_addr_length)); + + RC(nxt_perl_psgi_add_sptr(my_perl, hash_env, NL("SERVER_NAME"), + &r->server_name, r->server_name_length)); + RC(nxt_perl_psgi_add_str(my_perl, hash_env, NL("SERVER_PORT"), "80", 2)); + + for (i = 0; i < r->fields_count; i++) { + f = r->fields + i; + + RC(nxt_perl_psgi_add_sptr(my_perl, hash_env, nxt_unit_sptr_get(&f->name), + f->name_length, &f->value, f->value_length)); + } + + if (r->content_length_field != NXT_UNIT_NONE_FIELD) { + f = r->fields + r->content_length_field; + + RC(nxt_perl_psgi_add_sptr(my_perl, hash_env, NL("CONTENT_LENGTH"), + &f->value, f->value_length)); + } + + if (r->content_type_field != NXT_UNIT_NONE_FIELD) { + f = r->fields + r->content_type_field; + + RC(nxt_perl_psgi_add_sptr(my_perl, hash_env, NL("CONTENT_TYPE"), &f->value, + f->value_length)); + } #undef NL #undef RC - return newRV_noinc((SV *) hash_env); + return newRV_noinc((SV *)hash_env); fail: - SvREFCNT_dec(hash_env); + SvREFCNT_dec(hash_env); - return NULL; + return NULL; } - -nxt_inline int -nxt_perl_psgi_add_sptr(PerlInterpreter *my_perl, HV *hash_env, - const char *name, uint32_t name_len, nxt_unit_sptr_t *sptr, uint32_t len) -{ - return nxt_perl_psgi_add_str(my_perl, hash_env, name, name_len, - nxt_unit_sptr_get(sptr), len); +nxt_inline int nxt_perl_psgi_add_sptr(PerlInterpreter *my_perl, HV *hash_env, + const char *name, uint32_t name_len, + nxt_unit_sptr_t *sptr, uint32_t len) { + return nxt_perl_psgi_add_str(my_perl, hash_env, name, name_len, + nxt_unit_sptr_get(sptr), len); } +nxt_inline int nxt_perl_psgi_add_str(PerlInterpreter *my_perl, HV *hash_env, + const char *name, uint32_t name_len, + const char *str, uint32_t len) { + SV **ha; -nxt_inline int -nxt_perl_psgi_add_str(PerlInterpreter *my_perl, HV *hash_env, - const char *name, uint32_t name_len, const char *str, uint32_t len) -{ - SV **ha; - - ha = hv_store(hash_env, name, (I32) name_len, - newSVpv(str, (STRLEN) len), 0); - if (nxt_slow_path(ha == NULL)) { - return NXT_UNIT_ERROR; - } + ha = hv_store(hash_env, name, (I32)name_len, newSVpv(str, (STRLEN)len), 0); + if (nxt_slow_path(ha == NULL)) { + return NXT_UNIT_ERROR; + } - return NXT_UNIT_OK; + return NXT_UNIT_OK; } +nxt_inline int nxt_perl_psgi_add_value(PerlInterpreter *my_perl, HV *hash_env, + const char *name, uint32_t name_len, + void *value) { + SV **ha; -nxt_inline int -nxt_perl_psgi_add_value(PerlInterpreter *my_perl, HV *hash_env, - const char *name, uint32_t name_len, void *value) -{ - SV **ha; - - ha = hv_store(hash_env, name, (I32) name_len, value, 0); - if (nxt_slow_path(ha == NULL)) { - return NXT_UNIT_ERROR; - } + ha = hv_store(hash_env, name, (I32)name_len, value, 0); + if (nxt_slow_path(ha == NULL)) { + return NXT_UNIT_ERROR; + } - return NXT_UNIT_OK; + return NXT_UNIT_OK; } +static nxt_int_t nxt_perl_psgi_result_status(PerlInterpreter *my_perl, + SV *result) { + SV **sv_status; + AV *array; + u_char *space; + nxt_str_t status; -static nxt_int_t -nxt_perl_psgi_result_status(PerlInterpreter *my_perl, SV *result) -{ - SV **sv_status; - AV *array; - u_char *space; - nxt_str_t status; - - array = (AV *) SvRV(result); - sv_status = av_fetch(array, 0, 0); + array = (AV *)SvRV(result); + sv_status = av_fetch(array, 0, 0); - status.start = (u_char *) SvPV(*sv_status, status.length); + status.start = (u_char *)SvPV(*sv_status, status.length); - space = memchr(status.start, ' ', status.length); - if (space != NULL) { - status.length = space - status.start; - } + space = memchr(status.start, ' ', status.length); + if (space != NULL) { + status.length = space - status.start; + } - return nxt_int_parse(status.start, status.length); + return nxt_int_parse(status.start, status.length); } +static int nxt_perl_psgi_result_head(PerlInterpreter *my_perl, SV *sv_head, + nxt_unit_request_info_t *req, + uint16_t status) { + AV *array_head; + SV **entry; + int rc; + long i, array_len; + char *name, *value; + STRLEN name_len, value_len; + uint32_t fields, size; + + if (nxt_slow_path(SvROK(sv_head) == 0 || SvTYPE(SvRV(sv_head)) != SVt_PVAV)) { + nxt_unit_req_error(req, "PSGI: An unsupported format was received from " + "Perl Application for head part"); -static int -nxt_perl_psgi_result_head(PerlInterpreter *my_perl, SV *sv_head, - nxt_unit_request_info_t *req, uint16_t status) -{ - AV *array_head; - SV **entry; - int rc; - long i, array_len; - char *name, *value; - STRLEN name_len, value_len; - uint32_t fields, size; - - if (nxt_slow_path(SvROK(sv_head) == 0 - || SvTYPE(SvRV(sv_head)) != SVt_PVAV)) - { - nxt_unit_req_error(req, - "PSGI: An unsupported format was received from " - "Perl Application for head part"); - - return NXT_UNIT_ERROR; - } + return NXT_UNIT_ERROR; + } - array_head = (AV *) SvRV(sv_head); - array_len = av_len(array_head); + array_head = (AV *)SvRV(sv_head); + array_len = av_len(array_head); - if (array_len < 1) { - return nxt_unit_response_init(req, status, 0, 0); - } + if (array_len < 1) { + return nxt_unit_response_init(req, status, 0, 0); + } - if (nxt_slow_path((array_len % 2) == 0)) { - nxt_unit_req_error(req, "PSGI: Bad format for head from " - "Perl Application"); + if (nxt_slow_path((array_len % 2) == 0)) { + nxt_unit_req_error(req, "PSGI: Bad format for head from " + "Perl Application"); - return NXT_UNIT_ERROR; - } + return NXT_UNIT_ERROR; + } - fields = 0; - size = 0; + fields = 0; + size = 0; - for (i = 0; i <= array_len; i++) { - entry = av_fetch(array_head, i, 0); + for (i = 0; i <= array_len; i++) { + entry = av_fetch(array_head, i, 0); - if (nxt_fast_path(entry == NULL)) { - nxt_unit_req_error(req, "PSGI: Failed to get head entry from " - "Perl Application"); + if (nxt_fast_path(entry == NULL)) { + nxt_unit_req_error(req, "PSGI: Failed to get head entry from " + "Perl Application"); - return NXT_UNIT_ERROR; - } + return NXT_UNIT_ERROR; + } - value = SvPV(*entry, value_len); - size += value_len; + value = SvPV(*entry, value_len); + size += value_len; - if ((i % 2) == 0) { - fields++; - } + if ((i % 2) == 0) { + fields++; } + } - rc = nxt_unit_response_init(req, status, fields, size); - if (nxt_slow_path(rc != NXT_UNIT_OK)) { - return rc; - } + rc = nxt_unit_response_init(req, status, fields, size); + if (nxt_slow_path(rc != NXT_UNIT_OK)) { + return rc; + } - for (i = 0; i <= array_len; i += 2) { - entry = av_fetch(array_head, i, 0); - name = SvPV(*entry, name_len); + for (i = 0; i <= array_len; i += 2) { + entry = av_fetch(array_head, i, 0); + name = SvPV(*entry, name_len); - entry = av_fetch(array_head, i + 1, 0); - value = SvPV(*entry, value_len); + entry = av_fetch(array_head, i + 1, 0); + value = SvPV(*entry, value_len); - rc = nxt_unit_response_add_field(req, name, name_len, value, value_len); - if (nxt_slow_path(rc != NXT_UNIT_OK)) { - return rc; - } + rc = nxt_unit_response_add_field(req, name, name_len, value, value_len); + if (nxt_slow_path(rc != NXT_UNIT_OK)) { + return rc; } + } - return NXT_UNIT_OK; + return NXT_UNIT_OK; } +static int nxt_perl_psgi_result_body(PerlInterpreter *my_perl, SV *sv_body, + nxt_unit_request_info_t *req) { + SV **entry; + AV *body_array; + int rc; + long i; + nxt_str_t body; -static int -nxt_perl_psgi_result_body(PerlInterpreter *my_perl, SV *sv_body, - nxt_unit_request_info_t *req) -{ - SV **entry; - AV *body_array; - int rc; - long i; - nxt_str_t body; - - if (nxt_slow_path(SvROK(sv_body) == 0 - || SvTYPE(SvRV(sv_body)) != SVt_PVAV)) - { - nxt_unit_req_error(req, "PSGI: An unsupported format was received from " - "Perl Application for a body part"); - - return NXT_UNIT_ERROR; - } + if (nxt_slow_path(SvROK(sv_body) == 0 || SvTYPE(SvRV(sv_body)) != SVt_PVAV)) { + nxt_unit_req_error(req, "PSGI: An unsupported format was received from " + "Perl Application for a body part"); - body_array = (AV *) SvRV(sv_body); + return NXT_UNIT_ERROR; + } - for (i = 0; i <= av_len(body_array); i++) { + body_array = (AV *)SvRV(sv_body); - entry = av_fetch(body_array, i, 0); + for (i = 0; i <= av_len(body_array); i++) { - if (nxt_fast_path(entry == NULL)) { - nxt_unit_req_error(req, "PSGI: Failed to get body entry from " - "Perl Application"); + entry = av_fetch(body_array, i, 0); - return NXT_UNIT_ERROR; - } + if (nxt_fast_path(entry == NULL)) { + nxt_unit_req_error(req, "PSGI: Failed to get body entry from " + "Perl Application"); - body.start = (u_char *) SvPV(*entry, body.length); + return NXT_UNIT_ERROR; + } + + body.start = (u_char *)SvPV(*entry, body.length); - if (body.length == 0) { - continue; - } + if (body.length == 0) { + continue; + } - rc = nxt_unit_response_write(req, body.start, body.length); + rc = nxt_unit_response_write(req, body.start, body.length); - if (nxt_slow_path(rc != NXT_UNIT_OK)) { - nxt_unit_req_error(req, "PSGI: Failed to write content from " - "Perl Application"); - return rc; - } + if (nxt_slow_path(rc != NXT_UNIT_OK)) { + nxt_unit_req_error(req, "PSGI: Failed to write content from " + "Perl Application"); + return rc; } + } - return NXT_UNIT_OK; + return NXT_UNIT_OK; } +static int nxt_perl_psgi_result_body_ref(PerlInterpreter *my_perl, SV *sv_body, + nxt_unit_request_info_t *req) { + SV *data, *old_rs, *old_perl_rs; + int rc; + size_t len; + const char *body; -static int -nxt_perl_psgi_result_body_ref(PerlInterpreter *my_perl, SV *sv_body, - nxt_unit_request_info_t *req) -{ - SV *data, *old_rs, *old_perl_rs; - int rc; - size_t len; - const char *body; - - /* - * Servers should set the $/ special variable to the buffer size - * when reading content from $body using the getline method. - * This is done by setting $/ with a reference to an integer ($/ = \8192). - */ + /* + * Servers should set the $/ special variable to the buffer size + * when reading content from $body using the getline method. + * This is done by setting $/ with a reference to an integer ($/ = \8192). + */ - old_rs = PL_rs; - old_perl_rs = get_sv("/", GV_ADD); + old_rs = PL_rs; + old_perl_rs = get_sv("/", GV_ADD); - PL_rs = sv_2mortal(newRV_noinc(newSViv(nxt_unit_buf_min()))); + PL_rs = sv_2mortal(newRV_noinc(newSViv(nxt_unit_buf_min()))); - sv_setsv(old_perl_rs, PL_rs); + sv_setsv(old_perl_rs, PL_rs); - rc = NXT_UNIT_OK; + rc = NXT_UNIT_OK; - for ( ;; ) { - data = nxt_perl_psgi_call_method(my_perl, sv_body, "getline", req); - if (nxt_slow_path(data == NULL)) { - rc = NXT_UNIT_ERROR; - break; - } + for (;;) { + data = nxt_perl_psgi_call_method(my_perl, sv_body, "getline", req); + if (nxt_slow_path(data == NULL)) { + rc = NXT_UNIT_ERROR; + break; + } - body = SvPV(data, len); + body = SvPV(data, len); - if (len == 0) { - SvREFCNT_dec(data); + if (len == 0) { + SvREFCNT_dec(data); - data = nxt_perl_psgi_call_method(my_perl, sv_body, "close", req); - if (nxt_fast_path(data != NULL)) { - SvREFCNT_dec(data); - } + data = nxt_perl_psgi_call_method(my_perl, sv_body, "close", req); + if (nxt_fast_path(data != NULL)) { + SvREFCNT_dec(data); + } - break; - } + break; + } - rc = nxt_unit_response_write(req, body, len); + rc = nxt_unit_response_write(req, body, len); - SvREFCNT_dec(data); + SvREFCNT_dec(data); - if (nxt_slow_path(rc != NXT_UNIT_OK)) { - nxt_unit_req_error(req, "PSGI: Failed to write content from " - "Perl Application"); - break; - } - }; + if (nxt_slow_path(rc != NXT_UNIT_OK)) { + nxt_unit_req_error(req, "PSGI: Failed to write content from " + "Perl Application"); + break; + } + }; - PL_rs = old_rs; - sv_setsv(get_sv("/", GV_ADD), old_perl_rs); + PL_rs = old_rs; + sv_setsv(get_sv("/", GV_ADD), old_perl_rs); - return rc; + return rc; } - typedef struct { - PerlInterpreter *my_perl; - PerlIO *fp; + PerlInterpreter *my_perl; + PerlIO *fp; } nxt_perl_psgi_io_ctx_t; +static int nxt_perl_psgi_result_body_fh(PerlInterpreter *my_perl, SV *sv_body, + nxt_unit_request_info_t *req) { + IO *io; + nxt_unit_read_info_t read_info; + nxt_perl_psgi_io_ctx_t io_ctx; -static int -nxt_perl_psgi_result_body_fh(PerlInterpreter *my_perl, SV *sv_body, - nxt_unit_request_info_t *req) -{ - IO *io; - nxt_unit_read_info_t read_info; - nxt_perl_psgi_io_ctx_t io_ctx; - - io = GvIO(SvRV(sv_body)); + io = GvIO(SvRV(sv_body)); - if (io == NULL) { - return NXT_UNIT_OK; - } + if (io == NULL) { + return NXT_UNIT_OK; + } - io_ctx.my_perl = my_perl; - io_ctx.fp = IoIFP(io); + io_ctx.my_perl = my_perl; + io_ctx.fp = IoIFP(io); - read_info.read = nxt_perl_psgi_io_read; - read_info.eof = PerlIO_eof(io_ctx.fp); - read_info.buf_size = 8192; - read_info.data = &io_ctx; + read_info.read = nxt_perl_psgi_io_read; + read_info.eof = PerlIO_eof(io_ctx.fp); + read_info.buf_size = 8192; + read_info.data = &io_ctx; - return nxt_unit_response_write_cb(req, &read_info); + return nxt_unit_response_write_cb(req, &read_info); } +static ssize_t nxt_perl_psgi_io_read(nxt_unit_read_info_t *read_info, void *dst, + size_t size) { + ssize_t res; + nxt_perl_psgi_io_ctx_t *ctx; -static ssize_t -nxt_perl_psgi_io_read(nxt_unit_read_info_t *read_info, void *dst, size_t size) -{ - ssize_t res; - nxt_perl_psgi_io_ctx_t *ctx; - - ctx = read_info->data; + ctx = read_info->data; - dTHXa(ctx->my_perl); + dTHXa(ctx->my_perl); - res = PerlIO_read(ctx->fp, dst, size); + res = PerlIO_read(ctx->fp, dst, size); - read_info->eof = PerlIO_eof(ctx->fp); + read_info->eof = PerlIO_eof(ctx->fp); - return res; + return res; } +static int nxt_perl_psgi_result_array(PerlInterpreter *my_perl, SV *result, + nxt_unit_request_info_t *req) { + AV *array; + SV **sv_temp; + int rc; + long array_len; + nxt_int_t status; -static int -nxt_perl_psgi_result_array(PerlInterpreter *my_perl, SV *result, - nxt_unit_request_info_t *req) -{ - AV *array; - SV **sv_temp; - int rc; - long array_len; - nxt_int_t status; - - array = (AV *) SvRV(result); - array_len = av_len(array); + array = (AV *)SvRV(result); + array_len = av_len(array); - if (nxt_slow_path(array_len < 0)) { - nxt_unit_req_error(req, - "PSGI: Invalid result format from Perl Application"); + if (nxt_slow_path(array_len < 0)) { + nxt_unit_req_error(req, + "PSGI: Invalid result format from Perl Application"); - return NXT_UNIT_ERROR; - } - - status = nxt_perl_psgi_result_status(my_perl, result); + return NXT_UNIT_ERROR; + } - if (nxt_slow_path(status < 0)) { - nxt_unit_req_error(req, - "PSGI: An unexpected status was received " - "from Perl Application"); + status = nxt_perl_psgi_result_status(my_perl, result); - return NXT_UNIT_ERROR; - } + if (nxt_slow_path(status < 0)) { + nxt_unit_req_error(req, "PSGI: An unexpected status was received " + "from Perl Application"); - if (array_len >= 1) { - sv_temp = av_fetch(array, 1, 0); - - if (nxt_slow_path(sv_temp == NULL)) { - nxt_unit_req_error(req, "PSGI: Failed to get head from " - "Perl ARRAY variable"); + return NXT_UNIT_ERROR; + } - return NXT_UNIT_ERROR; - } + if (array_len >= 1) { + sv_temp = av_fetch(array, 1, 0); - rc = nxt_perl_psgi_result_head(my_perl, *sv_temp, req, status); - if (nxt_slow_path(rc != NXT_UNIT_OK)) { - return rc; - } + if (nxt_slow_path(sv_temp == NULL)) { + nxt_unit_req_error(req, "PSGI: Failed to get head from " + "Perl ARRAY variable"); - } else { - return nxt_unit_response_init(req, status, 0, 0); + return NXT_UNIT_ERROR; } - if (nxt_fast_path(array_len < 2)) { - return NXT_UNIT_OK; + rc = nxt_perl_psgi_result_head(my_perl, *sv_temp, req, status); + if (nxt_slow_path(rc != NXT_UNIT_OK)) { + return rc; } - sv_temp = av_fetch(array, 2, 0); + } else { + return nxt_unit_response_init(req, status, 0, 0); + } - if (nxt_slow_path(sv_temp == NULL || SvROK(*sv_temp) == FALSE)) { - nxt_unit_req_error(req, - "PSGI: Failed to get body from " - "Perl ARRAY variable"); + if (nxt_fast_path(array_len < 2)) { + return NXT_UNIT_OK; + } - return NXT_UNIT_ERROR; - } + sv_temp = av_fetch(array, 2, 0); - if (SvTYPE(SvRV(*sv_temp)) == SVt_PVAV) { - return nxt_perl_psgi_result_body(my_perl, *sv_temp, req); - } + if (nxt_slow_path(sv_temp == NULL || SvROK(*sv_temp) == FALSE)) { + nxt_unit_req_error(req, "PSGI: Failed to get body from " + "Perl ARRAY variable"); - if (SvTYPE(SvRV(*sv_temp)) == SVt_PVGV) { - return nxt_perl_psgi_result_body_fh(my_perl, *sv_temp, req); - } + return NXT_UNIT_ERROR; + } - return nxt_perl_psgi_result_body_ref(my_perl, *sv_temp, req); -} + if (SvTYPE(SvRV(*sv_temp)) == SVt_PVAV) { + return nxt_perl_psgi_result_body(my_perl, *sv_temp, req); + } + if (SvTYPE(SvRV(*sv_temp)) == SVt_PVGV) { + return nxt_perl_psgi_result_body_fh(my_perl, *sv_temp, req); + } -static void -nxt_perl_psgi_result_cb(PerlInterpreter *my_perl, SV *result, - nxt_unit_request_info_t *req) -{ - nxt_perl_psgi_ctx_t *pctx; + return nxt_perl_psgi_result_body_ref(my_perl, *sv_temp, req); +} + +static void nxt_perl_psgi_result_cb(PerlInterpreter *my_perl, SV *result, + nxt_unit_request_info_t *req) { + nxt_perl_psgi_ctx_t *pctx; - dSP; + dSP; - pctx = req->ctx->data; + pctx = req->ctx->data; - ENTER; - SAVETMPS; + ENTER; + SAVETMPS; - PUSHMARK(sp); - XPUSHs(newRV_noinc((SV*) pctx->cb)); - PUTBACK; + PUSHMARK(sp); + XPUSHs(newRV_noinc((SV *)pctx->cb)); + PUTBACK; - call_sv(result, G_EVAL|G_SCALAR); + call_sv(result, G_EVAL | G_SCALAR); - SPAGAIN; + SPAGAIN; - if (SvTRUE(ERRSV)) { - nxt_unit_error(NULL, "PSGI: Failed to execute result callback: \n%s", - SvPV_nolen(ERRSV)); + if (SvTRUE(ERRSV)) { + nxt_unit_error(NULL, "PSGI: Failed to execute result callback: \n%s", + SvPV_nolen(ERRSV)); - nxt_perl_psgi_cb_request_done(pctx, NXT_UNIT_ERROR); - } + nxt_perl_psgi_cb_request_done(pctx, NXT_UNIT_ERROR); + } - PUTBACK; - FREETMPS; - LEAVE; + PUTBACK; + FREETMPS; + LEAVE; } +static nxt_int_t nxt_perl_psgi_start(nxt_task_t *task, + nxt_process_data_t *data) { + int rc, pargc; + char **pargv, **penv; + nxt_unit_ctx_t *unit_ctx; + nxt_unit_init_t perl_init; + nxt_perl_psgi_ctx_t pctx; + nxt_perl_app_conf_t *c; + nxt_common_app_conf_t *common_conf; -static nxt_int_t -nxt_perl_psgi_start(nxt_task_t *task, nxt_process_data_t *data) -{ - int rc, pargc; - char **pargv, **penv; - nxt_unit_ctx_t *unit_ctx; - nxt_unit_init_t perl_init; - nxt_perl_psgi_ctx_t pctx; - nxt_perl_app_conf_t *c; - nxt_common_app_conf_t *common_conf; - - common_conf = data->app; - c = &common_conf->u.perl; + common_conf = data->app; + c = &common_conf->u.perl; - pargc = 0; - pargv = NULL; - penv = NULL; + pargc = 0; + pargv = NULL; + penv = NULL; - PERL_SYS_INIT3(&pargc, &pargv, &penv); + PERL_SYS_INIT3(&pargc, &pargv, &penv); - memset(&pctx, 0, sizeof(nxt_perl_psgi_ctx_t)); + memset(&pctx, 0, sizeof(nxt_perl_psgi_ctx_t)); - rc = nxt_perl_psgi_ctx_init(c->script, &pctx); - if (nxt_slow_path(rc != NXT_UNIT_OK)) { - goto fail; - } + rc = nxt_perl_psgi_ctx_init(c->script, &pctx); + if (nxt_slow_path(rc != NXT_UNIT_OK)) { + goto fail; + } - rc = nxt_perl_psgi_init_threads(c); + rc = nxt_perl_psgi_init_threads(c); - PERL_SET_CONTEXT(pctx.my_perl); + PERL_SET_CONTEXT(pctx.my_perl); - if (nxt_slow_path(rc != NXT_UNIT_OK)) { - goto fail; - } + if (nxt_slow_path(rc != NXT_UNIT_OK)) { + goto fail; + } - nxt_unit_default_init(task, &perl_init, common_conf); + nxt_unit_default_init(task, &perl_init, common_conf); - perl_init.callbacks.request_handler = nxt_perl_psgi_request_handler; - perl_init.callbacks.ready_handler = nxt_perl_psgi_ready_handler; - perl_init.data = c; - perl_init.ctx_data = &pctx; + perl_init.callbacks.request_handler = nxt_perl_psgi_request_handler; + perl_init.callbacks.ready_handler = nxt_perl_psgi_ready_handler; + perl_init.data = c; + perl_init.ctx_data = &pctx; - unit_ctx = nxt_unit_init(&perl_init); - if (nxt_slow_path(unit_ctx == NULL)) { - goto fail; - } + unit_ctx = nxt_unit_init(&perl_init); + if (nxt_slow_path(unit_ctx == NULL)) { + goto fail; + } - rc = nxt_unit_run(unit_ctx); + rc = nxt_unit_run(unit_ctx); - nxt_perl_psgi_join_threads(unit_ctx, c); + nxt_perl_psgi_join_threads(unit_ctx, c); - nxt_unit_done(unit_ctx); + nxt_unit_done(unit_ctx); - nxt_perl_psgi_ctx_free(&pctx); + nxt_perl_psgi_ctx_free(&pctx); - PERL_SYS_TERM(); + PERL_SYS_TERM(); - exit(rc); + exit(rc); - return NXT_OK; + return NXT_OK; fail: - nxt_perl_psgi_join_threads(NULL, c); + nxt_perl_psgi_join_threads(NULL, c); - nxt_perl_psgi_ctx_free(&pctx); + nxt_perl_psgi_ctx_free(&pctx); - PERL_SYS_TERM(); + PERL_SYS_TERM(); - return NXT_ERROR; + return NXT_ERROR; } +static void nxt_perl_psgi_request_handler(nxt_unit_request_info_t *req) { + SV *env, *result; + nxt_int_t rc; + PerlInterpreter *my_perl; + nxt_perl_psgi_ctx_t *pctx; + + pctx = req->ctx->data; + my_perl = pctx->my_perl; + + pctx->req = req; + + /* + * Create environ variable for perl sub "application". + * > sub application { + * > my ($environ) = @_; + */ + env = nxt_perl_psgi_env_create(my_perl, req); + if (nxt_slow_path(env == NULL)) { + nxt_unit_req_error(req, + "PSGI: Failed to create 'env' for Perl Application"); + nxt_unit_request_done(req, NXT_UNIT_ERROR); + pctx->req = NULL; -static void -nxt_perl_psgi_request_handler(nxt_unit_request_info_t *req) -{ - SV *env, *result; - nxt_int_t rc; - PerlInterpreter *my_perl; - nxt_perl_psgi_ctx_t *pctx; - - pctx = req->ctx->data; - my_perl = pctx->my_perl; - - pctx->req = req; - - /* - * Create environ variable for perl sub "application". - * > sub application { - * > my ($environ) = @_; - */ - env = nxt_perl_psgi_env_create(my_perl, req); - if (nxt_slow_path(env == NULL)) { - nxt_unit_req_error(req, - "PSGI: Failed to create 'env' for Perl Application"); - nxt_unit_request_done(req, NXT_UNIT_ERROR); - pctx->req = NULL; - - return; - } + return; + } - /* Call perl sub and get result as SV*. */ - result = nxt_perl_psgi_call_var_application(my_perl, env, pctx->app, - req); + /* Call perl sub and get result as SV*. */ + result = nxt_perl_psgi_call_var_application(my_perl, env, pctx->app, req); - if (nxt_fast_path(SvOK(result) != 0 && SvROK(result) != 0)) { + if (nxt_fast_path(SvOK(result) != 0 && SvROK(result) != 0)) { - if (SvTYPE(SvRV(result)) == SVt_PVAV) { - rc = nxt_perl_psgi_result_array(my_perl, result, req); - nxt_unit_request_done(req, rc); - pctx->req = NULL; + if (SvTYPE(SvRV(result)) == SVt_PVAV) { + rc = nxt_perl_psgi_result_array(my_perl, result, req); + nxt_unit_request_done(req, rc); + pctx->req = NULL; - goto release; - } + goto release; + } - if (SvTYPE(SvRV(result)) == SVt_PVCV) { - nxt_perl_psgi_result_cb(my_perl, result, req); - goto release; - } + if (SvTYPE(SvRV(result)) == SVt_PVCV) { + nxt_perl_psgi_result_cb(my_perl, result, req); + goto release; } + } - nxt_unit_req_error(req, "PSGI: An unexpected response was received " - "from Perl Application"); + nxt_unit_req_error(req, "PSGI: An unexpected response was received " + "from Perl Application"); - nxt_unit_request_done(req, NXT_UNIT_ERROR); - pctx->req = NULL; + nxt_unit_request_done(req, NXT_UNIT_ERROR); + pctx->req = NULL; release: - SvREFCNT_dec(result); - SvREFCNT_dec(env); + SvREFCNT_dec(result); + SvREFCNT_dec(env); } +static int nxt_perl_psgi_ready_handler(nxt_unit_ctx_t *ctx) { + int res; + uint32_t i; + nxt_perl_app_conf_t *c; + nxt_perl_psgi_ctx_t *pctx; -static int -nxt_perl_psgi_ready_handler(nxt_unit_ctx_t *ctx) -{ - int res; - uint32_t i; - nxt_perl_app_conf_t *c; - nxt_perl_psgi_ctx_t *pctx; - - c = ctx->unit->data; + c = ctx->unit->data; - if (c->threads <= 1) { - return NXT_UNIT_OK; - } + if (c->threads <= 1) { + return NXT_UNIT_OK; + } - for (i = 0; i < c->threads - 1; i++) { - pctx = &nxt_perl_psgi_ctxs[i]; + for (i = 0; i < c->threads - 1; i++) { + pctx = &nxt_perl_psgi_ctxs[i]; - pctx->ctx = ctx; + pctx->ctx = ctx; - res = pthread_create(&pctx->thread, nxt_perl_psgi_thread_attr, - nxt_perl_psgi_thread_func, pctx); + res = pthread_create(&pctx->thread, nxt_perl_psgi_thread_attr, + nxt_perl_psgi_thread_func, pctx); - if (nxt_fast_path(res == 0)) { - nxt_unit_debug(ctx, "thread #%d created", (int) (i + 1)); + if (nxt_fast_path(res == 0)) { + nxt_unit_debug(ctx, "thread #%d created", (int)(i + 1)); - } else { - nxt_unit_alert(ctx, "thread #%d create failed: %s (%d)", - (int) (i + 1), strerror(res), res); + } else { + nxt_unit_alert(ctx, "thread #%d create failed: %s (%d)", (int)(i + 1), + strerror(res), res); - return NXT_UNIT_ERROR; - } + return NXT_UNIT_ERROR; } + } - return NXT_UNIT_OK; + return NXT_UNIT_OK; } +static void *nxt_perl_psgi_thread_func(void *data) { + nxt_unit_ctx_t *ctx; + nxt_perl_psgi_ctx_t *pctx; -static void * -nxt_perl_psgi_thread_func(void *data) -{ - nxt_unit_ctx_t *ctx; - nxt_perl_psgi_ctx_t *pctx; - - pctx = data; + pctx = data; - nxt_unit_debug(pctx->ctx, "worker thread start"); + nxt_unit_debug(pctx->ctx, "worker thread start"); - ctx = nxt_unit_ctx_alloc(pctx->ctx, pctx); - if (nxt_slow_path(ctx == NULL)) { - return NULL; - } + ctx = nxt_unit_ctx_alloc(pctx->ctx, pctx); + if (nxt_slow_path(ctx == NULL)) { + return NULL; + } - pctx->ctx = ctx; + pctx->ctx = ctx; - PERL_SET_CONTEXT(pctx->my_perl); + PERL_SET_CONTEXT(pctx->my_perl); - (void) nxt_unit_run(ctx); + (void)nxt_unit_run(ctx); - nxt_unit_done(ctx); + nxt_unit_done(ctx); - nxt_unit_debug(NULL, "worker thread end"); + nxt_unit_debug(NULL, "worker thread end"); - return NULL; + return NULL; } +static int nxt_perl_psgi_init_threads(nxt_perl_app_conf_t *c) { + int rc; + uint32_t i; + static pthread_attr_t attr; -static int -nxt_perl_psgi_init_threads(nxt_perl_app_conf_t *c) -{ - int rc; - uint32_t i; - static pthread_attr_t attr; - - if (c->threads <= 1) { - return NXT_UNIT_OK; - } - - if (c->thread_stack_size > 0) { - rc = pthread_attr_init(&attr); - if (nxt_slow_path(rc != 0)) { - nxt_unit_alert(NULL, "thread attr init failed: %s (%d)", - strerror(rc), rc); + if (c->threads <= 1) { + return NXT_UNIT_OK; + } - return NXT_UNIT_ERROR; - } + if (c->thread_stack_size > 0) { + rc = pthread_attr_init(&attr); + if (nxt_slow_path(rc != 0)) { + nxt_unit_alert(NULL, "thread attr init failed: %s (%d)", strerror(rc), + rc); - rc = pthread_attr_setstacksize(&attr, c->thread_stack_size); - if (nxt_slow_path(rc != 0)) { - nxt_unit_alert(NULL, "thread attr set stack size failed: %s (%d)", - strerror(rc), rc); + return NXT_UNIT_ERROR; + } - return NXT_UNIT_ERROR; - } + rc = pthread_attr_setstacksize(&attr, c->thread_stack_size); + if (nxt_slow_path(rc != 0)) { + nxt_unit_alert(NULL, "thread attr set stack size failed: %s (%d)", + strerror(rc), rc); - nxt_perl_psgi_thread_attr = &attr; + return NXT_UNIT_ERROR; } - nxt_perl_psgi_ctxs = nxt_unit_malloc(NULL, sizeof(nxt_perl_psgi_ctx_t) - * (c->threads - 1)); - if (nxt_slow_path(nxt_perl_psgi_ctxs == NULL)) { - return NXT_UNIT_ERROR; - } + nxt_perl_psgi_thread_attr = &attr; + } - memset(nxt_perl_psgi_ctxs, 0, sizeof(nxt_perl_psgi_ctx_t) - * (c->threads - 1)); + nxt_perl_psgi_ctxs = + nxt_unit_malloc(NULL, sizeof(nxt_perl_psgi_ctx_t) * (c->threads - 1)); + if (nxt_slow_path(nxt_perl_psgi_ctxs == NULL)) { + return NXT_UNIT_ERROR; + } - for (i = 0; i < c->threads - 1; i++) { - rc = nxt_perl_psgi_ctx_init(c->script, &nxt_perl_psgi_ctxs[i]); + memset(nxt_perl_psgi_ctxs, 0, sizeof(nxt_perl_psgi_ctx_t) * (c->threads - 1)); - if (nxt_slow_path(rc != NXT_UNIT_OK)) { - return NXT_UNIT_ERROR; - } + for (i = 0; i < c->threads - 1; i++) { + rc = nxt_perl_psgi_ctx_init(c->script, &nxt_perl_psgi_ctxs[i]); + + if (nxt_slow_path(rc != NXT_UNIT_OK)) { + return NXT_UNIT_ERROR; } + } - return NXT_UNIT_OK; + return NXT_UNIT_OK; } +static void nxt_perl_psgi_join_threads(nxt_unit_ctx_t *ctx, + nxt_perl_app_conf_t *c) { + int res; + uint32_t i; + nxt_perl_psgi_ctx_t *pctx; -static void -nxt_perl_psgi_join_threads(nxt_unit_ctx_t *ctx, nxt_perl_app_conf_t *c) -{ - int res; - uint32_t i; - nxt_perl_psgi_ctx_t *pctx; - - if (nxt_perl_psgi_ctxs == NULL) { - return; - } + if (nxt_perl_psgi_ctxs == NULL) { + return; + } - for (i = 0; i < c->threads - 1; i++) { - pctx = &nxt_perl_psgi_ctxs[i]; + for (i = 0; i < c->threads - 1; i++) { + pctx = &nxt_perl_psgi_ctxs[i]; - res = pthread_join(pctx->thread, NULL); + res = pthread_join(pctx->thread, NULL); - if (nxt_fast_path(res == 0)) { - nxt_unit_debug(ctx, "thread #%d joined", (int) (i + 1)); + if (nxt_fast_path(res == 0)) { + nxt_unit_debug(ctx, "thread #%d joined", (int)(i + 1)); - } else { - nxt_unit_alert(ctx, "thread #%d join failed: %s (%d)", - (int) (i + 1), strerror(res), res); - } + } else { + nxt_unit_alert(ctx, "thread #%d join failed: %s (%d)", (int)(i + 1), + strerror(res), res); } + } - for (i = 0; i < c->threads - 1; i++) { - nxt_perl_psgi_ctx_free(&nxt_perl_psgi_ctxs[i]); - } + for (i = 0; i < c->threads - 1; i++) { + nxt_perl_psgi_ctx_free(&nxt_perl_psgi_ctxs[i]); + } - nxt_unit_free(NULL, nxt_perl_psgi_ctxs); + nxt_unit_free(NULL, nxt_perl_psgi_ctxs); } +static void nxt_perl_psgi_ctx_free(nxt_perl_psgi_ctx_t *pctx) { + PerlInterpreter *my_perl; -static void -nxt_perl_psgi_ctx_free(nxt_perl_psgi_ctx_t *pctx) -{ - PerlInterpreter *my_perl; - - my_perl = pctx->my_perl; + my_perl = pctx->my_perl; - if (nxt_slow_path(my_perl == NULL)) { - return; - } + if (nxt_slow_path(my_perl == NULL)) { + return; + } - PERL_SET_CONTEXT(my_perl); + PERL_SET_CONTEXT(my_perl); - SvREFCNT_dec(pctx->arg_input.rv); - SvREFCNT_dec(pctx->arg_error.rv); + SvREFCNT_dec(pctx->arg_input.rv); + SvREFCNT_dec(pctx->arg_error.rv); - nxt_perl_psgi_io_release(my_perl, &pctx->arg_input); - nxt_perl_psgi_io_release(my_perl, &pctx->arg_error); + nxt_perl_psgi_io_release(my_perl, &pctx->arg_input); + nxt_perl_psgi_io_release(my_perl, &pctx->arg_error); - perl_destruct(my_perl); - perl_free(my_perl); + perl_destruct(my_perl); + perl_free(my_perl); } diff --git a/src/perl/nxt_perl_psgi_layer.c b/src/perl/nxt_perl_psgi_layer.c index 303e5f27e..9fb6a0efb 100644 --- a/src/perl/nxt_perl_psgi_layer.c +++ b/src/perl/nxt_perl_psgi_layer.c @@ -6,51 +6,49 @@ #include - typedef struct { - struct _PerlIO base; + struct _PerlIO base; - SV *var; + SV *var; } nxt_perl_psgi_layer_stream_t; - static IV nxt_perl_psgi_layer_stream_pushed(pTHX_ PerlIO *f, const char *mode, - SV *arg, PerlIO_funcs *tab); + SV *arg, PerlIO_funcs *tab); static IV nxt_perl_psgi_layer_stream_popped(pTHX_ PerlIO *f); static PerlIO *nxt_perl_psgi_layer_stream_open(pTHX_ PerlIO_funcs *self, - PerlIO_list_t *layers, IV n, - const char *mode, int fd, int imode, int perm, - PerlIO *f, int narg, SV **args); + PerlIO_list_t *layers, IV n, + const char *mode, int fd, + int imode, int perm, PerlIO *f, + int narg, SV **args); static IV nxt_perl_psgi_layer_stream_close(pTHX_ PerlIO *f); -static SSize_t nxt_perl_psgi_layer_stream_read(pTHX_ PerlIO *f, - void *vbuf, Size_t count); +static SSize_t nxt_perl_psgi_layer_stream_read(pTHX_ PerlIO *f, void *vbuf, + Size_t count); static SSize_t nxt_perl_psgi_layer_stream_write(pTHX_ PerlIO *f, - const void *vbuf, Size_t count); + const void *vbuf, Size_t count); static IV nxt_perl_psgi_layer_stream_fileno(pTHX_ PerlIO *f); -static IV nxt_perl_psgi_layer_stream_seek(pTHX_ PerlIO *f, - Off_t offset, int whence); +static IV nxt_perl_psgi_layer_stream_seek(pTHX_ PerlIO *f, Off_t offset, + int whence); static Off_t nxt_perl_psgi_layer_stream_tell(pTHX_ PerlIO *f); static IV nxt_perl_psgi_layer_stream_fill(pTHX_ PerlIO *f); static IV nxt_perl_psgi_layer_stream_flush(pTHX_ PerlIO *f); -static SV *nxt_perl_psgi_layer_stream_arg(pTHX_ PerlIO *f, - CLONE_PARAMS *param, int flags); +static SV *nxt_perl_psgi_layer_stream_arg(pTHX_ PerlIO *f, CLONE_PARAMS *param, + int flags); static PerlIO *nxt_perl_psgi_layer_stream_dup(pTHX_ PerlIO *f, PerlIO *o, - CLONE_PARAMS *param, int flags); + CLONE_PARAMS *param, int flags); static IV nxt_perl_psgi_layer_stream_eof(pTHX_ PerlIO *f); static STDCHAR *nxt_perl_psgi_layer_stream_get_base(pTHX_ PerlIO *f); static STDCHAR *nxt_perl_psgi_layer_stream_get_ptr(pTHX_ PerlIO *f); static SSize_t nxt_perl_psgi_layer_stream_get_cnt(pTHX_ PerlIO *f); static Size_t nxt_perl_psgi_layer_stream_buffersize(pTHX_ PerlIO *f); -static void nxt_perl_psgi_layer_stream_set_ptrcnt(pTHX_ PerlIO *f, - STDCHAR *ptr, SSize_t cnt); - +static void nxt_perl_psgi_layer_stream_set_ptrcnt(pTHX_ PerlIO *f, STDCHAR *ptr, + SSize_t cnt); static PERLIO_FUNCS_DECL(PerlIO_NGINX_Unit) = { sizeof(PerlIO_funcs), @@ -83,300 +81,229 @@ static PERLIO_FUNCS_DECL(PerlIO_NGINX_Unit) = { nxt_perl_psgi_layer_stream_set_ptrcnt, }; +static IV nxt_perl_psgi_layer_stream_pushed(pTHX_ PerlIO *f, const char *mode, + SV *arg, PerlIO_funcs *tab) { + nxt_perl_psgi_layer_stream_t *unit_stream; -static IV -nxt_perl_psgi_layer_stream_pushed(pTHX_ PerlIO *f, const char *mode, SV *arg, - PerlIO_funcs *tab) -{ - nxt_perl_psgi_layer_stream_t *unit_stream; + unit_stream = PerlIOSelf(f, nxt_perl_psgi_layer_stream_t); - unit_stream = PerlIOSelf(f, nxt_perl_psgi_layer_stream_t); + if (arg != NULL && SvOK(arg)) { + unit_stream->var = SvREFCNT_inc(arg); + } - if (arg != NULL && SvOK(arg)) { - unit_stream->var = SvREFCNT_inc(arg); - } - - return PerlIOBase_pushed(aTHX_ f, mode, Nullsv, tab); + return PerlIOBase_pushed(aTHX_ f, mode, Nullsv, tab); } +static IV nxt_perl_psgi_layer_stream_popped(pTHX_ PerlIO *f) { + nxt_perl_psgi_io_arg_t *arg; + nxt_perl_psgi_layer_stream_t *unit_stream; -static IV -nxt_perl_psgi_layer_stream_popped(pTHX_ PerlIO *f) -{ - nxt_perl_psgi_io_arg_t *arg; - nxt_perl_psgi_layer_stream_t *unit_stream; + unit_stream = PerlIOSelf(f, nxt_perl_psgi_layer_stream_t); - unit_stream = PerlIOSelf(f, nxt_perl_psgi_layer_stream_t); + if (unit_stream->var != NULL) { + arg = (void *)(intptr_t)SvIV(SvRV(unit_stream->var)); - if (unit_stream->var != NULL) { - arg = (void *) (intptr_t) SvIV(SvRV(unit_stream->var)); + arg->io = NULL; + arg->fp = NULL; - arg->io = NULL; - arg->fp = NULL; + SvREFCNT_dec(unit_stream->var); + unit_stream->var = Nullsv; + } - SvREFCNT_dec(unit_stream->var); - unit_stream->var = Nullsv; - } - - return 0; + return 0; } +static PerlIO *nxt_perl_psgi_layer_stream_open(pTHX_ PerlIO_funcs *self, + PerlIO_list_t *layers, IV n, + const char *mode, int fd, + int imode, int perm, PerlIO *f, + int narg, SV **args) { + SV *arg; -static PerlIO * -nxt_perl_psgi_layer_stream_open(pTHX_ PerlIO_funcs *self, - PerlIO_list_t *layers, IV n, - const char *mode, int fd, int imode, int perm, - PerlIO *f, int narg, SV **args) -{ - SV *arg; - - arg = (narg > 0) ? *args : PerlIOArg; - - PERL_UNUSED_ARG(fd); - PERL_UNUSED_ARG(imode); - PERL_UNUSED_ARG(perm); + arg = (narg > 0) ? *args : PerlIOArg; - if (SvROK(arg) || SvPOK(arg)) { + PERL_UNUSED_ARG(fd); + PERL_UNUSED_ARG(imode); + PERL_UNUSED_ARG(perm); - if (f == NULL) { - f = PerlIO_allocate(aTHX); - } + if (SvROK(arg) || SvPOK(arg)) { - f = PerlIO_push(aTHX_ f, self, mode, arg); + if (f == NULL) { + f = PerlIO_allocate(aTHX); + } - if (f != NULL) { - PerlIOBase(f)->flags |= PERLIO_F_OPEN; - } + f = PerlIO_push(aTHX_ f, self, mode, arg); - return f; + if (f != NULL) { + PerlIOBase(f)->flags |= PERLIO_F_OPEN; } - return NULL; -} + return f; + } + return NULL; +} -static IV -nxt_perl_psgi_layer_stream_close(pTHX_ PerlIO *f) -{ - IV code; +static IV nxt_perl_psgi_layer_stream_close(pTHX_ PerlIO *f) { + IV code; - code = PerlIOBase_close(aTHX_ f); - PerlIOBase(f)->flags &= ~(PERLIO_F_RDBUF | PERLIO_F_WRBUF); + code = PerlIOBase_close(aTHX_ f); + PerlIOBase(f)->flags &= ~(PERLIO_F_RDBUF | PERLIO_F_WRBUF); - return code; + return code; } - -static IV -nxt_perl_psgi_layer_stream_fileno(pTHX_ PerlIO *f) -{ - PERL_UNUSED_ARG(f); - return -1; +static IV nxt_perl_psgi_layer_stream_fileno(pTHX_ PerlIO *f) { + PERL_UNUSED_ARG(f); + return -1; } +static SSize_t nxt_perl_psgi_layer_stream_read(pTHX_ PerlIO *f, void *vbuf, + Size_t count) { + nxt_perl_psgi_io_arg_t *arg; + nxt_perl_psgi_layer_stream_t *unit_stream; -static SSize_t -nxt_perl_psgi_layer_stream_read(pTHX_ PerlIO *f, void *vbuf, Size_t count) -{ - nxt_perl_psgi_io_arg_t *arg; - nxt_perl_psgi_layer_stream_t *unit_stream; - - if (f == NULL) { - return 0; - } + if (f == NULL) { + return 0; + } - if ((PerlIOBase(f)->flags & PERLIO_F_CANREAD) == 0) { - PerlIOBase(f)->flags |= PERLIO_F_ERROR; + if ((PerlIOBase(f)->flags & PERLIO_F_CANREAD) == 0) { + PerlIOBase(f)->flags |= PERLIO_F_ERROR; - SETERRNO(EBADF, SS_IVCHAN); + SETERRNO(EBADF, SS_IVCHAN); - return 0; - } + return 0; + } - unit_stream = PerlIOSelf(f, nxt_perl_psgi_layer_stream_t); - arg = (void *) (intptr_t) SvIV(SvRV(unit_stream->var)); + unit_stream = PerlIOSelf(f, nxt_perl_psgi_layer_stream_t); + arg = (void *)(intptr_t)SvIV(SvRV(unit_stream->var)); - return arg->io_tab->read(PERL_GET_CONTEXT, arg, vbuf, count); + return arg->io_tab->read(PERL_GET_CONTEXT, arg, vbuf, count); } +static SSize_t nxt_perl_psgi_layer_stream_write(pTHX_ PerlIO *f, + const void *vbuf, + Size_t count) { + nxt_perl_psgi_io_arg_t *arg; + nxt_perl_psgi_layer_stream_t *unit_stream; -static SSize_t -nxt_perl_psgi_layer_stream_write(pTHX_ PerlIO *f, - const void *vbuf, Size_t count) -{ - nxt_perl_psgi_io_arg_t *arg; - nxt_perl_psgi_layer_stream_t *unit_stream; - - if (PerlIOBase(f)->flags & PERLIO_F_CANWRITE) { - unit_stream = PerlIOSelf(f, nxt_perl_psgi_layer_stream_t); - arg = (void *) (intptr_t) SvIV(SvRV(unit_stream->var)); - - return arg->io_tab->write(PERL_GET_CONTEXT, arg, vbuf, count); - } - - return 0; -} + if (PerlIOBase(f)->flags & PERLIO_F_CANWRITE) { + unit_stream = PerlIOSelf(f, nxt_perl_psgi_layer_stream_t); + arg = (void *)(intptr_t)SvIV(SvRV(unit_stream->var)); + return arg->io_tab->write(PERL_GET_CONTEXT, arg, vbuf, count); + } -static IV -nxt_perl_psgi_layer_stream_seek(pTHX_ PerlIO *f, Off_t offset, int whence) -{ - PERL_UNUSED_ARG(f); - return 0; + return 0; } - -static Off_t -nxt_perl_psgi_layer_stream_tell(pTHX_ PerlIO *f) -{ - PERL_UNUSED_ARG(f); - return 0; +static IV nxt_perl_psgi_layer_stream_seek(pTHX_ PerlIO *f, Off_t offset, + int whence) { + PERL_UNUSED_ARG(f); + return 0; } - -static IV -nxt_perl_psgi_layer_stream_fill(pTHX_ PerlIO *f) -{ - PERL_UNUSED_ARG(f); - return -1; +static Off_t nxt_perl_psgi_layer_stream_tell(pTHX_ PerlIO *f) { + PERL_UNUSED_ARG(f); + return 0; } - -static IV -nxt_perl_psgi_layer_stream_flush(pTHX_ PerlIO *f) -{ - return 0; +static IV nxt_perl_psgi_layer_stream_fill(pTHX_ PerlIO *f) { + PERL_UNUSED_ARG(f); + return -1; } +static IV nxt_perl_psgi_layer_stream_flush(pTHX_ PerlIO *f) { return 0; } -static SV * -nxt_perl_psgi_layer_stream_arg(pTHX_ PerlIO * f, - CLONE_PARAMS *param, int flags) -{ - SV *var; - nxt_perl_psgi_layer_stream_t *unit_stream; - - unit_stream = PerlIOSelf(f, nxt_perl_psgi_layer_stream_t); - var = unit_stream->var; - - if (flags & PERLIO_DUP_CLONE) { - var = PerlIO_sv_dup(aTHX_ var, param); - - } else if (flags & PERLIO_DUP_FD) { - var = newSVsv(var); - - } else { - var = SvREFCNT_inc(var); - } - - return var; -} +static SV *nxt_perl_psgi_layer_stream_arg(pTHX_ PerlIO *f, CLONE_PARAMS *param, + int flags) { + SV *var; + nxt_perl_psgi_layer_stream_t *unit_stream; + unit_stream = PerlIOSelf(f, nxt_perl_psgi_layer_stream_t); + var = unit_stream->var; -static PerlIO * -nxt_perl_psgi_layer_stream_dup(pTHX_ PerlIO *f, PerlIO *o, - CLONE_PARAMS *param, int flags) -{ - nxt_perl_psgi_layer_stream_t *fs; + if (flags & PERLIO_DUP_CLONE) { + var = PerlIO_sv_dup(aTHX_ var, param); - f = PerlIOBase_dup(aTHX_ f, o, param, flags); + } else if (flags & PERLIO_DUP_FD) { + var = newSVsv(var); - if (f != NULL) { - fs = PerlIOSelf(f, nxt_perl_psgi_layer_stream_t); - fs->var = nxt_perl_psgi_layer_stream_arg(aTHX_ o, param, flags); - } + } else { + var = SvREFCNT_inc(var); + } - return f; + return var; } +static PerlIO *nxt_perl_psgi_layer_stream_dup(pTHX_ PerlIO *f, PerlIO *o, + CLONE_PARAMS *param, int flags) { + nxt_perl_psgi_layer_stream_t *fs; -static IV -nxt_perl_psgi_layer_stream_eof(pTHX_ PerlIO *f) -{ - return 1; -} + f = PerlIOBase_dup(aTHX_ f, o, param, flags); + if (f != NULL) { + fs = PerlIOSelf(f, nxt_perl_psgi_layer_stream_t); + fs->var = nxt_perl_psgi_layer_stream_arg(aTHX_ o, param, flags); + } -static STDCHAR * -nxt_perl_psgi_layer_stream_get_base(pTHX_ PerlIO *f) -{ - return (STDCHAR *) NULL; + return f; } +static IV nxt_perl_psgi_layer_stream_eof(pTHX_ PerlIO *f) { return 1; } -static STDCHAR * -nxt_perl_psgi_layer_stream_get_ptr(pTHX_ PerlIO *f) -{ - return (STDCHAR *) NULL; +static STDCHAR *nxt_perl_psgi_layer_stream_get_base(pTHX_ PerlIO *f) { + return (STDCHAR *)NULL; } - -static SSize_t -nxt_perl_psgi_layer_stream_get_cnt(pTHX_ PerlIO *f) -{ - return 0; +static STDCHAR *nxt_perl_psgi_layer_stream_get_ptr(pTHX_ PerlIO *f) { + return (STDCHAR *)NULL; } +static SSize_t nxt_perl_psgi_layer_stream_get_cnt(pTHX_ PerlIO *f) { return 0; } -static Size_t -nxt_perl_psgi_layer_stream_buffersize(pTHX_ PerlIO *f) -{ - return 0; +static Size_t nxt_perl_psgi_layer_stream_buffersize(pTHX_ PerlIO *f) { + return 0; } - -static void -nxt_perl_psgi_layer_stream_set_ptrcnt(pTHX_ PerlIO *f, - STDCHAR *ptr, SSize_t cnt) -{ - /* Need some code. */ +static void nxt_perl_psgi_layer_stream_set_ptrcnt(pTHX_ PerlIO *f, STDCHAR *ptr, + SSize_t cnt) { + /* Need some code. */ } - -void -nxt_perl_psgi_layer_stream_init(pTHX) -{ - PerlIO_define_layer(aTHX_ PERLIO_FUNCS_CAST(&PerlIO_NGINX_Unit)); +void nxt_perl_psgi_layer_stream_init(pTHX) { + PerlIO_define_layer(aTHX_ PERLIO_FUNCS_CAST(&PerlIO_NGINX_Unit)); } - -PerlIO * -nxt_perl_psgi_layer_stream_fp_create(pTHX_ SV *arg_rv, - const char *mode) -{ - return PerlIO_openn(aTHX_ "NGINX_Unit_PSGI_Layer_Stream", - mode, 0, 0, 0, NULL, 1, &arg_rv); +PerlIO *nxt_perl_psgi_layer_stream_fp_create(pTHX_ SV *arg_rv, + const char *mode) { + return PerlIO_openn(aTHX_ "NGINX_Unit_PSGI_Layer_Stream", mode, 0, 0, 0, NULL, + 1, &arg_rv); } - -void -nxt_perl_psgi_layer_stream_fp_destroy(pTHX_ PerlIO *io) -{ - PerlIO_close(io); +void nxt_perl_psgi_layer_stream_fp_destroy(pTHX_ PerlIO *io) { + PerlIO_close(io); } +SV *nxt_perl_psgi_layer_stream_io_create(pTHX_ PerlIO *fp) { + SV *rvio; + IO *thatio; -SV * -nxt_perl_psgi_layer_stream_io_create(pTHX_ PerlIO *fp) -{ - SV *rvio; - IO *thatio; - - thatio = newIO(); + thatio = newIO(); - if (thatio == NULL) { - return NULL; - } + if (thatio == NULL) { + return NULL; + } - IoOFP(thatio) = fp; - IoIFP(thatio) = fp; + IoOFP(thatio) = fp; + IoIFP(thatio) = fp; - rvio = newRV_noinc((SV *) thatio); + rvio = newRV_noinc((SV *)thatio); - if (rvio == NULL) { - SvREFCNT_dec(thatio); - return NULL; - } + if (rvio == NULL) { + SvREFCNT_dec(thatio); + return NULL; + } - return rvio; + return rvio; } diff --git a/src/perl/nxt_perl_psgi_layer.h b/src/perl/nxt_perl_psgi_layer.h index 0972d66f1..b75ad4bad 100644 --- a/src/perl/nxt_perl_psgi_layer.h +++ b/src/perl/nxt_perl_psgi_layer.h @@ -7,40 +7,35 @@ #ifndef _NXT_PERL_PSGI_LAYER_H_INCLUDED_ #define _NXT_PERL_PSGI_LAYER_H_INCLUDED_ - #include #include #include #include - typedef struct nxt_perl_psgi_io_tab_s nxt_perl_psgi_io_tab_t; typedef struct nxt_perl_psgi_io_arg_s nxt_perl_psgi_io_arg_t; - struct nxt_perl_psgi_io_tab_s { - SSize_t (*read)(PerlInterpreter *my_perl, - nxt_perl_psgi_io_arg_t *arg, void *vbuf, size_t length); - SSize_t (*write)(PerlInterpreter *my_perl, - nxt_perl_psgi_io_arg_t *arg, const void *vbuf, size_t length); + SSize_t (*read)(PerlInterpreter *my_perl, nxt_perl_psgi_io_arg_t *arg, + void *vbuf, size_t length); + SSize_t (*write)(PerlInterpreter *my_perl, nxt_perl_psgi_io_arg_t *arg, + const void *vbuf, size_t length); }; - struct nxt_perl_psgi_io_arg_s { - SV *rv; - SV *io; - PerlIO *fp; + SV *rv; + SV *io; + PerlIO *fp; - const nxt_perl_psgi_io_tab_t *io_tab; + const nxt_perl_psgi_io_tab_t *io_tab; - void *req; + void *req; }; - void nxt_perl_psgi_layer_stream_init(pTHX); PerlIO *nxt_perl_psgi_layer_stream_fp_create(pTHX_ SV *arg_rv, - const char *mode); + const char *mode); void nxt_perl_psgi_layer_stream_fp_destroy(pTHX_ PerlIO *io); SV *nxt_perl_psgi_layer_stream_io_create(pTHX_ PerlIO *fp); diff --git a/src/python/nxt_python.c b/src/python/nxt_python.c index 143d8d5dc..11f379adf 100644 --- a/src/python/nxt_python.c +++ b/src/python/nxt_python.c @@ -3,7 +3,6 @@ * Copyright (C) NGINX, Inc. */ - #include #include @@ -14,38 +13,37 @@ #include NXT_PYTHON_MOUNTS_H - typedef struct { - pthread_t thread; - nxt_unit_ctx_t *ctx; - void *ctx_data; + pthread_t thread; + nxt_unit_ctx_t *ctx; + void *ctx_data; } nxt_py_thread_info_t; - #if PY_MAJOR_VERSION == 3 static nxt_int_t nxt_python3_init_config(nxt_int_t pep405); #endif -static nxt_int_t nxt_python_start(nxt_task_t *task, - nxt_process_data_t *data); +static nxt_int_t nxt_python_start(nxt_task_t *task, nxt_process_data_t *data); static nxt_int_t nxt_python_set_target(nxt_task_t *task, - nxt_python_target_t *target, nxt_conf_value_t *conf); + nxt_python_target_t *target, + nxt_conf_value_t *conf); nxt_inline nxt_int_t nxt_python_set_prefix(nxt_task_t *task, - nxt_python_target_t *target, nxt_conf_value_t *value); + nxt_python_target_t *target, + nxt_conf_value_t *value); static nxt_int_t nxt_python_set_path(nxt_task_t *task, nxt_conf_value_t *value); static int nxt_python_init_threads(nxt_python_app_conf_t *c); static int nxt_python_ready_handler(nxt_unit_ctx_t *ctx); static void *nxt_python_thread_func(void *main_ctx); static void nxt_python_join_threads(nxt_unit_ctx_t *ctx, - nxt_python_app_conf_t *c); + nxt_python_app_conf_t *c); static void nxt_python_atexit(void); -static uint32_t compat[] = { - NXT_VERNUM, NXT_DEBUG, +static uint32_t compat[] = { + NXT_VERNUM, + NXT_DEBUG, }; - -NXT_EXPORT nxt_app_module_t nxt_app_module = { +NXT_EXPORT nxt_app_module_t nxt_app_module = { sizeof(compat), compat, nxt_string("python"), @@ -56,819 +54,776 @@ NXT_EXPORT nxt_app_module_t nxt_app_module = { nxt_python_start, }; -static PyObject *nxt_py_stderr_flush; -nxt_python_targets_t *nxt_py_targets; +static PyObject *nxt_py_stderr_flush; +nxt_python_targets_t *nxt_py_targets; #if PY_MAJOR_VERSION == 3 -static wchar_t *nxt_py_home; +static wchar_t *nxt_py_home; #else -static char *nxt_py_home; +static char *nxt_py_home; #endif -static pthread_attr_t *nxt_py_thread_attr; -static nxt_py_thread_info_t *nxt_py_threads; -static nxt_python_proto_t nxt_py_proto; - +static pthread_attr_t *nxt_py_thread_attr; +static nxt_py_thread_info_t *nxt_py_threads; +static nxt_python_proto_t nxt_py_proto; #if PY_VERSION_HEX >= NXT_PYTHON_VER(3, 8) -static nxt_int_t -nxt_python3_init_config(nxt_int_t pep405) -{ - PyConfig config; - PyStatus status; - nxt_int_t ret; - PyPreConfig preconfig; +static nxt_int_t nxt_python3_init_config(nxt_int_t pep405) { + PyConfig config; + PyStatus status; + nxt_int_t ret; + PyPreConfig preconfig; - ret = NXT_ERROR; + ret = NXT_ERROR; - PyPreConfig_InitIsolatedConfig(&preconfig); - /* - * Determine whether to use UTF-8 mode or not, UTF-8 - * will be enabled if LC_CTYPE is C, POSIX or some - * specific UTF-8 locale. - */ - preconfig.utf8_mode = -1; + PyPreConfig_InitIsolatedConfig(&preconfig); + /* + * Determine whether to use UTF-8 mode or not, UTF-8 + * will be enabled if LC_CTYPE is C, POSIX or some + * specific UTF-8 locale. + */ + preconfig.utf8_mode = -1; - status = Py_PreInitialize(&preconfig); - if (PyStatus_Exception(status)) { - return ret; - } + status = Py_PreInitialize(&preconfig); + if (PyStatus_Exception(status)) { + return ret; + } - PyConfig_InitIsolatedConfig(&config); + PyConfig_InitIsolatedConfig(&config); - if (pep405) { - status = PyConfig_SetString(&config, &config.program_name, - nxt_py_home); - if (PyStatus_Exception(status)) { - goto out_config_clear; - } - - } else { - status = PyConfig_SetString(&config, &config.home, nxt_py_home); - if (PyStatus_Exception(status)) { - goto out_config_clear; - } + if (pep405) { + status = PyConfig_SetString(&config, &config.program_name, nxt_py_home); + if (PyStatus_Exception(status)) { + goto out_config_clear; } - status = Py_InitializeFromConfig(&config); + } else { + status = PyConfig_SetString(&config, &config.home, nxt_py_home); if (PyStatus_Exception(status)) { - goto out_config_clear; + goto out_config_clear; } + } - ret = NXT_OK; + status = Py_InitializeFromConfig(&config); + if (PyStatus_Exception(status)) { + goto out_config_clear; + } + + ret = NXT_OK; out_config_clear: - PyConfig_Clear(&config); + PyConfig_Clear(&config); - return ret; + return ret; } #elif PY_MAJOR_VERSION == 3 -static nxt_int_t -nxt_python3_init_config(nxt_int_t pep405) -{ - if (pep405) { - Py_SetProgramName(nxt_py_home); +static nxt_int_t nxt_python3_init_config(nxt_int_t pep405) { + if (pep405) { + Py_SetProgramName(nxt_py_home); - } else { - Py_SetPythonHome(nxt_py_home); - } + } else { + Py_SetPythonHome(nxt_py_home); + } - return NXT_OK; + return NXT_OK; } #endif - -static nxt_int_t -nxt_python_start(nxt_task_t *task, nxt_process_data_t *data) -{ - int rc; - size_t len, size; - uint32_t next; - PyObject *obj; - nxt_str_t proto, probe_proto, name; - nxt_int_t ret, n, i; - nxt_unit_ctx_t *unit_ctx; - nxt_unit_init_t python_init; - nxt_conf_value_t *cv; - nxt_python_targets_t *targets; - nxt_common_app_conf_t *app_conf; - nxt_python_app_conf_t *c; +static nxt_int_t nxt_python_start(nxt_task_t *task, nxt_process_data_t *data) { + int rc; + size_t len, size; + uint32_t next; + PyObject *obj; + nxt_str_t proto, probe_proto, name; + nxt_int_t ret, n, i; + nxt_unit_ctx_t *unit_ctx; + nxt_unit_init_t python_init; + nxt_conf_value_t *cv; + nxt_python_targets_t *targets; + nxt_common_app_conf_t *app_conf; + nxt_python_app_conf_t *c; #if PY_MAJOR_VERSION == 3 - char *path; - nxt_int_t pep405; + char *path; + nxt_int_t pep405; - static const char pyvenv[] = "/pyvenv.cfg"; - static const char bin_python[] = "/bin/python"; + static const char pyvenv[] = "/pyvenv.cfg"; + static const char bin_python[] = "/bin/python"; #endif - static const nxt_str_t wsgi = nxt_string("wsgi"); - static const nxt_str_t asgi = nxt_string("asgi"); + static const nxt_str_t wsgi = nxt_string("wsgi"); + static const nxt_str_t asgi = nxt_string("asgi"); - app_conf = data->app; - c = &app_conf->u.python; + app_conf = data->app; + c = &app_conf->u.python; - if (c->home != NULL) { - len = nxt_strlen(c->home); + if (c->home != NULL) { + len = nxt_strlen(c->home); #if PY_MAJOR_VERSION == 3 - path = nxt_malloc(len + sizeof(pyvenv)); - if (nxt_slow_path(path == NULL)) { - nxt_alert(task, "Failed to allocate memory"); - return NXT_ERROR; - } + path = nxt_malloc(len + sizeof(pyvenv)); + if (nxt_slow_path(path == NULL)) { + nxt_alert(task, "Failed to allocate memory"); + return NXT_ERROR; + } - nxt_memcpy(path, c->home, len); - nxt_memcpy(path + len, pyvenv, sizeof(pyvenv)); + nxt_memcpy(path, c->home, len); + nxt_memcpy(path + len, pyvenv, sizeof(pyvenv)); - pep405 = (access(path, R_OK) == 0); + pep405 = (access(path, R_OK) == 0); - nxt_free(path); + nxt_free(path); - if (pep405) { - size = (len + sizeof(bin_python)) * sizeof(wchar_t); + if (pep405) { + size = (len + sizeof(bin_python)) * sizeof(wchar_t); - } else { - size = (len + 1) * sizeof(wchar_t); - } + } else { + size = (len + 1) * sizeof(wchar_t); + } - nxt_py_home = nxt_malloc(size); - if (nxt_slow_path(nxt_py_home == NULL)) { - nxt_alert(task, "Failed to allocate memory"); - return NXT_ERROR; - } + nxt_py_home = nxt_malloc(size); + if (nxt_slow_path(nxt_py_home == NULL)) { + nxt_alert(task, "Failed to allocate memory"); + return NXT_ERROR; + } - if (pep405) { - mbstowcs(nxt_py_home, c->home, len); - mbstowcs(nxt_py_home + len, bin_python, sizeof(bin_python)); + if (pep405) { + mbstowcs(nxt_py_home, c->home, len); + mbstowcs(nxt_py_home + len, bin_python, sizeof(bin_python)); - } else { - mbstowcs(nxt_py_home, c->home, len + 1); - } + } else { + mbstowcs(nxt_py_home, c->home, len + 1); + } - ret = nxt_python3_init_config(pep405); - if (nxt_slow_path(ret == NXT_ERROR)) { - nxt_alert(task, "Failed to initialise config"); - return NXT_ERROR; - } + ret = nxt_python3_init_config(pep405); + if (nxt_slow_path(ret == NXT_ERROR)) { + nxt_alert(task, "Failed to initialise config"); + return NXT_ERROR; + } #else - nxt_py_home = nxt_malloc(len + 1); - if (nxt_slow_path(nxt_py_home == NULL)) { - nxt_alert(task, "Failed to allocate memory"); - return NXT_ERROR; - } - - nxt_memcpy(nxt_py_home, c->home, len + 1); - Py_SetPythonHome(nxt_py_home); -#endif + nxt_py_home = nxt_malloc(len + 1); + if (nxt_slow_path(nxt_py_home == NULL)) { + nxt_alert(task, "Failed to allocate memory"); + return NXT_ERROR; } - Py_InitializeEx(0); + nxt_memcpy(nxt_py_home, c->home, len + 1); + Py_SetPythonHome(nxt_py_home); +#endif + } + + Py_InitializeEx(0); #if PY_VERSION_HEX < NXT_PYTHON_VER(3, 7) - if (c->threads > 1) { - PyEval_InitThreads(); - } + if (c->threads > 1) { + PyEval_InitThreads(); + } #endif - obj = NULL; + obj = NULL; - python_init.ctx_data = NULL; + python_init.ctx_data = NULL; - obj = PySys_GetObject((char *) "stderr"); - if (nxt_slow_path(obj == NULL)) { - nxt_alert(task, "Python failed to get \"sys.stderr\" object"); - goto fail; - } + obj = PySys_GetObject((char *)"stderr"); + if (nxt_slow_path(obj == NULL)) { + nxt_alert(task, "Python failed to get \"sys.stderr\" object"); + goto fail; + } - nxt_py_stderr_flush = PyObject_GetAttrString(obj, "flush"); + nxt_py_stderr_flush = PyObject_GetAttrString(obj, "flush"); - /* obj is a Borrowed reference. */ - obj = NULL; + /* obj is a Borrowed reference. */ + obj = NULL; - if (nxt_slow_path(nxt_py_stderr_flush == NULL)) { - nxt_alert(task, "Python failed to get \"flush\" attribute of " - "\"sys.stderr\" object"); - goto fail; - } + if (nxt_slow_path(nxt_py_stderr_flush == NULL)) { + nxt_alert(task, "Python failed to get \"flush\" attribute of " + "\"sys.stderr\" object"); + goto fail; + } - if (nxt_slow_path(nxt_python_set_path(task, c->path) != NXT_OK)) { - goto fail; - } + if (nxt_slow_path(nxt_python_set_path(task, c->path) != NXT_OK)) { + goto fail; + } - obj = Py_BuildValue("[s]", "unit"); - if (nxt_slow_path(obj == NULL)) { - nxt_alert(task, "Python failed to create the \"sys.argv\" list"); - goto fail; - } + obj = Py_BuildValue("[s]", "unit"); + if (nxt_slow_path(obj == NULL)) { + nxt_alert(task, "Python failed to create the \"sys.argv\" list"); + goto fail; + } - if (nxt_slow_path(PySys_SetObject((char *) "argv", obj) != 0)) { - nxt_alert(task, "Python failed to set the \"sys.argv\" list"); - goto fail; - } + if (nxt_slow_path(PySys_SetObject((char *)"argv", obj) != 0)) { + nxt_alert(task, "Python failed to set the \"sys.argv\" list"); + goto fail; + } - Py_CLEAR(obj); + Py_CLEAR(obj); - n = (c->targets != NULL ? nxt_conf_object_members_count(c->targets) : 1); + n = (c->targets != NULL ? nxt_conf_object_members_count(c->targets) : 1); - size = sizeof(nxt_python_targets_t) + n * sizeof(nxt_python_target_t); + size = sizeof(nxt_python_targets_t) + n * sizeof(nxt_python_target_t); - targets = nxt_unit_malloc(NULL, size); - if (nxt_slow_path(targets == NULL)) { - nxt_alert(task, "Could not allocate targets"); - goto fail; - } + targets = nxt_unit_malloc(NULL, size); + if (nxt_slow_path(targets == NULL)) { + nxt_alert(task, "Could not allocate targets"); + goto fail; + } - memset(targets, 0, size); + memset(targets, 0, size); - targets->count = n; - nxt_py_targets = targets; + targets->count = n; + nxt_py_targets = targets; - if (c->targets != NULL) { - next = 0; + if (c->targets != NULL) { + next = 0; - for (i = 0; /* void */; i++) { - cv = nxt_conf_next_object_member(c->targets, &name, &next); - if (cv == NULL) { - break; - } + for (i = 0; /* void */; i++) { + cv = nxt_conf_next_object_member(c->targets, &name, &next); + if (cv == NULL) { + break; + } - ret = nxt_python_set_target(task, &targets->target[i], cv); - if (nxt_slow_path(ret != NXT_OK)) { - goto fail; - } - } + ret = nxt_python_set_target(task, &targets->target[i], cv); + if (nxt_slow_path(ret != NXT_OK)) { + goto fail; + } + } - } else { - ret = nxt_python_set_target(task, &targets->target[0], app_conf->self); - if (nxt_slow_path(ret != NXT_OK)) { - goto fail; - } + } else { + ret = nxt_python_set_target(task, &targets->target[0], app_conf->self); + if (nxt_slow_path(ret != NXT_OK)) { + goto fail; } + } - nxt_unit_default_init(task, &python_init, data->app); + nxt_unit_default_init(task, &python_init, data->app); - python_init.data = c; - python_init.callbacks.ready_handler = nxt_python_ready_handler; + python_init.data = c; + python_init.callbacks.ready_handler = nxt_python_ready_handler; - proto = c->protocol; + proto = c->protocol; - if (proto.length == 0) { - proto = nxt_python_asgi_check(targets->target[0].application) - ? asgi : wsgi; + if (proto.length == 0) { + proto = nxt_python_asgi_check(targets->target[0].application) ? asgi : wsgi; - for (i = 1; i < targets->count; i++) { - probe_proto = nxt_python_asgi_check(targets->target[i].application) - ? asgi : wsgi; - if (probe_proto.start != proto.start) { - nxt_alert(task, "A mix of ASGI & WSGI targets is forbidden, " - "specify protocol in config if incorrect"); - goto fail; - } - } + for (i = 1; i < targets->count; i++) { + probe_proto = + nxt_python_asgi_check(targets->target[i].application) ? asgi : wsgi; + if (probe_proto.start != proto.start) { + nxt_alert(task, "A mix of ASGI & WSGI targets is forbidden, " + "specify protocol in config if incorrect"); + goto fail; + } } + } - if (nxt_strstr_eq(&proto, &asgi)) { - rc = nxt_python_asgi_init(&python_init, &nxt_py_proto); + if (nxt_strstr_eq(&proto, &asgi)) { + rc = nxt_python_asgi_init(&python_init, &nxt_py_proto); - } else { - rc = nxt_python_wsgi_init(&python_init, &nxt_py_proto); - } + } else { + rc = nxt_python_wsgi_init(&python_init, &nxt_py_proto); + } - if (nxt_slow_path(rc == NXT_UNIT_ERROR)) { - goto fail; - } + if (nxt_slow_path(rc == NXT_UNIT_ERROR)) { + goto fail; + } - rc = nxt_py_proto.ctx_data_alloc(&python_init.ctx_data, 1); - if (nxt_slow_path(rc != NXT_UNIT_OK)) { - goto fail; - } + rc = nxt_py_proto.ctx_data_alloc(&python_init.ctx_data, 1); + if (nxt_slow_path(rc != NXT_UNIT_OK)) { + goto fail; + } - rc = nxt_python_init_threads(c); - if (nxt_slow_path(rc == NXT_UNIT_ERROR)) { - goto fail; - } + rc = nxt_python_init_threads(c); + if (nxt_slow_path(rc == NXT_UNIT_ERROR)) { + goto fail; + } - if (nxt_py_proto.startup != NULL) { - if (nxt_py_proto.startup(python_init.ctx_data) != NXT_UNIT_OK) { - goto fail; - } + if (nxt_py_proto.startup != NULL) { + if (nxt_py_proto.startup(python_init.ctx_data) != NXT_UNIT_OK) { + goto fail; } + } - unit_ctx = nxt_unit_init(&python_init); - if (nxt_slow_path(unit_ctx == NULL)) { - goto fail; - } + unit_ctx = nxt_unit_init(&python_init); + if (nxt_slow_path(unit_ctx == NULL)) { + goto fail; + } - rc = nxt_py_proto.run(unit_ctx); + rc = nxt_py_proto.run(unit_ctx); - nxt_python_join_threads(unit_ctx, c); + nxt_python_join_threads(unit_ctx, c); - nxt_unit_done(unit_ctx); + nxt_unit_done(unit_ctx); - nxt_py_proto.ctx_data_free(python_init.ctx_data); + nxt_py_proto.ctx_data_free(python_init.ctx_data); - nxt_python_atexit(); + nxt_python_atexit(); - exit(rc); + exit(rc); - return NXT_OK; + return NXT_OK; fail: - nxt_python_join_threads(NULL, c); + nxt_python_join_threads(NULL, c); - if (python_init.ctx_data != NULL) { - nxt_py_proto.ctx_data_free(python_init.ctx_data); - } + if (python_init.ctx_data != NULL) { + nxt_py_proto.ctx_data_free(python_init.ctx_data); + } - Py_XDECREF(obj); + Py_XDECREF(obj); - nxt_python_atexit(); + nxt_python_atexit(); - return NXT_ERROR; + return NXT_ERROR; } - -static nxt_int_t -nxt_python_set_target(nxt_task_t *task, nxt_python_target_t *target, - nxt_conf_value_t *conf) -{ - char *callable, *module_name; - PyObject *module, *obj; - nxt_str_t str; - nxt_bool_t is_factory = 0; - nxt_conf_value_t *value; - - static const nxt_str_t module_str = nxt_string("module"); - static const nxt_str_t callable_str = nxt_string("callable"); - static const nxt_str_t prefix_str = nxt_string("prefix"); - static const nxt_str_t factory_flag_str = nxt_string("factory"); - - module = obj = NULL; - - value = nxt_conf_get_object_member(conf, &module_str, NULL); - if (nxt_slow_path(value == NULL)) { - goto fail; - } - +static nxt_int_t nxt_python_set_target(nxt_task_t *task, + nxt_python_target_t *target, + nxt_conf_value_t *conf) { + char *callable, *module_name; + PyObject *module, *obj; + nxt_str_t str; + nxt_bool_t is_factory = 0; + nxt_conf_value_t *value; + + static const nxt_str_t module_str = nxt_string("module"); + static const nxt_str_t callable_str = nxt_string("callable"); + static const nxt_str_t prefix_str = nxt_string("prefix"); + static const nxt_str_t factory_flag_str = nxt_string("factory"); + + module = obj = NULL; + + value = nxt_conf_get_object_member(conf, &module_str, NULL); + if (nxt_slow_path(value == NULL)) { + goto fail; + } + + nxt_conf_get_string(value, &str); + + module_name = nxt_alloca(str.length + 1); + nxt_memcpy(module_name, str.start, str.length); + module_name[str.length] = '\0'; + + module = PyImport_ImportModule(module_name); + if (nxt_slow_path(module == NULL)) { + nxt_alert(task, "Python failed to import module \"%s\"", module_name); + nxt_python_print_exception(); + goto fail; + } + + value = nxt_conf_get_object_member(conf, &callable_str, NULL); + if (value == NULL) { + callable = nxt_alloca(12); + nxt_memcpy(callable, "application", 12); + + } else { nxt_conf_get_string(value, &str); - module_name = nxt_alloca(str.length + 1); - nxt_memcpy(module_name, str.start, str.length); - module_name[str.length] = '\0'; + callable = nxt_alloca(str.length + 1); + nxt_memcpy(callable, str.start, str.length); + callable[str.length] = '\0'; + } + + obj = PyDict_GetItemString(PyModule_GetDict(module), callable); + if (nxt_slow_path(obj == NULL)) { + nxt_alert(task, "Python failed to get \"%s\" from module \"%s\"", callable, + module_name); + goto fail; + } + + value = nxt_conf_get_object_member(conf, &factory_flag_str, NULL); + if (value != NULL) { + is_factory = nxt_conf_get_boolean(value); + } + + if (is_factory) { + if (nxt_slow_path(PyCallable_Check(obj) == 0)) { + nxt_alert(task, + "factory \"%s\" in module \"%s\" " + "can not be called to fetch callable", + callable, module_name); + Py_INCREF(obj); /* borrowed reference */ + goto fail; + } + + obj = PyObject_CallObject(obj, NULL); + if (nxt_slow_path(PyCallable_Check(obj) == 0)) { + nxt_alert(task, + "factory \"%s\" in module \"%s\" " + "did not return callable object", + callable, module_name); + goto fail; + } + + } else if (nxt_slow_path(PyCallable_Check(obj) == 0)) { + nxt_alert(task, "\"%s\" in module \"%s\" is not a callable object", + callable, module_name); + goto fail; + } + + value = nxt_conf_get_object_member(conf, &prefix_str, NULL); + if (nxt_slow_path(nxt_python_set_prefix(task, target, value) != NXT_OK)) { + goto fail; + } + + target->application = obj; + obj = NULL; + + Py_INCREF(target->application); + Py_CLEAR(module); + + return NXT_OK; - module = PyImport_ImportModule(module_name); - if (nxt_slow_path(module == NULL)) { - nxt_alert(task, "Python failed to import module \"%s\"", module_name); - nxt_python_print_exception(); - goto fail; - } +fail: - value = nxt_conf_get_object_member(conf, &callable_str, NULL); - if (value == NULL) { - callable = nxt_alloca(12); - nxt_memcpy(callable, "application", 12); + Py_XDECREF(obj); + Py_XDECREF(module); - } else { - nxt_conf_get_string(value, &str); + return NXT_ERROR; +} - callable = nxt_alloca(str.length + 1); - nxt_memcpy(callable, str.start, str.length); - callable[str.length] = '\0'; - } +nxt_inline nxt_int_t nxt_python_set_prefix(nxt_task_t *task, + nxt_python_target_t *target, + nxt_conf_value_t *value) { + u_char *prefix; + nxt_str_t str; - obj = PyDict_GetItemString(PyModule_GetDict(module), callable); - if (nxt_slow_path(obj == NULL)) { - nxt_alert(task, "Python failed to get \"%s\" from module \"%s\"", - callable, module_name); - goto fail; - } + if (value == NULL) { + return NXT_OK; + } - value = nxt_conf_get_object_member(conf, &factory_flag_str, NULL); - if (value != NULL) { - is_factory = nxt_conf_get_boolean(value); - } + nxt_conf_get_string(value, &str); - if (is_factory) { - if (nxt_slow_path(PyCallable_Check(obj) == 0)) { - nxt_alert(task, - "factory \"%s\" in module \"%s\" " - "can not be called to fetch callable", - callable, module_name); - Py_INCREF(obj); /* borrowed reference */ - goto fail; - } - - obj = PyObject_CallObject(obj, NULL); - if (nxt_slow_path(PyCallable_Check(obj) == 0)) { - nxt_alert(task, - "factory \"%s\" in module \"%s\" " - "did not return callable object", - callable, module_name); - goto fail; - } - - } else if (nxt_slow_path(PyCallable_Check(obj) == 0)) { - nxt_alert(task, "\"%s\" in module \"%s\" is not a callable object", - callable, module_name); - goto fail; - } + if (str.length == 0) { + return NXT_OK; + } + + if (str.start[str.length - 1] == '/') { + str.length--; + } + target->prefix.length = str.length; + prefix = nxt_malloc(str.length); + if (nxt_slow_path(prefix == NULL)) { + nxt_alert(task, "Failed to allocate target prefix string"); + return NXT_ERROR; + } - value = nxt_conf_get_object_member(conf, &prefix_str, NULL); - if (nxt_slow_path(nxt_python_set_prefix(task, target, value) != NXT_OK)) { - goto fail; - } + target->py_prefix = PyString_FromStringAndSize((char *)str.start, str.length); + if (nxt_slow_path(target->py_prefix == NULL)) { + nxt_free(prefix); + nxt_alert(task, "Python failed to allocate target prefix " + "string"); + return NXT_ERROR; + } + nxt_memcpy(prefix, str.start, str.length); + target->prefix.start = prefix; - target->application = obj; - obj = NULL; + return NXT_OK; +} - Py_INCREF(target->application); - Py_CLEAR(module); +static nxt_int_t nxt_python_set_path(nxt_task_t *task, + nxt_conf_value_t *value) { + int ret; + PyObject *path, *sys; + nxt_str_t str; + nxt_uint_t n; + nxt_conf_value_t *array; + if (value == NULL) { return NXT_OK; + } -fail: - - Py_XDECREF(obj); - Py_XDECREF(module); - + sys = PySys_GetObject((char *)"path"); + if (nxt_slow_path(sys == NULL)) { + nxt_alert(task, "Python failed to get \"sys.path\" list"); return NXT_ERROR; -} + } + /* sys is a Borrowed reference. */ -nxt_inline nxt_int_t -nxt_python_set_prefix(nxt_task_t *task, nxt_python_target_t *target, - nxt_conf_value_t *value) -{ - u_char *prefix; - nxt_str_t str; + array = value; + n = nxt_conf_array_elements_count_or_1(array); - if (value == NULL) { - return NXT_OK; - } + while (n != 0) { + n--; - nxt_conf_get_string(value, &str); + /* + * Insertion in front of existing paths starting from the last element + * to preserve original order while giving priority to the values + * specified in the "path" option. + */ - if (str.length == 0) { - return NXT_OK; - } + value = nxt_conf_get_array_element_or_itself(array, n); - if (str.start[str.length - 1] == '/') { - str.length--; - } - target->prefix.length = str.length; - prefix = nxt_malloc(str.length); - if (nxt_slow_path(prefix == NULL)) { - nxt_alert(task, "Failed to allocate target prefix string"); - return NXT_ERROR; - } + nxt_conf_get_string(value, &str); - target->py_prefix = PyString_FromStringAndSize((char *)str.start, - str.length); - if (nxt_slow_path(target->py_prefix == NULL)) { - nxt_free(prefix); - nxt_alert(task, "Python failed to allocate target prefix " - "string"); - return NXT_ERROR; + path = PyString_FromStringAndSize((char *)str.start, str.length); + if (nxt_slow_path(path == NULL)) { + nxt_alert(task, "Python failed to create string object \"%V\"", &str); + return NXT_ERROR; } - nxt_memcpy(prefix, str.start, str.length); - target->prefix.start = prefix; - - return NXT_OK; -} - -static nxt_int_t -nxt_python_set_path(nxt_task_t *task, nxt_conf_value_t *value) -{ - int ret; - PyObject *path, *sys; - nxt_str_t str; - nxt_uint_t n; - nxt_conf_value_t *array; + ret = PyList_Insert(sys, 0, path); - if (value == NULL) { - return NXT_OK; - } + Py_DECREF(path); - sys = PySys_GetObject((char *) "path"); - if (nxt_slow_path(sys == NULL)) { - nxt_alert(task, "Python failed to get \"sys.path\" list"); - return NXT_ERROR; + if (nxt_slow_path(ret != 0)) { + nxt_alert(task, "Python failed to insert \"%V\" into \"sys.path\"", &str); + return NXT_ERROR; } + } - /* sys is a Borrowed reference. */ - - array = value; - n = nxt_conf_array_elements_count_or_1(array); - - while (n != 0) { - n--; - - /* - * Insertion in front of existing paths starting from the last element - * to preserve original order while giving priority to the values - * specified in the "path" option. - */ - - value = nxt_conf_get_array_element_or_itself(array, n); - - nxt_conf_get_string(value, &str); + return NXT_OK; +} - path = PyString_FromStringAndSize((char *) str.start, str.length); - if (nxt_slow_path(path == NULL)) { - nxt_alert(task, "Python failed to create string object \"%V\"", - &str); - return NXT_ERROR; - } +static int nxt_python_init_threads(nxt_python_app_conf_t *c) { + int res; + uint32_t i; + nxt_py_thread_info_t *ti; + static pthread_attr_t attr; - ret = PyList_Insert(sys, 0, path); + if (c->threads <= 1) { + return NXT_UNIT_OK; + } - Py_DECREF(path); + if (c->thread_stack_size > 0) { + res = pthread_attr_init(&attr); + if (nxt_slow_path(res != 0)) { + nxt_unit_alert(NULL, "thread attr init failed: %s (%d)", strerror(res), + res); - if (nxt_slow_path(ret != 0)) { - nxt_alert(task, "Python failed to insert \"%V\" into \"sys.path\"", - &str); - return NXT_ERROR; - } + return NXT_UNIT_ERROR; } - return NXT_OK; -} - + res = pthread_attr_setstacksize(&attr, c->thread_stack_size); + if (nxt_slow_path(res != 0)) { + nxt_unit_alert(NULL, "thread attr set stack size failed: %s (%d)", + strerror(res), res); -static int -nxt_python_init_threads(nxt_python_app_conf_t *c) -{ - int res; - uint32_t i; - nxt_py_thread_info_t *ti; - static pthread_attr_t attr; - - if (c->threads <= 1) { - return NXT_UNIT_OK; + return NXT_UNIT_ERROR; } - if (c->thread_stack_size > 0) { - res = pthread_attr_init(&attr); - if (nxt_slow_path(res != 0)) { - nxt_unit_alert(NULL, "thread attr init failed: %s (%d)", - strerror(res), res); - - return NXT_UNIT_ERROR; - } + nxt_py_thread_attr = &attr; + } - res = pthread_attr_setstacksize(&attr, c->thread_stack_size); - if (nxt_slow_path(res != 0)) { - nxt_unit_alert(NULL, "thread attr set stack size failed: %s (%d)", - strerror(res), res); + nxt_py_threads = + nxt_unit_malloc(NULL, sizeof(nxt_py_thread_info_t) * (c->threads - 1)); + if (nxt_slow_path(nxt_py_threads == NULL)) { + nxt_unit_alert(NULL, "Failed to allocate thread info array"); - return NXT_UNIT_ERROR; - } - - nxt_py_thread_attr = &attr; - } - - nxt_py_threads = nxt_unit_malloc(NULL, sizeof(nxt_py_thread_info_t) - * (c->threads - 1)); - if (nxt_slow_path(nxt_py_threads == NULL)) { - nxt_unit_alert(NULL, "Failed to allocate thread info array"); - - return NXT_UNIT_ERROR; - } + return NXT_UNIT_ERROR; + } - memset(nxt_py_threads, 0, sizeof(nxt_py_thread_info_t) * (c->threads - 1)); + memset(nxt_py_threads, 0, sizeof(nxt_py_thread_info_t) * (c->threads - 1)); - for (i = 0; i < c->threads - 1; i++) { - ti = &nxt_py_threads[i]; + for (i = 0; i < c->threads - 1; i++) { + ti = &nxt_py_threads[i]; - res = nxt_py_proto.ctx_data_alloc(&ti->ctx_data, 0); - if (nxt_slow_path(res != NXT_UNIT_OK)) { - return NXT_UNIT_ERROR; - } + res = nxt_py_proto.ctx_data_alloc(&ti->ctx_data, 0); + if (nxt_slow_path(res != NXT_UNIT_OK)) { + return NXT_UNIT_ERROR; } + } - return NXT_UNIT_OK; + return NXT_UNIT_OK; } +static int nxt_python_ready_handler(nxt_unit_ctx_t *ctx) { + int res; + uint32_t i; + nxt_py_thread_info_t *ti; + nxt_python_app_conf_t *c; -static int -nxt_python_ready_handler(nxt_unit_ctx_t *ctx) -{ - int res; - uint32_t i; - nxt_py_thread_info_t *ti; - nxt_python_app_conf_t *c; - - c = ctx->unit->data; + c = ctx->unit->data; - if (c->threads <= 1) { - return NXT_UNIT_OK; - } + if (c->threads <= 1) { + return NXT_UNIT_OK; + } - for (i = 0; i < c->threads - 1; i++) { - ti = &nxt_py_threads[i]; + for (i = 0; i < c->threads - 1; i++) { + ti = &nxt_py_threads[i]; - ti->ctx = ctx; + ti->ctx = ctx; - res = pthread_create(&ti->thread, nxt_py_thread_attr, - nxt_python_thread_func, ti); + res = pthread_create(&ti->thread, nxt_py_thread_attr, + nxt_python_thread_func, ti); - if (nxt_fast_path(res == 0)) { - nxt_unit_debug(ctx, "thread #%d created", (int) (i + 1)); + if (nxt_fast_path(res == 0)) { + nxt_unit_debug(ctx, "thread #%d created", (int)(i + 1)); - } else { - nxt_unit_alert(ctx, "thread #%d create failed: %s (%d)", - (int) (i + 1), strerror(res), res); - } + } else { + nxt_unit_alert(ctx, "thread #%d create failed: %s (%d)", (int)(i + 1), + strerror(res), res); } + } - return NXT_UNIT_OK; + return NXT_UNIT_OK; } +static void *nxt_python_thread_func(void *data) { + nxt_unit_ctx_t *ctx; + PyGILState_STATE gstate; + nxt_py_thread_info_t *ti; -static void * -nxt_python_thread_func(void *data) -{ - nxt_unit_ctx_t *ctx; - PyGILState_STATE gstate; - nxt_py_thread_info_t *ti; - - ti = data; + ti = data; - nxt_unit_debug(ti->ctx, "worker thread #%d start", - (int) (ti - nxt_py_threads + 1)); + nxt_unit_debug(ti->ctx, "worker thread #%d start", + (int)(ti - nxt_py_threads + 1)); - gstate = PyGILState_Ensure(); + gstate = PyGILState_Ensure(); - if (nxt_py_proto.startup != NULL) { - if (nxt_py_proto.startup(ti->ctx_data) != NXT_UNIT_OK) { - goto fail; - } + if (nxt_py_proto.startup != NULL) { + if (nxt_py_proto.startup(ti->ctx_data) != NXT_UNIT_OK) { + goto fail; } + } - ctx = nxt_unit_ctx_alloc(ti->ctx, ti->ctx_data); - if (nxt_slow_path(ctx == NULL)) { - goto fail; - } + ctx = nxt_unit_ctx_alloc(ti->ctx, ti->ctx_data); + if (nxt_slow_path(ctx == NULL)) { + goto fail; + } - (void) nxt_py_proto.run(ctx); + (void)nxt_py_proto.run(ctx); - nxt_unit_done(ctx); + nxt_unit_done(ctx); fail: - PyGILState_Release(gstate); + PyGILState_Release(gstate); - nxt_unit_debug(NULL, "worker thread #%d end", - (int) (ti - nxt_py_threads + 1)); + nxt_unit_debug(NULL, "worker thread #%d end", (int)(ti - nxt_py_threads + 1)); - return NULL; + return NULL; } +static void nxt_python_join_threads(nxt_unit_ctx_t *ctx, + nxt_python_app_conf_t *c) { + int res; + uint32_t i; + PyThreadState *thread_state; + nxt_py_thread_info_t *ti; -static void -nxt_python_join_threads(nxt_unit_ctx_t *ctx, nxt_python_app_conf_t *c) -{ - int res; - uint32_t i; - PyThreadState *thread_state; - nxt_py_thread_info_t *ti; - - if (nxt_py_threads == NULL) { - return; - } + if (nxt_py_threads == NULL) { + return; + } - thread_state = PyEval_SaveThread(); + thread_state = PyEval_SaveThread(); - for (i = 0; i < c->threads - 1; i++) { - ti = &nxt_py_threads[i]; + for (i = 0; i < c->threads - 1; i++) { + ti = &nxt_py_threads[i]; - if ((uintptr_t) ti->thread == 0) { - continue; - } + if ((uintptr_t)ti->thread == 0) { + continue; + } - res = pthread_join(ti->thread, NULL); + res = pthread_join(ti->thread, NULL); - if (nxt_fast_path(res == 0)) { - nxt_unit_debug(ctx, "thread #%d joined", (int) (i + 1)); + if (nxt_fast_path(res == 0)) { + nxt_unit_debug(ctx, "thread #%d joined", (int)(i + 1)); - } else { - nxt_unit_alert(ctx, "thread #%d join failed: %s (%d)", - (int) (i + 1), strerror(res), res); - } + } else { + nxt_unit_alert(ctx, "thread #%d join failed: %s (%d)", (int)(i + 1), + strerror(res), res); } + } - PyEval_RestoreThread(thread_state); + PyEval_RestoreThread(thread_state); - for (i = 0; i < c->threads - 1; i++) { - ti = &nxt_py_threads[i]; + for (i = 0; i < c->threads - 1; i++) { + ti = &nxt_py_threads[i]; - if (ti->ctx_data != NULL) { - nxt_py_proto.ctx_data_free(ti->ctx_data); - } + if (ti->ctx_data != NULL) { + nxt_py_proto.ctx_data_free(ti->ctx_data); } + } - nxt_unit_free(NULL, nxt_py_threads); + nxt_unit_free(NULL, nxt_py_threads); } +int nxt_python_init_strings(nxt_python_string_t *pstr) { + PyObject *obj; -int -nxt_python_init_strings(nxt_python_string_t *pstr) -{ - PyObject *obj; - - while (pstr->string.start != NULL) { - obj = PyString_FromStringAndSize((char *) pstr->string.start, - pstr->string.length); - if (nxt_slow_path(obj == NULL)) { - return NXT_UNIT_ERROR; - } + while (pstr->string.start != NULL) { + obj = PyString_FromStringAndSize((char *)pstr->string.start, + pstr->string.length); + if (nxt_slow_path(obj == NULL)) { + return NXT_UNIT_ERROR; + } - PyUnicode_InternInPlace(&obj); + PyUnicode_InternInPlace(&obj); - *pstr->object_p = obj; + *pstr->object_p = obj; - pstr++; - } + pstr++; + } - return NXT_UNIT_OK; + return NXT_UNIT_OK; } +void nxt_python_done_strings(nxt_python_string_t *pstr) { + PyObject *obj; -void -nxt_python_done_strings(nxt_python_string_t *pstr) -{ - PyObject *obj; - - while (pstr->string.start != NULL) { - obj = *pstr->object_p; + while (pstr->string.start != NULL) { + obj = *pstr->object_p; - Py_XDECREF(obj); - *pstr->object_p = NULL; + Py_XDECREF(obj); + *pstr->object_p = NULL; - pstr++; - } + pstr++; + } } +static void nxt_python_atexit(void) { + nxt_int_t i; + nxt_python_target_t *target; -static void -nxt_python_atexit(void) -{ - nxt_int_t i; - nxt_python_target_t *target; - - if (nxt_py_proto.done != NULL) { - nxt_py_proto.done(); - } - - Py_XDECREF(nxt_py_stderr_flush); + if (nxt_py_proto.done != NULL) { + nxt_py_proto.done(); + } - if (nxt_py_targets != NULL) { - for (i = 0; i < nxt_py_targets->count; i++) { - target = &nxt_py_targets->target[i]; + Py_XDECREF(nxt_py_stderr_flush); - Py_XDECREF(target->application); - Py_XDECREF(target->py_prefix); + if (nxt_py_targets != NULL) { + for (i = 0; i < nxt_py_targets->count; i++) { + target = &nxt_py_targets->target[i]; - nxt_free(target->prefix.start); - } + Py_XDECREF(target->application); + Py_XDECREF(target->py_prefix); - nxt_unit_free(NULL, nxt_py_targets); + nxt_free(target->prefix.start); } - Py_Finalize(); + nxt_unit_free(NULL, nxt_py_targets); + } - if (nxt_py_home != NULL) { - nxt_free(nxt_py_home); - } -} + Py_Finalize(); + if (nxt_py_home != NULL) { + nxt_free(nxt_py_home); + } +} -void -nxt_python_print_exception(void) -{ - PyErr_Print(); +void nxt_python_print_exception(void) { + PyErr_Print(); #if PY_MAJOR_VERSION == 3 - /* The backtrace may be buffered in sys.stderr file object. */ - { - PyObject *result; + /* The backtrace may be buffered in sys.stderr file object. */ + { + PyObject *result; - result = PyObject_CallFunction(nxt_py_stderr_flush, NULL); - if (nxt_slow_path(result == NULL)) { - PyErr_Clear(); - return; - } - - Py_DECREF(result); + result = PyObject_CallFunction(nxt_py_stderr_flush, NULL); + if (nxt_slow_path(result == NULL)) { + PyErr_Clear(); + return; } + + Py_DECREF(result); + } #endif } diff --git a/src/python/nxt_python.h b/src/python/nxt_python.h index f51545142..cdefde408 100644 --- a/src/python/nxt_python.h +++ b/src/python/nxt_python.h @@ -6,70 +6,62 @@ #ifndef _NXT_PYTHON_H_INCLUDED_ #define _NXT_PYTHON_H_INCLUDED_ - #include #include #include -#define NXT_PYTHON_VER(maj, min) ((maj << 24) | (min << 16)) - +#define NXT_PYTHON_VER(maj, min) ((maj << 24) | (min << 16)) #if PY_MAJOR_VERSION == 3 -#define NXT_PYTHON_BYTES_TYPE "bytestring" +#define NXT_PYTHON_BYTES_TYPE "bytestring" -#define PyString_FromStringAndSize(str, size) \ - PyUnicode_DecodeLatin1((str), (size), "strict") -#define PyString_AS_STRING PyUnicode_DATA +#define PyString_FromStringAndSize(str, size) \ + PyUnicode_DecodeLatin1((str), (size), "strict") +#define PyString_AS_STRING PyUnicode_DATA #else -#define NXT_PYTHON_BYTES_TYPE "string" - -#define PyBytes_FromStringAndSize PyString_FromStringAndSize -#define PyBytes_Check PyString_Check -#define PyBytes_GET_SIZE PyString_GET_SIZE -#define PyBytes_AS_STRING PyString_AS_STRING -#define PyUnicode_InternInPlace PyString_InternInPlace -#define PyUnicode_AsUTF8 PyString_AS_STRING -#define PyUnicode_GET_LENGTH PyUnicode_GET_SIZE +#define NXT_PYTHON_BYTES_TYPE "string" + +#define PyBytes_FromStringAndSize PyString_FromStringAndSize +#define PyBytes_Check PyString_Check +#define PyBytes_GET_SIZE PyString_GET_SIZE +#define PyBytes_AS_STRING PyString_AS_STRING +#define PyUnicode_InternInPlace PyString_InternInPlace +#define PyUnicode_AsUTF8 PyString_AS_STRING +#define PyUnicode_GET_LENGTH PyUnicode_GET_SIZE #endif #if PY_VERSION_HEX >= NXT_PYTHON_VER(3, 5) -#define NXT_HAVE_ASGI 1 +#define NXT_HAVE_ASGI 1 #endif - typedef struct { - PyObject *application; - PyObject *py_prefix; - nxt_str_t prefix; - nxt_bool_t asgi_legacy; + PyObject *application; + PyObject *py_prefix; + nxt_str_t prefix; + nxt_bool_t asgi_legacy; } nxt_python_target_t; - typedef struct { - nxt_int_t count; - nxt_python_target_t target[]; + nxt_int_t count; + nxt_python_target_t target[]; } nxt_python_targets_t; - -extern nxt_python_targets_t *nxt_py_targets; - +extern nxt_python_targets_t *nxt_py_targets; typedef struct { - nxt_str_t string; - PyObject **object_p; + nxt_str_t string; + PyObject **object_p; } nxt_python_string_t; - typedef struct { - int (*ctx_data_alloc)(void **pdata, int main); - void (*ctx_data_free)(void *data); - int (*startup)(void *data); - int (*run)(nxt_unit_ctx_t *ctx); - void (*done)(void); + int (*ctx_data_alloc)(void **pdata, int main); + void (*ctx_data_free)(void *data); + int (*startup)(void *data); + int (*run)(nxt_unit_ctx_t *ctx); + void (*done)(void); } nxt_python_proto_t; - int nxt_python_init_strings(nxt_python_string_t *pstr); void nxt_python_done_strings(nxt_python_string_t *pstr); @@ -80,5 +72,4 @@ int nxt_python_wsgi_init(nxt_unit_init_t *init, nxt_python_proto_t *proto); int nxt_python_asgi_check(PyObject *obj); int nxt_python_asgi_init(nxt_unit_init_t *init, nxt_python_proto_t *proto); - -#endif /* _NXT_PYTHON_H_INCLUDED_ */ +#endif /* _NXT_PYTHON_H_INCLUDED_ */ diff --git a/src/python/nxt_python_asgi.c b/src/python/nxt_python_asgi.c index 8f300b53a..7621a40f5 100644 --- a/src/python/nxt_python_asgi.c +++ b/src/python/nxt_python_asgi.c @@ -3,7 +3,6 @@ * Copyright (C) NGINX, Inc. */ - #include #if (NXT_HAVE_ASGI) @@ -15,1556 +14,1422 @@ #include #include - static PyObject *nxt_python_asgi_get_func(PyObject *obj); static PyObject *nxt_python_asgi_get_event_loop(PyObject *asyncio, - const char *event_loop_func); + const char *event_loop_func); static int nxt_python_asgi_ctx_data_alloc(void **pdata, int main); static void nxt_python_asgi_ctx_data_free(void *data); static int nxt_python_asgi_startup(void *data); static int nxt_python_asgi_run(nxt_unit_ctx_t *ctx); static void nxt_py_asgi_remove_reader(nxt_unit_ctx_t *ctx, - nxt_unit_port_t *port); + nxt_unit_port_t *port); static void nxt_py_asgi_request_handler(nxt_unit_request_info_t *req); static void nxt_py_asgi_close_handler(nxt_unit_request_info_t *req); static PyObject *nxt_py_asgi_create_http_scope(nxt_unit_request_info_t *req, - nxt_python_target_t *app_target); + nxt_python_target_t *app_target); static PyObject *nxt_py_asgi_create_address(nxt_unit_sptr_t *sptr, uint8_t len, - uint16_t port); + uint16_t port); static PyObject *nxt_py_asgi_create_ip_address(nxt_unit_sptr_t *sptr, - uint8_t len, uint16_t port); + uint8_t len, uint16_t port); static PyObject *nxt_py_asgi_create_header(nxt_unit_field_t *f); static PyObject *nxt_py_asgi_create_subprotocols(nxt_unit_field_t *f); static int nxt_py_asgi_add_port(nxt_unit_ctx_t *ctx, nxt_unit_port_t *port); static int nxt_py_asgi_add_reader(nxt_unit_ctx_t *ctx, nxt_unit_port_t *port); static void nxt_py_asgi_remove_port(nxt_unit_t *lib, nxt_unit_ctx_t *ctx, - nxt_unit_port_t *port); + nxt_unit_port_t *port); static void nxt_py_asgi_quit(nxt_unit_ctx_t *ctx); static void nxt_py_asgi_shm_ack_handler(nxt_unit_ctx_t *ctx); static PyObject *nxt_py_asgi_port_read(PyObject *self, PyObject *args); static void nxt_python_asgi_done(void); -static PyObject *nxt_py_port_read; +static PyObject *nxt_py_port_read; -static PyMethodDef nxt_py_port_read_method = - {"unit_port_read", nxt_py_asgi_port_read, METH_VARARGS, ""}; +static PyMethodDef nxt_py_port_read_method = { + "unit_port_read", nxt_py_asgi_port_read, METH_VARARGS, ""}; -static nxt_python_proto_t nxt_py_asgi_proto = { +static nxt_python_proto_t nxt_py_asgi_proto = { .ctx_data_alloc = nxt_python_asgi_ctx_data_alloc, - .ctx_data_free = nxt_python_asgi_ctx_data_free, - .startup = nxt_python_asgi_startup, - .run = nxt_python_asgi_run, - .done = nxt_python_asgi_done, + .ctx_data_free = nxt_python_asgi_ctx_data_free, + .startup = nxt_python_asgi_startup, + .run = nxt_python_asgi_run, + .done = nxt_python_asgi_done, }; -#define NXT_UNIT_HASH_WS_PROTOCOL 0xED0A - +#define NXT_UNIT_HASH_WS_PROTOCOL 0xED0A -int -nxt_python_asgi_check(PyObject *obj) -{ - int res; - PyObject *func; - PyCodeObject *code; +int nxt_python_asgi_check(PyObject *obj) { + int res; + PyObject *func; + PyCodeObject *code; - func = nxt_python_asgi_get_func(obj); + func = nxt_python_asgi_get_func(obj); - if (func == NULL) { - return 0; - } + if (func == NULL) { + return 0; + } - code = (PyCodeObject *) PyFunction_GET_CODE(func); + code = (PyCodeObject *)PyFunction_GET_CODE(func); - nxt_unit_debug(NULL, "asgi_check: callable is %sa coroutine function with " - "%d argument(s)", - (code->co_flags & CO_COROUTINE) != 0 ? "" : "not ", - code->co_argcount); + nxt_unit_debug(NULL, + "asgi_check: callable is %sa coroutine function with " + "%d argument(s)", + (code->co_flags & CO_COROUTINE) != 0 ? "" : "not ", + code->co_argcount); - res = (code->co_flags & CO_COROUTINE) != 0 || code->co_argcount == 1; + res = (code->co_flags & CO_COROUTINE) != 0 || code->co_argcount == 1; - Py_DECREF(func); + Py_DECREF(func); - return res; + return res; } +static PyObject *nxt_python_asgi_get_func(PyObject *obj) { + PyObject *call; -static PyObject * -nxt_python_asgi_get_func(PyObject *obj) -{ - PyObject *call; - - if (PyFunction_Check(obj)) { - Py_INCREF(obj); - return obj; - } - - if (PyMethod_Check(obj)) { - obj = PyMethod_GET_FUNCTION(obj); + if (PyFunction_Check(obj)) { + Py_INCREF(obj); + return obj; + } - Py_INCREF(obj); - return obj; - } + if (PyMethod_Check(obj)) { + obj = PyMethod_GET_FUNCTION(obj); - call = PyObject_GetAttrString(obj, "__call__"); + Py_INCREF(obj); + return obj; + } - if (call == NULL) { - return NULL; - } + call = PyObject_GetAttrString(obj, "__call__"); - if (PyFunction_Check(call)) { - return call; - } + if (call == NULL) { + return NULL; + } - if (PyMethod_Check(call)) { - obj = PyMethod_GET_FUNCTION(call); + if (PyFunction_Check(call)) { + return call; + } - if (PyFunction_Check(obj)) { - Py_INCREF(obj); + if (PyMethod_Check(call)) { + obj = PyMethod_GET_FUNCTION(call); - } else { - obj = NULL; - } + if (PyFunction_Check(obj)) { + Py_INCREF(obj); } else { - obj = NULL; + obj = NULL; } - Py_DECREF(call); + } else { + obj = NULL; + } - return obj; + Py_DECREF(call); + + return obj; } +int nxt_python_asgi_init(nxt_unit_init_t *init, nxt_python_proto_t *proto) { + PyObject *func; + nxt_int_t i; + PyCodeObject *code; -int -nxt_python_asgi_init(nxt_unit_init_t *init, nxt_python_proto_t *proto) -{ - PyObject *func; - nxt_int_t i; - PyCodeObject *code; + nxt_unit_debug(NULL, "asgi_init"); - nxt_unit_debug(NULL, "asgi_init"); + if (nxt_slow_path(nxt_py_asgi_str_init() != NXT_UNIT_OK)) { + nxt_unit_alert(NULL, "Python failed to init string objects"); + return NXT_UNIT_ERROR; + } - if (nxt_slow_path(nxt_py_asgi_str_init() != NXT_UNIT_OK)) { - nxt_unit_alert(NULL, "Python failed to init string objects"); - return NXT_UNIT_ERROR; - } + nxt_py_port_read = PyCFunction_New(&nxt_py_port_read_method, NULL); + if (nxt_slow_path(nxt_py_port_read == NULL)) { + nxt_unit_alert(NULL, + "Python failed to initialize the 'port_read' function"); + return NXT_UNIT_ERROR; + } - nxt_py_port_read = PyCFunction_New(&nxt_py_port_read_method, NULL); - if (nxt_slow_path(nxt_py_port_read == NULL)) { - nxt_unit_alert(NULL, - "Python failed to initialize the 'port_read' function"); - return NXT_UNIT_ERROR; - } + if (nxt_slow_path(nxt_py_asgi_http_init() == NXT_UNIT_ERROR)) { + return NXT_UNIT_ERROR; + } - if (nxt_slow_path(nxt_py_asgi_http_init() == NXT_UNIT_ERROR)) { - return NXT_UNIT_ERROR; - } + if (nxt_slow_path(nxt_py_asgi_websocket_init() == NXT_UNIT_ERROR)) { + return NXT_UNIT_ERROR; + } - if (nxt_slow_path(nxt_py_asgi_websocket_init() == NXT_UNIT_ERROR)) { - return NXT_UNIT_ERROR; + for (i = 0; i < nxt_py_targets->count; i++) { + func = nxt_python_asgi_get_func(nxt_py_targets->target[i].application); + if (nxt_slow_path(func == NULL)) { + nxt_unit_debug(NULL, + "asgi: cannot find function for callable, " + "unable to check for legacy mode (#%d)", + (int)i); + continue; } - for (i = 0; i < nxt_py_targets->count; i++) { - func = nxt_python_asgi_get_func(nxt_py_targets->target[i].application); - if (nxt_slow_path(func == NULL)) { - nxt_unit_debug(NULL, "asgi: cannot find function for callable, " - "unable to check for legacy mode (#%d)", - (int) i); - continue; - } - - code = (PyCodeObject *) PyFunction_GET_CODE(func); + code = (PyCodeObject *)PyFunction_GET_CODE(func); - if ((code->co_flags & CO_COROUTINE) == 0) { - nxt_unit_debug(NULL, "asgi: callable is not a coroutine function " - "switching to legacy mode"); - nxt_py_targets->target[i].asgi_legacy = 1; - } - - Py_DECREF(func); + if ((code->co_flags & CO_COROUTINE) == 0) { + nxt_unit_debug(NULL, "asgi: callable is not a coroutine function " + "switching to legacy mode"); + nxt_py_targets->target[i].asgi_legacy = 1; } - init->callbacks.request_handler = nxt_py_asgi_request_handler; - init->callbacks.data_handler = nxt_py_asgi_http_data_handler; - init->callbacks.websocket_handler = nxt_py_asgi_websocket_handler; - init->callbacks.close_handler = nxt_py_asgi_close_handler; - init->callbacks.quit = nxt_py_asgi_quit; - init->callbacks.shm_ack_handler = nxt_py_asgi_shm_ack_handler; - init->callbacks.add_port = nxt_py_asgi_add_port; - init->callbacks.remove_port = nxt_py_asgi_remove_port; + Py_DECREF(func); + } + + init->callbacks.request_handler = nxt_py_asgi_request_handler; + init->callbacks.data_handler = nxt_py_asgi_http_data_handler; + init->callbacks.websocket_handler = nxt_py_asgi_websocket_handler; + init->callbacks.close_handler = nxt_py_asgi_close_handler; + init->callbacks.quit = nxt_py_asgi_quit; + init->callbacks.shm_ack_handler = nxt_py_asgi_shm_ack_handler; + init->callbacks.add_port = nxt_py_asgi_add_port; + init->callbacks.remove_port = nxt_py_asgi_remove_port; - *proto = nxt_py_asgi_proto; + *proto = nxt_py_asgi_proto; - return NXT_UNIT_OK; + return NXT_UNIT_OK; } +static PyObject *nxt_python_asgi_get_event_loop(PyObject *asyncio, + const char *event_loop_func) { + PyObject *event_loop, *loop; -static PyObject * -nxt_python_asgi_get_event_loop(PyObject *asyncio, const char *event_loop_func) -{ - PyObject *event_loop, *loop; - - event_loop = PyDict_GetItemString(PyModule_GetDict(asyncio), - event_loop_func); - if (nxt_slow_path(event_loop == NULL)) { - nxt_unit_alert(NULL, "Python failed to get '%s' from module 'asyncio'", - event_loop_func); - return NULL; - } - - if (nxt_slow_path(PyCallable_Check(event_loop) == 0)) { - nxt_unit_alert(NULL, "'asyncio.%s' is not a callable object", - event_loop_func); - return NULL; - } + event_loop = PyDict_GetItemString(PyModule_GetDict(asyncio), event_loop_func); + if (nxt_slow_path(event_loop == NULL)) { + nxt_unit_alert(NULL, "Python failed to get '%s' from module 'asyncio'", + event_loop_func); + return NULL; + } - loop = PyObject_CallObject(event_loop, NULL); - if (nxt_slow_path(loop == NULL)) { - if (strcmp(event_loop_func, "get_running_loop") != 0) { - nxt_unit_alert(NULL, "Python failed to call 'asyncio.%s'", - event_loop_func); - } + if (nxt_slow_path(PyCallable_Check(event_loop) == 0)) { + nxt_unit_alert(NULL, "'asyncio.%s' is not a callable object", + event_loop_func); + return NULL; + } - return NULL; + loop = PyObject_CallObject(event_loop, NULL); + if (nxt_slow_path(loop == NULL)) { + if (strcmp(event_loop_func, "get_running_loop") != 0) { + nxt_unit_alert(NULL, "Python failed to call 'asyncio.%s'", + event_loop_func); } - return loop; -} + return NULL; + } + return loop; +} -static int -nxt_python_asgi_ctx_data_alloc(void **pdata, int main) -{ - uint32_t i; - PyObject *asyncio, *loop, *obj; - const char *event_loop_func; - nxt_py_asgi_ctx_data_t *ctx_data; +static int nxt_python_asgi_ctx_data_alloc(void **pdata, int main) { + uint32_t i; + PyObject *asyncio, *loop, *obj; + const char *event_loop_func; + nxt_py_asgi_ctx_data_t *ctx_data; #if PY_VERSION_HEX < NXT_PYTHON_VER(3, 7) - static const char *main_event_loop_func = "get_event_loop"; + static const char *main_event_loop_func = "get_event_loop"; #else - static const char *main_event_loop_func = "get_running_loop"; + static const char *main_event_loop_func = "get_running_loop"; #endif - ctx_data = nxt_unit_malloc(NULL, sizeof(nxt_py_asgi_ctx_data_t)); - if (nxt_slow_path(ctx_data == NULL)) { - nxt_unit_alert(NULL, "Failed to allocate context data"); - return NXT_UNIT_ERROR; - } + ctx_data = nxt_unit_malloc(NULL, sizeof(nxt_py_asgi_ctx_data_t)); + if (nxt_slow_path(ctx_data == NULL)) { + nxt_unit_alert(NULL, "Failed to allocate context data"); + return NXT_UNIT_ERROR; + } - memset(ctx_data, 0, sizeof(nxt_py_asgi_ctx_data_t)); + memset(ctx_data, 0, sizeof(nxt_py_asgi_ctx_data_t)); - nxt_queue_init(&ctx_data->drain_queue); + nxt_queue_init(&ctx_data->drain_queue); - struct { - const char *key; - PyObject **handler; + struct { + const char *key; + PyObject **handler; - } handlers[] = { - { "create_task", &ctx_data->loop_create_task }, - { "add_reader", &ctx_data->loop_add_reader }, - { "remove_reader", &ctx_data->loop_remove_reader }, - { "call_soon", &ctx_data->loop_call_soon }, - { "run_until_complete", &ctx_data->loop_run_until_complete }, - { "create_future", &ctx_data->loop_create_future }, - }; + } handlers[] = { + {"create_task", &ctx_data->loop_create_task}, + {"add_reader", &ctx_data->loop_add_reader}, + {"remove_reader", &ctx_data->loop_remove_reader}, + {"call_soon", &ctx_data->loop_call_soon}, + {"run_until_complete", &ctx_data->loop_run_until_complete}, + {"create_future", &ctx_data->loop_create_future}, + }; - loop = NULL; + loop = NULL; - asyncio = PyImport_ImportModule("asyncio"); - if (nxt_slow_path(asyncio == NULL)) { - nxt_unit_alert(NULL, "Python failed to import module 'asyncio'"); - nxt_python_print_exception(); - goto fail; - } + asyncio = PyImport_ImportModule("asyncio"); + if (nxt_slow_path(asyncio == NULL)) { + nxt_unit_alert(NULL, "Python failed to import module 'asyncio'"); + nxt_python_print_exception(); + goto fail; + } - event_loop_func = main ? main_event_loop_func : "new_event_loop"; + event_loop_func = main ? main_event_loop_func : "new_event_loop"; - loop = nxt_python_asgi_get_event_loop(asyncio, event_loop_func); - if (loop == NULL) { + loop = nxt_python_asgi_get_event_loop(asyncio, event_loop_func); + if (loop == NULL) { #if PY_VERSION_HEX < NXT_PYTHON_VER(3, 7) - goto fail; + goto fail; #else - if (!main) { - goto fail; - } - - PyErr_Clear(); - - loop = nxt_python_asgi_get_event_loop(asyncio, "new_event_loop"); - if (nxt_slow_path(loop == NULL)) { - goto fail; - } -#endif + if (!main) { + goto fail; } - for (i = 0; i < nxt_nitems(handlers); i++) { - obj = PyObject_GetAttrString(loop, handlers[i].key); - if (nxt_slow_path(obj == NULL)) { - nxt_unit_alert(NULL, "Python failed to get 'loop.%s'", - handlers[i].key); - goto fail; - } - - *handlers[i].handler = obj; - - if (nxt_slow_path(PyCallable_Check(obj) == 0)) { - nxt_unit_alert(NULL, "'loop.%s' is not a callable object", - handlers[i].key); - goto fail; - } - } + PyErr_Clear(); - obj = PyObject_CallObject(ctx_data->loop_create_future, NULL); - if (nxt_slow_path(obj == NULL)) { - nxt_unit_alert(NULL, "Python failed to create Future "); - nxt_python_print_exception(); - goto fail; + loop = nxt_python_asgi_get_event_loop(asyncio, "new_event_loop"); + if (nxt_slow_path(loop == NULL)) { + goto fail; } +#endif + } - ctx_data->quit_future = obj; - - obj = PyObject_GetAttrString(ctx_data->quit_future, "set_result"); + for (i = 0; i < nxt_nitems(handlers); i++) { + obj = PyObject_GetAttrString(loop, handlers[i].key); if (nxt_slow_path(obj == NULL)) { - nxt_unit_alert(NULL, "Python failed to get 'future.set_result'"); - goto fail; + nxt_unit_alert(NULL, "Python failed to get 'loop.%s'", handlers[i].key); + goto fail; } - ctx_data->quit_future_set_result = obj; + *handlers[i].handler = obj; if (nxt_slow_path(PyCallable_Check(obj) == 0)) { - nxt_unit_alert(NULL, "'future.set_result' is not a callable object"); - goto fail; + nxt_unit_alert(NULL, "'loop.%s' is not a callable object", + handlers[i].key); + goto fail; } + } - Py_DECREF(loop); - Py_DECREF(asyncio); - - *pdata = ctx_data; + obj = PyObject_CallObject(ctx_data->loop_create_future, NULL); + if (nxt_slow_path(obj == NULL)) { + nxt_unit_alert(NULL, "Python failed to create Future "); + nxt_python_print_exception(); + goto fail; + } - return NXT_UNIT_OK; - -fail: + ctx_data->quit_future = obj; - nxt_python_asgi_ctx_data_free(ctx_data); + obj = PyObject_GetAttrString(ctx_data->quit_future, "set_result"); + if (nxt_slow_path(obj == NULL)) { + nxt_unit_alert(NULL, "Python failed to get 'future.set_result'"); + goto fail; + } - Py_XDECREF(loop); - Py_XDECREF(asyncio); + ctx_data->quit_future_set_result = obj; - return NXT_UNIT_ERROR; -} + if (nxt_slow_path(PyCallable_Check(obj) == 0)) { + nxt_unit_alert(NULL, "'future.set_result' is not a callable object"); + goto fail; + } + Py_DECREF(loop); + Py_DECREF(asyncio); -static void -nxt_python_asgi_ctx_data_free(void *data) -{ - nxt_py_asgi_ctx_data_t *ctx_data; + *pdata = ctx_data; - ctx_data = data; + return NXT_UNIT_OK; - Py_XDECREF(ctx_data->loop_run_until_complete); - Py_XDECREF(ctx_data->loop_create_future); - Py_XDECREF(ctx_data->loop_create_task); - Py_XDECREF(ctx_data->loop_call_soon); - Py_XDECREF(ctx_data->loop_add_reader); - Py_XDECREF(ctx_data->loop_remove_reader); - Py_XDECREF(ctx_data->quit_future); - Py_XDECREF(ctx_data->quit_future_set_result); +fail: - nxt_unit_free(NULL, ctx_data); -} + nxt_python_asgi_ctx_data_free(ctx_data); + Py_XDECREF(loop); + Py_XDECREF(asyncio); -static int -nxt_python_asgi_startup(void *data) -{ - return nxt_py_asgi_lifespan_startup(data); + return NXT_UNIT_ERROR; } +static void nxt_python_asgi_ctx_data_free(void *data) { + nxt_py_asgi_ctx_data_t *ctx_data; -static int -nxt_python_asgi_run(nxt_unit_ctx_t *ctx) -{ - PyObject *res; - nxt_py_asgi_ctx_data_t *ctx_data; - - ctx_data = ctx->data; - - res = PyObject_CallFunctionObjArgs(ctx_data->loop_run_until_complete, - ctx_data->quit_future, NULL); - if (nxt_slow_path(res == NULL)) { - nxt_unit_alert(ctx, "Python failed to call loop.run_until_complete"); - nxt_python_print_exception(); - - return NXT_UNIT_ERROR; - } - - Py_DECREF(res); + ctx_data = data; - nxt_py_asgi_lifespan_shutdown(ctx); + Py_XDECREF(ctx_data->loop_run_until_complete); + Py_XDECREF(ctx_data->loop_create_future); + Py_XDECREF(ctx_data->loop_create_task); + Py_XDECREF(ctx_data->loop_call_soon); + Py_XDECREF(ctx_data->loop_add_reader); + Py_XDECREF(ctx_data->loop_remove_reader); + Py_XDECREF(ctx_data->quit_future); + Py_XDECREF(ctx_data->quit_future_set_result); - return NXT_UNIT_OK; + nxt_unit_free(NULL, ctx_data); } +static int nxt_python_asgi_startup(void *data) { + return nxt_py_asgi_lifespan_startup(data); +} -static void -nxt_py_asgi_remove_reader(nxt_unit_ctx_t *ctx, nxt_unit_port_t *port) -{ - PyObject *res, *fd; - nxt_py_asgi_ctx_data_t *ctx_data; +static int nxt_python_asgi_run(nxt_unit_ctx_t *ctx) { + PyObject *res; + nxt_py_asgi_ctx_data_t *ctx_data; - if (port == NULL || port->in_fd == -1) { - return; - } - - ctx_data = ctx->data; + ctx_data = ctx->data; - nxt_unit_debug(ctx, "asgi_remove_reader %d %p", port->in_fd, port); + res = PyObject_CallFunctionObjArgs(ctx_data->loop_run_until_complete, + ctx_data->quit_future, NULL); + if (nxt_slow_path(res == NULL)) { + nxt_unit_alert(ctx, "Python failed to call loop.run_until_complete"); + nxt_python_print_exception(); - fd = PyLong_FromLong(port->in_fd); - if (nxt_slow_path(fd == NULL)) { - nxt_unit_alert(ctx, "Python failed to create Long object"); - nxt_python_print_exception(); + return NXT_UNIT_ERROR; + } - return; - } + Py_DECREF(res); - res = PyObject_CallFunctionObjArgs(ctx_data->loop_remove_reader, fd, NULL); - if (nxt_slow_path(res == NULL)) { - nxt_unit_alert(ctx, "Python failed to remove_reader"); - nxt_python_print_exception(); - - } else { - Py_DECREF(res); - } + nxt_py_asgi_lifespan_shutdown(ctx); - Py_DECREF(fd); + return NXT_UNIT_OK; } +static void nxt_py_asgi_remove_reader(nxt_unit_ctx_t *ctx, + nxt_unit_port_t *port) { + PyObject *res, *fd; + nxt_py_asgi_ctx_data_t *ctx_data; -static void -nxt_py_asgi_request_handler(nxt_unit_request_info_t *req) -{ - PyObject *scope, *res, *task, *receive, *send, *done, *asgi; - PyObject *state, *newstate, *lifespan; - PyObject *stage2; - nxt_python_target_t *target; - nxt_py_asgi_ctx_data_t *ctx_data; - - if (req->request->websocket_handshake) { - asgi = nxt_py_asgi_websocket_create(req); - - } else { - asgi = nxt_py_asgi_http_create(req); - } - - if (nxt_slow_path(asgi == NULL)) { - nxt_unit_req_alert(req, "Python failed to create asgi object"); - nxt_unit_request_done(req, NXT_UNIT_ERROR); - - return; - } - - receive = PyObject_GetAttrString(asgi, "receive"); - if (nxt_slow_path(receive == NULL)) { - nxt_unit_req_alert(req, "Python failed to get 'receive' method"); - nxt_unit_request_done(req, NXT_UNIT_ERROR); + if (port == NULL || port->in_fd == -1) { + return; + } - goto release_asgi; - } + ctx_data = ctx->data; - send = PyObject_GetAttrString(asgi, "send"); - if (nxt_slow_path(send == NULL)) { - nxt_unit_req_alert(req, "Python failed to get 'send' method"); - nxt_unit_request_done(req, NXT_UNIT_ERROR); + nxt_unit_debug(ctx, "asgi_remove_reader %d %p", port->in_fd, port); - goto release_receive; - } + fd = PyLong_FromLong(port->in_fd); + if (nxt_slow_path(fd == NULL)) { + nxt_unit_alert(ctx, "Python failed to create Long object"); + nxt_python_print_exception(); - done = PyObject_GetAttrString(asgi, "_done"); - if (nxt_slow_path(done == NULL)) { - nxt_unit_req_alert(req, "Python failed to get '_done' method"); - nxt_unit_request_done(req, NXT_UNIT_ERROR); + return; + } - goto release_send; - } + res = PyObject_CallFunctionObjArgs(ctx_data->loop_remove_reader, fd, NULL); + if (nxt_slow_path(res == NULL)) { + nxt_unit_alert(ctx, "Python failed to remove_reader"); + nxt_python_print_exception(); - req->data = asgi; - ctx_data = req->ctx->data; - target = &nxt_py_targets->target[req->request->app_target]; - lifespan = ctx_data->target_lifespans[req->request->app_target]; - state = PyObject_GetAttr(lifespan, nxt_py_state_str); - if (nxt_slow_path(state == NULL)) { - nxt_unit_req_alert(req, "Python failed to get 'state' attribute"); - nxt_unit_request_done(req, NXT_UNIT_ERROR); + } else { + Py_DECREF(res); + } - goto release_done; - } + Py_DECREF(fd); +} - newstate = PyDict_Copy(state); - if (nxt_slow_path(newstate == NULL)) { - nxt_unit_req_alert(req, "Python failed to call state.copy()"); - nxt_unit_request_done(req, NXT_UNIT_ERROR); - Py_DECREF(state); - goto release_done; - } +static void nxt_py_asgi_request_handler(nxt_unit_request_info_t *req) { + PyObject *scope, *res, *task, *receive, *send, *done, *asgi; + PyObject *state, *newstate, *lifespan; + PyObject *stage2; + nxt_python_target_t *target; + nxt_py_asgi_ctx_data_t *ctx_data; + + if (req->request->websocket_handshake) { + asgi = nxt_py_asgi_websocket_create(req); + + } else { + asgi = nxt_py_asgi_http_create(req); + } + + if (nxt_slow_path(asgi == NULL)) { + nxt_unit_req_alert(req, "Python failed to create asgi object"); + nxt_unit_request_done(req, NXT_UNIT_ERROR); + + return; + } + + receive = PyObject_GetAttrString(asgi, "receive"); + if (nxt_slow_path(receive == NULL)) { + nxt_unit_req_alert(req, "Python failed to get 'receive' method"); + nxt_unit_request_done(req, NXT_UNIT_ERROR); + + goto release_asgi; + } + + send = PyObject_GetAttrString(asgi, "send"); + if (nxt_slow_path(send == NULL)) { + nxt_unit_req_alert(req, "Python failed to get 'send' method"); + nxt_unit_request_done(req, NXT_UNIT_ERROR); + + goto release_receive; + } + + done = PyObject_GetAttrString(asgi, "_done"); + if (nxt_slow_path(done == NULL)) { + nxt_unit_req_alert(req, "Python failed to get '_done' method"); + nxt_unit_request_done(req, NXT_UNIT_ERROR); + + goto release_send; + } + + req->data = asgi; + ctx_data = req->ctx->data; + target = &nxt_py_targets->target[req->request->app_target]; + lifespan = ctx_data->target_lifespans[req->request->app_target]; + state = PyObject_GetAttr(lifespan, nxt_py_state_str); + if (nxt_slow_path(state == NULL)) { + nxt_unit_req_alert(req, "Python failed to get 'state' attribute"); + nxt_unit_request_done(req, NXT_UNIT_ERROR); + + goto release_done; + } + + newstate = PyDict_Copy(state); + if (nxt_slow_path(newstate == NULL)) { + nxt_unit_req_alert(req, "Python failed to call state.copy()"); + nxt_unit_request_done(req, NXT_UNIT_ERROR); Py_DECREF(state); + goto release_done; + } + Py_DECREF(state); - scope = nxt_py_asgi_create_http_scope(req, target); - if (nxt_slow_path(scope == NULL)) { - nxt_unit_request_done(req, NXT_UNIT_ERROR); - Py_DECREF(newstate); - goto release_done; - } - - if (nxt_slow_path(PyDict_SetItem(scope, nxt_py_state_str, newstate) - == -1)) - { - Py_DECREF(newstate); - goto release_scope; - } + scope = nxt_py_asgi_create_http_scope(req, target); + if (nxt_slow_path(scope == NULL)) { + nxt_unit_request_done(req, NXT_UNIT_ERROR); Py_DECREF(newstate); + goto release_done; + } - if (!target->asgi_legacy) { - nxt_unit_req_debug(req, "Python call ASGI 3.0 application"); - - res = PyObject_CallFunctionObjArgs(target->application, - scope, receive, send, NULL); - - } else { - nxt_unit_req_debug(req, "Python call legacy application"); + if (nxt_slow_path(PyDict_SetItem(scope, nxt_py_state_str, newstate) == -1)) { + Py_DECREF(newstate); + goto release_scope; + } + Py_DECREF(newstate); - res = PyObject_CallFunctionObjArgs(target->application, scope, NULL); + if (!target->asgi_legacy) { + nxt_unit_req_debug(req, "Python call ASGI 3.0 application"); - if (nxt_slow_path(res == NULL)) { - nxt_unit_req_error(req, "Python failed to call legacy app stage1"); - nxt_python_print_exception(); - nxt_unit_request_done(req, NXT_UNIT_ERROR); + res = PyObject_CallFunctionObjArgs(target->application, scope, receive, + send, NULL); - goto release_scope; - } + } else { + nxt_unit_req_debug(req, "Python call legacy application"); - if (nxt_slow_path(PyCallable_Check(res) == 0)) { - nxt_unit_req_error(req, - "Legacy ASGI application returns not a callable"); - nxt_unit_request_done(req, NXT_UNIT_ERROR); + res = PyObject_CallFunctionObjArgs(target->application, scope, NULL); - Py_DECREF(res); + if (nxt_slow_path(res == NULL)) { + nxt_unit_req_error(req, "Python failed to call legacy app stage1"); + nxt_python_print_exception(); + nxt_unit_request_done(req, NXT_UNIT_ERROR); - goto release_scope; - } + goto release_scope; + } - stage2 = res; + if (nxt_slow_path(PyCallable_Check(res) == 0)) { + nxt_unit_req_error(req, "Legacy ASGI application returns not a callable"); + nxt_unit_request_done(req, NXT_UNIT_ERROR); - res = PyObject_CallFunctionObjArgs(stage2, receive, send, NULL); + Py_DECREF(res); - Py_DECREF(stage2); + goto release_scope; } - if (nxt_slow_path(res == NULL)) { - nxt_unit_req_error(req, "Python failed to call the application"); - nxt_python_print_exception(); - nxt_unit_request_done(req, NXT_UNIT_ERROR); + stage2 = res; - goto release_scope; - } + res = PyObject_CallFunctionObjArgs(stage2, receive, send, NULL); - if (nxt_slow_path(!PyCoro_CheckExact(res))) { - nxt_unit_req_error(req, "Application result type is not a coroutine"); - nxt_unit_request_done(req, NXT_UNIT_ERROR); + Py_DECREF(stage2); + } - Py_DECREF(res); + if (nxt_slow_path(res == NULL)) { + nxt_unit_req_error(req, "Python failed to call the application"); + nxt_python_print_exception(); + nxt_unit_request_done(req, NXT_UNIT_ERROR); - goto release_scope; - } + goto release_scope; + } + if (nxt_slow_path(!PyCoro_CheckExact(res))) { + nxt_unit_req_error(req, "Application result type is not a coroutine"); + nxt_unit_request_done(req, NXT_UNIT_ERROR); - task = PyObject_CallFunctionObjArgs(ctx_data->loop_create_task, res, NULL); - if (nxt_slow_path(task == NULL)) { - nxt_unit_req_error(req, "Python failed to call the create_task"); - nxt_python_print_exception(); - nxt_unit_request_done(req, NXT_UNIT_ERROR); + Py_DECREF(res); - Py_DECREF(res); + goto release_scope; + } - goto release_scope; - } + task = PyObject_CallFunctionObjArgs(ctx_data->loop_create_task, res, NULL); + if (nxt_slow_path(task == NULL)) { + nxt_unit_req_error(req, "Python failed to call the create_task"); + nxt_python_print_exception(); + nxt_unit_request_done(req, NXT_UNIT_ERROR); Py_DECREF(res); - res = PyObject_CallMethodObjArgs(task, nxt_py_add_done_callback_str, done, - NULL); - if (nxt_slow_path(res == NULL)) { - nxt_unit_req_error(req, - "Python failed to call 'task.add_done_callback'"); - nxt_python_print_exception(); - nxt_unit_request_done(req, NXT_UNIT_ERROR); + goto release_scope; + } - goto release_task; - } + Py_DECREF(res); - Py_DECREF(res); + res = PyObject_CallMethodObjArgs(task, nxt_py_add_done_callback_str, done, + NULL); + if (nxt_slow_path(res == NULL)) { + nxt_unit_req_error(req, "Python failed to call 'task.add_done_callback'"); + nxt_python_print_exception(); + nxt_unit_request_done(req, NXT_UNIT_ERROR); + + goto release_task; + } + + Py_DECREF(res); release_task: - Py_DECREF(task); + Py_DECREF(task); release_scope: - Py_DECREF(scope); + Py_DECREF(scope); release_done: - Py_DECREF(done); + Py_DECREF(done); release_send: - Py_DECREF(send); + Py_DECREF(send); release_receive: - Py_DECREF(receive); + Py_DECREF(receive); release_asgi: - Py_DECREF(asgi); + Py_DECREF(asgi); } +static void nxt_py_asgi_close_handler(nxt_unit_request_info_t *req) { + if (req->request->websocket_handshake) { + nxt_py_asgi_websocket_close_handler(req); -static void -nxt_py_asgi_close_handler(nxt_unit_request_info_t *req) -{ - if (req->request->websocket_handshake) { - nxt_py_asgi_websocket_close_handler(req); - - } else { - nxt_py_asgi_http_close_handler(req); - } + } else { + nxt_py_asgi_http_close_handler(req); + } } - static PyObject * nxt_py_asgi_create_http_scope(nxt_unit_request_info_t *req, - nxt_python_target_t *app_target) -{ - char *p, *target, *query; - uint32_t target_length, i, path_length; - PyObject *scope, *v, *type, *scheme; - PyObject *headers, *header; - nxt_str_t prefix; - nxt_unit_field_t *f; - nxt_unit_request_t *r; - - static const nxt_str_t ws_protocol = nxt_string("sec-websocket-protocol"); - -#define SET_ITEM(dict, key, value) \ - if (nxt_slow_path(PyDict_SetItem(dict, nxt_py_ ## key ## _str, value) \ - == -1)) \ - { \ - nxt_unit_req_alert(req, "Python failed to set '" \ - #dict "." #key "' item"); \ - goto fail; \ + nxt_python_target_t *app_target) { + char *p, *target, *query; + uint32_t target_length, i, path_length; + PyObject *scope, *v, *type, *scheme; + PyObject *headers, *header; + nxt_str_t prefix; + nxt_unit_field_t *f; + nxt_unit_request_t *r; + + static const nxt_str_t ws_protocol = nxt_string("sec-websocket-protocol"); + +#define SET_ITEM(dict, key, value) \ + if (nxt_slow_path(PyDict_SetItem(dict, nxt_py_##key##_str, value) == -1)) { \ + nxt_unit_req_alert(req, "Python failed to set '" #dict "." #key "' item"); \ + goto fail; \ + } + + v = NULL; + headers = NULL; + + r = req->request; + + if (r->websocket_handshake) { + type = nxt_py_websocket_str; + scheme = r->tls ? nxt_py_wss_str : nxt_py_ws_str; + + } else { + type = nxt_py_http_str; + scheme = r->tls ? nxt_py_https_str : nxt_py_http_str; + } + + scope = nxt_py_asgi_new_scope(req, type, nxt_py_2_1_str); + if (nxt_slow_path(scope == NULL)) { + return NULL; + } + + prefix = app_target->prefix; + path_length = r->path_length; + p = nxt_unit_sptr_get(&r->path); + if (prefix.length > 0 && + ((path_length > prefix.length && p[prefix.length] == '/') || + path_length == prefix.length) && + memcmp(prefix.start, p, prefix.length) == 0) { + SET_ITEM(scope, root_path, app_target->py_prefix); + } + + p = nxt_unit_sptr_get(&r->version); + SET_ITEM(scope, http_version, p[7] == '1' ? nxt_py_1_1_str : nxt_py_1_0_str) + SET_ITEM(scope, scheme, scheme) + + v = PyString_FromStringAndSize(nxt_unit_sptr_get(&r->method), + r->method_length); + if (nxt_slow_path(v == NULL)) { + nxt_unit_req_alert(req, "Python failed to create 'method' string"); + goto fail; + } + + SET_ITEM(scope, method, v) + Py_DECREF(v); + + v = PyUnicode_DecodeUTF8(nxt_unit_sptr_get(&r->path), r->path_length, + "replace"); + if (nxt_slow_path(v == NULL)) { + nxt_unit_req_alert(req, "Python failed to create 'path' string"); + goto fail; + } + + SET_ITEM(scope, path, v) + Py_DECREF(v); + + target = nxt_unit_sptr_get(&r->target); + query = nxt_unit_sptr_get(&r->query); + + if (r->query.offset != 0) { + target_length = query - target - 1; + + } else { + target_length = r->target_length; + } + + v = PyBytes_FromStringAndSize(target, target_length); + if (nxt_slow_path(v == NULL)) { + nxt_unit_req_alert(req, "Python failed to create 'raw_path' string"); + goto fail; + } + + SET_ITEM(scope, raw_path, v) + Py_DECREF(v); + + v = PyBytes_FromStringAndSize(query, r->query_length); + if (nxt_slow_path(v == NULL)) { + nxt_unit_req_alert(req, "Python failed to create 'query' string"); + goto fail; + } + + SET_ITEM(scope, query_string, v) + Py_DECREF(v); + + v = nxt_py_asgi_create_address(&r->remote, r->remote_length, 0); + if (nxt_slow_path(v == NULL)) { + nxt_unit_req_alert(req, "Python failed to create 'client' pair"); + goto fail; + } + + SET_ITEM(scope, client, v) + Py_DECREF(v); + + v = nxt_py_asgi_create_address(&r->local_addr, r->local_addr_length, 80); + if (nxt_slow_path(v == NULL)) { + nxt_unit_req_alert(req, "Python failed to create 'server' pair"); + goto fail; + } + + SET_ITEM(scope, server, v) + Py_DECREF(v); + + v = NULL; + + headers = PyTuple_New(r->fields_count); + if (nxt_slow_path(headers == NULL)) { + nxt_unit_req_alert(req, "Python failed to create 'headers' object"); + goto fail; + } + + for (i = 0; i < r->fields_count; i++) { + f = r->fields + i; + + header = nxt_py_asgi_create_header(f); + if (nxt_slow_path(header == NULL)) { + nxt_unit_req_alert(req, "Python failed to create 'header' pair"); + goto fail; } - v = NULL; - headers = NULL; - - r = req->request; + PyTuple_SET_ITEM(headers, i, header); - if (r->websocket_handshake) { - type = nxt_py_websocket_str; - scheme = r->tls ? nxt_py_wss_str : nxt_py_ws_str; + if (f->hash == NXT_UNIT_HASH_WS_PROTOCOL && + f->name_length == ws_protocol.length && f->value_length > 0 && + r->websocket_handshake) { + v = nxt_py_asgi_create_subprotocols(f); + if (nxt_slow_path(v == NULL)) { + nxt_unit_req_alert(req, "Failed to create subprotocols"); + goto fail; + } - } else { - type = nxt_py_http_str; - scheme = r->tls ? nxt_py_https_str : nxt_py_http_str; + SET_ITEM(scope, subprotocols, v); + Py_DECREF(v); } + } - scope = nxt_py_asgi_new_scope(req, type, nxt_py_2_1_str); - if (nxt_slow_path(scope == NULL)) { - return NULL; - } + SET_ITEM(scope, headers, headers) + Py_DECREF(headers); - prefix = app_target->prefix; - path_length = r->path_length; - p = nxt_unit_sptr_get(&r->path); - if (prefix.length > 0 - && ((path_length > prefix.length && p[prefix.length] == '/') - || path_length == prefix.length) - && memcmp(prefix.start, p, prefix.length) == 0) - { - SET_ITEM(scope, root_path, app_target->py_prefix); - } + return scope; - p = nxt_unit_sptr_get(&r->version); - SET_ITEM(scope, http_version, p[7] == '1' ? nxt_py_1_1_str - : nxt_py_1_0_str) - SET_ITEM(scope, scheme, scheme) +fail: - v = PyString_FromStringAndSize(nxt_unit_sptr_get(&r->method), - r->method_length); - if (nxt_slow_path(v == NULL)) { - nxt_unit_req_alert(req, "Python failed to create 'method' string"); - goto fail; - } + Py_XDECREF(v); + Py_XDECREF(headers); + Py_DECREF(scope); - SET_ITEM(scope, method, v) - Py_DECREF(v); + return NULL; - v = PyUnicode_DecodeUTF8(nxt_unit_sptr_get(&r->path), r->path_length, - "replace"); - if (nxt_slow_path(v == NULL)) { - nxt_unit_req_alert(req, "Python failed to create 'path' string"); - goto fail; - } - - SET_ITEM(scope, path, v) - Py_DECREF(v); +#undef SET_ITEM +} - target = nxt_unit_sptr_get(&r->target); - query = nxt_unit_sptr_get(&r->query); +static PyObject *nxt_py_asgi_create_address(nxt_unit_sptr_t *sptr, uint8_t len, + uint16_t port) { +#if (NXT_HAVE_UNIX_DOMAIN) + size_t prefix_len; + PyObject *pair, *v; + nxt_str_t addr; - if (r->query.offset != 0) { - target_length = query - target - 1; + addr.length = len; + addr.start = nxt_unit_sptr_get(sptr); - } else { - target_length = r->target_length; - } + prefix_len = nxt_length("unix:"); + if (nxt_str_start(&addr, "unix:", prefix_len)) { - v = PyBytes_FromStringAndSize(target, target_length); - if (nxt_slow_path(v == NULL)) { - nxt_unit_req_alert(req, "Python failed to create 'raw_path' string"); - goto fail; + pair = PyTuple_New(2); + if (nxt_slow_path(pair == NULL)) { + return NULL; } - SET_ITEM(scope, raw_path, v) - Py_DECREF(v); + addr.start += prefix_len; + addr.length -= prefix_len; - v = PyBytes_FromStringAndSize(query, r->query_length); + v = PyString_FromStringAndSize((const char *)addr.start, addr.length); if (nxt_slow_path(v == NULL)) { - nxt_unit_req_alert(req, "Python failed to create 'query' string"); - goto fail; - } - - SET_ITEM(scope, query_string, v) - Py_DECREF(v); + Py_DECREF(pair); - v = nxt_py_asgi_create_address(&r->remote, r->remote_length, 0); - if (nxt_slow_path(v == NULL)) { - nxt_unit_req_alert(req, "Python failed to create 'client' pair"); - goto fail; + return NULL; } - SET_ITEM(scope, client, v) - Py_DECREF(v); + PyTuple_SET_ITEM(pair, 0, v); + PyTuple_SET_ITEM(pair, 1, Py_None); - v = nxt_py_asgi_create_address(&r->local_addr, r->local_addr_length, 80); - if (nxt_slow_path(v == NULL)) { - nxt_unit_req_alert(req, "Python failed to create 'server' pair"); - goto fail; - } + return pair; + } - SET_ITEM(scope, server, v) - Py_DECREF(v); +#endif + return nxt_py_asgi_create_ip_address(sptr, len, port); +} - v = NULL; +static PyObject *nxt_py_asgi_create_ip_address(nxt_unit_sptr_t *sptr, + uint8_t len, uint16_t port) { + char *p; + PyObject *pair, *v; - headers = PyTuple_New(r->fields_count); - if (nxt_slow_path(headers == NULL)) { - nxt_unit_req_alert(req, "Python failed to create 'headers' object"); - goto fail; - } + pair = PyTuple_New(2); + if (nxt_slow_path(pair == NULL)) { + return NULL; + } - for (i = 0; i < r->fields_count; i++) { - f = r->fields + i; - - header = nxt_py_asgi_create_header(f); - if (nxt_slow_path(header == NULL)) { - nxt_unit_req_alert(req, "Python failed to create 'header' pair"); - goto fail; - } - - PyTuple_SET_ITEM(headers, i, header); - - if (f->hash == NXT_UNIT_HASH_WS_PROTOCOL - && f->name_length == ws_protocol.length - && f->value_length > 0 - && r->websocket_handshake) - { - v = nxt_py_asgi_create_subprotocols(f); - if (nxt_slow_path(v == NULL)) { - nxt_unit_req_alert(req, "Failed to create subprotocols"); - goto fail; - } - - SET_ITEM(scope, subprotocols, v); - Py_DECREF(v); - } - } + p = nxt_unit_sptr_get(sptr); - SET_ITEM(scope, headers, headers) - Py_DECREF(headers); + v = PyString_FromStringAndSize(p, len); + if (nxt_slow_path(v == NULL)) { + Py_DECREF(pair); - return scope; + return NULL; + } -fail: + PyTuple_SET_ITEM(pair, 0, v); - Py_XDECREF(v); - Py_XDECREF(headers); - Py_DECREF(scope); + v = PyLong_FromLong(port); + if (nxt_slow_path(v == NULL)) { + Py_DECREF(pair); return NULL; + } -#undef SET_ITEM + PyTuple_SET_ITEM(pair, 1, v); + + return pair; } +static PyObject *nxt_py_asgi_create_header(nxt_unit_field_t *f) { + char c, *name; + uint8_t pos; + PyObject *header, *v; -static PyObject * -nxt_py_asgi_create_address(nxt_unit_sptr_t *sptr, uint8_t len, uint16_t port) -{ -#if (NXT_HAVE_UNIX_DOMAIN) - size_t prefix_len; - PyObject *pair, *v; - nxt_str_t addr; + header = PyTuple_New(2); + if (nxt_slow_path(header == NULL)) { + return NULL; + } - addr.length = len; - addr.start = nxt_unit_sptr_get(sptr); + name = nxt_unit_sptr_get(&f->name); - prefix_len = nxt_length("unix:"); - if (nxt_str_start(&addr, "unix:", prefix_len)) { + for (pos = 0; pos < f->name_length; pos++) { + c = name[pos]; + if (c >= 'A' && c <= 'Z') { + name[pos] = (c | 0x20); + } + } - pair = PyTuple_New(2); - if (nxt_slow_path(pair == NULL)) { - return NULL; - } + v = PyBytes_FromStringAndSize(name, f->name_length); + if (nxt_slow_path(v == NULL)) { + Py_DECREF(header); - addr.start += prefix_len; - addr.length -= prefix_len; + return NULL; + } - v = PyString_FromStringAndSize((const char *) addr.start, addr.length); - if (nxt_slow_path(v == NULL)) { - Py_DECREF(pair); + PyTuple_SET_ITEM(header, 0, v); - return NULL; - } + v = PyBytes_FromStringAndSize(nxt_unit_sptr_get(&f->value), f->value_length); + if (nxt_slow_path(v == NULL)) { + Py_DECREF(header); - PyTuple_SET_ITEM(pair, 0, v); - PyTuple_SET_ITEM(pair, 1, Py_None); + return NULL; + } - return pair; - } + PyTuple_SET_ITEM(header, 1, v); -#endif - return nxt_py_asgi_create_ip_address(sptr, len, port); + return header; } +static PyObject *nxt_py_asgi_create_subprotocols(nxt_unit_field_t *f) { + char *v; + uint32_t i, n, start; + PyObject *res, *proto; -static PyObject * -nxt_py_asgi_create_ip_address(nxt_unit_sptr_t *sptr, uint8_t len, uint16_t port) -{ - char *p; - PyObject *pair, *v; + v = nxt_unit_sptr_get(&f->value); + n = 1; - pair = PyTuple_New(2); - if (nxt_slow_path(pair == NULL)) { - return NULL; + for (i = 0; i < f->value_length; i++) { + if (v[i] == ',') { + n++; } + } - p = nxt_unit_sptr_get(sptr); - - v = PyString_FromStringAndSize(p, len); - if (nxt_slow_path(v == NULL)) { - Py_DECREF(pair); - - return NULL; - } + res = PyTuple_New(n); + if (nxt_slow_path(res == NULL)) { + return NULL; + } - PyTuple_SET_ITEM(pair, 0, v); + n = 0; + start = 0; - v = PyLong_FromLong(port); - if (nxt_slow_path(v == NULL)) { - Py_DECREF(pair); + for (i = 0; i < f->value_length;) { + if (v[i] != ',') { + i++; - return NULL; + continue; } - PyTuple_SET_ITEM(pair, 1, v); - - return pair; -} - + if (i - start > 0) { + proto = PyString_FromStringAndSize(v + start, i - start); + if (nxt_slow_path(proto == NULL)) { + goto fail; + } -static PyObject * -nxt_py_asgi_create_header(nxt_unit_field_t *f) -{ - char c, *name; - uint8_t pos; - PyObject *header, *v; + PyTuple_SET_ITEM(res, n, proto); - header = PyTuple_New(2); - if (nxt_slow_path(header == NULL)) { - return NULL; + n++; } - name = nxt_unit_sptr_get(&f->name); + do { + i++; + } while (i < f->value_length && v[i] == ' '); - for (pos = 0; pos < f->name_length; pos++) { - c = name[pos]; - if (c >= 'A' && c <= 'Z') { - name[pos] = (c | 0x20); - } - } + start = i; + } - v = PyBytes_FromStringAndSize(name, f->name_length); - if (nxt_slow_path(v == NULL)) { - Py_DECREF(header); - - return NULL; + if (i - start > 0) { + proto = PyString_FromStringAndSize(v + start, i - start); + if (nxt_slow_path(proto == NULL)) { + goto fail; } - PyTuple_SET_ITEM(header, 0, v); + PyTuple_SET_ITEM(res, n, proto); + } - v = PyBytes_FromStringAndSize(nxt_unit_sptr_get(&f->value), - f->value_length); - if (nxt_slow_path(v == NULL)) { - Py_DECREF(header); + return res; - return NULL; - } +fail: - PyTuple_SET_ITEM(header, 1, v); + Py_DECREF(res); - return header; + return NULL; } +static int nxt_py_asgi_add_port(nxt_unit_ctx_t *ctx, nxt_unit_port_t *port) { + int nb; -static PyObject * -nxt_py_asgi_create_subprotocols(nxt_unit_field_t *f) -{ - char *v; - uint32_t i, n, start; - PyObject *res, *proto; - - v = nxt_unit_sptr_get(&f->value); - n = 1; - - for (i = 0; i < f->value_length; i++) { - if (v[i] == ',') { - n++; - } - } - - res = PyTuple_New(n); - if (nxt_slow_path(res == NULL)) { - return NULL; - } - - n = 0; - start = 0; - - for (i = 0; i < f->value_length; ) { - if (v[i] != ',') { - i++; + if (port->in_fd == -1) { + return NXT_UNIT_OK; + } - continue; - } + nb = 1; - if (i - start > 0) { - proto = PyString_FromStringAndSize(v + start, i - start); - if (nxt_slow_path(proto == NULL)) { - goto fail; - } + if (nxt_slow_path(ioctl(port->in_fd, FIONBIO, &nb) == -1)) { + nxt_unit_alert(ctx, "ioctl(%d, FIONBIO, 0) failed: %s (%d)", port->in_fd, + strerror(errno), errno); - PyTuple_SET_ITEM(res, n, proto); + return NXT_UNIT_ERROR; + } - n++; - } + nxt_unit_debug(ctx, "asgi_add_port %d %p %p", port->in_fd, ctx, port); - do { - i++; - } while (i < f->value_length && v[i] == ' '); + return nxt_py_asgi_add_reader(ctx, port); +} - start = i; - } +static int nxt_py_asgi_add_reader(nxt_unit_ctx_t *ctx, nxt_unit_port_t *port) { + int rc; + PyObject *res, *fd, *py_ctx, *py_port; + nxt_py_asgi_ctx_data_t *ctx_data; - if (i - start > 0) { - proto = PyString_FromStringAndSize(v + start, i - start); - if (nxt_slow_path(proto == NULL)) { - goto fail; - } + nxt_unit_debug(ctx, "asgi_add_reader %d %p %p", port->in_fd, ctx, port); - PyTuple_SET_ITEM(res, n, proto); - } + ctx_data = ctx->data; - return res; + fd = PyLong_FromLong(port->in_fd); + if (nxt_slow_path(fd == NULL)) { + nxt_unit_alert(ctx, "Python failed to create fd"); + nxt_python_print_exception(); -fail: + return NXT_UNIT_ERROR; + } - Py_DECREF(res); + rc = NXT_UNIT_ERROR; - return NULL; -} + py_ctx = PyLong_FromVoidPtr(ctx); + if (nxt_slow_path(py_ctx == NULL)) { + nxt_unit_alert(ctx, "Python failed to create py_ctx"); + nxt_python_print_exception(); + goto clean_fd; + } -static int -nxt_py_asgi_add_port(nxt_unit_ctx_t *ctx, nxt_unit_port_t *port) -{ - int nb; + py_port = PyLong_FromVoidPtr(port); + if (nxt_slow_path(py_port == NULL)) { + nxt_unit_alert(ctx, "Python failed to create py_port"); + nxt_python_print_exception(); - if (port->in_fd == -1) { - return NXT_UNIT_OK; - } + goto clean_py_ctx; + } - nb = 1; + res = PyObject_CallFunctionObjArgs(ctx_data->loop_add_reader, fd, + nxt_py_port_read, py_ctx, py_port, NULL); + if (nxt_slow_path(res == NULL)) { + nxt_unit_alert(ctx, "Python failed to add_reader"); + nxt_python_print_exception(); - if (nxt_slow_path(ioctl(port->in_fd, FIONBIO, &nb) == -1)) { - nxt_unit_alert(ctx, "ioctl(%d, FIONBIO, 0) failed: %s (%d)", - port->in_fd, strerror(errno), errno); + } else { + Py_DECREF(res); - return NXT_UNIT_ERROR; - } + rc = NXT_UNIT_OK; + } - nxt_unit_debug(ctx, "asgi_add_port %d %p %p", port->in_fd, ctx, port); + Py_DECREF(py_port); - return nxt_py_asgi_add_reader(ctx, port); -} +clean_py_ctx: + Py_DECREF(py_ctx); -static int -nxt_py_asgi_add_reader(nxt_unit_ctx_t *ctx, nxt_unit_port_t *port) -{ - int rc; - PyObject *res, *fd, *py_ctx, *py_port; - nxt_py_asgi_ctx_data_t *ctx_data; +clean_fd: - nxt_unit_debug(ctx, "asgi_add_reader %d %p %p", port->in_fd, ctx, port); + Py_DECREF(fd); - ctx_data = ctx->data; + return rc; +} - fd = PyLong_FromLong(port->in_fd); - if (nxt_slow_path(fd == NULL)) { - nxt_unit_alert(ctx, "Python failed to create fd"); - nxt_python_print_exception(); +static void nxt_py_asgi_remove_port(nxt_unit_t *lib, nxt_unit_ctx_t *ctx, + nxt_unit_port_t *port) { + if (port->in_fd == -1 || ctx == NULL) { + return; + } - return NXT_UNIT_ERROR; - } + nxt_unit_debug(NULL, "asgi_remove_port %d %p", port->in_fd, port); - rc = NXT_UNIT_ERROR; + nxt_py_asgi_remove_reader(ctx, port); +} - py_ctx = PyLong_FromVoidPtr(ctx); - if (nxt_slow_path(py_ctx == NULL)) { - nxt_unit_alert(ctx, "Python failed to create py_ctx"); - nxt_python_print_exception(); +static void nxt_py_asgi_quit(nxt_unit_ctx_t *ctx) { + PyObject *res, *p; + nxt_py_asgi_ctx_data_t *ctx_data; - goto clean_fd; - } + nxt_unit_debug(ctx, "asgi_quit %p", ctx); - py_port = PyLong_FromVoidPtr(port); - if (nxt_slow_path(py_port == NULL)) { - nxt_unit_alert(ctx, "Python failed to create py_port"); - nxt_python_print_exception(); + ctx_data = ctx->data; - goto clean_py_ctx; - } + p = PyLong_FromLong(0); + if (nxt_slow_path(p == NULL)) { + nxt_unit_alert(NULL, "Python failed to create Long"); + nxt_python_print_exception(); - res = PyObject_CallFunctionObjArgs(ctx_data->loop_add_reader, - fd, nxt_py_port_read, - py_ctx, py_port, NULL); + } else { + res = + PyObject_CallFunctionObjArgs(ctx_data->quit_future_set_result, p, NULL); if (nxt_slow_path(res == NULL)) { - nxt_unit_alert(ctx, "Python failed to add_reader"); - nxt_python_print_exception(); + nxt_unit_alert(ctx, "Python failed to set_result"); + nxt_python_print_exception(); } else { - Py_DECREF(res); - - rc = NXT_UNIT_OK; + Py_DECREF(res); } - Py_DECREF(py_port); - -clean_py_ctx: - - Py_DECREF(py_ctx); - -clean_fd: + Py_DECREF(p); + } +} - Py_DECREF(fd); +static void nxt_py_asgi_shm_ack_handler(nxt_unit_ctx_t *ctx) { + int rc; + nxt_queue_link_t *lnk; + nxt_py_asgi_ctx_data_t *ctx_data; - return rc; -} + ctx_data = ctx->data; + while (!nxt_queue_is_empty(&ctx_data->drain_queue)) { + lnk = nxt_queue_first(&ctx_data->drain_queue); -static void -nxt_py_asgi_remove_port(nxt_unit_t *lib, nxt_unit_ctx_t *ctx, - nxt_unit_port_t *port) -{ - if (port->in_fd == -1 || ctx == NULL) { - return; + rc = nxt_py_asgi_http_drain(lnk); + if (rc == NXT_UNIT_AGAIN) { + return; } - nxt_unit_debug(NULL, "asgi_remove_port %d %p", port->in_fd, port); - - nxt_py_asgi_remove_reader(ctx, port); + nxt_queue_remove(lnk); + } } +static PyObject *nxt_py_asgi_port_read(PyObject *self, PyObject *args) { + int rc; + PyObject *arg0, *arg1, *res; + Py_ssize_t n; + nxt_unit_ctx_t *ctx; + nxt_unit_port_t *port; + nxt_py_asgi_ctx_data_t *ctx_data; -static void -nxt_py_asgi_quit(nxt_unit_ctx_t *ctx) -{ - PyObject *res, *p; - nxt_py_asgi_ctx_data_t *ctx_data; + n = PyTuple_GET_SIZE(args); - nxt_unit_debug(ctx, "asgi_quit %p", ctx); + if (n != 2) { + nxt_unit_alert( + NULL, "nxt_py_asgi_port_read: invalid number of arguments %d", (int)n); - ctx_data = ctx->data; + return PyErr_Format(PyExc_TypeError, "invalid number of arguments"); + } - p = PyLong_FromLong(0); - if (nxt_slow_path(p == NULL)) { - nxt_unit_alert(NULL, "Python failed to create Long"); - nxt_python_print_exception(); + arg0 = PyTuple_GET_ITEM(args, 0); + if (nxt_slow_path(arg0 == NULL || PyLong_Check(arg0) == 0)) { + return PyErr_Format(PyExc_TypeError, "the first argument is not a long"); + } - } else { - res = PyObject_CallFunctionObjArgs(ctx_data->quit_future_set_result, - p, NULL); - if (nxt_slow_path(res == NULL)) { - nxt_unit_alert(ctx, "Python failed to set_result"); - nxt_python_print_exception(); + ctx = PyLong_AsVoidPtr(arg0); - } else { - Py_DECREF(res); - } + arg1 = PyTuple_GET_ITEM(args, 1); + if (nxt_slow_path(arg1 == NULL || PyLong_Check(arg1) == 0)) { + return PyErr_Format(PyExc_TypeError, "the second argument is not a long"); + } - Py_DECREF(p); - } -} + port = PyLong_AsVoidPtr(arg1); + + rc = nxt_unit_process_port_msg(ctx, port); + nxt_unit_debug(ctx, "asgi_port_read(%p,%p): %d", ctx, port, rc); -static void -nxt_py_asgi_shm_ack_handler(nxt_unit_ctx_t *ctx) -{ - int rc; - nxt_queue_link_t *lnk; - nxt_py_asgi_ctx_data_t *ctx_data; + if (nxt_slow_path(rc == NXT_UNIT_ERROR)) { + return PyErr_Format(PyExc_RuntimeError, "error processing port %d message", + port->id.id); + } + if (rc == NXT_UNIT_OK) { ctx_data = ctx->data; - while (!nxt_queue_is_empty(&ctx_data->drain_queue)) { - lnk = nxt_queue_first(&ctx_data->drain_queue); + res = PyObject_CallFunctionObjArgs(ctx_data->loop_call_soon, + nxt_py_port_read, arg0, arg1, NULL); + if (nxt_slow_path(res == NULL)) { + nxt_unit_alert(ctx, "Python failed to call 'loop.call_soon'"); + nxt_python_print_exception(); + } - rc = nxt_py_asgi_http_drain(lnk); - if (rc == NXT_UNIT_AGAIN) { - return; - } + Py_XDECREF(res); + } - nxt_queue_remove(lnk); - } + Py_RETURN_NONE; } +PyObject *nxt_py_asgi_enum_headers(PyObject *headers, + nxt_py_asgi_enum_header_cb cb, void *data) { + int i; + PyObject *iter, *header, *h_iter, *name, *val, *res; -static PyObject * -nxt_py_asgi_port_read(PyObject *self, PyObject *args) -{ - int rc; - PyObject *arg0, *arg1, *res; - Py_ssize_t n; - nxt_unit_ctx_t *ctx; - nxt_unit_port_t *port; - nxt_py_asgi_ctx_data_t *ctx_data; - - n = PyTuple_GET_SIZE(args); - - if (n != 2) { - nxt_unit_alert(NULL, - "nxt_py_asgi_port_read: invalid number of arguments %d", - (int) n); - - return PyErr_Format(PyExc_TypeError, "invalid number of arguments"); - } + iter = PyObject_GetIter(headers); + if (nxt_slow_path(iter == NULL)) { + return PyErr_Format(PyExc_TypeError, "'headers' is not an iterable"); + } - arg0 = PyTuple_GET_ITEM(args, 0); - if (nxt_slow_path(arg0 == NULL || PyLong_Check(arg0) == 0)) { - return PyErr_Format(PyExc_TypeError, - "the first argument is not a long"); + for (i = 0; /* void */; i++) { + header = PyIter_Next(iter); + if (header == NULL) { + break; } - ctx = PyLong_AsVoidPtr(arg0); + h_iter = PyObject_GetIter(header); + if (nxt_slow_path(h_iter == NULL)) { + Py_DECREF(header); + Py_DECREF(iter); - arg1 = PyTuple_GET_ITEM(args, 1); - if (nxt_slow_path(arg1 == NULL || PyLong_Check(arg1) == 0)) { - return PyErr_Format(PyExc_TypeError, - "the second argument is not a long"); + return PyErr_Format(PyExc_TypeError, + "'headers' item #%d is not an iterable", i); } - port = PyLong_AsVoidPtr(arg1); - - rc = nxt_unit_process_port_msg(ctx, port); - - nxt_unit_debug(ctx, "asgi_port_read(%p,%p): %d", ctx, port, rc); + name = PyIter_Next(h_iter); + if (nxt_slow_path(name == NULL || !PyBytes_Check(name))) { + Py_XDECREF(name); + Py_DECREF(h_iter); + Py_DECREF(header); + Py_DECREF(iter); - if (nxt_slow_path(rc == NXT_UNIT_ERROR)) { - return PyErr_Format(PyExc_RuntimeError, - "error processing port %d message", port->id.id); + return PyErr_Format(PyExc_TypeError, + "'headers' item #%d 'name' is not a byte string", i); } - if (rc == NXT_UNIT_OK) { - ctx_data = ctx->data; - - res = PyObject_CallFunctionObjArgs(ctx_data->loop_call_soon, - nxt_py_port_read, - arg0, arg1, NULL); - if (nxt_slow_path(res == NULL)) { - nxt_unit_alert(ctx, "Python failed to call 'loop.call_soon'"); - nxt_python_print_exception(); - } + val = PyIter_Next(h_iter); + if (nxt_slow_path(val == NULL || !PyBytes_Check(val))) { + Py_XDECREF(val); + Py_DECREF(h_iter); + Py_DECREF(header); + Py_DECREF(iter); - Py_XDECREF(res); + return PyErr_Format(PyExc_TypeError, + "'headers' item #%d 'value' is not a byte string", i); } - Py_RETURN_NONE; -} + res = cb(data, i, name, val); + Py_DECREF(name); + Py_DECREF(val); + Py_DECREF(h_iter); + Py_DECREF(header); -PyObject * -nxt_py_asgi_enum_headers(PyObject *headers, nxt_py_asgi_enum_header_cb cb, - void *data) -{ - int i; - PyObject *iter, *header, *h_iter, *name, *val, *res; + if (nxt_slow_path(res == NULL)) { + Py_DECREF(iter); - iter = PyObject_GetIter(headers); - if (nxt_slow_path(iter == NULL)) { - return PyErr_Format(PyExc_TypeError, "'headers' is not an iterable"); + return NULL; } - for (i = 0; /* void */; i++) { - header = PyIter_Next(iter); - if (header == NULL) { - break; - } - - h_iter = PyObject_GetIter(header); - if (nxt_slow_path(h_iter == NULL)) { - Py_DECREF(header); - Py_DECREF(iter); - - return PyErr_Format(PyExc_TypeError, - "'headers' item #%d is not an iterable", i); - } - - name = PyIter_Next(h_iter); - if (nxt_slow_path(name == NULL || !PyBytes_Check(name))) { - Py_XDECREF(name); - Py_DECREF(h_iter); - Py_DECREF(header); - Py_DECREF(iter); - - return PyErr_Format(PyExc_TypeError, - "'headers' item #%d 'name' is not a byte string", i); - } - - val = PyIter_Next(h_iter); - if (nxt_slow_path(val == NULL || !PyBytes_Check(val))) { - Py_XDECREF(val); - Py_DECREF(h_iter); - Py_DECREF(header); - Py_DECREF(iter); - - return PyErr_Format(PyExc_TypeError, - "'headers' item #%d 'value' is not a byte string", i); - } - - res = cb(data, i, name, val); - - Py_DECREF(name); - Py_DECREF(val); - Py_DECREF(h_iter); - Py_DECREF(header); - - if (nxt_slow_path(res == NULL)) { - Py_DECREF(iter); - - return NULL; - } - - Py_DECREF(res); - } + Py_DECREF(res); + } - Py_DECREF(iter); + Py_DECREF(iter); - Py_RETURN_NONE; + Py_RETURN_NONE; } +PyObject *nxt_py_asgi_calc_size(void *data, int i, PyObject *name, + PyObject *val) { + nxt_py_asgi_calc_size_ctx_t *ctx; -PyObject * -nxt_py_asgi_calc_size(void *data, int i, PyObject *name, PyObject *val) -{ - nxt_py_asgi_calc_size_ctx_t *ctx; - - ctx = data; + ctx = data; - ctx->fields_count++; - ctx->fields_size += PyBytes_GET_SIZE(name) + PyBytes_GET_SIZE(val); + ctx->fields_count++; + ctx->fields_size += PyBytes_GET_SIZE(name) + PyBytes_GET_SIZE(val); - Py_RETURN_NONE; + Py_RETURN_NONE; } +PyObject *nxt_py_asgi_add_field(void *data, int i, PyObject *name, + PyObject *val) { + int rc; + char *name_str, *val_str; + uint32_t name_len, val_len; + nxt_off_t content_length; + nxt_unit_request_info_t *req; + nxt_py_asgi_add_field_ctx_t *ctx; -PyObject * -nxt_py_asgi_add_field(void *data, int i, PyObject *name, PyObject *val) -{ - int rc; - char *name_str, *val_str; - uint32_t name_len, val_len; - nxt_off_t content_length; - nxt_unit_request_info_t *req; - nxt_py_asgi_add_field_ctx_t *ctx; + name_str = PyBytes_AS_STRING(name); + name_len = PyBytes_GET_SIZE(name); - name_str = PyBytes_AS_STRING(name); - name_len = PyBytes_GET_SIZE(name); + val_str = PyBytes_AS_STRING(val); + val_len = PyBytes_GET_SIZE(val); - val_str = PyBytes_AS_STRING(val); - val_len = PyBytes_GET_SIZE(val); + ctx = data; + req = ctx->req; - ctx = data; - req = ctx->req; + rc = nxt_unit_response_add_field(req, name_str, name_len, val_str, val_len); + if (nxt_slow_path(rc != NXT_UNIT_OK)) { + return PyErr_Format(PyExc_RuntimeError, "failed to add header #%d", i); + } - rc = nxt_unit_response_add_field(req, name_str, name_len, - val_str, val_len); - if (nxt_slow_path(rc != NXT_UNIT_OK)) { - return PyErr_Format(PyExc_RuntimeError, - "failed to add header #%d", i); - } - - if (req->response->fields[i].hash == NXT_UNIT_HASH_CONTENT_LENGTH) { - content_length = nxt_off_t_parse((u_char *) val_str, val_len); - if (nxt_slow_path(content_length < 0)) { - nxt_unit_req_error(req, "failed to parse Content-Length " - "value %.*s", (int) val_len, val_str); - - return PyErr_Format(PyExc_ValueError, - "Failed to parse Content-Length: '%.*s'", - (int) val_len, val_str); - } + if (req->response->fields[i].hash == NXT_UNIT_HASH_CONTENT_LENGTH) { + content_length = nxt_off_t_parse((u_char *)val_str, val_len); + if (nxt_slow_path(content_length < 0)) { + nxt_unit_req_error(req, + "failed to parse Content-Length " + "value %.*s", + (int)val_len, val_str); - ctx->content_length = content_length; + return PyErr_Format(PyExc_ValueError, + "Failed to parse Content-Length: '%.*s'", + (int)val_len, val_str); } - Py_RETURN_NONE; -} + ctx->content_length = content_length; + } + Py_RETURN_NONE; +} -PyObject * -nxt_py_asgi_set_result_soon(nxt_unit_request_info_t *req, - nxt_py_asgi_ctx_data_t *ctx_data, PyObject *future, PyObject *result) -{ - PyObject *set_result, *res; +PyObject *nxt_py_asgi_set_result_soon(nxt_unit_request_info_t *req, + nxt_py_asgi_ctx_data_t *ctx_data, + PyObject *future, PyObject *result) { + PyObject *set_result, *res; - if (nxt_slow_path(result == NULL)) { - Py_DECREF(future); + if (nxt_slow_path(result == NULL)) { + Py_DECREF(future); - return NULL; - } + return NULL; + } - set_result = PyObject_GetAttrString(future, "set_result"); - if (nxt_slow_path(set_result == NULL)) { - nxt_unit_req_alert(req, "failed to get 'set_result' for future"); + set_result = PyObject_GetAttrString(future, "set_result"); + if (nxt_slow_path(set_result == NULL)) { + nxt_unit_req_alert(req, "failed to get 'set_result' for future"); - Py_CLEAR(future); + Py_CLEAR(future); - goto cleanup_result; - } + goto cleanup_result; + } - if (nxt_slow_path(PyCallable_Check(set_result) == 0)) { - nxt_unit_req_alert(req, "'future.set_result' is not a callable"); + if (nxt_slow_path(PyCallable_Check(set_result) == 0)) { + nxt_unit_req_alert(req, "'future.set_result' is not a callable"); - Py_CLEAR(future); + Py_CLEAR(future); - goto cleanup; - } + goto cleanup; + } - res = PyObject_CallFunctionObjArgs(ctx_data->loop_call_soon, set_result, - result, NULL); - if (nxt_slow_path(res == NULL)) { - nxt_unit_req_alert(req, "Python failed to call 'loop.call_soon'"); - nxt_python_print_exception(); + res = PyObject_CallFunctionObjArgs(ctx_data->loop_call_soon, set_result, + result, NULL); + if (nxt_slow_path(res == NULL)) { + nxt_unit_req_alert(req, "Python failed to call 'loop.call_soon'"); + nxt_python_print_exception(); - Py_CLEAR(future); - } + Py_CLEAR(future); + } - Py_XDECREF(res); + Py_XDECREF(res); cleanup: - Py_DECREF(set_result); + Py_DECREF(set_result); cleanup_result: - Py_DECREF(result); + Py_DECREF(result); - return future; + return future; } +PyObject *nxt_py_asgi_new_msg(nxt_unit_request_info_t *req, PyObject *type) { + PyObject *msg; -PyObject * -nxt_py_asgi_new_msg(nxt_unit_request_info_t *req, PyObject *type) -{ - PyObject *msg; + msg = PyDict_New(); + if (nxt_slow_path(msg == NULL)) { + nxt_unit_req_alert(req, "Python failed to create message dict"); + nxt_python_print_exception(); - msg = PyDict_New(); - if (nxt_slow_path(msg == NULL)) { - nxt_unit_req_alert(req, "Python failed to create message dict"); - nxt_python_print_exception(); + return PyErr_Format(PyExc_RuntimeError, "failed to create message dict"); + } - return PyErr_Format(PyExc_RuntimeError, - "failed to create message dict"); - } + if (nxt_slow_path(PyDict_SetItem(msg, nxt_py_type_str, type) == -1)) { + nxt_unit_req_alert(req, "Python failed to set 'msg.type' item"); - if (nxt_slow_path(PyDict_SetItem(msg, nxt_py_type_str, type) == -1)) { - nxt_unit_req_alert(req, "Python failed to set 'msg.type' item"); + Py_DECREF(msg); - Py_DECREF(msg); - - return PyErr_Format(PyExc_RuntimeError, - "failed to set 'msg.type' item"); - } + return PyErr_Format(PyExc_RuntimeError, "failed to set 'msg.type' item"); + } - return msg; + return msg; } +PyObject *nxt_py_asgi_new_scope(nxt_unit_request_info_t *req, PyObject *type, + PyObject *spec_version) { + PyObject *scope, *asgi; -PyObject * -nxt_py_asgi_new_scope(nxt_unit_request_info_t *req, PyObject *type, - PyObject *spec_version) -{ - PyObject *scope, *asgi; + scope = PyDict_New(); + if (nxt_slow_path(scope == NULL)) { + nxt_unit_req_alert(req, "Python failed to create 'scope' dict"); + nxt_python_print_exception(); - scope = PyDict_New(); - if (nxt_slow_path(scope == NULL)) { - nxt_unit_req_alert(req, "Python failed to create 'scope' dict"); - nxt_python_print_exception(); + return PyErr_Format(PyExc_RuntimeError, "failed to create 'scope' dict"); + } - return PyErr_Format(PyExc_RuntimeError, - "failed to create 'scope' dict"); - } - - if (nxt_slow_path(PyDict_SetItem(scope, nxt_py_type_str, type) == -1)) { - nxt_unit_req_alert(req, "Python failed to set 'scope.type' item"); - - Py_DECREF(scope); - - return PyErr_Format(PyExc_RuntimeError, - "failed to set 'scope.type' item"); - } + if (nxt_slow_path(PyDict_SetItem(scope, nxt_py_type_str, type) == -1)) { + nxt_unit_req_alert(req, "Python failed to set 'scope.type' item"); - asgi = PyDict_New(); - if (nxt_slow_path(asgi == NULL)) { - nxt_unit_req_alert(req, "Python failed to create 'asgi' dict"); - nxt_python_print_exception(); + Py_DECREF(scope); - Py_DECREF(scope); + return PyErr_Format(PyExc_RuntimeError, "failed to set 'scope.type' item"); + } - return PyErr_Format(PyExc_RuntimeError, - "failed to create 'asgi' dict"); - } + asgi = PyDict_New(); + if (nxt_slow_path(asgi == NULL)) { + nxt_unit_req_alert(req, "Python failed to create 'asgi' dict"); + nxt_python_print_exception(); - if (nxt_slow_path(PyDict_SetItem(scope, nxt_py_asgi_str, asgi) == -1)) { - nxt_unit_req_alert(req, "Python failed to set 'scope.asgi' item"); + Py_DECREF(scope); - Py_DECREF(asgi); - Py_DECREF(scope); + return PyErr_Format(PyExc_RuntimeError, "failed to create 'asgi' dict"); + } - return PyErr_Format(PyExc_RuntimeError, - "failed to set 'scope.asgi' item"); - } + if (nxt_slow_path(PyDict_SetItem(scope, nxt_py_asgi_str, asgi) == -1)) { + nxt_unit_req_alert(req, "Python failed to set 'scope.asgi' item"); - if (nxt_slow_path(PyDict_SetItem(asgi, nxt_py_version_str, - nxt_py_3_0_str) == -1)) - { - nxt_unit_req_alert(req, "Python failed to set 'asgi.version' item"); + Py_DECREF(asgi); + Py_DECREF(scope); - Py_DECREF(asgi); - Py_DECREF(scope); + return PyErr_Format(PyExc_RuntimeError, "failed to set 'scope.asgi' item"); + } - return PyErr_Format(PyExc_RuntimeError, - "failed to set 'asgi.version' item"); - } + if (nxt_slow_path(PyDict_SetItem(asgi, nxt_py_version_str, nxt_py_3_0_str) == + -1)) { + nxt_unit_req_alert(req, "Python failed to set 'asgi.version' item"); - if (nxt_slow_path(PyDict_SetItem(asgi, nxt_py_spec_version_str, - spec_version) == -1)) - { - nxt_unit_req_alert(req, - "Python failed to set 'asgi.spec_version' item"); + Py_DECREF(asgi); + Py_DECREF(scope); - Py_DECREF(asgi); - Py_DECREF(scope); + return PyErr_Format(PyExc_RuntimeError, + "failed to set 'asgi.version' item"); + } - return PyErr_Format(PyExc_RuntimeError, - "failed to set 'asgi.spec_version' item"); - } + if (nxt_slow_path( + PyDict_SetItem(asgi, nxt_py_spec_version_str, spec_version) == -1)) { + nxt_unit_req_alert(req, "Python failed to set 'asgi.spec_version' item"); Py_DECREF(asgi); + Py_DECREF(scope); - return scope; -} - - -void -nxt_py_asgi_drain_wait(nxt_unit_request_info_t *req, nxt_queue_link_t *link) -{ - nxt_py_asgi_ctx_data_t *ctx_data; + return PyErr_Format(PyExc_RuntimeError, + "failed to set 'asgi.spec_version' item"); + } - ctx_data = req->ctx->data; + Py_DECREF(asgi); - nxt_queue_insert_tail(&ctx_data->drain_queue, link); + return scope; } +void nxt_py_asgi_drain_wait(nxt_unit_request_info_t *req, + nxt_queue_link_t *link) { + nxt_py_asgi_ctx_data_t *ctx_data; -void -nxt_py_asgi_dealloc(PyObject *self) -{ - PyObject_Del(self); -} + ctx_data = req->ctx->data; - -PyObject * -nxt_py_asgi_await(PyObject *self) -{ - Py_INCREF(self); - return self; + nxt_queue_insert_tail(&ctx_data->drain_queue, link); } +void nxt_py_asgi_dealloc(PyObject *self) { PyObject_Del(self); } -PyObject * -nxt_py_asgi_iter(PyObject *self) -{ - Py_INCREF(self); - return self; +PyObject *nxt_py_asgi_await(PyObject *self) { + Py_INCREF(self); + return self; } - -PyObject * -nxt_py_asgi_next(PyObject *self) -{ - return NULL; +PyObject *nxt_py_asgi_iter(PyObject *self) { + Py_INCREF(self); + return self; } +PyObject *nxt_py_asgi_next(PyObject *self) { return NULL; } -static void -nxt_python_asgi_done(void) -{ - nxt_py_asgi_str_done(); +static void nxt_python_asgi_done(void) { + nxt_py_asgi_str_done(); - Py_XDECREF(nxt_py_port_read); + Py_XDECREF(nxt_py_port_read); } #else /* !(NXT_HAVE_ASGI) */ +int nxt_python_asgi_check(PyObject *obj) { return 0; } -int -nxt_python_asgi_check(PyObject *obj) -{ - return 0; +int nxt_python_asgi_init(nxt_unit_init_t *init, nxt_python_proto_t *proto) { + nxt_unit_alert(NULL, "ASGI not implemented"); + return NXT_UNIT_ERROR; } - -int -nxt_python_asgi_init(nxt_unit_init_t *init, nxt_python_proto_t *proto) -{ - nxt_unit_alert(NULL, "ASGI not implemented"); - return NXT_UNIT_ERROR; -} - - #endif /* NXT_HAVE_ASGI */ diff --git a/src/python/nxt_python_asgi.h b/src/python/nxt_python_asgi.h index 94478a361..6879840bf 100644 --- a/src/python/nxt_python_asgi.h +++ b/src/python/nxt_python_asgi.h @@ -6,47 +6,47 @@ #ifndef _NXT_PYTHON_ASGI_H_INCLUDED_ #define _NXT_PYTHON_ASGI_H_INCLUDED_ - -typedef PyObject * (*nxt_py_asgi_enum_header_cb)(void *ctx, int i, - PyObject *name, PyObject *val); +typedef PyObject *(*nxt_py_asgi_enum_header_cb)(void *ctx, int i, + PyObject *name, PyObject *val); void nxt_py_asgi_drain_wait(nxt_unit_request_info_t *req, - nxt_queue_link_t *link); + nxt_queue_link_t *link); typedef struct { - uint32_t fields_count; - uint32_t fields_size; + uint32_t fields_count; + uint32_t fields_size; } nxt_py_asgi_calc_size_ctx_t; typedef struct { - nxt_unit_request_info_t *req; - uint64_t content_length; + nxt_unit_request_info_t *req; + uint64_t content_length; } nxt_py_asgi_add_field_ctx_t; typedef struct { - nxt_queue_t drain_queue; - PyObject *loop_run_until_complete; - PyObject *loop_create_future; - PyObject *loop_create_task; - PyObject *loop_call_soon; - PyObject *loop_add_reader; - PyObject *loop_remove_reader; - PyObject *quit_future; - PyObject *quit_future_set_result; - PyObject **target_lifespans; + nxt_queue_t drain_queue; + PyObject *loop_run_until_complete; + PyObject *loop_create_future; + PyObject *loop_create_task; + PyObject *loop_call_soon; + PyObject *loop_add_reader; + PyObject *loop_remove_reader; + PyObject *quit_future; + PyObject *quit_future_set_result; + PyObject **target_lifespans; } nxt_py_asgi_ctx_data_t; PyObject *nxt_py_asgi_enum_headers(PyObject *headers, - nxt_py_asgi_enum_header_cb cb, void *data); + nxt_py_asgi_enum_header_cb cb, void *data); PyObject *nxt_py_asgi_calc_size(void *data, int i, PyObject *n, PyObject *v); PyObject *nxt_py_asgi_add_field(void *data, int i, PyObject *n, PyObject *v); PyObject *nxt_py_asgi_set_result_soon(nxt_unit_request_info_t *req, - nxt_py_asgi_ctx_data_t *ctx_data, PyObject *future, PyObject *result); + nxt_py_asgi_ctx_data_t *ctx_data, + PyObject *future, PyObject *result); PyObject *nxt_py_asgi_new_msg(nxt_unit_request_info_t *req, PyObject *type); PyObject *nxt_py_asgi_new_scope(nxt_unit_request_info_t *req, PyObject *type, - PyObject *spec_version); + PyObject *spec_version); void nxt_py_asgi_dealloc(PyObject *self); PyObject *nxt_py_asgi_await(PyObject *self); @@ -67,5 +67,4 @@ void nxt_py_asgi_websocket_close_handler(nxt_unit_request_info_t *req); int nxt_py_asgi_lifespan_startup(nxt_py_asgi_ctx_data_t *ctx_data); int nxt_py_asgi_lifespan_shutdown(nxt_unit_ctx_t *ctx); - -#endif /* _NXT_PYTHON_ASGI_H_INCLUDED_ */ +#endif /* _NXT_PYTHON_ASGI_H_INCLUDED_ */ diff --git a/src/python/nxt_python_asgi_http.c b/src/python/nxt_python_asgi_http.c index cdd6357e6..cc53d6e69 100644 --- a/src/python/nxt_python_asgi_http.c +++ b/src/python/nxt_python_asgi_http.c @@ -3,7 +3,6 @@ * Copyright (C) NGINX, Inc. */ - #include #if (NXT_HAVE_ASGI) @@ -14,42 +13,37 @@ #include #include - typedef struct { - PyObject_HEAD - nxt_unit_request_info_t *req; - nxt_queue_link_t link; - PyObject *receive_future; - PyObject *send_future; - uint64_t content_length; - uint64_t bytes_sent; - PyObject *send_body; - Py_ssize_t send_body_off; - uint8_t complete; - uint8_t closed; - uint8_t empty_body_received; + PyObject_HEAD nxt_unit_request_info_t *req; + nxt_queue_link_t link; + PyObject *receive_future; + PyObject *send_future; + uint64_t content_length; + uint64_t bytes_sent; + PyObject *send_body; + Py_ssize_t send_body_off; + uint8_t complete; + uint8_t closed; + uint8_t empty_body_received; } nxt_py_asgi_http_t; - static PyObject *nxt_py_asgi_http_receive(PyObject *self, PyObject *none); static PyObject *nxt_py_asgi_http_read_msg(nxt_py_asgi_http_t *http); static PyObject *nxt_py_asgi_http_send(PyObject *self, PyObject *dict); static PyObject *nxt_py_asgi_http_response_start(nxt_py_asgi_http_t *http, - PyObject *dict); + PyObject *dict); static PyObject *nxt_py_asgi_http_response_body(nxt_py_asgi_http_t *http, - PyObject *dict); + PyObject *dict); static void nxt_py_asgi_http_emit_disconnect(nxt_py_asgi_http_t *http); static void nxt_py_asgi_http_set_result(nxt_py_asgi_http_t *http, - PyObject *future, PyObject *msg); + PyObject *future, PyObject *msg); static PyObject *nxt_py_asgi_http_done(PyObject *self, PyObject *future); - static PyMethodDef nxt_py_asgi_http_methods[] = { - { "receive", nxt_py_asgi_http_receive, METH_NOARGS, 0 }, - { "send", nxt_py_asgi_http_send, METH_O, 0 }, - { "_done", nxt_py_asgi_http_done, METH_O, 0 }, - { NULL, NULL, 0, 0 } -}; + {"receive", nxt_py_asgi_http_receive, METH_NOARGS, 0}, + {"send", nxt_py_asgi_http_send, METH_O, 0}, + {"_done", nxt_py_asgi_http_done, METH_O, 0}, + {NULL, NULL, 0, 0}}; static PyAsyncMethods nxt_py_asgi_async_methods = { .am_await = nxt_py_asgi_await, @@ -58,632 +52,583 @@ static PyAsyncMethods nxt_py_asgi_async_methods = { static PyTypeObject nxt_py_asgi_http_type = { PyVarObject_HEAD_INIT(NULL, 0) - .tp_name = "unit._asgi_http", + .tp_name = "unit._asgi_http", .tp_basicsize = sizeof(nxt_py_asgi_http_t), - .tp_dealloc = nxt_py_asgi_dealloc, - .tp_as_async = &nxt_py_asgi_async_methods, - .tp_flags = Py_TPFLAGS_DEFAULT, - .tp_doc = "unit ASGI HTTP request object", - .tp_iter = nxt_py_asgi_iter, - .tp_iternext = nxt_py_asgi_next, - .tp_methods = nxt_py_asgi_http_methods, + .tp_dealloc = nxt_py_asgi_dealloc, + .tp_as_async = &nxt_py_asgi_async_methods, + .tp_flags = Py_TPFLAGS_DEFAULT, + .tp_doc = "unit ASGI HTTP request object", + .tp_iter = nxt_py_asgi_iter, + .tp_iternext = nxt_py_asgi_next, + .tp_methods = nxt_py_asgi_http_methods, }; -static Py_ssize_t nxt_py_asgi_http_body_buf_size = 32 * 1024 * 1024; - +static Py_ssize_t nxt_py_asgi_http_body_buf_size = 32 * 1024 * 1024; -int -nxt_py_asgi_http_init(void) -{ - if (nxt_slow_path(PyType_Ready(&nxt_py_asgi_http_type) != 0)) { - nxt_unit_alert(NULL, - "Python failed to initialize the 'http' type object"); - return NXT_UNIT_ERROR; - } +int nxt_py_asgi_http_init(void) { + if (nxt_slow_path(PyType_Ready(&nxt_py_asgi_http_type) != 0)) { + nxt_unit_alert(NULL, "Python failed to initialize the 'http' type object"); + return NXT_UNIT_ERROR; + } - return NXT_UNIT_OK; + return NXT_UNIT_OK; } +PyObject *nxt_py_asgi_http_create(nxt_unit_request_info_t *req) { + nxt_py_asgi_http_t *http; -PyObject * -nxt_py_asgi_http_create(nxt_unit_request_info_t *req) -{ - nxt_py_asgi_http_t *http; - - http = PyObject_New(nxt_py_asgi_http_t, &nxt_py_asgi_http_type); - - if (nxt_fast_path(http != NULL)) { - http->req = req; - http->receive_future = NULL; - http->send_future = NULL; - http->content_length = -1; - http->bytes_sent = 0; - http->send_body = NULL; - http->send_body_off = 0; - http->complete = 0; - http->closed = 0; - http->empty_body_received = 0; - } + http = PyObject_New(nxt_py_asgi_http_t, &nxt_py_asgi_http_type); - return (PyObject *) http; + if (nxt_fast_path(http != NULL)) { + http->req = req; + http->receive_future = NULL; + http->send_future = NULL; + http->content_length = -1; + http->bytes_sent = 0; + http->send_body = NULL; + http->send_body_off = 0; + http->complete = 0; + http->closed = 0; + http->empty_body_received = 0; + } + + return (PyObject *)http; } +static PyObject *nxt_py_asgi_http_receive(PyObject *self, PyObject *none) { + PyObject *msg, *future; + nxt_py_asgi_http_t *http; + nxt_py_asgi_ctx_data_t *ctx_data; + nxt_unit_request_info_t *req; -static PyObject * -nxt_py_asgi_http_receive(PyObject *self, PyObject *none) -{ - PyObject *msg, *future; - nxt_py_asgi_http_t *http; - nxt_py_asgi_ctx_data_t *ctx_data; - nxt_unit_request_info_t *req; - - http = (nxt_py_asgi_http_t *) self; - req = http->req; + http = (nxt_py_asgi_http_t *)self; + req = http->req; - nxt_unit_req_debug(req, "asgi_http_receive"); + nxt_unit_req_debug(req, "asgi_http_receive"); - if (nxt_slow_path(http->closed || http->complete )) { - msg = nxt_py_asgi_new_msg(req, nxt_py_http_disconnect_str); + if (nxt_slow_path(http->closed || http->complete)) { + msg = nxt_py_asgi_new_msg(req, nxt_py_http_disconnect_str); - } else { - msg = nxt_py_asgi_http_read_msg(http); - } + } else { + msg = nxt_py_asgi_http_read_msg(http); + } - if (nxt_slow_path(msg == NULL)) { - return NULL; - } + if (nxt_slow_path(msg == NULL)) { + return NULL; + } - ctx_data = req->ctx->data; + ctx_data = req->ctx->data; - future = PyObject_CallObject(ctx_data->loop_create_future, NULL); - if (nxt_slow_path(future == NULL)) { - nxt_unit_req_alert(req, "Python failed to create Future object"); - nxt_python_print_exception(); + future = PyObject_CallObject(ctx_data->loop_create_future, NULL); + if (nxt_slow_path(future == NULL)) { + nxt_unit_req_alert(req, "Python failed to create Future object"); + nxt_python_print_exception(); - Py_DECREF(msg); + Py_DECREF(msg); - return PyErr_Format(PyExc_RuntimeError, - "failed to create Future object"); - } + return PyErr_Format(PyExc_RuntimeError, "failed to create Future object"); + } - if (msg != Py_None) { - return nxt_py_asgi_set_result_soon(req, ctx_data, future, msg); - } + if (msg != Py_None) { + return nxt_py_asgi_set_result_soon(req, ctx_data, future, msg); + } - http->receive_future = future; - Py_INCREF(http->receive_future); + http->receive_future = future; + Py_INCREF(http->receive_future); - Py_DECREF(msg); + Py_DECREF(msg); - return future; + return future; } +static PyObject *nxt_py_asgi_http_read_msg(nxt_py_asgi_http_t *http) { + char *body_buf; + ssize_t read_res; + PyObject *msg, *body; + Py_ssize_t size; + nxt_unit_request_info_t *req; -static PyObject * -nxt_py_asgi_http_read_msg(nxt_py_asgi_http_t *http) -{ - char *body_buf; - ssize_t read_res; - PyObject *msg, *body; - Py_ssize_t size; - nxt_unit_request_info_t *req; + req = http->req; - req = http->req; + size = req->content_length; - size = req->content_length; + if (size > nxt_py_asgi_http_body_buf_size) { + size = nxt_py_asgi_http_body_buf_size; + } - if (size > nxt_py_asgi_http_body_buf_size) { - size = nxt_py_asgi_http_body_buf_size; + if (size == 0) { + if (http->empty_body_received) { + Py_RETURN_NONE; } - if (size == 0) { - if (http->empty_body_received) { - Py_RETURN_NONE; - } + http->empty_body_received = 1; + } + + if (size > 0) { + body = PyBytes_FromStringAndSize(NULL, size); + if (nxt_slow_path(body == NULL)) { + nxt_unit_req_alert(req, "Python failed to create body byte string"); + nxt_python_print_exception(); - http->empty_body_received = 1; + return PyErr_Format(PyExc_RuntimeError, "failed to create Bytes object"); } - if (size > 0) { - body = PyBytes_FromStringAndSize(NULL, size); - if (nxt_slow_path(body == NULL)) { - nxt_unit_req_alert(req, "Python failed to create body byte string"); - nxt_python_print_exception(); + body_buf = PyBytes_AS_STRING(body); - return PyErr_Format(PyExc_RuntimeError, - "failed to create Bytes object"); - } + read_res = nxt_unit_request_read(req, body_buf, size); - body_buf = PyBytes_AS_STRING(body); + } else { + body = NULL; + read_res = 0; + } - read_res = nxt_unit_request_read(req, body_buf, size); + if (read_res > 0 || read_res == size) { + msg = nxt_py_asgi_new_msg(req, nxt_py_http_request_str); + if (nxt_slow_path(msg == NULL)) { + Py_XDECREF(body); - } else { - body = NULL; - read_res = 0; + return NULL; } - if (read_res > 0 || read_res == size) { - msg = nxt_py_asgi_new_msg(req, nxt_py_http_request_str); - if (nxt_slow_path(msg == NULL)) { - Py_XDECREF(body); +#define SET_ITEM(dict, key, value) \ + if (nxt_slow_path(PyDict_SetItem(dict, nxt_py_##key##_str, value) == -1)) { \ + nxt_unit_req_alert(req, "Python failed to set '" #dict "." #key "' item"); \ + PyErr_SetString(PyExc_RuntimeError, \ + "Python failed to set '" #dict "." #key "' item"); \ + goto fail; \ + } - return NULL; - } - -#define SET_ITEM(dict, key, value) \ - if (nxt_slow_path(PyDict_SetItem(dict, nxt_py_ ## key ## _str, value) \ - == -1)) \ - { \ - nxt_unit_req_alert(req, \ - "Python failed to set '" #dict "." #key "' item"); \ - PyErr_SetString(PyExc_RuntimeError, \ - "Python failed to set '" #dict "." #key "' item"); \ - goto fail; \ + if (body != NULL) { + SET_ITEM(msg, body, body) } - if (body != NULL) { - SET_ITEM(msg, body, body) - } - - if (req->content_length > 0) { - SET_ITEM(msg, more_body, Py_True) - } + if (req->content_length > 0) { + SET_ITEM(msg, more_body, Py_True) + } #undef SET_ITEM - Py_XDECREF(body); + Py_XDECREF(body); - return msg; - } + return msg; + } - Py_XDECREF(body); + Py_XDECREF(body); - Py_RETURN_NONE; + Py_RETURN_NONE; fail: - Py_DECREF(msg); - Py_XDECREF(body); + Py_DECREF(msg); + Py_XDECREF(body); - return NULL; + return NULL; } +static PyObject *nxt_py_asgi_http_send(PyObject *self, PyObject *dict) { + PyObject *type; + const char *type_str; + Py_ssize_t type_len; + nxt_py_asgi_http_t *http; -static PyObject * -nxt_py_asgi_http_send(PyObject *self, PyObject *dict) -{ - PyObject *type; - const char *type_str; - Py_ssize_t type_len; - nxt_py_asgi_http_t *http; - - static const nxt_str_t response_start = nxt_string("http.response.start"); - static const nxt_str_t response_body = nxt_string("http.response.body"); + static const nxt_str_t response_start = nxt_string("http.response.start"); + static const nxt_str_t response_body = nxt_string("http.response.body"); - http = (nxt_py_asgi_http_t *) self; - - type = PyDict_GetItem(dict, nxt_py_type_str); - if (nxt_slow_path(type == NULL || !PyUnicode_Check(type))) { - nxt_unit_req_error(http->req, "asgi_http_send: " - "'type' is not a unicode string"); - return PyErr_Format(PyExc_TypeError, "'type' is not a unicode string"); - } + http = (nxt_py_asgi_http_t *)self; - type_str = PyUnicode_AsUTF8AndSize(type, &type_len); + type = PyDict_GetItem(dict, nxt_py_type_str); + if (nxt_slow_path(type == NULL || !PyUnicode_Check(type))) { + nxt_unit_req_error(http->req, "asgi_http_send: " + "'type' is not a unicode string"); + return PyErr_Format(PyExc_TypeError, "'type' is not a unicode string"); + } - nxt_unit_req_debug(http->req, "asgi_http_send type is '%.*s'", - (int) type_len, type_str); + type_str = PyUnicode_AsUTF8AndSize(type, &type_len); - if (nxt_unit_response_is_init(http->req)) { - if (nxt_str_eq(&response_body, type_str, (size_t) type_len)) { - return nxt_py_asgi_http_response_body(http, dict); - } - - return PyErr_Format(PyExc_RuntimeError, - "Expected ASGI message 'http.response.body', " - "but got '%U'", type); - } + nxt_unit_req_debug(http->req, "asgi_http_send type is '%.*s'", (int)type_len, + type_str); - if (nxt_str_eq(&response_start, type_str, (size_t) type_len)) { - return nxt_py_asgi_http_response_start(http, dict); + if (nxt_unit_response_is_init(http->req)) { + if (nxt_str_eq(&response_body, type_str, (size_t)type_len)) { + return nxt_py_asgi_http_response_body(http, dict); } return PyErr_Format(PyExc_RuntimeError, - "Expected ASGI message 'http.response.start', " - "but got '%U'", type); + "Expected ASGI message 'http.response.body', " + "but got '%U'", + type); + } + + if (nxt_str_eq(&response_start, type_str, (size_t)type_len)) { + return nxt_py_asgi_http_response_start(http, dict); + } + + return PyErr_Format(PyExc_RuntimeError, + "Expected ASGI message 'http.response.start', " + "but got '%U'", + type); } - -static PyObject * -nxt_py_asgi_http_response_start(nxt_py_asgi_http_t *http, PyObject *dict) -{ - int rc; - PyObject *status, *headers, *res; - nxt_py_asgi_calc_size_ctx_t calc_size_ctx; - nxt_py_asgi_add_field_ctx_t add_field_ctx; - - status = PyDict_GetItem(dict, nxt_py_status_str); - if (nxt_slow_path(status == NULL || !PyLong_Check(status))) { - nxt_unit_req_error(http->req, "asgi_http_response_start: " - "'status' is not an integer"); - return PyErr_Format(PyExc_TypeError, "'status' is not an integer"); +static PyObject *nxt_py_asgi_http_response_start(nxt_py_asgi_http_t *http, + PyObject *dict) { + int rc; + PyObject *status, *headers, *res; + nxt_py_asgi_calc_size_ctx_t calc_size_ctx; + nxt_py_asgi_add_field_ctx_t add_field_ctx; + + status = PyDict_GetItem(dict, nxt_py_status_str); + if (nxt_slow_path(status == NULL || !PyLong_Check(status))) { + nxt_unit_req_error(http->req, "asgi_http_response_start: " + "'status' is not an integer"); + return PyErr_Format(PyExc_TypeError, "'status' is not an integer"); + } + + calc_size_ctx.fields_size = 0; + calc_size_ctx.fields_count = 0; + + headers = PyDict_GetItem(dict, nxt_py_headers_str); + if (headers != NULL) { + res = nxt_py_asgi_enum_headers(headers, nxt_py_asgi_calc_size, + &calc_size_ctx); + if (nxt_slow_path(res == NULL)) { + return NULL; } - calc_size_ctx.fields_size = 0; - calc_size_ctx.fields_count = 0; + Py_DECREF(res); + } - headers = PyDict_GetItem(dict, nxt_py_headers_str); - if (headers != NULL) { - res = nxt_py_asgi_enum_headers(headers, nxt_py_asgi_calc_size, - &calc_size_ctx); - if (nxt_slow_path(res == NULL)) { - return NULL; - } + rc = nxt_unit_response_init(http->req, PyLong_AsLong(status), + calc_size_ctx.fields_count, + calc_size_ctx.fields_size); + if (nxt_slow_path(rc != NXT_UNIT_OK)) { + return PyErr_Format(PyExc_RuntimeError, + "failed to allocate response object"); + } - Py_DECREF(res); - } + add_field_ctx.req = http->req; + add_field_ctx.content_length = -1; - rc = nxt_unit_response_init(http->req, PyLong_AsLong(status), - calc_size_ctx.fields_count, - calc_size_ctx.fields_size); - if (nxt_slow_path(rc != NXT_UNIT_OK)) { - return PyErr_Format(PyExc_RuntimeError, - "failed to allocate response object"); + if (headers != NULL) { + res = nxt_py_asgi_enum_headers(headers, nxt_py_asgi_add_field, + &add_field_ctx); + if (nxt_slow_path(res == NULL)) { + return NULL; } - add_field_ctx.req = http->req; - add_field_ctx.content_length = -1; + Py_DECREF(res); + } - if (headers != NULL) { - res = nxt_py_asgi_enum_headers(headers, nxt_py_asgi_add_field, - &add_field_ctx); - if (nxt_slow_path(res == NULL)) { - return NULL; - } - - Py_DECREF(res); - } - - http->content_length = add_field_ctx.content_length; + http->content_length = add_field_ctx.content_length; - Py_INCREF(http); - return (PyObject *) http; + Py_INCREF(http); + return (PyObject *)http; } +static PyObject *nxt_py_asgi_http_response_body(nxt_py_asgi_http_t *http, + PyObject *dict) { + int rc; + char *body_str; + ssize_t sent; + PyObject *body, *more_body, *future; + Py_ssize_t body_len, body_off; + nxt_py_asgi_ctx_data_t *ctx_data; + + if (nxt_slow_path(http->complete)) { + return PyErr_Format(PyExc_RuntimeError, + "Unexpected ASGI message 'http.response.body' " + "sent, after response already completed"); + } -static PyObject * -nxt_py_asgi_http_response_body(nxt_py_asgi_http_t *http, PyObject *dict) -{ - int rc; - char *body_str; - ssize_t sent; - PyObject *body, *more_body, *future; - Py_ssize_t body_len, body_off; - nxt_py_asgi_ctx_data_t *ctx_data; - - if (nxt_slow_path(http->complete)) { - return PyErr_Format(PyExc_RuntimeError, - "Unexpected ASGI message 'http.response.body' " - "sent, after response already completed"); - } - - if (nxt_slow_path(http->send_future != NULL)) { - return PyErr_Format(PyExc_RuntimeError, "Concurrent send"); - } - - more_body = PyDict_GetItem(dict, nxt_py_more_body_str); - if (nxt_slow_path(more_body != NULL && !PyBool_Check(more_body))) { - return PyErr_Format(PyExc_TypeError, "'more_body' is not a bool"); - } - - body = PyDict_GetItem(dict, nxt_py_body_str); + if (nxt_slow_path(http->send_future != NULL)) { + return PyErr_Format(PyExc_RuntimeError, "Concurrent send"); + } - if (body != NULL) { - if (PyBytes_Check(body)) { - body_str = PyBytes_AS_STRING(body); - body_len = PyBytes_GET_SIZE(body); + more_body = PyDict_GetItem(dict, nxt_py_more_body_str); + if (nxt_slow_path(more_body != NULL && !PyBool_Check(more_body))) { + return PyErr_Format(PyExc_TypeError, "'more_body' is not a bool"); + } - } else if (PyByteArray_Check(body)) { - body_str = PyByteArray_AS_STRING(body); - body_len = PyByteArray_GET_SIZE(body); + body = PyDict_GetItem(dict, nxt_py_body_str); - } else { - return PyErr_Format(PyExc_TypeError, - "'body' is not a byte string or bytearray"); - } + if (body != NULL) { + if (PyBytes_Check(body)) { + body_str = PyBytes_AS_STRING(body); + body_len = PyBytes_GET_SIZE(body); - nxt_unit_req_debug(http->req, "asgi_http_response_body: %d, %d", - (int) body_len, (more_body == Py_True) ); + } else if (PyByteArray_Check(body)) { + body_str = PyByteArray_AS_STRING(body); + body_len = PyByteArray_GET_SIZE(body); - if (nxt_slow_path(http->bytes_sent + body_len - > http->content_length)) - { - return PyErr_Format(PyExc_RuntimeError, - "Response content longer than Content-Length"); - } + } else { + return PyErr_Format(PyExc_TypeError, + "'body' is not a byte string or bytearray"); + } - body_off = 0; + nxt_unit_req_debug(http->req, "asgi_http_response_body: %d, %d", + (int)body_len, (more_body == Py_True)); - ctx_data = http->req->ctx->data; + if (nxt_slow_path(http->bytes_sent + body_len > http->content_length)) { + return PyErr_Format(PyExc_RuntimeError, + "Response content longer than Content-Length"); + } - while (body_len > 0) { - sent = nxt_unit_response_write_nb(http->req, body_str, body_len, 0); - if (nxt_slow_path(sent < 0)) { - return PyErr_Format(PyExc_RuntimeError, "failed to send body"); - } + body_off = 0; - if (nxt_slow_path(sent == 0)) { - nxt_unit_req_debug(http->req, "asgi_http_response_body: " - "out of shared memory, %d", - (int) body_len); + ctx_data = http->req->ctx->data; - future = PyObject_CallObject(ctx_data->loop_create_future, - NULL); - if (nxt_slow_path(future == NULL)) { - nxt_unit_req_alert(http->req, - "Python failed to create Future object"); - nxt_python_print_exception(); + while (body_len > 0) { + sent = nxt_unit_response_write_nb(http->req, body_str, body_len, 0); + if (nxt_slow_path(sent < 0)) { + return PyErr_Format(PyExc_RuntimeError, "failed to send body"); + } + + if (nxt_slow_path(sent == 0)) { + nxt_unit_req_debug(http->req, + "asgi_http_response_body: " + "out of shared memory, %d", + (int)body_len); + + future = PyObject_CallObject(ctx_data->loop_create_future, NULL); + if (nxt_slow_path(future == NULL)) { + nxt_unit_req_alert(http->req, + "Python failed to create Future object"); + nxt_python_print_exception(); + + return PyErr_Format(PyExc_RuntimeError, + "failed to create Future object"); + } - return PyErr_Format(PyExc_RuntimeError, - "failed to create Future object"); - } + http->send_body = body; + Py_INCREF(http->send_body); + http->send_body_off = body_off; - http->send_body = body; - Py_INCREF(http->send_body); - http->send_body_off = body_off; + nxt_py_asgi_drain_wait(http->req, &http->link); - nxt_py_asgi_drain_wait(http->req, &http->link); + http->send_future = future; + Py_INCREF(http->send_future); - http->send_future = future; - Py_INCREF(http->send_future); + return future; + } - return future; - } + body_str += sent; + body_len -= sent; + body_off += sent; + http->bytes_sent += sent; + } - body_str += sent; - body_len -= sent; - body_off += sent; - http->bytes_sent += sent; - } + } else { + nxt_unit_req_debug(http->req, "asgi_http_response_body: 0, %d", + (more_body == Py_True)); - } else { - nxt_unit_req_debug(http->req, "asgi_http_response_body: 0, %d", - (more_body == Py_True) ); - - if (!nxt_unit_response_is_sent(http->req)) { - rc = nxt_unit_response_send(http->req); - if (nxt_slow_path(rc != NXT_UNIT_OK)) { - return PyErr_Format(PyExc_RuntimeError, - "failed to send response"); - } - } + if (!nxt_unit_response_is_sent(http->req)) { + rc = nxt_unit_response_send(http->req); + if (nxt_slow_path(rc != NXT_UNIT_OK)) { + return PyErr_Format(PyExc_RuntimeError, "failed to send response"); + } } + } - if (more_body == NULL || more_body == Py_False) { - http->complete = 1; + if (more_body == NULL || more_body == Py_False) { + http->complete = 1; - nxt_py_asgi_http_emit_disconnect(http); - } + nxt_py_asgi_http_emit_disconnect(http); + } - Py_INCREF(http); - return (PyObject *) http; + Py_INCREF(http); + return (PyObject *)http; } +static void nxt_py_asgi_http_emit_disconnect(nxt_py_asgi_http_t *http) { + PyObject *msg, *future; -static void -nxt_py_asgi_http_emit_disconnect(nxt_py_asgi_http_t *http) -{ - PyObject *msg, *future; - - if (http->receive_future == NULL) { - return; - } + if (http->receive_future == NULL) { + return; + } - msg = nxt_py_asgi_new_msg(http->req, nxt_py_http_disconnect_str); - if (nxt_slow_path(msg == NULL)) { - return; - } + msg = nxt_py_asgi_new_msg(http->req, nxt_py_http_disconnect_str); + if (nxt_slow_path(msg == NULL)) { + return; + } - if (msg == Py_None) { - Py_DECREF(msg); - return; - } + if (msg == Py_None) { + Py_DECREF(msg); + return; + } - future = http->receive_future; - http->receive_future = NULL; + future = http->receive_future; + http->receive_future = NULL; - nxt_py_asgi_http_set_result(http, future, msg); + nxt_py_asgi_http_set_result(http, future, msg); - Py_DECREF(msg); + Py_DECREF(msg); } +static void nxt_py_asgi_http_set_result(nxt_py_asgi_http_t *http, + PyObject *future, PyObject *msg) { + PyObject *res; -static void -nxt_py_asgi_http_set_result(nxt_py_asgi_http_t *http, PyObject *future, - PyObject *msg) -{ - PyObject *res; + res = PyObject_CallMethodObjArgs(future, nxt_py_done_str, NULL); + if (nxt_slow_path(res == NULL)) { + nxt_unit_req_alert(http->req, "'done' call failed"); + nxt_python_print_exception(); + } - res = PyObject_CallMethodObjArgs(future, nxt_py_done_str, NULL); + if (nxt_fast_path(res == Py_False)) { + res = PyObject_CallMethodObjArgs(future, nxt_py_set_result_str, msg, NULL); if (nxt_slow_path(res == NULL)) { - nxt_unit_req_alert(http->req, "'done' call failed"); - nxt_python_print_exception(); + nxt_unit_req_alert(http->req, "'set_result' call failed"); + nxt_python_print_exception(); } - if (nxt_fast_path(res == Py_False)) { - res = PyObject_CallMethodObjArgs(future, nxt_py_set_result_str, msg, - NULL); - if (nxt_slow_path(res == NULL)) { - nxt_unit_req_alert(http->req, "'set_result' call failed"); - nxt_python_print_exception(); - } - - } else { - res = NULL; - } + } else { + res = NULL; + } - Py_XDECREF(res); - Py_DECREF(future); + Py_XDECREF(res); + Py_DECREF(future); } +void nxt_py_asgi_http_data_handler(nxt_unit_request_info_t *req) { + PyObject *msg, *future; + nxt_py_asgi_http_t *http; -void -nxt_py_asgi_http_data_handler(nxt_unit_request_info_t *req) -{ - PyObject *msg, *future; - nxt_py_asgi_http_t *http; + http = req->data; - http = req->data; + nxt_unit_req_debug(req, "asgi_http_data_handler"); - nxt_unit_req_debug(req, "asgi_http_data_handler"); + if (http->receive_future == NULL) { + return; + } - if (http->receive_future == NULL) { - return; - } + msg = nxt_py_asgi_http_read_msg(http); + if (nxt_slow_path(msg == NULL)) { + return; + } - msg = nxt_py_asgi_http_read_msg(http); - if (nxt_slow_path(msg == NULL)) { - return; - } + if (msg == Py_None) { + Py_DECREF(msg); + return; + } - if (msg == Py_None) { - Py_DECREF(msg); - return; - } + future = http->receive_future; + http->receive_future = NULL; - future = http->receive_future; - http->receive_future = NULL; + nxt_py_asgi_http_set_result(http, future, msg); - nxt_py_asgi_http_set_result(http, future, msg); - - Py_DECREF(msg); + Py_DECREF(msg); } +int nxt_py_asgi_http_drain(nxt_queue_link_t *lnk) { + char *body_str; + ssize_t sent; + PyObject *future, *exc, *res; + Py_ssize_t body_len; + nxt_py_asgi_http_t *http; -int -nxt_py_asgi_http_drain(nxt_queue_link_t *lnk) -{ - char *body_str; - ssize_t sent; - PyObject *future, *exc, *res; - Py_ssize_t body_len; - nxt_py_asgi_http_t *http; + http = nxt_container_of(lnk, nxt_py_asgi_http_t, link); - http = nxt_container_of(lnk, nxt_py_asgi_http_t, link); + body_str = PyBytes_AS_STRING(http->send_body) + http->send_body_off; + body_len = PyBytes_GET_SIZE(http->send_body) - http->send_body_off; - body_str = PyBytes_AS_STRING(http->send_body) + http->send_body_off; - body_len = PyBytes_GET_SIZE(http->send_body) - http->send_body_off; + nxt_unit_req_debug(http->req, "asgi_http_drain: %d", (int)body_len); - nxt_unit_req_debug(http->req, "asgi_http_drain: %d", (int) body_len); - - while (body_len > 0) { - sent = nxt_unit_response_write_nb(http->req, body_str, body_len, 0); - if (nxt_slow_path(sent < 0)) { - goto fail; - } + while (body_len > 0) { + sent = nxt_unit_response_write_nb(http->req, body_str, body_len, 0); + if (nxt_slow_path(sent < 0)) { + goto fail; + } - if (nxt_slow_path(sent == 0)) { - return NXT_UNIT_AGAIN; - } + if (nxt_slow_path(sent == 0)) { + return NXT_UNIT_AGAIN; + } - body_str += sent; - body_len -= sent; + body_str += sent; + body_len -= sent; - http->send_body_off += sent; - http->bytes_sent += sent; - } + http->send_body_off += sent; + http->bytes_sent += sent; + } - Py_CLEAR(http->send_body); + Py_CLEAR(http->send_body); - future = http->send_future; - http->send_future = NULL; + future = http->send_future; + http->send_future = NULL; - nxt_py_asgi_http_set_result(http, future, Py_None); + nxt_py_asgi_http_set_result(http, future, Py_None); - return NXT_UNIT_OK; + return NXT_UNIT_OK; fail: - exc = PyObject_CallFunctionObjArgs(PyExc_RuntimeError, - nxt_py_failed_to_send_body_str, - NULL); - if (nxt_slow_path(exc == NULL)) { - nxt_unit_req_alert(http->req, "RuntimeError create failed"); - nxt_python_print_exception(); + exc = PyObject_CallFunctionObjArgs(PyExc_RuntimeError, + nxt_py_failed_to_send_body_str, NULL); + if (nxt_slow_path(exc == NULL)) { + nxt_unit_req_alert(http->req, "RuntimeError create failed"); + nxt_python_print_exception(); - exc = Py_None; - Py_INCREF(exc); - } + exc = Py_None; + Py_INCREF(exc); + } - future = http->send_future; - http->send_future = NULL; + future = http->send_future; + http->send_future = NULL; - res = PyObject_CallMethodObjArgs(future, nxt_py_set_exception_str, exc, - NULL); - if (nxt_slow_path(res == NULL)) { - nxt_unit_req_alert(http->req, "'set_exception' call failed"); - nxt_python_print_exception(); - } + res = PyObject_CallMethodObjArgs(future, nxt_py_set_exception_str, exc, NULL); + if (nxt_slow_path(res == NULL)) { + nxt_unit_req_alert(http->req, "'set_exception' call failed"); + nxt_python_print_exception(); + } - Py_XDECREF(res); - Py_DECREF(future); - Py_DECREF(exc); + Py_XDECREF(res); + Py_DECREF(future); + Py_DECREF(exc); - return NXT_UNIT_ERROR; + return NXT_UNIT_ERROR; } +void nxt_py_asgi_http_close_handler(nxt_unit_request_info_t *req) { + nxt_py_asgi_http_t *http; -void -nxt_py_asgi_http_close_handler(nxt_unit_request_info_t *req) -{ - nxt_py_asgi_http_t *http; + http = req->data; - http = req->data; + nxt_unit_req_debug(req, "asgi_http_close_handler"); - nxt_unit_req_debug(req, "asgi_http_close_handler"); + if (nxt_fast_path(http != NULL)) { + http->closed = 1; - if (nxt_fast_path(http != NULL)) { - http->closed = 1; - - nxt_py_asgi_http_emit_disconnect(http); - } + nxt_py_asgi_http_emit_disconnect(http); + } } +static PyObject *nxt_py_asgi_http_done(PyObject *self, PyObject *future) { + int rc; + PyObject *res; + nxt_py_asgi_http_t *http; -static PyObject * -nxt_py_asgi_http_done(PyObject *self, PyObject *future) -{ - int rc; - PyObject *res; - nxt_py_asgi_http_t *http; + http = (nxt_py_asgi_http_t *)self; - http = (nxt_py_asgi_http_t *) self; + nxt_unit_req_debug(http->req, "asgi_http_done"); - nxt_unit_req_debug(http->req, "asgi_http_done"); + /* + * Get Future.result() and it raises an exception, if coroutine exited + * with exception. + */ + res = PyObject_CallMethodObjArgs(future, nxt_py_result_str, NULL); + if (nxt_slow_path(res == NULL)) { + nxt_unit_req_error(http->req, "Python failed to call 'future.result()'"); + nxt_python_print_exception(); - /* - * Get Future.result() and it raises an exception, if coroutine exited - * with exception. - */ - res = PyObject_CallMethodObjArgs(future, nxt_py_result_str, NULL); - if (nxt_slow_path(res == NULL)) { - nxt_unit_req_error(http->req, - "Python failed to call 'future.result()'"); - nxt_python_print_exception(); + rc = NXT_UNIT_ERROR; - rc = NXT_UNIT_ERROR; + } else { + Py_DECREF(res); - } else { - Py_DECREF(res); + rc = NXT_UNIT_OK; + } - rc = NXT_UNIT_OK; - } - - nxt_unit_request_done(http->req, rc); + nxt_unit_request_done(http->req, rc); - Py_RETURN_NONE; + Py_RETURN_NONE; } - #endif /* NXT_HAVE_ASGI */ diff --git a/src/python/nxt_python_asgi_lifespan.c b/src/python/nxt_python_asgi_lifespan.c index 041cca212..3782672e5 100644 --- a/src/python/nxt_python_asgi_lifespan.c +++ b/src/python/nxt_python_asgi_lifespan.c @@ -3,7 +3,6 @@ * Copyright (C) NGINX, Inc. */ - #include #if (NXT_HAVE_ASGI) @@ -14,65 +13,64 @@ #include - -typedef struct { - PyObject_HEAD - nxt_py_asgi_ctx_data_t *ctx_data; - int disabled; - int startup_received; - int startup_sent; - int shutdown_received; - int shutdown_sent; - int shutdown_called; - PyObject *startup_future; - PyObject *shutdown_future; - PyObject *receive_future; - PyObject *state; +typedef struct { + PyObject_HEAD nxt_py_asgi_ctx_data_t *ctx_data; + int disabled; + int startup_received; + int startup_sent; + int shutdown_received; + int shutdown_sent; + int shutdown_called; + PyObject *startup_future; + PyObject *shutdown_future; + PyObject *receive_future; + PyObject *state; } nxt_py_asgi_lifespan_t; -static PyObject *nxt_py_asgi_lifespan_target_startup( - nxt_py_asgi_ctx_data_t *ctx_data, nxt_python_target_t *target); -static int nxt_py_asgi_lifespan_target_shutdown( - nxt_py_asgi_lifespan_t *lifespan); +static PyObject * +nxt_py_asgi_lifespan_target_startup(nxt_py_asgi_ctx_data_t *ctx_data, + nxt_python_target_t *target); +static int +nxt_py_asgi_lifespan_target_shutdown(nxt_py_asgi_lifespan_t *lifespan); static PyObject *nxt_py_asgi_lifespan_receive(PyObject *self, PyObject *none); static PyObject *nxt_py_asgi_lifespan_send(PyObject *self, PyObject *dict); -static PyObject *nxt_py_asgi_lifespan_send_startup( - nxt_py_asgi_lifespan_t *lifespan, int v, PyObject *dict); +static PyObject * +nxt_py_asgi_lifespan_send_startup(nxt_py_asgi_lifespan_t *lifespan, int v, + PyObject *dict); static PyObject *nxt_py_asgi_lifespan_send_(nxt_py_asgi_lifespan_t *lifespan, - int v, int *sent, PyObject **future); -static PyObject *nxt_py_asgi_lifespan_send_shutdown( - nxt_py_asgi_lifespan_t *lifespan, int v, PyObject *dict); + int v, int *sent, + PyObject **future); +static PyObject * +nxt_py_asgi_lifespan_send_shutdown(nxt_py_asgi_lifespan_t *lifespan, int v, + PyObject *dict); static PyObject *nxt_py_asgi_lifespan_disable(nxt_py_asgi_lifespan_t *lifespan); static PyObject *nxt_py_asgi_lifespan_done(PyObject *self, PyObject *future); static void nxt_py_asgi_lifespan_dealloc(PyObject *self); - static PyMethodDef nxt_py_asgi_lifespan_methods[] = { - { "receive", nxt_py_asgi_lifespan_receive, METH_NOARGS, 0 }, - { "send", nxt_py_asgi_lifespan_send, METH_O, 0 }, - { "_done", nxt_py_asgi_lifespan_done, METH_O, 0 }, - { NULL, NULL, 0, 0 } -}; + {"receive", nxt_py_asgi_lifespan_receive, METH_NOARGS, 0}, + {"send", nxt_py_asgi_lifespan_send, METH_O, 0}, + {"_done", nxt_py_asgi_lifespan_done, METH_O, 0}, + {NULL, NULL, 0, 0}}; static PyMemberDef nxt_py_asgi_lifespan_members[] = { { #if PY_VERSION_HEX >= NXT_PYTHON_VER(3, 7) - .name = "state", + .name = "state", #else - .name = (char *)"state", + .name = (char *)"state", #endif - .type = T_OBJECT_EX, + .type = T_OBJECT_EX, .offset = offsetof(nxt_py_asgi_lifespan_t, state), - .flags = READONLY, + .flags = READONLY, #if PY_VERSION_HEX >= NXT_PYTHON_VER(3, 7) - .doc = PyDoc_STR("lifespan.state") + .doc = PyDoc_STR("lifespan.state") #else - .doc = (char *)PyDoc_STR("lifespan.state") + .doc = (char *)PyDoc_STR("lifespan.state") #endif }, - { NULL, 0, 0, 0, NULL } -}; + {NULL, 0, 0, 0, NULL}}; static PyAsyncMethods nxt_py_asgi_async_methods = { .am_await = nxt_py_asgi_await, @@ -81,579 +79,533 @@ static PyAsyncMethods nxt_py_asgi_async_methods = { static PyTypeObject nxt_py_asgi_lifespan_type = { PyVarObject_HEAD_INIT(NULL, 0) - .tp_name = "unit._asgi_lifespan", + .tp_name = "unit._asgi_lifespan", .tp_basicsize = sizeof(nxt_py_asgi_lifespan_t), - .tp_dealloc = nxt_py_asgi_lifespan_dealloc, - .tp_as_async = &nxt_py_asgi_async_methods, - .tp_flags = Py_TPFLAGS_DEFAULT, - .tp_doc = "unit ASGI Lifespan object", - .tp_iter = nxt_py_asgi_iter, - .tp_iternext = nxt_py_asgi_next, - .tp_methods = nxt_py_asgi_lifespan_methods, - .tp_members = nxt_py_asgi_lifespan_members, + .tp_dealloc = nxt_py_asgi_lifespan_dealloc, + .tp_as_async = &nxt_py_asgi_async_methods, + .tp_flags = Py_TPFLAGS_DEFAULT, + .tp_doc = "unit ASGI Lifespan object", + .tp_iter = nxt_py_asgi_iter, + .tp_iternext = nxt_py_asgi_next, + .tp_methods = nxt_py_asgi_lifespan_methods, + .tp_members = nxt_py_asgi_lifespan_members, }; +int nxt_py_asgi_lifespan_startup(nxt_py_asgi_ctx_data_t *ctx_data) { + size_t size; + PyObject *lifespan; + PyObject **target_lifespans; + nxt_int_t i; + nxt_python_target_t *target; -int -nxt_py_asgi_lifespan_startup(nxt_py_asgi_ctx_data_t *ctx_data) -{ - size_t size; - PyObject *lifespan; - PyObject **target_lifespans; - nxt_int_t i; - nxt_python_target_t *target; + size = nxt_py_targets->count * sizeof(PyObject *); - size = nxt_py_targets->count * sizeof(PyObject*); + target_lifespans = nxt_unit_malloc(NULL, size); + if (nxt_slow_path(target_lifespans == NULL)) { + nxt_unit_alert(NULL, "Failed to allocate lifespan data"); + return NXT_UNIT_ERROR; + } - target_lifespans = nxt_unit_malloc(NULL, size); - if (nxt_slow_path(target_lifespans == NULL)) { - nxt_unit_alert(NULL, "Failed to allocate lifespan data"); - return NXT_UNIT_ERROR; - } - - memset(target_lifespans, 0, size); + memset(target_lifespans, 0, size); - for (i = 0; i < nxt_py_targets->count; i++) { - target = &nxt_py_targets->target[i]; + for (i = 0; i < nxt_py_targets->count; i++) { + target = &nxt_py_targets->target[i]; - lifespan = nxt_py_asgi_lifespan_target_startup(ctx_data, target); - if (nxt_slow_path(lifespan == NULL)) { - return NXT_UNIT_ERROR; - } - - target_lifespans[i] = lifespan; + lifespan = nxt_py_asgi_lifespan_target_startup(ctx_data, target); + if (nxt_slow_path(lifespan == NULL)) { + return NXT_UNIT_ERROR; } - ctx_data->target_lifespans = target_lifespans; + target_lifespans[i] = lifespan; + } - return NXT_UNIT_OK; -} + ctx_data->target_lifespans = target_lifespans; + return NXT_UNIT_OK; +} static PyObject * nxt_py_asgi_lifespan_target_startup(nxt_py_asgi_ctx_data_t *ctx_data, - nxt_python_target_t *target) -{ - PyObject *scope, *res, *py_task, *receive, *send, *done; - PyObject *stage2; - nxt_py_asgi_lifespan_t *lifespan, *ret; - - if (nxt_slow_path(PyType_Ready(&nxt_py_asgi_lifespan_type) != 0)) { - nxt_unit_alert(NULL, - "Python failed to initialize the 'asgi_lifespan' type object"); - return NULL; - } + nxt_python_target_t *target) { + PyObject *scope, *res, *py_task, *receive, *send, *done; + PyObject *stage2; + nxt_py_asgi_lifespan_t *lifespan, *ret; + + if (nxt_slow_path(PyType_Ready(&nxt_py_asgi_lifespan_type) != 0)) { + nxt_unit_alert( + NULL, "Python failed to initialize the 'asgi_lifespan' type object"); + return NULL; + } + + lifespan = PyObject_New(nxt_py_asgi_lifespan_t, &nxt_py_asgi_lifespan_type); + if (nxt_slow_path(lifespan == NULL)) { + nxt_unit_alert(NULL, "Python failed to create lifespan object"); + return NULL; + } + + ret = NULL; + + receive = PyObject_GetAttrString((PyObject *)lifespan, "receive"); + if (nxt_slow_path(receive == NULL)) { + nxt_unit_alert(NULL, "Python failed to get 'receive' method"); + goto release_lifespan; + } + + send = PyObject_GetAttrString((PyObject *)lifespan, "send"); + if (nxt_slow_path(receive == NULL)) { + nxt_unit_alert(NULL, "Python failed to get 'send' method"); + goto release_receive; + } + + done = PyObject_GetAttrString((PyObject *)lifespan, "_done"); + if (nxt_slow_path(receive == NULL)) { + nxt_unit_alert(NULL, "Python failed to get '_done' method"); + goto release_send; + } + + lifespan->startup_future = + PyObject_CallObject(ctx_data->loop_create_future, NULL); + if (nxt_slow_path(lifespan->startup_future == NULL)) { + nxt_unit_alert(NULL, "Python failed to create Future object"); + nxt_python_print_exception(); + + goto release_done; + } + + lifespan->ctx_data = ctx_data; + lifespan->disabled = 0; + lifespan->startup_received = 0; + lifespan->startup_sent = 0; + lifespan->shutdown_received = 0; + lifespan->shutdown_sent = 0; + lifespan->shutdown_called = 0; + lifespan->shutdown_future = NULL; + lifespan->receive_future = NULL; + lifespan->state = NULL; + + scope = nxt_py_asgi_new_scope(NULL, nxt_py_lifespan_str, nxt_py_2_0_str); + if (nxt_slow_path(scope == NULL)) { + goto release_future; + } + + lifespan->state = PyDict_New(); + if (nxt_slow_path(lifespan->state == NULL)) { + nxt_unit_req_error(NULL, "Python failed to create 'state' dict"); + goto release_future; + } + + if (nxt_slow_path(PyDict_SetItem(scope, nxt_py_state_str, lifespan->state) == + -1)) { + nxt_unit_req_error(NULL, "Python failed to set 'scope.state' item"); + Py_CLEAR(lifespan->state); + goto release_future; + } - lifespan = PyObject_New(nxt_py_asgi_lifespan_t, &nxt_py_asgi_lifespan_type); - if (nxt_slow_path(lifespan == NULL)) { - nxt_unit_alert(NULL, "Python failed to create lifespan object"); - return NULL; - } + if (!target->asgi_legacy) { + nxt_unit_req_debug(NULL, "Python call ASGI 3.0 application"); - ret = NULL; + res = PyObject_CallFunctionObjArgs(target->application, scope, receive, + send, NULL); - receive = PyObject_GetAttrString((PyObject *) lifespan, "receive"); - if (nxt_slow_path(receive == NULL)) { - nxt_unit_alert(NULL, "Python failed to get 'receive' method"); - goto release_lifespan; - } + } else { + nxt_unit_req_debug(NULL, "Python call legacy application"); - send = PyObject_GetAttrString((PyObject *) lifespan, "send"); - if (nxt_slow_path(receive == NULL)) { - nxt_unit_alert(NULL, "Python failed to get 'send' method"); - goto release_receive; - } + res = PyObject_CallFunctionObjArgs(target->application, scope, NULL); + if (nxt_slow_path(res == NULL)) { + nxt_unit_log(NULL, NXT_UNIT_LOG_INFO, + "ASGI Lifespan processing exception"); + nxt_python_print_exception(); - done = PyObject_GetAttrString((PyObject *) lifespan, "_done"); - if (nxt_slow_path(receive == NULL)) { - nxt_unit_alert(NULL, "Python failed to get '_done' method"); - goto release_send; - } + lifespan->disabled = 1; - lifespan->startup_future = PyObject_CallObject(ctx_data->loop_create_future, - NULL); - if (nxt_slow_path(lifespan->startup_future == NULL)) { - nxt_unit_alert(NULL, "Python failed to create Future object"); - nxt_python_print_exception(); + Py_INCREF(lifespan); + ret = lifespan; - goto release_done; + goto release_scope; } - lifespan->ctx_data = ctx_data; - lifespan->disabled = 0; - lifespan->startup_received = 0; - lifespan->startup_sent = 0; - lifespan->shutdown_received = 0; - lifespan->shutdown_sent = 0; - lifespan->shutdown_called = 0; - lifespan->shutdown_future = NULL; - lifespan->receive_future = NULL; - lifespan->state = NULL; - - scope = nxt_py_asgi_new_scope(NULL, nxt_py_lifespan_str, nxt_py_2_0_str); - if (nxt_slow_path(scope == NULL)) { - goto release_future; - } + if (nxt_slow_path(PyCallable_Check(res) == 0)) { + nxt_unit_req_error(NULL, + "Legacy ASGI application returns not a callable"); - lifespan->state = PyDict_New(); - if (nxt_slow_path(lifespan->state == NULL)) { - nxt_unit_req_error(NULL, - "Python failed to create 'state' dict"); - goto release_future; - } + Py_DECREF(res); - if (nxt_slow_path(PyDict_SetItem(scope, nxt_py_state_str, - lifespan->state) == -1)) - { - nxt_unit_req_error(NULL, - "Python failed to set 'scope.state' item"); - Py_CLEAR(lifespan->state); - goto release_future; + goto release_scope; } - if (!target->asgi_legacy) { - nxt_unit_req_debug(NULL, "Python call ASGI 3.0 application"); - - res = PyObject_CallFunctionObjArgs(target->application, - scope, receive, send, NULL); - - } else { - nxt_unit_req_debug(NULL, "Python call legacy application"); - - res = PyObject_CallFunctionObjArgs(target->application, scope, NULL); - if (nxt_slow_path(res == NULL)) { - nxt_unit_log(NULL, NXT_UNIT_LOG_INFO, - "ASGI Lifespan processing exception"); - nxt_python_print_exception(); - - lifespan->disabled = 1; - - Py_INCREF(lifespan); - ret = lifespan; - - goto release_scope; - } - - if (nxt_slow_path(PyCallable_Check(res) == 0)) { - nxt_unit_req_error(NULL, - "Legacy ASGI application returns not a callable"); + stage2 = res; - Py_DECREF(res); + res = PyObject_CallFunctionObjArgs(stage2, receive, send, NULL); - goto release_scope; - } + Py_DECREF(stage2); + } - stage2 = res; - - res = PyObject_CallFunctionObjArgs(stage2, receive, send, NULL); - - Py_DECREF(stage2); - } - - if (nxt_slow_path(res == NULL)) { - nxt_unit_error(NULL, "Python failed to call the application"); - nxt_python_print_exception(); - goto release_scope; - } - - if (nxt_slow_path(!PyCoro_CheckExact(res))) { - nxt_unit_error(NULL, "Application result type is not a coroutine"); - Py_DECREF(res); - goto release_scope; - } + if (nxt_slow_path(res == NULL)) { + nxt_unit_error(NULL, "Python failed to call the application"); + nxt_python_print_exception(); + goto release_scope; + } - py_task = PyObject_CallFunctionObjArgs(ctx_data->loop_create_task, res, - NULL); - if (nxt_slow_path(py_task == NULL)) { - nxt_unit_alert(NULL, "Python failed to call the create_task"); - nxt_python_print_exception(); - Py_DECREF(res); - goto release_scope; - } + if (nxt_slow_path(!PyCoro_CheckExact(res))) { + nxt_unit_error(NULL, "Application result type is not a coroutine"); + Py_DECREF(res); + goto release_scope; + } + py_task = PyObject_CallFunctionObjArgs(ctx_data->loop_create_task, res, NULL); + if (nxt_slow_path(py_task == NULL)) { + nxt_unit_alert(NULL, "Python failed to call the create_task"); + nxt_python_print_exception(); Py_DECREF(res); + goto release_scope; + } - res = PyObject_CallMethodObjArgs(py_task, nxt_py_add_done_callback_str, - done, NULL); - if (nxt_slow_path(res == NULL)) { - nxt_unit_alert(NULL, "Python failed to call 'task.add_done_callback'"); - nxt_python_print_exception(); - goto release_task; - } + Py_DECREF(res); - Py_DECREF(res); + res = PyObject_CallMethodObjArgs(py_task, nxt_py_add_done_callback_str, done, + NULL); + if (nxt_slow_path(res == NULL)) { + nxt_unit_alert(NULL, "Python failed to call 'task.add_done_callback'"); + nxt_python_print_exception(); + goto release_task; + } - res = PyObject_CallFunctionObjArgs(ctx_data->loop_run_until_complete, - lifespan->startup_future, NULL); - if (nxt_slow_path(res == NULL)) { - nxt_unit_alert(NULL, "Python failed to call loop.run_until_complete"); - nxt_python_print_exception(); - goto release_task; - } + Py_DECREF(res); - Py_DECREF(res); + res = PyObject_CallFunctionObjArgs(ctx_data->loop_run_until_complete, + lifespan->startup_future, NULL); + if (nxt_slow_path(res == NULL)) { + nxt_unit_alert(NULL, "Python failed to call loop.run_until_complete"); + nxt_python_print_exception(); + goto release_task; + } - if (lifespan->startup_sent == 1 || lifespan->disabled) { - Py_INCREF(lifespan); + Py_DECREF(res); - ret = lifespan; - } + if (lifespan->startup_sent == 1 || lifespan->disabled) { + Py_INCREF(lifespan); + + ret = lifespan; + } release_task: - Py_DECREF(py_task); + Py_DECREF(py_task); release_scope: - Py_DECREF(scope); + Py_DECREF(scope); release_future: - Py_CLEAR(lifespan->startup_future); + Py_CLEAR(lifespan->startup_future); release_done: - Py_DECREF(done); + Py_DECREF(done); release_send: - Py_DECREF(send); + Py_DECREF(send); release_receive: - Py_DECREF(receive); + Py_DECREF(receive); release_lifespan: - Py_DECREF(lifespan); + Py_DECREF(lifespan); - return (PyObject *) ret; + return (PyObject *)ret; } +int nxt_py_asgi_lifespan_shutdown(nxt_unit_ctx_t *ctx) { + nxt_int_t i, ret; + nxt_py_asgi_lifespan_t *lifespan; + nxt_py_asgi_ctx_data_t *ctx_data; -int -nxt_py_asgi_lifespan_shutdown(nxt_unit_ctx_t *ctx) -{ - nxt_int_t i, ret; - nxt_py_asgi_lifespan_t *lifespan; - nxt_py_asgi_ctx_data_t *ctx_data; - - ctx_data = ctx->data; + ctx_data = ctx->data; - for (i = 0; i < nxt_py_targets->count; i++) { - lifespan = (nxt_py_asgi_lifespan_t *)ctx_data->target_lifespans[i]; + for (i = 0; i < nxt_py_targets->count; i++) { + lifespan = (nxt_py_asgi_lifespan_t *)ctx_data->target_lifespans[i]; - ret = nxt_py_asgi_lifespan_target_shutdown(lifespan); - if (nxt_slow_path(ret != NXT_UNIT_OK)) { - return NXT_UNIT_ERROR; - } + ret = nxt_py_asgi_lifespan_target_shutdown(lifespan); + if (nxt_slow_path(ret != NXT_UNIT_OK)) { + return NXT_UNIT_ERROR; } + } - nxt_unit_free(NULL, ctx_data->target_lifespans); + nxt_unit_free(NULL, ctx_data->target_lifespans); - return NXT_UNIT_OK; + return NXT_UNIT_OK; } - static int -nxt_py_asgi_lifespan_target_shutdown(nxt_py_asgi_lifespan_t *lifespan) -{ - PyObject *msg, *future, *res; - nxt_py_asgi_ctx_data_t *ctx_data; +nxt_py_asgi_lifespan_target_shutdown(nxt_py_asgi_lifespan_t *lifespan) { + PyObject *msg, *future, *res; + nxt_py_asgi_ctx_data_t *ctx_data; - ctx_data = lifespan->ctx_data; - - if (nxt_slow_path(lifespan == NULL || lifespan->disabled)) { - return NXT_UNIT_OK; - } + ctx_data = lifespan->ctx_data; - lifespan->shutdown_called = 1; - - if (lifespan->receive_future != NULL) { - future = lifespan->receive_future; - lifespan->receive_future = NULL; - - msg = nxt_py_asgi_new_msg(NULL, nxt_py_lifespan_shutdown_str); - - if (nxt_fast_path(msg != NULL)) { - res = PyObject_CallMethodObjArgs(future, nxt_py_set_result_str, - msg, NULL); - Py_XDECREF(res); - Py_DECREF(msg); - } + if (nxt_slow_path(lifespan == NULL || lifespan->disabled)) { + return NXT_UNIT_OK; + } - Py_DECREF(future); - } + lifespan->shutdown_called = 1; - if (lifespan->shutdown_sent) { - return NXT_UNIT_OK; - } + if (lifespan->receive_future != NULL) { + future = lifespan->receive_future; + lifespan->receive_future = NULL; - lifespan->shutdown_future = PyObject_CallObject(ctx_data->loop_create_future, - NULL); - if (nxt_slow_path(lifespan->shutdown_future == NULL)) { - nxt_unit_alert(NULL, "Python failed to create Future object"); - nxt_python_print_exception(); - return NXT_UNIT_ERROR; - } + msg = nxt_py_asgi_new_msg(NULL, nxt_py_lifespan_shutdown_str); - res = PyObject_CallFunctionObjArgs(ctx_data->loop_run_until_complete, - lifespan->shutdown_future, NULL); - if (nxt_slow_path(res == NULL)) { - nxt_unit_alert(NULL, "Python failed to call loop.run_until_complete"); - nxt_python_print_exception(); - return NXT_UNIT_ERROR; + if (nxt_fast_path(msg != NULL)) { + res = + PyObject_CallMethodObjArgs(future, nxt_py_set_result_str, msg, NULL); + Py_XDECREF(res); + Py_DECREF(msg); } - Py_DECREF(res); - Py_CLEAR(lifespan->shutdown_future); + Py_DECREF(future); + } + if (lifespan->shutdown_sent) { return NXT_UNIT_OK; + } + + lifespan->shutdown_future = + PyObject_CallObject(ctx_data->loop_create_future, NULL); + if (nxt_slow_path(lifespan->shutdown_future == NULL)) { + nxt_unit_alert(NULL, "Python failed to create Future object"); + nxt_python_print_exception(); + return NXT_UNIT_ERROR; + } + + res = PyObject_CallFunctionObjArgs(ctx_data->loop_run_until_complete, + lifespan->shutdown_future, NULL); + if (nxt_slow_path(res == NULL)) { + nxt_unit_alert(NULL, "Python failed to call loop.run_until_complete"); + nxt_python_print_exception(); + return NXT_UNIT_ERROR; + } + + Py_DECREF(res); + Py_CLEAR(lifespan->shutdown_future); + + return NXT_UNIT_OK; } +static PyObject *nxt_py_asgi_lifespan_receive(PyObject *self, PyObject *none) { + PyObject *msg, *future; + nxt_py_asgi_lifespan_t *lifespan; + nxt_py_asgi_ctx_data_t *ctx_data; -static PyObject * -nxt_py_asgi_lifespan_receive(PyObject *self, PyObject *none) -{ - PyObject *msg, *future; - nxt_py_asgi_lifespan_t *lifespan; - nxt_py_asgi_ctx_data_t *ctx_data; - - lifespan = (nxt_py_asgi_lifespan_t *) self; - ctx_data = lifespan->ctx_data; + lifespan = (nxt_py_asgi_lifespan_t *)self; + ctx_data = lifespan->ctx_data; - nxt_unit_debug(NULL, "asgi_lifespan_receive"); + nxt_unit_debug(NULL, "asgi_lifespan_receive"); - future = PyObject_CallObject(ctx_data->loop_create_future, NULL); - if (nxt_slow_path(future == NULL)) { - nxt_unit_alert(NULL, "Python failed to create Future object"); - nxt_python_print_exception(); + future = PyObject_CallObject(ctx_data->loop_create_future, NULL); + if (nxt_slow_path(future == NULL)) { + nxt_unit_alert(NULL, "Python failed to create Future object"); + nxt_python_print_exception(); - return PyErr_Format(PyExc_RuntimeError, - "failed to create Future object"); - } + return PyErr_Format(PyExc_RuntimeError, "failed to create Future object"); + } - if (!lifespan->startup_received) { - lifespan->startup_received = 1; + if (!lifespan->startup_received) { + lifespan->startup_received = 1; - msg = nxt_py_asgi_new_msg(NULL, nxt_py_lifespan_startup_str); + msg = nxt_py_asgi_new_msg(NULL, nxt_py_lifespan_startup_str); - return nxt_py_asgi_set_result_soon(NULL, ctx_data, future, msg); - } + return nxt_py_asgi_set_result_soon(NULL, ctx_data, future, msg); + } - if (lifespan->shutdown_called && !lifespan->shutdown_received) { - lifespan->shutdown_received = 1; + if (lifespan->shutdown_called && !lifespan->shutdown_received) { + lifespan->shutdown_received = 1; - msg = nxt_py_asgi_new_msg(NULL, nxt_py_lifespan_shutdown_str); + msg = nxt_py_asgi_new_msg(NULL, nxt_py_lifespan_shutdown_str); - return nxt_py_asgi_set_result_soon(NULL, ctx_data, future, msg); - } + return nxt_py_asgi_set_result_soon(NULL, ctx_data, future, msg); + } - Py_INCREF(future); - lifespan->receive_future = future; + Py_INCREF(future); + lifespan->receive_future = future; - return future; + return future; } - -static PyObject * -nxt_py_asgi_lifespan_send(PyObject *self, PyObject *dict) -{ - PyObject *type, *msg; - const char *type_str; - Py_ssize_t type_len; - nxt_py_asgi_lifespan_t *lifespan; - - static const nxt_str_t startup_complete - = nxt_string("lifespan.startup.complete"); - static const nxt_str_t startup_failed - = nxt_string("lifespan.startup.failed"); - static const nxt_str_t shutdown_complete - = nxt_string("lifespan.shutdown.complete"); - static const nxt_str_t shutdown_failed - = nxt_string("lifespan.shutdown.failed"); - - lifespan = (nxt_py_asgi_lifespan_t *) self; - - type = PyDict_GetItem(dict, nxt_py_type_str); - if (nxt_slow_path(type == NULL || !PyUnicode_Check(type))) { - nxt_unit_error(NULL, - "asgi_lifespan_send: 'type' is not a unicode string"); - return PyErr_Format(PyExc_TypeError, - "'type' is not a unicode string"); - } - - type_str = PyUnicode_AsUTF8AndSize(type, &type_len); - - nxt_unit_debug(NULL, "asgi_lifespan_send type is '%.*s'", - (int) type_len, type_str); - - if (type_len == (Py_ssize_t) startup_complete.length - && memcmp(type_str, startup_complete.start, type_len) == 0) - { - return nxt_py_asgi_lifespan_send_startup(lifespan, 0, NULL); - } - - if (type_len == (Py_ssize_t) startup_failed.length - && memcmp(type_str, startup_failed.start, type_len) == 0) - { - msg = PyDict_GetItem(dict, nxt_py_message_str); - return nxt_py_asgi_lifespan_send_startup(lifespan, 1, msg); - } - - if (type_len == (Py_ssize_t) shutdown_complete.length - && memcmp(type_str, shutdown_complete.start, type_len) == 0) - { - return nxt_py_asgi_lifespan_send_shutdown(lifespan, 0, NULL); - } - - if (type_len == (Py_ssize_t) shutdown_failed.length - && memcmp(type_str, shutdown_failed.start, type_len) == 0) - { - msg = PyDict_GetItem(dict, nxt_py_message_str); - return nxt_py_asgi_lifespan_send_shutdown(lifespan, 1, msg); - } - - return nxt_py_asgi_lifespan_disable(lifespan); +static PyObject *nxt_py_asgi_lifespan_send(PyObject *self, PyObject *dict) { + PyObject *type, *msg; + const char *type_str; + Py_ssize_t type_len; + nxt_py_asgi_lifespan_t *lifespan; + + static const nxt_str_t startup_complete = + nxt_string("lifespan.startup.complete"); + static const nxt_str_t startup_failed = nxt_string("lifespan.startup.failed"); + static const nxt_str_t shutdown_complete = + nxt_string("lifespan.shutdown.complete"); + static const nxt_str_t shutdown_failed = + nxt_string("lifespan.shutdown.failed"); + + lifespan = (nxt_py_asgi_lifespan_t *)self; + + type = PyDict_GetItem(dict, nxt_py_type_str); + if (nxt_slow_path(type == NULL || !PyUnicode_Check(type))) { + nxt_unit_error(NULL, "asgi_lifespan_send: 'type' is not a unicode string"); + return PyErr_Format(PyExc_TypeError, "'type' is not a unicode string"); + } + + type_str = PyUnicode_AsUTF8AndSize(type, &type_len); + + nxt_unit_debug(NULL, "asgi_lifespan_send type is '%.*s'", (int)type_len, + type_str); + + if (type_len == (Py_ssize_t)startup_complete.length && + memcmp(type_str, startup_complete.start, type_len) == 0) { + return nxt_py_asgi_lifespan_send_startup(lifespan, 0, NULL); + } + + if (type_len == (Py_ssize_t)startup_failed.length && + memcmp(type_str, startup_failed.start, type_len) == 0) { + msg = PyDict_GetItem(dict, nxt_py_message_str); + return nxt_py_asgi_lifespan_send_startup(lifespan, 1, msg); + } + + if (type_len == (Py_ssize_t)shutdown_complete.length && + memcmp(type_str, shutdown_complete.start, type_len) == 0) { + return nxt_py_asgi_lifespan_send_shutdown(lifespan, 0, NULL); + } + + if (type_len == (Py_ssize_t)shutdown_failed.length && + memcmp(type_str, shutdown_failed.start, type_len) == 0) { + msg = PyDict_GetItem(dict, nxt_py_message_str); + return nxt_py_asgi_lifespan_send_shutdown(lifespan, 1, msg); + } + + return nxt_py_asgi_lifespan_disable(lifespan); } - static PyObject * nxt_py_asgi_lifespan_send_startup(nxt_py_asgi_lifespan_t *lifespan, int v, - PyObject *message) -{ - const char *message_str; - Py_ssize_t message_len; + PyObject *message) { + const char *message_str; + Py_ssize_t message_len; - if (nxt_slow_path(v != 0)) { - nxt_unit_error(NULL, "Application startup failed"); + if (nxt_slow_path(v != 0)) { + nxt_unit_error(NULL, "Application startup failed"); - if (nxt_fast_path(message != NULL && PyUnicode_Check(message))) { - message_str = PyUnicode_AsUTF8AndSize(message, &message_len); + if (nxt_fast_path(message != NULL && PyUnicode_Check(message))) { + message_str = PyUnicode_AsUTF8AndSize(message, &message_len); - nxt_unit_error(NULL, "%.*s", (int) message_len, message_str); - } + nxt_unit_error(NULL, "%.*s", (int)message_len, message_str); } + } - return nxt_py_asgi_lifespan_send_(lifespan, v, - &lifespan->startup_sent, - &lifespan->startup_future); + return nxt_py_asgi_lifespan_send_(lifespan, v, &lifespan->startup_sent, + &lifespan->startup_future); } +static PyObject *nxt_py_asgi_lifespan_send_(nxt_py_asgi_lifespan_t *lifespan, + int v, int *sent, + PyObject **pfuture) { + PyObject *future, *res; -static PyObject * -nxt_py_asgi_lifespan_send_(nxt_py_asgi_lifespan_t *lifespan, int v, int *sent, - PyObject **pfuture) -{ - PyObject *future, *res; - - if (*sent) { - return nxt_py_asgi_lifespan_disable(lifespan); - } - - *sent = 1 + v; + if (*sent) { + return nxt_py_asgi_lifespan_disable(lifespan); + } - if (*pfuture != NULL) { - future = *pfuture; - *pfuture = NULL; + *sent = 1 + v; - res = PyObject_CallMethodObjArgs(future, nxt_py_set_result_str, - Py_None, NULL); - if (nxt_slow_path(res == NULL)) { - nxt_unit_alert(NULL, "Failed to call 'future.set_result'"); - nxt_python_print_exception(); + if (*pfuture != NULL) { + future = *pfuture; + *pfuture = NULL; - return nxt_py_asgi_lifespan_disable(lifespan); - } + res = PyObject_CallMethodObjArgs(future, nxt_py_set_result_str, Py_None, + NULL); + if (nxt_slow_path(res == NULL)) { + nxt_unit_alert(NULL, "Failed to call 'future.set_result'"); + nxt_python_print_exception(); - Py_DECREF(res); - Py_DECREF(future); + return nxt_py_asgi_lifespan_disable(lifespan); } - Py_INCREF(lifespan); + Py_DECREF(res); + Py_DECREF(future); + } - return (PyObject *) lifespan; -} + Py_INCREF(lifespan); + return (PyObject *)lifespan; +} static PyObject * -nxt_py_asgi_lifespan_disable(nxt_py_asgi_lifespan_t *lifespan) -{ - nxt_unit_warn(NULL, "Got invalid state transition on lifespan protocol"); +nxt_py_asgi_lifespan_disable(nxt_py_asgi_lifespan_t *lifespan) { + nxt_unit_warn(NULL, "Got invalid state transition on lifespan protocol"); - lifespan->disabled = 1; + lifespan->disabled = 1; - return PyErr_Format(PyExc_AssertionError, - "Got invalid state transition on lifespan protocol"); + return PyErr_Format(PyExc_AssertionError, + "Got invalid state transition on lifespan protocol"); } - static PyObject * nxt_py_asgi_lifespan_send_shutdown(nxt_py_asgi_lifespan_t *lifespan, int v, - PyObject *message) -{ - return nxt_py_asgi_lifespan_send_(lifespan, v, - &lifespan->shutdown_sent, - &lifespan->shutdown_future); + PyObject *message) { + return nxt_py_asgi_lifespan_send_(lifespan, v, &lifespan->shutdown_sent, + &lifespan->shutdown_future); } +static PyObject *nxt_py_asgi_lifespan_done(PyObject *self, PyObject *future) { + PyObject *res; + nxt_py_asgi_lifespan_t *lifespan; -static PyObject * -nxt_py_asgi_lifespan_done(PyObject *self, PyObject *future) -{ - PyObject *res; - nxt_py_asgi_lifespan_t *lifespan; - - nxt_unit_debug(NULL, "asgi_lifespan_done"); + nxt_unit_debug(NULL, "asgi_lifespan_done"); - lifespan = (nxt_py_asgi_lifespan_t *) self; - - if (lifespan->startup_sent == 0) { - lifespan->disabled = 1; - } + lifespan = (nxt_py_asgi_lifespan_t *)self; - /* - * Get Future.result() and it raises an exception, if coroutine exited - * with exception. - */ - res = PyObject_CallMethodObjArgs(future, nxt_py_result_str, NULL); + if (lifespan->startup_sent == 0) { + lifespan->disabled = 1; + } + + /* + * Get Future.result() and it raises an exception, if coroutine exited + * with exception. + */ + res = PyObject_CallMethodObjArgs(future, nxt_py_result_str, NULL); + if (nxt_slow_path(res == NULL)) { + nxt_unit_log(NULL, NXT_UNIT_LOG_INFO, "ASGI Lifespan processing exception"); + nxt_python_print_exception(); + } + + Py_XDECREF(res); + + if (lifespan->startup_future != NULL) { + future = lifespan->startup_future; + lifespan->startup_future = NULL; + + res = PyObject_CallMethodObjArgs(future, nxt_py_set_result_str, Py_None, + NULL); if (nxt_slow_path(res == NULL)) { - nxt_unit_log(NULL, NXT_UNIT_LOG_INFO, - "ASGI Lifespan processing exception"); - nxt_python_print_exception(); + nxt_unit_alert(NULL, "Failed to call 'future.set_result'"); + nxt_python_print_exception(); } Py_XDECREF(res); + Py_DECREF(future); + } - if (lifespan->startup_future != NULL) { - future = lifespan->startup_future; - lifespan->startup_future = NULL; - - res = PyObject_CallMethodObjArgs(future, nxt_py_set_result_str, - Py_None, NULL); - if (nxt_slow_path(res == NULL)) { - nxt_unit_alert(NULL, "Failed to call 'future.set_result'"); - nxt_python_print_exception(); - } + if (lifespan->shutdown_future != NULL) { + future = lifespan->shutdown_future; + lifespan->shutdown_future = NULL; - Py_XDECREF(res); - Py_DECREF(future); + res = PyObject_CallMethodObjArgs(future, nxt_py_set_result_str, Py_None, + NULL); + if (nxt_slow_path(res == NULL)) { + nxt_unit_alert(NULL, "Failed to call 'future.set_result'"); + nxt_python_print_exception(); } - if (lifespan->shutdown_future != NULL) { - future = lifespan->shutdown_future; - lifespan->shutdown_future = NULL; - - res = PyObject_CallMethodObjArgs(future, nxt_py_set_result_str, - Py_None, NULL); - if (nxt_slow_path(res == NULL)) { - nxt_unit_alert(NULL, "Failed to call 'future.set_result'"); - nxt_python_print_exception(); - } - - Py_XDECREF(res); - Py_DECREF(future); - } + Py_XDECREF(res); + Py_DECREF(future); + } - Py_RETURN_NONE; + Py_RETURN_NONE; } +static void nxt_py_asgi_lifespan_dealloc(PyObject *self) { + nxt_py_asgi_lifespan_t *lifespan = (nxt_py_asgi_lifespan_t *)self; -static void -nxt_py_asgi_lifespan_dealloc(PyObject *self) -{ - nxt_py_asgi_lifespan_t *lifespan = (nxt_py_asgi_lifespan_t *)self; - - Py_CLEAR(lifespan->state); - PyObject_Del(self); + Py_CLEAR(lifespan->state); + PyObject_Del(self); } - #endif /* NXT_HAVE_ASGI */ diff --git a/src/python/nxt_python_asgi_str.c b/src/python/nxt_python_asgi_str.c index 3bea87d5f..14323abea 100644 --- a/src/python/nxt_python_asgi_str.c +++ b/src/python/nxt_python_asgi_str.c @@ -3,7 +3,6 @@ * Copyright (C) NGINX, Inc. */ - #include #if (NXT_HAVE_ASGI) @@ -11,133 +10,125 @@ #include #include - -PyObject *nxt_py_1_0_str; -PyObject *nxt_py_1_1_str; -PyObject *nxt_py_2_0_str; -PyObject *nxt_py_2_1_str; -PyObject *nxt_py_3_0_str; -PyObject *nxt_py_add_done_callback_str; -PyObject *nxt_py_asgi_str; -PyObject *nxt_py_bad_state_str; -PyObject *nxt_py_body_str; -PyObject *nxt_py_bytes_str; -PyObject *nxt_py_client_str; -PyObject *nxt_py_code_str; -PyObject *nxt_py_done_str; -PyObject *nxt_py_exception_str; -PyObject *nxt_py_failed_to_send_body_str; -PyObject *nxt_py_headers_str; -PyObject *nxt_py_http_str; -PyObject *nxt_py_http_disconnect_str; -PyObject *nxt_py_http_request_str; -PyObject *nxt_py_http_version_str; -PyObject *nxt_py_https_str; -PyObject *nxt_py_lifespan_str; -PyObject *nxt_py_lifespan_shutdown_str; -PyObject *nxt_py_lifespan_startup_str; -PyObject *nxt_py_method_str; -PyObject *nxt_py_message_str; -PyObject *nxt_py_message_too_big_str; -PyObject *nxt_py_more_body_str; -PyObject *nxt_py_path_str; -PyObject *nxt_py_query_string_str; -PyObject *nxt_py_raw_path_str; -PyObject *nxt_py_result_str; -PyObject *nxt_py_root_path_str; -PyObject *nxt_py_scheme_str; -PyObject *nxt_py_server_str; -PyObject *nxt_py_set_exception_str; -PyObject *nxt_py_set_result_str; -PyObject *nxt_py_spec_version_str; -PyObject *nxt_py_status_str; -PyObject *nxt_py_subprotocol_str; -PyObject *nxt_py_subprotocols_str; -PyObject *nxt_py_text_str; -PyObject *nxt_py_type_str; -PyObject *nxt_py_state_str; -PyObject *nxt_py_version_str; -PyObject *nxt_py_websocket_str; -PyObject *nxt_py_websocket_accept_str; -PyObject *nxt_py_websocket_close_str; -PyObject *nxt_py_websocket_connect_str; -PyObject *nxt_py_websocket_disconnect_str; -PyObject *nxt_py_websocket_receive_str; -PyObject *nxt_py_websocket_send_str; -PyObject *nxt_py_ws_str; -PyObject *nxt_py_wss_str; +PyObject *nxt_py_1_0_str; +PyObject *nxt_py_1_1_str; +PyObject *nxt_py_2_0_str; +PyObject *nxt_py_2_1_str; +PyObject *nxt_py_3_0_str; +PyObject *nxt_py_add_done_callback_str; +PyObject *nxt_py_asgi_str; +PyObject *nxt_py_bad_state_str; +PyObject *nxt_py_body_str; +PyObject *nxt_py_bytes_str; +PyObject *nxt_py_client_str; +PyObject *nxt_py_code_str; +PyObject *nxt_py_done_str; +PyObject *nxt_py_exception_str; +PyObject *nxt_py_failed_to_send_body_str; +PyObject *nxt_py_headers_str; +PyObject *nxt_py_http_str; +PyObject *nxt_py_http_disconnect_str; +PyObject *nxt_py_http_request_str; +PyObject *nxt_py_http_version_str; +PyObject *nxt_py_https_str; +PyObject *nxt_py_lifespan_str; +PyObject *nxt_py_lifespan_shutdown_str; +PyObject *nxt_py_lifespan_startup_str; +PyObject *nxt_py_method_str; +PyObject *nxt_py_message_str; +PyObject *nxt_py_message_too_big_str; +PyObject *nxt_py_more_body_str; +PyObject *nxt_py_path_str; +PyObject *nxt_py_query_string_str; +PyObject *nxt_py_raw_path_str; +PyObject *nxt_py_result_str; +PyObject *nxt_py_root_path_str; +PyObject *nxt_py_scheme_str; +PyObject *nxt_py_server_str; +PyObject *nxt_py_set_exception_str; +PyObject *nxt_py_set_result_str; +PyObject *nxt_py_spec_version_str; +PyObject *nxt_py_status_str; +PyObject *nxt_py_subprotocol_str; +PyObject *nxt_py_subprotocols_str; +PyObject *nxt_py_text_str; +PyObject *nxt_py_type_str; +PyObject *nxt_py_state_str; +PyObject *nxt_py_version_str; +PyObject *nxt_py_websocket_str; +PyObject *nxt_py_websocket_accept_str; +PyObject *nxt_py_websocket_close_str; +PyObject *nxt_py_websocket_connect_str; +PyObject *nxt_py_websocket_disconnect_str; +PyObject *nxt_py_websocket_receive_str; +PyObject *nxt_py_websocket_send_str; +PyObject *nxt_py_ws_str; +PyObject *nxt_py_wss_str; static nxt_python_string_t nxt_py_asgi_strings[] = { - { nxt_string("1.0"), &nxt_py_1_0_str }, - { nxt_string("1.1"), &nxt_py_1_1_str }, - { nxt_string("2.0"), &nxt_py_2_0_str }, - { nxt_string("2.1"), &nxt_py_2_1_str }, - { nxt_string("3.0"), &nxt_py_3_0_str }, - { nxt_string("add_done_callback"), &nxt_py_add_done_callback_str }, - { nxt_string("asgi"), &nxt_py_asgi_str }, - { nxt_string("bad state"), &nxt_py_bad_state_str }, - { nxt_string("body"), &nxt_py_body_str }, - { nxt_string("bytes"), &nxt_py_bytes_str }, - { nxt_string("client"), &nxt_py_client_str }, - { nxt_string("code"), &nxt_py_code_str }, - { nxt_string("done"), &nxt_py_done_str }, - { nxt_string("exception"), &nxt_py_exception_str }, - { nxt_string("failed to send body"), &nxt_py_failed_to_send_body_str }, - { nxt_string("headers"), &nxt_py_headers_str }, - { nxt_string("http"), &nxt_py_http_str }, - { nxt_string("http.disconnect"), &nxt_py_http_disconnect_str }, - { nxt_string("http.request"), &nxt_py_http_request_str }, - { nxt_string("http_version"), &nxt_py_http_version_str }, - { nxt_string("https"), &nxt_py_https_str }, - { nxt_string("lifespan"), &nxt_py_lifespan_str }, - { nxt_string("lifespan.shutdown"), &nxt_py_lifespan_shutdown_str }, - { nxt_string("lifespan.startup"), &nxt_py_lifespan_startup_str }, - { nxt_string("message"), &nxt_py_message_str }, - { nxt_string("message too big"), &nxt_py_message_too_big_str }, - { nxt_string("method"), &nxt_py_method_str }, - { nxt_string("more_body"), &nxt_py_more_body_str }, - { nxt_string("path"), &nxt_py_path_str }, - { nxt_string("query_string"), &nxt_py_query_string_str }, - { nxt_string("raw_path"), &nxt_py_raw_path_str }, - { nxt_string("result"), &nxt_py_result_str }, - { nxt_string("root_path"), &nxt_py_root_path_str }, - { nxt_string("scheme"), &nxt_py_scheme_str }, - { nxt_string("server"), &nxt_py_server_str }, - { nxt_string("set_exception"), &nxt_py_set_exception_str }, - { nxt_string("set_result"), &nxt_py_set_result_str }, - { nxt_string("spec_version"), &nxt_py_spec_version_str }, - { nxt_string("status"), &nxt_py_status_str }, - { nxt_string("subprotocol"), &nxt_py_subprotocol_str }, - { nxt_string("subprotocols"), &nxt_py_subprotocols_str }, - { nxt_string("text"), &nxt_py_text_str }, - { nxt_string("type"), &nxt_py_type_str }, - { nxt_string("state"), &nxt_py_state_str }, - { nxt_string("version"), &nxt_py_version_str }, - { nxt_string("websocket"), &nxt_py_websocket_str }, - { nxt_string("websocket.accept"), &nxt_py_websocket_accept_str }, - { nxt_string("websocket.close"), &nxt_py_websocket_close_str }, - { nxt_string("websocket.connect"), &nxt_py_websocket_connect_str }, - { nxt_string("websocket.disconnect"), &nxt_py_websocket_disconnect_str }, - { nxt_string("websocket.receive"), &nxt_py_websocket_receive_str }, - { nxt_string("websocket.send"), &nxt_py_websocket_send_str }, - { nxt_string("ws"), &nxt_py_ws_str }, - { nxt_string("wss"), &nxt_py_wss_str }, - { nxt_null_string, NULL }, + {nxt_string("1.0"), &nxt_py_1_0_str}, + {nxt_string("1.1"), &nxt_py_1_1_str}, + {nxt_string("2.0"), &nxt_py_2_0_str}, + {nxt_string("2.1"), &nxt_py_2_1_str}, + {nxt_string("3.0"), &nxt_py_3_0_str}, + {nxt_string("add_done_callback"), &nxt_py_add_done_callback_str}, + {nxt_string("asgi"), &nxt_py_asgi_str}, + {nxt_string("bad state"), &nxt_py_bad_state_str}, + {nxt_string("body"), &nxt_py_body_str}, + {nxt_string("bytes"), &nxt_py_bytes_str}, + {nxt_string("client"), &nxt_py_client_str}, + {nxt_string("code"), &nxt_py_code_str}, + {nxt_string("done"), &nxt_py_done_str}, + {nxt_string("exception"), &nxt_py_exception_str}, + {nxt_string("failed to send body"), &nxt_py_failed_to_send_body_str}, + {nxt_string("headers"), &nxt_py_headers_str}, + {nxt_string("http"), &nxt_py_http_str}, + {nxt_string("http.disconnect"), &nxt_py_http_disconnect_str}, + {nxt_string("http.request"), &nxt_py_http_request_str}, + {nxt_string("http_version"), &nxt_py_http_version_str}, + {nxt_string("https"), &nxt_py_https_str}, + {nxt_string("lifespan"), &nxt_py_lifespan_str}, + {nxt_string("lifespan.shutdown"), &nxt_py_lifespan_shutdown_str}, + {nxt_string("lifespan.startup"), &nxt_py_lifespan_startup_str}, + {nxt_string("message"), &nxt_py_message_str}, + {nxt_string("message too big"), &nxt_py_message_too_big_str}, + {nxt_string("method"), &nxt_py_method_str}, + {nxt_string("more_body"), &nxt_py_more_body_str}, + {nxt_string("path"), &nxt_py_path_str}, + {nxt_string("query_string"), &nxt_py_query_string_str}, + {nxt_string("raw_path"), &nxt_py_raw_path_str}, + {nxt_string("result"), &nxt_py_result_str}, + {nxt_string("root_path"), &nxt_py_root_path_str}, + {nxt_string("scheme"), &nxt_py_scheme_str}, + {nxt_string("server"), &nxt_py_server_str}, + {nxt_string("set_exception"), &nxt_py_set_exception_str}, + {nxt_string("set_result"), &nxt_py_set_result_str}, + {nxt_string("spec_version"), &nxt_py_spec_version_str}, + {nxt_string("status"), &nxt_py_status_str}, + {nxt_string("subprotocol"), &nxt_py_subprotocol_str}, + {nxt_string("subprotocols"), &nxt_py_subprotocols_str}, + {nxt_string("text"), &nxt_py_text_str}, + {nxt_string("type"), &nxt_py_type_str}, + {nxt_string("state"), &nxt_py_state_str}, + {nxt_string("version"), &nxt_py_version_str}, + {nxt_string("websocket"), &nxt_py_websocket_str}, + {nxt_string("websocket.accept"), &nxt_py_websocket_accept_str}, + {nxt_string("websocket.close"), &nxt_py_websocket_close_str}, + {nxt_string("websocket.connect"), &nxt_py_websocket_connect_str}, + {nxt_string("websocket.disconnect"), &nxt_py_websocket_disconnect_str}, + {nxt_string("websocket.receive"), &nxt_py_websocket_receive_str}, + {nxt_string("websocket.send"), &nxt_py_websocket_send_str}, + {nxt_string("ws"), &nxt_py_ws_str}, + {nxt_string("wss"), &nxt_py_wss_str}, + {nxt_null_string, NULL}, }; - -int -nxt_py_asgi_str_init(void) -{ - return nxt_python_init_strings(nxt_py_asgi_strings); +int nxt_py_asgi_str_init(void) { + return nxt_python_init_strings(nxt_py_asgi_strings); } - -void -nxt_py_asgi_str_done(void) -{ - nxt_python_done_strings(nxt_py_asgi_strings); +void nxt_py_asgi_str_done(void) { + nxt_python_done_strings(nxt_py_asgi_strings); } - #endif /* NXT_HAVE_ASGI */ diff --git a/src/python/nxt_python_asgi_str.h b/src/python/nxt_python_asgi_str.h index 3c7a3ed92..99af75b5c 100644 --- a/src/python/nxt_python_asgi_str.h +++ b/src/python/nxt_python_asgi_str.h @@ -6,65 +6,62 @@ #ifndef _NXT_PYTHON_ASGI_STR_H_INCLUDED_ #define _NXT_PYTHON_ASGI_STR_H_INCLUDED_ - -extern PyObject *nxt_py_1_0_str; -extern PyObject *nxt_py_1_1_str; -extern PyObject *nxt_py_2_0_str; -extern PyObject *nxt_py_2_1_str; -extern PyObject *nxt_py_3_0_str; -extern PyObject *nxt_py_add_done_callback_str; -extern PyObject *nxt_py_asgi_str; -extern PyObject *nxt_py_bad_state_str; -extern PyObject *nxt_py_body_str; -extern PyObject *nxt_py_bytes_str; -extern PyObject *nxt_py_client_str; -extern PyObject *nxt_py_code_str; -extern PyObject *nxt_py_done_str; -extern PyObject *nxt_py_exception_str; -extern PyObject *nxt_py_failed_to_send_body_str; -extern PyObject *nxt_py_headers_str; -extern PyObject *nxt_py_http_str; -extern PyObject *nxt_py_http_disconnect_str; -extern PyObject *nxt_py_http_request_str; -extern PyObject *nxt_py_http_version_str; -extern PyObject *nxt_py_https_str; -extern PyObject *nxt_py_lifespan_str; -extern PyObject *nxt_py_lifespan_shutdown_str; -extern PyObject *nxt_py_lifespan_startup_str; -extern PyObject *nxt_py_method_str; -extern PyObject *nxt_py_message_str; -extern PyObject *nxt_py_message_too_big_str; -extern PyObject *nxt_py_more_body_str; -extern PyObject *nxt_py_path_str; -extern PyObject *nxt_py_query_string_str; -extern PyObject *nxt_py_result_str; -extern PyObject *nxt_py_raw_path_str; -extern PyObject *nxt_py_root_path_str; -extern PyObject *nxt_py_scheme_str; -extern PyObject *nxt_py_server_str; -extern PyObject *nxt_py_set_exception_str; -extern PyObject *nxt_py_set_result_str; -extern PyObject *nxt_py_spec_version_str; -extern PyObject *nxt_py_status_str; -extern PyObject *nxt_py_subprotocol_str; -extern PyObject *nxt_py_subprotocols_str; -extern PyObject *nxt_py_text_str; -extern PyObject *nxt_py_type_str; -extern PyObject *nxt_py_state_str; -extern PyObject *nxt_py_version_str; -extern PyObject *nxt_py_websocket_str; -extern PyObject *nxt_py_websocket_accept_str; -extern PyObject *nxt_py_websocket_close_str; -extern PyObject *nxt_py_websocket_connect_str; -extern PyObject *nxt_py_websocket_disconnect_str; -extern PyObject *nxt_py_websocket_receive_str; -extern PyObject *nxt_py_websocket_send_str; -extern PyObject *nxt_py_ws_str; -extern PyObject *nxt_py_wss_str; - +extern PyObject *nxt_py_1_0_str; +extern PyObject *nxt_py_1_1_str; +extern PyObject *nxt_py_2_0_str; +extern PyObject *nxt_py_2_1_str; +extern PyObject *nxt_py_3_0_str; +extern PyObject *nxt_py_add_done_callback_str; +extern PyObject *nxt_py_asgi_str; +extern PyObject *nxt_py_bad_state_str; +extern PyObject *nxt_py_body_str; +extern PyObject *nxt_py_bytes_str; +extern PyObject *nxt_py_client_str; +extern PyObject *nxt_py_code_str; +extern PyObject *nxt_py_done_str; +extern PyObject *nxt_py_exception_str; +extern PyObject *nxt_py_failed_to_send_body_str; +extern PyObject *nxt_py_headers_str; +extern PyObject *nxt_py_http_str; +extern PyObject *nxt_py_http_disconnect_str; +extern PyObject *nxt_py_http_request_str; +extern PyObject *nxt_py_http_version_str; +extern PyObject *nxt_py_https_str; +extern PyObject *nxt_py_lifespan_str; +extern PyObject *nxt_py_lifespan_shutdown_str; +extern PyObject *nxt_py_lifespan_startup_str; +extern PyObject *nxt_py_method_str; +extern PyObject *nxt_py_message_str; +extern PyObject *nxt_py_message_too_big_str; +extern PyObject *nxt_py_more_body_str; +extern PyObject *nxt_py_path_str; +extern PyObject *nxt_py_query_string_str; +extern PyObject *nxt_py_result_str; +extern PyObject *nxt_py_raw_path_str; +extern PyObject *nxt_py_root_path_str; +extern PyObject *nxt_py_scheme_str; +extern PyObject *nxt_py_server_str; +extern PyObject *nxt_py_set_exception_str; +extern PyObject *nxt_py_set_result_str; +extern PyObject *nxt_py_spec_version_str; +extern PyObject *nxt_py_status_str; +extern PyObject *nxt_py_subprotocol_str; +extern PyObject *nxt_py_subprotocols_str; +extern PyObject *nxt_py_text_str; +extern PyObject *nxt_py_type_str; +extern PyObject *nxt_py_state_str; +extern PyObject *nxt_py_version_str; +extern PyObject *nxt_py_websocket_str; +extern PyObject *nxt_py_websocket_accept_str; +extern PyObject *nxt_py_websocket_close_str; +extern PyObject *nxt_py_websocket_connect_str; +extern PyObject *nxt_py_websocket_disconnect_str; +extern PyObject *nxt_py_websocket_receive_str; +extern PyObject *nxt_py_websocket_send_str; +extern PyObject *nxt_py_ws_str; +extern PyObject *nxt_py_wss_str; int nxt_py_asgi_str_init(void); void nxt_py_asgi_str_done(void); - -#endif /* _NXT_PYTHON_ASGI_STR_H_INCLUDED_ */ +#endif /* _NXT_PYTHON_ASGI_STR_H_INCLUDED_ */ diff --git a/src/python/nxt_python_asgi_websocket.c b/src/python/nxt_python_asgi_websocket.c index ab1d0324e..41ab7d658 100644 --- a/src/python/nxt_python_asgi_websocket.c +++ b/src/python/nxt_python_asgi_websocket.c @@ -3,7 +3,6 @@ * Copyright (C) NGINX, Inc. */ - #include #if (NXT_HAVE_ASGI) @@ -16,65 +15,58 @@ #include #include - enum { - NXT_WS_INIT, - NXT_WS_CONNECT, - NXT_WS_ACCEPTED, - NXT_WS_DISCONNECTED, - NXT_WS_CLOSED, + NXT_WS_INIT, + NXT_WS_CONNECT, + NXT_WS_ACCEPTED, + NXT_WS_DISCONNECTED, + NXT_WS_CLOSED, }; - typedef struct { - nxt_queue_link_t link; - nxt_unit_websocket_frame_t *frame; + nxt_queue_link_t link; + nxt_unit_websocket_frame_t *frame; } nxt_py_asgi_penging_frame_t; - typedef struct { - PyObject_HEAD - nxt_unit_request_info_t *req; - PyObject *receive_future; - PyObject *receive_exc_str; - int state; - nxt_queue_t pending_frames; - uint64_t pending_payload_len; - uint64_t pending_frame_len; - int pending_fins; + PyObject_HEAD nxt_unit_request_info_t *req; + PyObject *receive_future; + PyObject *receive_exc_str; + int state; + nxt_queue_t pending_frames; + uint64_t pending_payload_len; + uint64_t pending_frame_len; + int pending_fins; } nxt_py_asgi_websocket_t; - static PyObject *nxt_py_asgi_websocket_receive(PyObject *self, PyObject *none); static PyObject *nxt_py_asgi_websocket_send(PyObject *self, PyObject *dict); static PyObject *nxt_py_asgi_websocket_accept(nxt_py_asgi_websocket_t *ws, - PyObject *dict); + PyObject *dict); static PyObject *nxt_py_asgi_websocket_close(nxt_py_asgi_websocket_t *ws, - PyObject *dict); + PyObject *dict); static PyObject *nxt_py_asgi_websocket_send_frame(nxt_py_asgi_websocket_t *ws, - PyObject *dict); + PyObject *dict); static void nxt_py_asgi_websocket_receive_done(nxt_py_asgi_websocket_t *ws, - PyObject *msg); + PyObject *msg); static void nxt_py_asgi_websocket_receive_fail(nxt_py_asgi_websocket_t *ws, - PyObject *exc); + PyObject *exc); static void nxt_py_asgi_websocket_suspend_frame(nxt_unit_websocket_frame_t *f); -static PyObject *nxt_py_asgi_websocket_pop_msg(nxt_py_asgi_websocket_t *ws, - nxt_unit_websocket_frame_t *frame); -static uint64_t nxt_py_asgi_websocket_pending_len( - nxt_py_asgi_websocket_t *ws); -static nxt_unit_websocket_frame_t *nxt_py_asgi_websocket_pop_frame( - nxt_py_asgi_websocket_t *ws); -static PyObject *nxt_py_asgi_websocket_disconnect_msg( - nxt_py_asgi_websocket_t *ws); +static PyObject * +nxt_py_asgi_websocket_pop_msg(nxt_py_asgi_websocket_t *ws, + nxt_unit_websocket_frame_t *frame); +static uint64_t nxt_py_asgi_websocket_pending_len(nxt_py_asgi_websocket_t *ws); +static nxt_unit_websocket_frame_t * +nxt_py_asgi_websocket_pop_frame(nxt_py_asgi_websocket_t *ws); +static PyObject * +nxt_py_asgi_websocket_disconnect_msg(nxt_py_asgi_websocket_t *ws); static PyObject *nxt_py_asgi_websocket_done(PyObject *self, PyObject *future); - static PyMethodDef nxt_py_asgi_websocket_methods[] = { - { "receive", nxt_py_asgi_websocket_receive, METH_NOARGS, 0 }, - { "send", nxt_py_asgi_websocket_send, METH_O, 0 }, - { "_done", nxt_py_asgi_websocket_done, METH_O, 0 }, - { NULL, NULL, 0, 0 } -}; + {"receive", nxt_py_asgi_websocket_receive, METH_NOARGS, 0}, + {"send", nxt_py_asgi_websocket_send, METH_O, 0}, + {"_done", nxt_py_asgi_websocket_done, METH_O, 0}, + {NULL, NULL, 0, 0}}; static PyAsyncMethods nxt_py_asgi_async_methods = { .am_await = nxt_py_asgi_await, @@ -83,1009 +75,935 @@ static PyAsyncMethods nxt_py_asgi_async_methods = { static PyTypeObject nxt_py_asgi_websocket_type = { PyVarObject_HEAD_INIT(NULL, 0) - .tp_name = "unit._asgi_websocket", + .tp_name = "unit._asgi_websocket", .tp_basicsize = sizeof(nxt_py_asgi_websocket_t), - .tp_dealloc = nxt_py_asgi_dealloc, - .tp_as_async = &nxt_py_asgi_async_methods, - .tp_flags = Py_TPFLAGS_DEFAULT, - .tp_doc = "unit ASGI WebSocket connection object", - .tp_iter = nxt_py_asgi_iter, - .tp_iternext = nxt_py_asgi_next, - .tp_methods = nxt_py_asgi_websocket_methods, + .tp_dealloc = nxt_py_asgi_dealloc, + .tp_as_async = &nxt_py_asgi_async_methods, + .tp_flags = Py_TPFLAGS_DEFAULT, + .tp_doc = "unit ASGI WebSocket connection object", + .tp_iter = nxt_py_asgi_iter, + .tp_iternext = nxt_py_asgi_next, + .tp_methods = nxt_py_asgi_websocket_methods, }; -static uint64_t nxt_py_asgi_ws_max_frame_size = 1024 * 1024; -static uint64_t nxt_py_asgi_ws_max_buffer_size = 10 * 1024 * 1024; +static uint64_t nxt_py_asgi_ws_max_frame_size = 1024 * 1024; +static uint64_t nxt_py_asgi_ws_max_buffer_size = 10 * 1024 * 1024; +int nxt_py_asgi_websocket_init(void) { + if (nxt_slow_path(PyType_Ready(&nxt_py_asgi_websocket_type) != 0)) { + nxt_unit_alert( + NULL, "Python failed to initialize the \"asgi_websocket\" type object"); + return NXT_UNIT_ERROR; + } -int -nxt_py_asgi_websocket_init(void) -{ - if (nxt_slow_path(PyType_Ready(&nxt_py_asgi_websocket_type) != 0)) { - nxt_unit_alert(NULL, - "Python failed to initialize the \"asgi_websocket\" type object"); - return NXT_UNIT_ERROR; - } - - return NXT_UNIT_OK; + return NXT_UNIT_OK; } +PyObject *nxt_py_asgi_websocket_create(nxt_unit_request_info_t *req) { + nxt_py_asgi_websocket_t *ws; -PyObject * -nxt_py_asgi_websocket_create(nxt_unit_request_info_t *req) -{ - nxt_py_asgi_websocket_t *ws; - - ws = PyObject_New(nxt_py_asgi_websocket_t, &nxt_py_asgi_websocket_type); + ws = PyObject_New(nxt_py_asgi_websocket_t, &nxt_py_asgi_websocket_type); - if (nxt_fast_path(ws != NULL)) { - ws->req = req; - ws->receive_future = NULL; - ws->receive_exc_str = NULL; - ws->state = NXT_WS_INIT; - nxt_queue_init(&ws->pending_frames); - ws->pending_payload_len = 0; - ws->pending_frame_len = 0; - ws->pending_fins = 0; - } - - return (PyObject *) ws; + if (nxt_fast_path(ws != NULL)) { + ws->req = req; + ws->receive_future = NULL; + ws->receive_exc_str = NULL; + ws->state = NXT_WS_INIT; + nxt_queue_init(&ws->pending_frames); + ws->pending_payload_len = 0; + ws->pending_frame_len = 0; + ws->pending_fins = 0; + } + + return (PyObject *)ws; } +static PyObject *nxt_py_asgi_websocket_receive(PyObject *self, PyObject *none) { + PyObject *future, *msg; + nxt_py_asgi_ctx_data_t *ctx_data; + nxt_py_asgi_websocket_t *ws; -static PyObject * -nxt_py_asgi_websocket_receive(PyObject *self, PyObject *none) -{ - PyObject *future, *msg; - nxt_py_asgi_ctx_data_t *ctx_data; - nxt_py_asgi_websocket_t *ws; + ws = (nxt_py_asgi_websocket_t *)self; - ws = (nxt_py_asgi_websocket_t *) self; + nxt_unit_req_debug(ws->req, "asgi_websocket_receive"); - nxt_unit_req_debug(ws->req, "asgi_websocket_receive"); + /* If exception happened out of receive() call, raise it now. */ + if (nxt_slow_path(ws->receive_exc_str != NULL)) { + PyErr_SetObject(PyExc_RuntimeError, ws->receive_exc_str); - /* If exception happened out of receive() call, raise it now. */ - if (nxt_slow_path(ws->receive_exc_str != NULL)) { - PyErr_SetObject(PyExc_RuntimeError, ws->receive_exc_str); + ws->receive_exc_str = NULL; - ws->receive_exc_str = NULL; + return NULL; + } - return NULL; - } + if (nxt_slow_path(ws->state == NXT_WS_CLOSED)) { + nxt_unit_req_error(ws->req, "receive() called for closed WebSocket"); - if (nxt_slow_path(ws->state == NXT_WS_CLOSED)) { - nxt_unit_req_error(ws->req, - "receive() called for closed WebSocket"); + return PyErr_Format(PyExc_RuntimeError, "WebSocket already closed"); + } - return PyErr_Format(PyExc_RuntimeError, - "WebSocket already closed"); - } - - ctx_data = ws->req->ctx->data; + ctx_data = ws->req->ctx->data; - future = PyObject_CallObject(ctx_data->loop_create_future, NULL); - if (nxt_slow_path(future == NULL)) { - nxt_unit_req_alert(ws->req, "Python failed to create Future object"); - nxt_python_print_exception(); + future = PyObject_CallObject(ctx_data->loop_create_future, NULL); + if (nxt_slow_path(future == NULL)) { + nxt_unit_req_alert(ws->req, "Python failed to create Future object"); + nxt_python_print_exception(); - return PyErr_Format(PyExc_RuntimeError, - "failed to create Future object"); - } + return PyErr_Format(PyExc_RuntimeError, "failed to create Future object"); + } - if (nxt_slow_path(ws->state == NXT_WS_INIT)) { - ws->state = NXT_WS_CONNECT; + if (nxt_slow_path(ws->state == NXT_WS_INIT)) { + ws->state = NXT_WS_CONNECT; - msg = nxt_py_asgi_new_msg(ws->req, nxt_py_websocket_connect_str); + msg = nxt_py_asgi_new_msg(ws->req, nxt_py_websocket_connect_str); - return nxt_py_asgi_set_result_soon(ws->req, ctx_data, future, msg); - } + return nxt_py_asgi_set_result_soon(ws->req, ctx_data, future, msg); + } - if (ws->pending_fins > 0) { - msg = nxt_py_asgi_websocket_pop_msg(ws, NULL); + if (ws->pending_fins > 0) { + msg = nxt_py_asgi_websocket_pop_msg(ws, NULL); - return nxt_py_asgi_set_result_soon(ws->req, ctx_data, future, msg); - } + return nxt_py_asgi_set_result_soon(ws->req, ctx_data, future, msg); + } - if (nxt_slow_path(ws->state == NXT_WS_DISCONNECTED)) { - msg = nxt_py_asgi_websocket_disconnect_msg(ws); + if (nxt_slow_path(ws->state == NXT_WS_DISCONNECTED)) { + msg = nxt_py_asgi_websocket_disconnect_msg(ws); - return nxt_py_asgi_set_result_soon(ws->req, ctx_data, future, msg); - } + return nxt_py_asgi_set_result_soon(ws->req, ctx_data, future, msg); + } - ws->receive_future = future; - Py_INCREF(ws->receive_future); + ws->receive_future = future; + Py_INCREF(ws->receive_future); - return future; + return future; } +static PyObject *nxt_py_asgi_websocket_send(PyObject *self, PyObject *dict) { + PyObject *type; + const char *type_str; + Py_ssize_t type_len; + nxt_py_asgi_websocket_t *ws; -static PyObject * -nxt_py_asgi_websocket_send(PyObject *self, PyObject *dict) -{ - PyObject *type; - const char *type_str; - Py_ssize_t type_len; - nxt_py_asgi_websocket_t *ws; - - static const nxt_str_t websocket_accept = nxt_string("websocket.accept"); - static const nxt_str_t websocket_close = nxt_string("websocket.close"); - static const nxt_str_t websocket_send = nxt_string("websocket.send"); - - ws = (nxt_py_asgi_websocket_t *) self; - - type = PyDict_GetItem(dict, nxt_py_type_str); - if (nxt_slow_path(type == NULL || !PyUnicode_Check(type))) { - nxt_unit_req_error(ws->req, "asgi_websocket_send: " - "'type' is not a unicode string"); - return PyErr_Format(PyExc_TypeError, - "'type' is not a unicode string"); - } + static const nxt_str_t websocket_accept = nxt_string("websocket.accept"); + static const nxt_str_t websocket_close = nxt_string("websocket.close"); + static const nxt_str_t websocket_send = nxt_string("websocket.send"); - type_str = PyUnicode_AsUTF8AndSize(type, &type_len); - - nxt_unit_req_debug(ws->req, "asgi_websocket_send type is '%.*s'", - (int) type_len, type_str); - - if (type_len == (Py_ssize_t) websocket_accept.length - && memcmp(type_str, websocket_accept.start, type_len) == 0) - { - return nxt_py_asgi_websocket_accept(ws, dict); - } - - if (type_len == (Py_ssize_t) websocket_close.length - && memcmp(type_str, websocket_close.start, type_len) == 0) - { - return nxt_py_asgi_websocket_close(ws, dict); - } - - if (type_len == (Py_ssize_t) websocket_send.length - && memcmp(type_str, websocket_send.start, type_len) == 0) - { - return nxt_py_asgi_websocket_send_frame(ws, dict); - } + ws = (nxt_py_asgi_websocket_t *)self; + type = PyDict_GetItem(dict, nxt_py_type_str); + if (nxt_slow_path(type == NULL || !PyUnicode_Check(type))) { nxt_unit_req_error(ws->req, "asgi_websocket_send: " - "unexpected 'type': '%.*s'", (int) type_len, type_str); - return PyErr_Format(PyExc_AssertionError, "unexpected 'type': '%U'", type); + "'type' is not a unicode string"); + return PyErr_Format(PyExc_TypeError, "'type' is not a unicode string"); + } + + type_str = PyUnicode_AsUTF8AndSize(type, &type_len); + + nxt_unit_req_debug(ws->req, "asgi_websocket_send type is '%.*s'", + (int)type_len, type_str); + + if (type_len == (Py_ssize_t)websocket_accept.length && + memcmp(type_str, websocket_accept.start, type_len) == 0) { + return nxt_py_asgi_websocket_accept(ws, dict); + } + + if (type_len == (Py_ssize_t)websocket_close.length && + memcmp(type_str, websocket_close.start, type_len) == 0) { + return nxt_py_asgi_websocket_close(ws, dict); + } + + if (type_len == (Py_ssize_t)websocket_send.length && + memcmp(type_str, websocket_send.start, type_len) == 0) { + return nxt_py_asgi_websocket_send_frame(ws, dict); + } + + nxt_unit_req_error(ws->req, + "asgi_websocket_send: " + "unexpected 'type': '%.*s'", + (int)type_len, type_str); + return PyErr_Format(PyExc_AssertionError, "unexpected 'type': '%U'", type); } - -static PyObject * -nxt_py_asgi_websocket_accept(nxt_py_asgi_websocket_t *ws, PyObject *dict) -{ - int rc; - char *subprotocol_str; - PyObject *res, *headers, *subprotocol; - Py_ssize_t subprotocol_len; - nxt_py_asgi_calc_size_ctx_t calc_size_ctx; - nxt_py_asgi_add_field_ctx_t add_field_ctx; - - static const nxt_str_t ws_protocol = nxt_string("sec-websocket-protocol"); - - switch(ws->state) { - case NXT_WS_INIT: - return PyErr_Format(PyExc_RuntimeError, - "WebSocket connect not received"); - case NXT_WS_CONNECT: - break; - - case NXT_WS_ACCEPTED: - return PyErr_Format(PyExc_RuntimeError, "WebSocket already accepted"); - - case NXT_WS_DISCONNECTED: - return PyErr_Format(PyExc_RuntimeError, "WebSocket disconnected"); - - case NXT_WS_CLOSED: - return PyErr_Format(PyExc_RuntimeError, "WebSocket already closed"); - } - - if (nxt_slow_path(nxt_unit_response_is_websocket(ws->req))) { - return PyErr_Format(PyExc_RuntimeError, "WebSocket already accepted"); - } - - if (nxt_slow_path(nxt_unit_response_is_sent(ws->req))) { - return PyErr_Format(PyExc_RuntimeError, "response already sent"); - } - - calc_size_ctx.fields_size = 0; - calc_size_ctx.fields_count = 0; - - headers = PyDict_GetItem(dict, nxt_py_headers_str); - if (headers != NULL) { - res = nxt_py_asgi_enum_headers(headers, nxt_py_asgi_calc_size, - &calc_size_ctx); - if (nxt_slow_path(res == NULL)) { - return NULL; - } +static PyObject *nxt_py_asgi_websocket_accept(nxt_py_asgi_websocket_t *ws, + PyObject *dict) { + int rc; + char *subprotocol_str; + PyObject *res, *headers, *subprotocol; + Py_ssize_t subprotocol_len; + nxt_py_asgi_calc_size_ctx_t calc_size_ctx; + nxt_py_asgi_add_field_ctx_t add_field_ctx; + + static const nxt_str_t ws_protocol = nxt_string("sec-websocket-protocol"); + + switch (ws->state) { + case NXT_WS_INIT: + return PyErr_Format(PyExc_RuntimeError, "WebSocket connect not received"); + case NXT_WS_CONNECT: + break; + + case NXT_WS_ACCEPTED: + return PyErr_Format(PyExc_RuntimeError, "WebSocket already accepted"); + + case NXT_WS_DISCONNECTED: + return PyErr_Format(PyExc_RuntimeError, "WebSocket disconnected"); + + case NXT_WS_CLOSED: + return PyErr_Format(PyExc_RuntimeError, "WebSocket already closed"); + } + + if (nxt_slow_path(nxt_unit_response_is_websocket(ws->req))) { + return PyErr_Format(PyExc_RuntimeError, "WebSocket already accepted"); + } + + if (nxt_slow_path(nxt_unit_response_is_sent(ws->req))) { + return PyErr_Format(PyExc_RuntimeError, "response already sent"); + } + + calc_size_ctx.fields_size = 0; + calc_size_ctx.fields_count = 0; + + headers = PyDict_GetItem(dict, nxt_py_headers_str); + if (headers != NULL) { + res = nxt_py_asgi_enum_headers(headers, nxt_py_asgi_calc_size, + &calc_size_ctx); + if (nxt_slow_path(res == NULL)) { + return NULL; } + } - subprotocol = PyDict_GetItem(dict, nxt_py_subprotocol_str); - if (subprotocol != NULL && PyUnicode_Check(subprotocol)) { - subprotocol_str = PyUnicode_DATA(subprotocol); - subprotocol_len = PyUnicode_GET_LENGTH(subprotocol); - - calc_size_ctx.fields_size += ws_protocol.length + subprotocol_len; - calc_size_ctx.fields_count++; + subprotocol = PyDict_GetItem(dict, nxt_py_subprotocol_str); + if (subprotocol != NULL && PyUnicode_Check(subprotocol)) { + subprotocol_str = PyUnicode_DATA(subprotocol); + subprotocol_len = PyUnicode_GET_LENGTH(subprotocol); - } else { - subprotocol_str = NULL; - subprotocol_len = 0; - } + calc_size_ctx.fields_size += ws_protocol.length + subprotocol_len; + calc_size_ctx.fields_count++; - rc = nxt_unit_response_init(ws->req, 101, - calc_size_ctx.fields_count, - calc_size_ctx.fields_size); - if (nxt_slow_path(rc != NXT_UNIT_OK)) { - return PyErr_Format(PyExc_RuntimeError, - "failed to allocate response object"); - } + } else { + subprotocol_str = NULL; + subprotocol_len = 0; + } - add_field_ctx.req = ws->req; - add_field_ctx.content_length = -1; + rc = nxt_unit_response_init(ws->req, 101, calc_size_ctx.fields_count, + calc_size_ctx.fields_size); + if (nxt_slow_path(rc != NXT_UNIT_OK)) { + return PyErr_Format(PyExc_RuntimeError, + "failed to allocate response object"); + } - if (headers != NULL) { - res = nxt_py_asgi_enum_headers(headers, nxt_py_asgi_add_field, - &add_field_ctx); - if (nxt_slow_path(res == NULL)) { - return NULL; - } - } + add_field_ctx.req = ws->req; + add_field_ctx.content_length = -1; - if (subprotocol_len > 0) { - rc = nxt_unit_response_add_field(ws->req, - (const char *) ws_protocol.start, - ws_protocol.length, - subprotocol_str, subprotocol_len); - if (nxt_slow_path(rc != NXT_UNIT_OK)) { - return PyErr_Format(PyExc_RuntimeError, - "failed to add header"); - } + if (headers != NULL) { + res = nxt_py_asgi_enum_headers(headers, nxt_py_asgi_add_field, + &add_field_ctx); + if (nxt_slow_path(res == NULL)) { + return NULL; } + } - rc = nxt_unit_response_send(ws->req); + if (subprotocol_len > 0) { + rc = nxt_unit_response_add_field(ws->req, (const char *)ws_protocol.start, + ws_protocol.length, subprotocol_str, + subprotocol_len); if (nxt_slow_path(rc != NXT_UNIT_OK)) { - return PyErr_Format(PyExc_RuntimeError, "failed to send response"); + return PyErr_Format(PyExc_RuntimeError, "failed to add header"); } + } - ws->state = NXT_WS_ACCEPTED; - - Py_INCREF(ws); - - return (PyObject *) ws; -} - + rc = nxt_unit_response_send(ws->req); + if (nxt_slow_path(rc != NXT_UNIT_OK)) { + return PyErr_Format(PyExc_RuntimeError, "failed to send response"); + } -static PyObject * -nxt_py_asgi_websocket_close(nxt_py_asgi_websocket_t *ws, PyObject *dict) -{ - int rc; - uint16_t status_code; - PyObject *code; - - if (nxt_slow_path(ws->state == NXT_WS_INIT)) { - return PyErr_Format(PyExc_RuntimeError, - "WebSocket connect not received"); - } + ws->state = NXT_WS_ACCEPTED; - if (nxt_slow_path(ws->state == NXT_WS_DISCONNECTED)) { - return PyErr_Format(PyExc_RuntimeError, "WebSocket disconnected"); - } - - if (nxt_slow_path(ws->state == NXT_WS_CLOSED)) { - return PyErr_Format(PyExc_RuntimeError, "WebSocket already closed"); - } - - if (nxt_unit_response_is_websocket(ws->req)) { - code = PyDict_GetItem(dict, nxt_py_code_str); - if (nxt_slow_path(code != NULL && !PyLong_Check(code))) { - return PyErr_Format(PyExc_TypeError, "'code' is not integer"); - } - - status_code = (code != NULL) ? htons(PyLong_AsLong(code)) - : htons(NXT_WEBSOCKET_CR_NORMAL); - - rc = nxt_unit_websocket_send(ws->req, NXT_WEBSOCKET_OP_CLOSE, - 1, &status_code, 2); - if (nxt_slow_path(rc != NXT_UNIT_OK)) { - return PyErr_Format(PyExc_RuntimeError, - "failed to send close frame"); - } + Py_INCREF(ws); - } else { - rc = nxt_unit_response_init(ws->req, 403, 0, 0); - if (nxt_slow_path(rc != NXT_UNIT_OK)) { - return PyErr_Format(PyExc_RuntimeError, - "failed to allocate response object"); - } - - rc = nxt_unit_response_send(ws->req); - if (nxt_slow_path(rc != NXT_UNIT_OK)) { - return PyErr_Format(PyExc_RuntimeError, - "failed to send response"); - } - } - - ws->state = NXT_WS_CLOSED; - - Py_INCREF(ws); - - return (PyObject *) ws; + return (PyObject *)ws; } +static PyObject *nxt_py_asgi_websocket_close(nxt_py_asgi_websocket_t *ws, + PyObject *dict) { + int rc; + uint16_t status_code; + PyObject *code; -static PyObject * -nxt_py_asgi_websocket_send_frame(nxt_py_asgi_websocket_t *ws, PyObject *dict) -{ - int rc; - uint8_t opcode; - PyObject *bytes, *text; - const void *buf; - Py_ssize_t buf_size; - - if (nxt_slow_path(ws->state == NXT_WS_INIT)) { - return PyErr_Format(PyExc_RuntimeError, - "WebSocket connect not received"); - } + if (nxt_slow_path(ws->state == NXT_WS_INIT)) { + return PyErr_Format(PyExc_RuntimeError, "WebSocket connect not received"); + } - if (nxt_slow_path(ws->state == NXT_WS_CONNECT)) { - return PyErr_Format(PyExc_RuntimeError, - "WebSocket not accepted yet"); - } + if (nxt_slow_path(ws->state == NXT_WS_DISCONNECTED)) { + return PyErr_Format(PyExc_RuntimeError, "WebSocket disconnected"); + } - if (nxt_slow_path(ws->state == NXT_WS_DISCONNECTED)) { - return PyErr_Format(PyExc_RuntimeError, "WebSocket disconnected"); - } + if (nxt_slow_path(ws->state == NXT_WS_CLOSED)) { + return PyErr_Format(PyExc_RuntimeError, "WebSocket already closed"); + } - if (nxt_slow_path(ws->state == NXT_WS_CLOSED)) { - return PyErr_Format(PyExc_RuntimeError, "WebSocket already closed"); + if (nxt_unit_response_is_websocket(ws->req)) { + code = PyDict_GetItem(dict, nxt_py_code_str); + if (nxt_slow_path(code != NULL && !PyLong_Check(code))) { + return PyErr_Format(PyExc_TypeError, "'code' is not integer"); } - bytes = PyDict_GetItem(dict, nxt_py_bytes_str); - if (bytes == Py_None) { - bytes = NULL; - } + status_code = (code != NULL) ? htons(PyLong_AsLong(code)) + : htons(NXT_WEBSOCKET_CR_NORMAL); - if (nxt_slow_path(bytes != NULL && !PyBytes_Check(bytes))) { - return PyErr_Format(PyExc_TypeError, - "'bytes' is not a byte string"); - } - - text = PyDict_GetItem(dict, nxt_py_text_str); - if (text == Py_None) { - text = NULL; + rc = nxt_unit_websocket_send(ws->req, NXT_WEBSOCKET_OP_CLOSE, 1, + &status_code, 2); + if (nxt_slow_path(rc != NXT_UNIT_OK)) { + return PyErr_Format(PyExc_RuntimeError, "failed to send close frame"); } - if (nxt_slow_path(text != NULL && !PyUnicode_Check(text))) { - return PyErr_Format(PyExc_TypeError, - "'text' is not a unicode string"); + } else { + rc = nxt_unit_response_init(ws->req, 403, 0, 0); + if (nxt_slow_path(rc != NXT_UNIT_OK)) { + return PyErr_Format(PyExc_RuntimeError, + "failed to allocate response object"); } - if (nxt_slow_path(((bytes != NULL) ^ (text != NULL)) == 0)) { - return PyErr_Format(PyExc_ValueError, - "Exactly one of 'bytes' or 'text' must be non-None"); + rc = nxt_unit_response_send(ws->req); + if (nxt_slow_path(rc != NXT_UNIT_OK)) { + return PyErr_Format(PyExc_RuntimeError, "failed to send response"); } + } - if (bytes != NULL) { - buf = PyBytes_AS_STRING(bytes); - buf_size = PyBytes_GET_SIZE(bytes); - opcode = NXT_WEBSOCKET_OP_BINARY; - - } else { - buf = PyUnicode_AsUTF8AndSize(text, &buf_size); - opcode = NXT_WEBSOCKET_OP_TEXT; - } + ws->state = NXT_WS_CLOSED; - rc = nxt_unit_websocket_send(ws->req, opcode, 1, buf, buf_size); - if (nxt_slow_path(rc != NXT_UNIT_OK)) { - return PyErr_Format(PyExc_RuntimeError, "failed to send close frame"); - } + Py_INCREF(ws); - Py_INCREF(ws); - return (PyObject *) ws; + return (PyObject *)ws; } +static PyObject *nxt_py_asgi_websocket_send_frame(nxt_py_asgi_websocket_t *ws, + PyObject *dict) { + int rc; + uint8_t opcode; + PyObject *bytes, *text; + const void *buf; + Py_ssize_t buf_size; + + if (nxt_slow_path(ws->state == NXT_WS_INIT)) { + return PyErr_Format(PyExc_RuntimeError, "WebSocket connect not received"); + } + + if (nxt_slow_path(ws->state == NXT_WS_CONNECT)) { + return PyErr_Format(PyExc_RuntimeError, "WebSocket not accepted yet"); + } + + if (nxt_slow_path(ws->state == NXT_WS_DISCONNECTED)) { + return PyErr_Format(PyExc_RuntimeError, "WebSocket disconnected"); + } + + if (nxt_slow_path(ws->state == NXT_WS_CLOSED)) { + return PyErr_Format(PyExc_RuntimeError, "WebSocket already closed"); + } + + bytes = PyDict_GetItem(dict, nxt_py_bytes_str); + if (bytes == Py_None) { + bytes = NULL; + } + + if (nxt_slow_path(bytes != NULL && !PyBytes_Check(bytes))) { + return PyErr_Format(PyExc_TypeError, "'bytes' is not a byte string"); + } + + text = PyDict_GetItem(dict, nxt_py_text_str); + if (text == Py_None) { + text = NULL; + } + + if (nxt_slow_path(text != NULL && !PyUnicode_Check(text))) { + return PyErr_Format(PyExc_TypeError, "'text' is not a unicode string"); + } + + if (nxt_slow_path(((bytes != NULL) ^ (text != NULL)) == 0)) { + return PyErr_Format(PyExc_ValueError, + "Exactly one of 'bytes' or 'text' must be non-None"); + } + + if (bytes != NULL) { + buf = PyBytes_AS_STRING(bytes); + buf_size = PyBytes_GET_SIZE(bytes); + opcode = NXT_WEBSOCKET_OP_BINARY; + + } else { + buf = PyUnicode_AsUTF8AndSize(text, &buf_size); + opcode = NXT_WEBSOCKET_OP_TEXT; + } + + rc = nxt_unit_websocket_send(ws->req, opcode, 1, buf, buf_size); + if (nxt_slow_path(rc != NXT_UNIT_OK)) { + return PyErr_Format(PyExc_RuntimeError, "failed to send close frame"); + } + + Py_INCREF(ws); + return (PyObject *)ws; +} -void -nxt_py_asgi_websocket_handler(nxt_unit_websocket_frame_t *frame) -{ - uint8_t opcode; - uint16_t status_code; - uint64_t rest; - PyObject *msg, *exc; - nxt_py_asgi_websocket_t *ws; +void nxt_py_asgi_websocket_handler(nxt_unit_websocket_frame_t *frame) { + uint8_t opcode; + uint16_t status_code; + uint64_t rest; + PyObject *msg, *exc; + nxt_py_asgi_websocket_t *ws; - ws = frame->req->data; + ws = frame->req->data; - nxt_unit_req_debug(ws->req, "asgi_websocket_handler"); + nxt_unit_req_debug(ws->req, "asgi_websocket_handler"); - opcode = frame->header->opcode; - if (nxt_slow_path(opcode != NXT_WEBSOCKET_OP_CONT - && opcode != NXT_WEBSOCKET_OP_TEXT - && opcode != NXT_WEBSOCKET_OP_BINARY - && opcode != NXT_WEBSOCKET_OP_CLOSE)) - { - nxt_unit_websocket_done(frame); + opcode = frame->header->opcode; + if (nxt_slow_path(opcode != NXT_WEBSOCKET_OP_CONT && + opcode != NXT_WEBSOCKET_OP_TEXT && + opcode != NXT_WEBSOCKET_OP_BINARY && + opcode != NXT_WEBSOCKET_OP_CLOSE)) { + nxt_unit_websocket_done(frame); - nxt_unit_req_debug(ws->req, - "asgi_websocket_handler: ignore frame with opcode %d", - opcode); + nxt_unit_req_debug( + ws->req, "asgi_websocket_handler: ignore frame with opcode %d", opcode); - return; - } + return; + } - if (nxt_slow_path(ws->state != NXT_WS_ACCEPTED)) { - nxt_unit_websocket_done(frame); + if (nxt_slow_path(ws->state != NXT_WS_ACCEPTED)) { + nxt_unit_websocket_done(frame); - goto bad_state; - } + goto bad_state; + } - rest = nxt_py_asgi_ws_max_frame_size - ws->pending_frame_len; + rest = nxt_py_asgi_ws_max_frame_size - ws->pending_frame_len; - if (nxt_slow_path(frame->payload_len > rest)) { - nxt_unit_websocket_done(frame); + if (nxt_slow_path(frame->payload_len > rest)) { + nxt_unit_websocket_done(frame); - goto too_big; - } + goto too_big; + } - rest = nxt_py_asgi_ws_max_buffer_size - ws->pending_payload_len; + rest = nxt_py_asgi_ws_max_buffer_size - ws->pending_payload_len; - if (nxt_slow_path(frame->payload_len > rest)) { - nxt_unit_websocket_done(frame); + if (nxt_slow_path(frame->payload_len > rest)) { + nxt_unit_websocket_done(frame); - goto too_big; - } + goto too_big; + } - if (ws->receive_future == NULL || frame->header->fin == 0) { - nxt_py_asgi_websocket_suspend_frame(frame); + if (ws->receive_future == NULL || frame->header->fin == 0) { + nxt_py_asgi_websocket_suspend_frame(frame); - return; - } + return; + } - if (!nxt_queue_is_empty(&ws->pending_frames)) { - if (nxt_slow_path(opcode == NXT_WEBSOCKET_OP_TEXT - || opcode == NXT_WEBSOCKET_OP_BINARY)) - { - nxt_unit_req_alert(ws->req, + if (!nxt_queue_is_empty(&ws->pending_frames)) { + if (nxt_slow_path(opcode == NXT_WEBSOCKET_OP_TEXT || + opcode == NXT_WEBSOCKET_OP_BINARY)) { + nxt_unit_req_alert(ws->req, "Invalid state: pending frames with active receiver. " - "CONT frame expected. (%d)", opcode); + "CONT frame expected. (%d)", + opcode); - PyErr_SetString(PyExc_AssertionError, - "Invalid state: pending frames with active receiver. " - "CONT frame expected."); + PyErr_SetString(PyExc_AssertionError, + "Invalid state: pending frames with active receiver. " + "CONT frame expected."); - nxt_unit_websocket_done(frame); + nxt_unit_websocket_done(frame); - return; - } + return; } + } - msg = nxt_py_asgi_websocket_pop_msg(ws, frame); - if (nxt_slow_path(msg == NULL)) { - exc = PyErr_Occurred(); - Py_INCREF(exc); + msg = nxt_py_asgi_websocket_pop_msg(ws, frame); + if (nxt_slow_path(msg == NULL)) { + exc = PyErr_Occurred(); + Py_INCREF(exc); - goto raise; - } + goto raise; + } - nxt_py_asgi_websocket_receive_done(ws, msg); + nxt_py_asgi_websocket_receive_done(ws, msg); - return; + return; bad_state: - if (ws->receive_future == NULL) { - ws->receive_exc_str = nxt_py_bad_state_str; + if (ws->receive_future == NULL) { + ws->receive_exc_str = nxt_py_bad_state_str; - return; - } + return; + } - exc = PyObject_CallFunctionObjArgs(PyExc_RuntimeError, - nxt_py_bad_state_str, - NULL); - if (nxt_slow_path(exc == NULL)) { - nxt_unit_req_alert(ws->req, "RuntimeError create failed"); - nxt_python_print_exception(); + exc = PyObject_CallFunctionObjArgs(PyExc_RuntimeError, nxt_py_bad_state_str, + NULL); + if (nxt_slow_path(exc == NULL)) { + nxt_unit_req_alert(ws->req, "RuntimeError create failed"); + nxt_python_print_exception(); - exc = Py_None; - Py_INCREF(exc); - } + exc = Py_None; + Py_INCREF(exc); + } - goto raise; + goto raise; too_big: - status_code = htons(NXT_WEBSOCKET_CR_MESSAGE_TOO_BIG); + status_code = htons(NXT_WEBSOCKET_CR_MESSAGE_TOO_BIG); - (void) nxt_unit_websocket_send(ws->req, NXT_WEBSOCKET_OP_CLOSE, - 1, &status_code, 2); + (void)nxt_unit_websocket_send(ws->req, NXT_WEBSOCKET_OP_CLOSE, 1, + &status_code, 2); - ws->state = NXT_WS_CLOSED; + ws->state = NXT_WS_CLOSED; - if (ws->receive_future == NULL) { - ws->receive_exc_str = nxt_py_message_too_big_str; + if (ws->receive_future == NULL) { + ws->receive_exc_str = nxt_py_message_too_big_str; - return; - } + return; + } - exc = PyObject_CallFunctionObjArgs(PyExc_RuntimeError, - nxt_py_message_too_big_str, - NULL); - if (nxt_slow_path(exc == NULL)) { - nxt_unit_req_alert(ws->req, "RuntimeError create failed"); - nxt_python_print_exception(); + exc = PyObject_CallFunctionObjArgs(PyExc_RuntimeError, + nxt_py_message_too_big_str, NULL); + if (nxt_slow_path(exc == NULL)) { + nxt_unit_req_alert(ws->req, "RuntimeError create failed"); + nxt_python_print_exception(); - exc = Py_None; - Py_INCREF(exc); - } + exc = Py_None; + Py_INCREF(exc); + } raise: - nxt_py_asgi_websocket_receive_fail(ws, exc); + nxt_py_asgi_websocket_receive_fail(ws, exc); } +static void nxt_py_asgi_websocket_receive_done(nxt_py_asgi_websocket_t *ws, + PyObject *msg) { + PyObject *future, *res; -static void -nxt_py_asgi_websocket_receive_done(nxt_py_asgi_websocket_t *ws, PyObject *msg) -{ - PyObject *future, *res; - - future = ws->receive_future; - ws->receive_future = NULL; + future = ws->receive_future; + ws->receive_future = NULL; - res = PyObject_CallMethodObjArgs(future, nxt_py_set_result_str, msg, NULL); - if (nxt_slow_path(res == NULL)) { - nxt_unit_req_alert(ws->req, "'set_result' call failed"); - nxt_python_print_exception(); - } + res = PyObject_CallMethodObjArgs(future, nxt_py_set_result_str, msg, NULL); + if (nxt_slow_path(res == NULL)) { + nxt_unit_req_alert(ws->req, "'set_result' call failed"); + nxt_python_print_exception(); + } - Py_XDECREF(res); - Py_DECREF(future); + Py_XDECREF(res); + Py_DECREF(future); - Py_DECREF(msg); + Py_DECREF(msg); } +static void nxt_py_asgi_websocket_receive_fail(nxt_py_asgi_websocket_t *ws, + PyObject *exc) { + PyObject *future, *res; -static void -nxt_py_asgi_websocket_receive_fail(nxt_py_asgi_websocket_t *ws, PyObject *exc) -{ - PyObject *future, *res; - - future = ws->receive_future; - ws->receive_future = NULL; + future = ws->receive_future; + ws->receive_future = NULL; - res = PyObject_CallMethodObjArgs(future, nxt_py_set_exception_str, exc, - NULL); - if (nxt_slow_path(res == NULL)) { - nxt_unit_req_alert(ws->req, "'set_exception' call failed"); - nxt_python_print_exception(); - } + res = PyObject_CallMethodObjArgs(future, nxt_py_set_exception_str, exc, NULL); + if (nxt_slow_path(res == NULL)) { + nxt_unit_req_alert(ws->req, "'set_exception' call failed"); + nxt_python_print_exception(); + } - Py_XDECREF(res); - Py_DECREF(future); + Py_XDECREF(res); + Py_DECREF(future); - Py_DECREF(exc); + Py_DECREF(exc); } - static void -nxt_py_asgi_websocket_suspend_frame(nxt_unit_websocket_frame_t *frame) -{ - int rc; - nxt_py_asgi_websocket_t *ws; - nxt_py_asgi_penging_frame_t *p; +nxt_py_asgi_websocket_suspend_frame(nxt_unit_websocket_frame_t *frame) { + int rc; + nxt_py_asgi_websocket_t *ws; + nxt_py_asgi_penging_frame_t *p; - nxt_unit_req_debug(frame->req, "asgi_websocket_suspend_frame: " - "%d, %"PRIu64", %d", - frame->header->opcode, frame->payload_len, - frame->header->fin); + nxt_unit_req_debug(frame->req, + "asgi_websocket_suspend_frame: " + "%d, %" PRIu64 ", %d", + frame->header->opcode, frame->payload_len, + frame->header->fin); - ws = frame->req->data; + ws = frame->req->data; - rc = nxt_unit_websocket_retain(frame); - if (nxt_slow_path(rc == NXT_UNIT_ERROR)) { - nxt_unit_req_alert(ws->req, "Failed to retain frame for suspension."); + rc = nxt_unit_websocket_retain(frame); + if (nxt_slow_path(rc == NXT_UNIT_ERROR)) { + nxt_unit_req_alert(ws->req, "Failed to retain frame for suspension."); - nxt_unit_websocket_done(frame); + nxt_unit_websocket_done(frame); - PyErr_SetString(PyExc_RuntimeError, - "Failed to retain frame for suspension."); + PyErr_SetString(PyExc_RuntimeError, + "Failed to retain frame for suspension."); - return; - } + return; + } - p = nxt_unit_malloc(frame->req->ctx, sizeof(nxt_py_asgi_penging_frame_t)); - if (nxt_slow_path(p == NULL)) { - nxt_unit_req_alert(ws->req, - "Failed to allocate buffer to suspend frame."); + p = nxt_unit_malloc(frame->req->ctx, sizeof(nxt_py_asgi_penging_frame_t)); + if (nxt_slow_path(p == NULL)) { + nxt_unit_req_alert(ws->req, "Failed to allocate buffer to suspend frame."); - nxt_unit_websocket_done(frame); + nxt_unit_websocket_done(frame); - PyErr_SetString(PyExc_RuntimeError, - "Failed to allocate buffer to suspend frame."); + PyErr_SetString(PyExc_RuntimeError, + "Failed to allocate buffer to suspend frame."); - return; - } + return; + } - p->frame = frame; - nxt_queue_insert_tail(&ws->pending_frames, &p->link); + p->frame = frame; + nxt_queue_insert_tail(&ws->pending_frames, &p->link); - ws->pending_payload_len += frame->payload_len; - ws->pending_fins += frame->header->fin; + ws->pending_payload_len += frame->payload_len; + ws->pending_fins += frame->header->fin; - if (frame->header->fin) { - ws->pending_frame_len = 0; + if (frame->header->fin) { + ws->pending_frame_len = 0; - } else { - if (frame->header->opcode == NXT_WEBSOCKET_OP_CONT) { - ws->pending_frame_len += frame->payload_len; + } else { + if (frame->header->opcode == NXT_WEBSOCKET_OP_CONT) { + ws->pending_frame_len += frame->payload_len; - } else { - ws->pending_frame_len = frame->payload_len; - } + } else { + ws->pending_frame_len = frame->payload_len; } + } } - static PyObject * nxt_py_asgi_websocket_pop_msg(nxt_py_asgi_websocket_t *ws, - nxt_unit_websocket_frame_t *frame) -{ - int fin; - char *buf; - uint8_t code_buf[2], opcode; - uint16_t code; - PyObject *msg, *data, *type, *data_key; - uint64_t payload_len; - nxt_unit_websocket_frame_t *fin_frame; - - nxt_unit_req_debug(ws->req, "asgi_websocket_pop_msg"); - - fin_frame = NULL; - - if (nxt_queue_is_empty(&ws->pending_frames) - || (frame != NULL - && frame->header->opcode == NXT_WEBSOCKET_OP_CLOSE)) - { - payload_len = frame->payload_len; - - } else { - if (frame != NULL) { - payload_len = ws->pending_payload_len + frame->payload_len; - fin_frame = frame; + nxt_unit_websocket_frame_t *frame) { + int fin; + char *buf; + uint8_t code_buf[2], opcode; + uint16_t code; + PyObject *msg, *data, *type, *data_key; + uint64_t payload_len; + nxt_unit_websocket_frame_t *fin_frame; - } else { - payload_len = nxt_py_asgi_websocket_pending_len(ws); - } + nxt_unit_req_debug(ws->req, "asgi_websocket_pop_msg"); - frame = nxt_py_asgi_websocket_pop_frame(ws); - } + fin_frame = NULL; - opcode = frame->header->opcode; + if (nxt_queue_is_empty(&ws->pending_frames) || + (frame != NULL && frame->header->opcode == NXT_WEBSOCKET_OP_CLOSE)) { + payload_len = frame->payload_len; - if (nxt_slow_path(opcode == NXT_WEBSOCKET_OP_CONT)) { - nxt_unit_req_alert(ws->req, - "Invalid state: attempt to process CONT frame."); + } else { + if (frame != NULL) { + payload_len = ws->pending_payload_len + frame->payload_len; + fin_frame = frame; - nxt_unit_websocket_done(frame); - - return PyErr_Format(PyExc_AssertionError, - "Invalid state: attempt to process CONT frame."); + } else { + payload_len = nxt_py_asgi_websocket_pending_len(ws); } - type = nxt_py_websocket_receive_str; + frame = nxt_py_asgi_websocket_pop_frame(ws); + } - switch (opcode) { - case NXT_WEBSOCKET_OP_TEXT: - buf = nxt_unit_malloc(frame->req->ctx, payload_len); - if (nxt_slow_path(buf == NULL)) { - nxt_unit_req_alert(ws->req, - "Failed to allocate buffer for payload (%d).", - (int) payload_len); + opcode = frame->header->opcode; - nxt_unit_websocket_done(frame); + if (nxt_slow_path(opcode == NXT_WEBSOCKET_OP_CONT)) { + nxt_unit_req_alert(ws->req, + "Invalid state: attempt to process CONT frame."); - return PyErr_Format(PyExc_RuntimeError, - "Failed to allocate buffer for payload (%d).", - (int) payload_len); - } + nxt_unit_websocket_done(frame); - data = NULL; - data_key = nxt_py_text_str; + return PyErr_Format(PyExc_AssertionError, + "Invalid state: attempt to process CONT frame."); + } - break; + type = nxt_py_websocket_receive_str; - case NXT_WEBSOCKET_OP_BINARY: - data = PyBytes_FromStringAndSize(NULL, payload_len); - if (nxt_slow_path(data == NULL)) { - nxt_unit_req_alert(ws->req, - "Failed to create Bytes for payload (%d).", - (int) payload_len); - nxt_python_print_exception(); + switch (opcode) { + case NXT_WEBSOCKET_OP_TEXT: + buf = nxt_unit_malloc(frame->req->ctx, payload_len); + if (nxt_slow_path(buf == NULL)) { + nxt_unit_req_alert(ws->req, "Failed to allocate buffer for payload (%d).", + (int)payload_len); - nxt_unit_websocket_done(frame); + nxt_unit_websocket_done(frame); - return PyErr_Format(PyExc_RuntimeError, - "Failed to create Bytes for payload."); - } + return PyErr_Format(PyExc_RuntimeError, + "Failed to allocate buffer for payload (%d).", + (int)payload_len); + } - buf = (char *) PyBytes_AS_STRING(data); - data_key = nxt_py_bytes_str; + data = NULL; + data_key = nxt_py_text_str; - break; + break; - case NXT_WEBSOCKET_OP_CLOSE: - if (frame->payload_len >= 2) { - nxt_unit_websocket_read(frame, code_buf, 2); - code = ((uint16_t) code_buf[0]) << 8 | code_buf[1]; + case NXT_WEBSOCKET_OP_BINARY: + data = PyBytes_FromStringAndSize(NULL, payload_len); + if (nxt_slow_path(data == NULL)) { + nxt_unit_req_alert(ws->req, "Failed to create Bytes for payload (%d).", + (int)payload_len); + nxt_python_print_exception(); - } else { - code = NXT_WEBSOCKET_CR_NORMAL; - } + nxt_unit_websocket_done(frame); - nxt_unit_websocket_done(frame); + return PyErr_Format(PyExc_RuntimeError, + "Failed to create Bytes for payload."); + } - data = PyLong_FromLong(code); - if (nxt_slow_path(data == NULL)) { - nxt_unit_req_alert(ws->req, - "Failed to create Long from code %d.", - (int) code); - nxt_python_print_exception(); + buf = (char *)PyBytes_AS_STRING(data); + data_key = nxt_py_bytes_str; - return PyErr_Format(PyExc_RuntimeError, - "Failed to create Long from code %d.", - (int) code); - } + break; - buf = NULL; - type = nxt_py_websocket_disconnect_str; - data_key = nxt_py_code_str; + case NXT_WEBSOCKET_OP_CLOSE: + if (frame->payload_len >= 2) { + nxt_unit_websocket_read(frame, code_buf, 2); + code = ((uint16_t)code_buf[0]) << 8 | code_buf[1]; - break; + } else { + code = NXT_WEBSOCKET_CR_NORMAL; + } - default: - nxt_unit_req_alert(ws->req, "Unexpected opcode %d", opcode); + nxt_unit_websocket_done(frame); - nxt_unit_websocket_done(frame); + data = PyLong_FromLong(code); + if (nxt_slow_path(data == NULL)) { + nxt_unit_req_alert(ws->req, "Failed to create Long from code %d.", + (int)code); + nxt_python_print_exception(); - return PyErr_Format(PyExc_AssertionError, "Unexpected opcode %d", - opcode); + return PyErr_Format(PyExc_RuntimeError, + "Failed to create Long from code %d.", (int)code); } - if (buf != NULL) { - fin = frame->header->fin; - buf += nxt_unit_websocket_read(frame, buf, frame->payload_len); - - nxt_unit_websocket_done(frame); + buf = NULL; + type = nxt_py_websocket_disconnect_str; + data_key = nxt_py_code_str; - if (!fin) { - while (!nxt_queue_is_empty(&ws->pending_frames)) { - frame = nxt_py_asgi_websocket_pop_frame(ws); - fin = frame->header->fin; + break; - buf += nxt_unit_websocket_read(frame, buf, frame->payload_len); + default: + nxt_unit_req_alert(ws->req, "Unexpected opcode %d", opcode); - nxt_unit_websocket_done(frame); + nxt_unit_websocket_done(frame); - if (fin) { - break; - } - } + return PyErr_Format(PyExc_AssertionError, "Unexpected opcode %d", opcode); + } - if (fin_frame != NULL) { - buf += nxt_unit_websocket_read(fin_frame, buf, - fin_frame->payload_len); - nxt_unit_websocket_done(fin_frame); - } - } + if (buf != NULL) { + fin = frame->header->fin; + buf += nxt_unit_websocket_read(frame, buf, frame->payload_len); - if (opcode == NXT_WEBSOCKET_OP_TEXT) { - buf -= payload_len; + nxt_unit_websocket_done(frame); - data = PyUnicode_DecodeUTF8(buf, payload_len, NULL); + if (!fin) { + while (!nxt_queue_is_empty(&ws->pending_frames)) { + frame = nxt_py_asgi_websocket_pop_frame(ws); + fin = frame->header->fin; - nxt_unit_free(ws->req->ctx, buf); + buf += nxt_unit_websocket_read(frame, buf, frame->payload_len); - if (nxt_slow_path(data == NULL)) { - nxt_unit_req_alert(ws->req, - "Failed to create Unicode for payload (%d).", - (int) payload_len); - nxt_python_print_exception(); + nxt_unit_websocket_done(frame); - return PyErr_Format(PyExc_RuntimeError, - "Failed to create Unicode."); - } + if (fin) { + break; } - } + } - msg = nxt_py_asgi_new_msg(ws->req, type); - if (nxt_slow_path(msg == NULL)) { - Py_DECREF(data); - return NULL; + if (fin_frame != NULL) { + buf += nxt_unit_websocket_read(fin_frame, buf, fin_frame->payload_len); + nxt_unit_websocket_done(fin_frame); + } } - if (nxt_slow_path(PyDict_SetItem(msg, data_key, data) == -1)) { - nxt_unit_req_alert(ws->req, "Python failed to set 'msg.data' item"); + if (opcode == NXT_WEBSOCKET_OP_TEXT) { + buf -= payload_len; + + data = PyUnicode_DecodeUTF8(buf, payload_len, NULL); - Py_DECREF(msg); - Py_DECREF(data); + nxt_unit_free(ws->req->ctx, buf); - return PyErr_Format(PyExc_RuntimeError, - "Python failed to set 'msg.data' item"); + if (nxt_slow_path(data == NULL)) { + nxt_unit_req_alert(ws->req, + "Failed to create Unicode for payload (%d).", + (int)payload_len); + nxt_python_print_exception(); + + return PyErr_Format(PyExc_RuntimeError, "Failed to create Unicode."); + } } + } + msg = nxt_py_asgi_new_msg(ws->req, type); + if (nxt_slow_path(msg == NULL)) { Py_DECREF(data); + return NULL; + } - return msg; -} + if (nxt_slow_path(PyDict_SetItem(msg, data_key, data) == -1)) { + nxt_unit_req_alert(ws->req, "Python failed to set 'msg.data' item"); + + Py_DECREF(msg); + Py_DECREF(data); + return PyErr_Format(PyExc_RuntimeError, + "Python failed to set 'msg.data' item"); + } -static uint64_t -nxt_py_asgi_websocket_pending_len(nxt_py_asgi_websocket_t *ws) -{ - uint64_t res; - nxt_py_asgi_penging_frame_t *p; + Py_DECREF(data); - res = 0; + return msg; +} - nxt_queue_each(p, &ws->pending_frames, nxt_py_asgi_penging_frame_t, link) { - res += p->frame->payload_len; +static uint64_t nxt_py_asgi_websocket_pending_len(nxt_py_asgi_websocket_t *ws) { + uint64_t res; + nxt_py_asgi_penging_frame_t *p; - if (p->frame->header->fin) { - nxt_unit_req_debug(ws->req, "asgi_websocket_pending_len: %d", - (int) res); - return res; - } - } nxt_queue_loop; + res = 0; - nxt_unit_req_debug(ws->req, "asgi_websocket_pending_len: %d (all)", - (int) res); - return res; -} + nxt_queue_each(p, &ws->pending_frames, nxt_py_asgi_penging_frame_t, link) { + res += p->frame->payload_len; + if (p->frame->header->fin) { + nxt_unit_req_debug(ws->req, "asgi_websocket_pending_len: %d", (int)res); + return res; + } + } + nxt_queue_loop; + + nxt_unit_req_debug(ws->req, "asgi_websocket_pending_len: %d (all)", (int)res); + return res; +} static nxt_unit_websocket_frame_t * -nxt_py_asgi_websocket_pop_frame(nxt_py_asgi_websocket_t *ws) -{ - nxt_queue_link_t *lnk; - nxt_unit_websocket_frame_t *frame; - nxt_py_asgi_penging_frame_t *p; +nxt_py_asgi_websocket_pop_frame(nxt_py_asgi_websocket_t *ws) { + nxt_queue_link_t *lnk; + nxt_unit_websocket_frame_t *frame; + nxt_py_asgi_penging_frame_t *p; - lnk = nxt_queue_first(&ws->pending_frames); - nxt_queue_remove(lnk); + lnk = nxt_queue_first(&ws->pending_frames); + nxt_queue_remove(lnk); - p = nxt_queue_link_data(lnk, nxt_py_asgi_penging_frame_t, link); + p = nxt_queue_link_data(lnk, nxt_py_asgi_penging_frame_t, link); - frame = p->frame; - ws->pending_payload_len -= frame->payload_len; - ws->pending_fins -= frame->header->fin; + frame = p->frame; + ws->pending_payload_len -= frame->payload_len; + ws->pending_fins -= frame->header->fin; - nxt_unit_free(frame->req->ctx, p); + nxt_unit_free(frame->req->ctx, p); - nxt_unit_req_debug(frame->req, "asgi_websocket_pop_frame: " - "%d, %"PRIu64", %d", - frame->header->opcode, frame->payload_len, - frame->header->fin); + nxt_unit_req_debug(frame->req, + "asgi_websocket_pop_frame: " + "%d, %" PRIu64 ", %d", + frame->header->opcode, frame->payload_len, + frame->header->fin); - return frame; + return frame; } +void nxt_py_asgi_websocket_close_handler(nxt_unit_request_info_t *req) { + PyObject *msg, *exc; + nxt_py_asgi_websocket_t *ws; -void -nxt_py_asgi_websocket_close_handler(nxt_unit_request_info_t *req) -{ - PyObject *msg, *exc; - nxt_py_asgi_websocket_t *ws; - - ws = req->data; + ws = req->data; - nxt_unit_req_debug(req, "asgi_websocket_close_handler"); + nxt_unit_req_debug(req, "asgi_websocket_close_handler"); - if (nxt_slow_path(ws == NULL)) { - return; - } + if (nxt_slow_path(ws == NULL)) { + return; + } - if (ws->receive_future == NULL) { - ws->state = NXT_WS_DISCONNECTED; + if (ws->receive_future == NULL) { + ws->state = NXT_WS_DISCONNECTED; - return; - } + return; + } - msg = nxt_py_asgi_websocket_disconnect_msg(ws); - if (nxt_slow_path(msg == NULL)) { - exc = PyErr_Occurred(); - Py_INCREF(exc); + msg = nxt_py_asgi_websocket_disconnect_msg(ws); + if (nxt_slow_path(msg == NULL)) { + exc = PyErr_Occurred(); + Py_INCREF(exc); - nxt_py_asgi_websocket_receive_fail(ws, exc); + nxt_py_asgi_websocket_receive_fail(ws, exc); - } else { - nxt_py_asgi_websocket_receive_done(ws, msg); - } + } else { + nxt_py_asgi_websocket_receive_done(ws, msg); + } } - static PyObject * -nxt_py_asgi_websocket_disconnect_msg(nxt_py_asgi_websocket_t *ws) -{ - PyObject *msg, *code; +nxt_py_asgi_websocket_disconnect_msg(nxt_py_asgi_websocket_t *ws) { + PyObject *msg, *code; - msg = nxt_py_asgi_new_msg(ws->req, nxt_py_websocket_disconnect_str); - if (nxt_slow_path(msg == NULL)) { - return NULL; - } + msg = nxt_py_asgi_new_msg(ws->req, nxt_py_websocket_disconnect_str); + if (nxt_slow_path(msg == NULL)) { + return NULL; + } - code = PyLong_FromLong(NXT_WEBSOCKET_CR_GOING_AWAY); - if (nxt_slow_path(code == NULL)) { - nxt_unit_req_alert(ws->req, "Python failed to create long"); - nxt_python_print_exception(); + code = PyLong_FromLong(NXT_WEBSOCKET_CR_GOING_AWAY); + if (nxt_slow_path(code == NULL)) { + nxt_unit_req_alert(ws->req, "Python failed to create long"); + nxt_python_print_exception(); - Py_DECREF(msg); + Py_DECREF(msg); - return PyErr_Format(PyExc_RuntimeError, "failed to create long"); - } + return PyErr_Format(PyExc_RuntimeError, "failed to create long"); + } - if (nxt_slow_path(PyDict_SetItem(msg, nxt_py_code_str, code) == -1)) { - nxt_unit_req_alert(ws->req, "Python failed to set 'msg.code' item"); + if (nxt_slow_path(PyDict_SetItem(msg, nxt_py_code_str, code) == -1)) { + nxt_unit_req_alert(ws->req, "Python failed to set 'msg.code' item"); - Py_DECREF(msg); - Py_DECREF(code); + Py_DECREF(msg); + Py_DECREF(code); - return PyErr_Format(PyExc_RuntimeError, - "Python failed to set 'msg.code' item"); - } + return PyErr_Format(PyExc_RuntimeError, + "Python failed to set 'msg.code' item"); + } - Py_DECREF(code); + Py_DECREF(code); - return msg; + return msg; } +static PyObject *nxt_py_asgi_websocket_done(PyObject *self, PyObject *future) { + int rc; + uint16_t status_code; + PyObject *res; + nxt_py_asgi_websocket_t *ws; -static PyObject * -nxt_py_asgi_websocket_done(PyObject *self, PyObject *future) -{ - int rc; - uint16_t status_code; - PyObject *res; - nxt_py_asgi_websocket_t *ws; - - ws = (nxt_py_asgi_websocket_t *) self; - - nxt_unit_req_debug(ws->req, "asgi_websocket_done: %p", self); - - /* - * Get Future.result() and it raises an exception, if coroutine exited - * with exception. - */ - res = PyObject_CallMethodObjArgs(future, nxt_py_result_str, NULL); - if (nxt_slow_path(res == NULL)) { - nxt_unit_req_error(ws->req, - "Python failed to call 'future.result()'"); - nxt_python_print_exception(); + ws = (nxt_py_asgi_websocket_t *)self; - rc = NXT_UNIT_ERROR; + nxt_unit_req_debug(ws->req, "asgi_websocket_done: %p", self); - } else { - Py_DECREF(res); + /* + * Get Future.result() and it raises an exception, if coroutine exited + * with exception. + */ + res = PyObject_CallMethodObjArgs(future, nxt_py_result_str, NULL); + if (nxt_slow_path(res == NULL)) { + nxt_unit_req_error(ws->req, "Python failed to call 'future.result()'"); + nxt_python_print_exception(); - rc = NXT_UNIT_OK; - } + rc = NXT_UNIT_ERROR; + + } else { + Py_DECREF(res); + + rc = NXT_UNIT_OK; + } - if (ws->state == NXT_WS_ACCEPTED) { - status_code = (rc == NXT_UNIT_OK) + if (ws->state == NXT_WS_ACCEPTED) { + status_code = (rc == NXT_UNIT_OK) ? htons(NXT_WEBSOCKET_CR_NORMAL) : htons(NXT_WEBSOCKET_CR_INTERNAL_SERVER_ERROR); - rc = nxt_unit_websocket_send(ws->req, NXT_WEBSOCKET_OP_CLOSE, - 1, &status_code, 2); - } + rc = nxt_unit_websocket_send(ws->req, NXT_WEBSOCKET_OP_CLOSE, 1, + &status_code, 2); + } - while (!nxt_queue_is_empty(&ws->pending_frames)) { - nxt_unit_websocket_done(nxt_py_asgi_websocket_pop_frame(ws)); - } + while (!nxt_queue_is_empty(&ws->pending_frames)) { + nxt_unit_websocket_done(nxt_py_asgi_websocket_pop_frame(ws)); + } - nxt_unit_request_done(ws->req, rc); + nxt_unit_request_done(ws->req, rc); - Py_RETURN_NONE; + Py_RETURN_NONE; } - #endif /* NXT_HAVE_ASGI */ diff --git a/src/python/nxt_python_wsgi.c b/src/python/nxt_python_wsgi.c index c621097ea..6068cffa1 100644 --- a/src/python/nxt_python_wsgi.c +++ b/src/python/nxt_python_wsgi.c @@ -5,7 +5,6 @@ * Copyright (C) NGINX, Inc. */ - #include #include @@ -37,19 +36,17 @@ * will use PyString_* or corresponding PyBytes_* functions */ - typedef struct { - PyObject_HEAD - - uint64_t content_length; - uint64_t bytes_sent; - PyObject *environ; - PyObject *start_resp; - PyObject *write; - nxt_unit_request_info_t *req; - PyThreadState *thread_state; -} nxt_python_ctx_t; + PyObject_HEAD + uint64_t content_length; + uint64_t bytes_sent; + PyObject *environ; + PyObject *start_resp; + PyObject *write; + nxt_unit_request_info_t *req; + PyThreadState *thread_state; +} nxt_python_ctx_t; static int nxt_python_wsgi_ctx_data_alloc(void **pdata, int main); static void nxt_python_wsgi_ctx_data_free(void *data); @@ -61,1354 +58,1241 @@ static void nxt_python_request_handler(nxt_unit_request_info_t *req); static PyObject *nxt_python_create_environ(nxt_python_app_conf_t *c); static PyObject *nxt_python_copy_environ(nxt_unit_request_info_t *req); static PyObject *nxt_python_get_environ(nxt_python_ctx_t *pctx, - nxt_python_target_t *app_target); + nxt_python_target_t *app_target); static int nxt_python_add_sptr(nxt_python_ctx_t *pctx, PyObject *name, - nxt_unit_sptr_t *sptr, uint32_t size); + nxt_unit_sptr_t *sptr, uint32_t size); static int nxt_python_add_char(nxt_python_ctx_t *pctx, PyObject *name, - char *src, uint32_t size); + char *src, uint32_t size); static int nxt_python_add_py_string(nxt_python_ctx_t *pctx, PyObject *name, - PyObject *value); -static int nxt_python_add_field(nxt_python_ctx_t *pctx, - nxt_unit_field_t *field, int n, uint32_t vl); + PyObject *value); +static int nxt_python_add_field(nxt_python_ctx_t *pctx, nxt_unit_field_t *field, + int n, uint32_t vl); static PyObject *nxt_python_field_name(const char *name, uint8_t len); static PyObject *nxt_python_field_value(nxt_unit_field_t *f, int n, - uint32_t vl); + uint32_t vl); static int nxt_python_add_obj(nxt_python_ctx_t *pctx, PyObject *name, - PyObject *value); + PyObject *value); static PyObject *nxt_py_start_resp(PyObject *self, PyObject *args); -static int nxt_python_response_add_field(nxt_python_ctx_t *pctx, - PyObject *name, PyObject *value, int i); +static int nxt_python_response_add_field(nxt_python_ctx_t *pctx, PyObject *name, + PyObject *value, int i); static int nxt_python_str_buf(PyObject *str, char **buf, uint32_t *len, - PyObject **bytes); + PyObject **bytes); static PyObject *nxt_py_write(PyObject *self, PyObject *args); static void nxt_py_input_dealloc(nxt_python_ctx_t *pctx); static PyObject *nxt_py_input_read(nxt_python_ctx_t *pctx, PyObject *args); -static PyObject *nxt_py_input_readline(nxt_python_ctx_t *pctx, - PyObject *args); +static PyObject *nxt_py_input_readline(nxt_python_ctx_t *pctx, PyObject *args); static PyObject *nxt_py_input_getline(nxt_python_ctx_t *pctx, size_t size); -static PyObject *nxt_py_input_readlines(nxt_python_ctx_t *self, - PyObject *args); +static PyObject *nxt_py_input_readlines(nxt_python_ctx_t *self, PyObject *args); static PyObject *nxt_py_input_iter(PyObject *pctx); static PyObject *nxt_py_input_next(PyObject *pctx); static int nxt_python_write(nxt_python_ctx_t *pctx, PyObject *bytes); - static PyMethodDef nxt_py_start_resp_method[] = { - {"unit_start_response", nxt_py_start_resp, METH_VARARGS, ""} -}; - + {"unit_start_response", nxt_py_start_resp, METH_VARARGS, ""}}; static PyMethodDef nxt_py_write_method[] = { - {"unit_write", nxt_py_write, METH_O, ""} -}; - + {"unit_write", nxt_py_write, METH_O, ""}}; static PyMethodDef nxt_py_input_methods[] = { - { "read", (PyCFunction) nxt_py_input_read, METH_VARARGS, 0 }, - { "readline", (PyCFunction) nxt_py_input_readline, METH_VARARGS, 0 }, - { "readlines", (PyCFunction) nxt_py_input_readlines, METH_VARARGS, 0 }, - { NULL, NULL, 0, 0 } -}; - + {"read", (PyCFunction)nxt_py_input_read, METH_VARARGS, 0}, + {"readline", (PyCFunction)nxt_py_input_readline, METH_VARARGS, 0}, + {"readlines", (PyCFunction)nxt_py_input_readlines, METH_VARARGS, 0}, + {NULL, NULL, 0, 0}}; static PyTypeObject nxt_py_input_type = { PyVarObject_HEAD_INIT(NULL, 0) - .tp_name = "unit._input", + .tp_name = "unit._input", .tp_basicsize = sizeof(nxt_python_ctx_t), - .tp_dealloc = (destructor) nxt_py_input_dealloc, - .tp_flags = Py_TPFLAGS_DEFAULT, - .tp_doc = "unit input object.", - .tp_iter = nxt_py_input_iter, - .tp_iternext = nxt_py_input_next, - .tp_methods = nxt_py_input_methods, + .tp_dealloc = (destructor)nxt_py_input_dealloc, + .tp_flags = Py_TPFLAGS_DEFAULT, + .tp_doc = "unit input object.", + .tp_iter = nxt_py_input_iter, + .tp_iternext = nxt_py_input_next, + .tp_methods = nxt_py_input_methods, }; - -static PyObject *nxt_py_environ_ptyp; - -static PyObject *nxt_py_80_str; -static PyObject *nxt_py_close_str; -static PyObject *nxt_py_content_length_str; -static PyObject *nxt_py_content_type_str; -static PyObject *nxt_py_http_str; -static PyObject *nxt_py_https_str; -static PyObject *nxt_py_path_info_str; -static PyObject *nxt_py_query_string_str; -static PyObject *nxt_py_remote_addr_str; -static PyObject *nxt_py_request_method_str; -static PyObject *nxt_py_request_uri_str; -static PyObject *nxt_py_script_name_str; -static PyObject *nxt_py_server_addr_str; -static PyObject *nxt_py_server_name_str; -static PyObject *nxt_py_server_port_str; -static PyObject *nxt_py_server_protocol_str; -static PyObject *nxt_py_wsgi_input_str; -static PyObject *nxt_py_wsgi_uri_scheme_str; +static PyObject *nxt_py_environ_ptyp; + +static PyObject *nxt_py_80_str; +static PyObject *nxt_py_close_str; +static PyObject *nxt_py_content_length_str; +static PyObject *nxt_py_content_type_str; +static PyObject *nxt_py_http_str; +static PyObject *nxt_py_https_str; +static PyObject *nxt_py_path_info_str; +static PyObject *nxt_py_query_string_str; +static PyObject *nxt_py_remote_addr_str; +static PyObject *nxt_py_request_method_str; +static PyObject *nxt_py_request_uri_str; +static PyObject *nxt_py_script_name_str; +static PyObject *nxt_py_server_addr_str; +static PyObject *nxt_py_server_name_str; +static PyObject *nxt_py_server_port_str; +static PyObject *nxt_py_server_protocol_str; +static PyObject *nxt_py_wsgi_input_str; +static PyObject *nxt_py_wsgi_uri_scheme_str; static nxt_python_string_t nxt_python_strings[] = { - { nxt_string("80"), &nxt_py_80_str }, - { nxt_string("close"), &nxt_py_close_str }, - { nxt_string("CONTENT_LENGTH"), &nxt_py_content_length_str }, - { nxt_string("CONTENT_TYPE"), &nxt_py_content_type_str }, - { nxt_string("http"), &nxt_py_http_str }, - { nxt_string("https"), &nxt_py_https_str }, - { nxt_string("PATH_INFO"), &nxt_py_path_info_str }, - { nxt_string("QUERY_STRING"), &nxt_py_query_string_str }, - { nxt_string("REMOTE_ADDR"), &nxt_py_remote_addr_str }, - { nxt_string("REQUEST_METHOD"), &nxt_py_request_method_str }, - { nxt_string("REQUEST_URI"), &nxt_py_request_uri_str }, - { nxt_string("SCRIPT_NAME"), &nxt_py_script_name_str }, - { nxt_string("SERVER_ADDR"), &nxt_py_server_addr_str }, - { nxt_string("SERVER_NAME"), &nxt_py_server_name_str }, - { nxt_string("SERVER_PORT"), &nxt_py_server_port_str }, - { nxt_string("SERVER_PROTOCOL"), &nxt_py_server_protocol_str }, - { nxt_string("wsgi.input"), &nxt_py_wsgi_input_str }, - { nxt_string("wsgi.url_scheme"), &nxt_py_wsgi_uri_scheme_str }, - { nxt_null_string, NULL }, + {nxt_string("80"), &nxt_py_80_str}, + {nxt_string("close"), &nxt_py_close_str}, + {nxt_string("CONTENT_LENGTH"), &nxt_py_content_length_str}, + {nxt_string("CONTENT_TYPE"), &nxt_py_content_type_str}, + {nxt_string("http"), &nxt_py_http_str}, + {nxt_string("https"), &nxt_py_https_str}, + {nxt_string("PATH_INFO"), &nxt_py_path_info_str}, + {nxt_string("QUERY_STRING"), &nxt_py_query_string_str}, + {nxt_string("REMOTE_ADDR"), &nxt_py_remote_addr_str}, + {nxt_string("REQUEST_METHOD"), &nxt_py_request_method_str}, + {nxt_string("REQUEST_URI"), &nxt_py_request_uri_str}, + {nxt_string("SCRIPT_NAME"), &nxt_py_script_name_str}, + {nxt_string("SERVER_ADDR"), &nxt_py_server_addr_str}, + {nxt_string("SERVER_NAME"), &nxt_py_server_name_str}, + {nxt_string("SERVER_PORT"), &nxt_py_server_port_str}, + {nxt_string("SERVER_PROTOCOL"), &nxt_py_server_protocol_str}, + {nxt_string("wsgi.input"), &nxt_py_wsgi_input_str}, + {nxt_string("wsgi.url_scheme"), &nxt_py_wsgi_uri_scheme_str}, + {nxt_null_string, NULL}, }; -static nxt_python_proto_t nxt_py_wsgi_proto = { +static nxt_python_proto_t nxt_py_wsgi_proto = { .ctx_data_alloc = nxt_python_wsgi_ctx_data_alloc, - .ctx_data_free = nxt_python_wsgi_ctx_data_free, - .run = nxt_python_wsgi_run, - .done = nxt_python_wsgi_done, + .ctx_data_free = nxt_python_wsgi_ctx_data_free, + .run = nxt_python_wsgi_run, + .done = nxt_python_wsgi_done, }; +int nxt_python_wsgi_init(nxt_unit_init_t *init, nxt_python_proto_t *proto) { + PyObject *obj; -int -nxt_python_wsgi_init(nxt_unit_init_t *init, nxt_python_proto_t *proto) -{ - PyObject *obj; + obj = NULL; - obj = NULL; + if (nxt_slow_path(nxt_python_init_strings(nxt_python_strings) != + NXT_UNIT_OK)) { + nxt_unit_alert(NULL, "Python failed to init string objects"); + goto fail; + } - if (nxt_slow_path(nxt_python_init_strings(nxt_python_strings) - != NXT_UNIT_OK)) - { - nxt_unit_alert(NULL, "Python failed to init string objects"); - goto fail; - } + obj = nxt_python_create_environ(init->data); + if (nxt_slow_path(obj == NULL)) { + goto fail; + } - obj = nxt_python_create_environ(init->data); - if (nxt_slow_path(obj == NULL)) { - goto fail; - } + nxt_py_environ_ptyp = obj; + obj = NULL; - nxt_py_environ_ptyp = obj; - obj = NULL; + init->callbacks.request_handler = nxt_python_request_handler; - init->callbacks.request_handler = nxt_python_request_handler; + *proto = nxt_py_wsgi_proto; - *proto = nxt_py_wsgi_proto; - - return NXT_UNIT_OK; + return NXT_UNIT_OK; fail: - Py_XDECREF(obj); + Py_XDECREF(obj); - return NXT_UNIT_ERROR; + return NXT_UNIT_ERROR; } +static int nxt_python_wsgi_ctx_data_alloc(void **pdata, int main) { + nxt_python_ctx_t *pctx; -static int -nxt_python_wsgi_ctx_data_alloc(void **pdata, int main) -{ - nxt_python_ctx_t *pctx; - - pctx = PyObject_New(nxt_python_ctx_t, &nxt_py_input_type); - if (nxt_slow_path(pctx == NULL)) { - nxt_unit_alert(NULL, - "Python failed to create the \"wsgi.input\" object"); - return NXT_UNIT_ERROR; - } + pctx = PyObject_New(nxt_python_ctx_t, &nxt_py_input_type); + if (nxt_slow_path(pctx == NULL)) { + nxt_unit_alert(NULL, "Python failed to create the \"wsgi.input\" object"); + return NXT_UNIT_ERROR; + } - pctx->write = NULL; - pctx->environ = NULL; + pctx->write = NULL; + pctx->environ = NULL; - pctx->start_resp = PyCFunction_New(nxt_py_start_resp_method, - (PyObject *) pctx); - if (nxt_slow_path(pctx->start_resp == NULL)) { - nxt_unit_alert(NULL, - "Python failed to initialize the \"start_response\" function"); - goto fail; - } + pctx->start_resp = + PyCFunction_New(nxt_py_start_resp_method, (PyObject *)pctx); + if (nxt_slow_path(pctx->start_resp == NULL)) { + nxt_unit_alert( + NULL, "Python failed to initialize the \"start_response\" function"); + goto fail; + } - pctx->write = PyCFunction_New(nxt_py_write_method, (PyObject *) pctx); - if (nxt_slow_path(pctx->write == NULL)) { - nxt_unit_alert(NULL, - "Python failed to initialize the \"write\" function"); - goto fail; - } + pctx->write = PyCFunction_New(nxt_py_write_method, (PyObject *)pctx); + if (nxt_slow_path(pctx->write == NULL)) { + nxt_unit_alert(NULL, "Python failed to initialize the \"write\" function"); + goto fail; + } - pctx->environ = nxt_python_copy_environ(NULL); - if (nxt_slow_path(pctx->environ == NULL)) { - goto fail; - } + pctx->environ = nxt_python_copy_environ(NULL); + if (nxt_slow_path(pctx->environ == NULL)) { + goto fail; + } - *pdata = pctx; + *pdata = pctx; - return NXT_UNIT_OK; + return NXT_UNIT_OK; fail: - nxt_python_wsgi_ctx_data_free(pctx); + nxt_python_wsgi_ctx_data_free(pctx); - return NXT_UNIT_ERROR; + return NXT_UNIT_ERROR; } +static void nxt_python_wsgi_ctx_data_free(void *data) { + nxt_python_ctx_t *pctx; -static void -nxt_python_wsgi_ctx_data_free(void *data) -{ - nxt_python_ctx_t *pctx; + pctx = data; - pctx = data; - - Py_XDECREF(pctx->start_resp); - Py_XDECREF(pctx->write); - Py_XDECREF(pctx->environ); - Py_XDECREF(pctx); + Py_XDECREF(pctx->start_resp); + Py_XDECREF(pctx->write); + Py_XDECREF(pctx->environ); + Py_XDECREF(pctx); } +static int nxt_python_wsgi_run(nxt_unit_ctx_t *ctx) { + int rc; + nxt_python_ctx_t *pctx; -static int -nxt_python_wsgi_run(nxt_unit_ctx_t *ctx) -{ - int rc; - nxt_python_ctx_t *pctx; - - pctx = ctx->data; + pctx = ctx->data; - pctx->thread_state = PyEval_SaveThread(); + pctx->thread_state = PyEval_SaveThread(); - rc = nxt_unit_run(ctx); + rc = nxt_unit_run(ctx); - PyEval_RestoreThread(pctx->thread_state); + PyEval_RestoreThread(pctx->thread_state); - return rc; + return rc; } +static void nxt_python_wsgi_done(void) { + nxt_python_done_strings(nxt_python_strings); -static void -nxt_python_wsgi_done(void) -{ - nxt_python_done_strings(nxt_python_strings); - - Py_XDECREF(nxt_py_environ_ptyp); + Py_XDECREF(nxt_py_environ_ptyp); } +static void nxt_python_request_handler(nxt_unit_request_info_t *req) { + int rc; + PyObject *environ, *args, *response, *iterator, *item; + PyObject *close, *result; + nxt_bool_t prepare_environ; + nxt_python_ctx_t *pctx; + nxt_python_target_t *target; -static void -nxt_python_request_handler(nxt_unit_request_info_t *req) -{ - int rc; - PyObject *environ, *args, *response, *iterator, *item; - PyObject *close, *result; - nxt_bool_t prepare_environ; - nxt_python_ctx_t *pctx; - nxt_python_target_t *target; - - pctx = req->ctx->data; - - pctx->content_length = -1; - pctx->bytes_sent = 0; - pctx->req = req; - - PyEval_RestoreThread(pctx->thread_state); - - if (nxt_slow_path(pctx->environ == NULL)) { - pctx->environ = nxt_python_copy_environ(req); - - if (pctx->environ == NULL) { - prepare_environ = 0; + pctx = req->ctx->data; - rc = NXT_UNIT_ERROR; - goto done; - } - } + pctx->content_length = -1; + pctx->bytes_sent = 0; + pctx->req = req; - prepare_environ = 1; + PyEval_RestoreThread(pctx->thread_state); - target = &nxt_py_targets->target[req->request->app_target]; - - environ = nxt_python_get_environ(pctx, target); - if (nxt_slow_path(environ == NULL)) { - rc = NXT_UNIT_ERROR; - goto done; - } + if (nxt_slow_path(pctx->environ == NULL)) { + pctx->environ = nxt_python_copy_environ(req); - args = PyTuple_New(2); - if (nxt_slow_path(args == NULL)) { - Py_DECREF(environ); + if (pctx->environ == NULL) { + prepare_environ = 0; - nxt_unit_req_error(req, "Python failed to create arguments tuple"); - - rc = NXT_UNIT_ERROR; - goto done; + rc = NXT_UNIT_ERROR; + goto done; } + } - PyTuple_SET_ITEM(args, 0, environ); - - Py_INCREF(pctx->start_resp); - PyTuple_SET_ITEM(args, 1, pctx->start_resp); + prepare_environ = 1; - response = PyObject_CallObject(target->application, args); + target = &nxt_py_targets->target[req->request->app_target]; - Py_DECREF(args); - - if (nxt_slow_path(response == NULL)) { - nxt_unit_req_error(req, "Python failed to call the application"); - nxt_python_print_exception(); + environ = nxt_python_get_environ(pctx, target); + if (nxt_slow_path(environ == NULL)) { + rc = NXT_UNIT_ERROR; + goto done; + } - rc = NXT_UNIT_ERROR; - goto done; - } + args = PyTuple_New(2); + if (nxt_slow_path(args == NULL)) { + Py_DECREF(environ); - /* Shortcut: avoid iterate over response string symbols. */ - if (PyBytes_Check(response)) { - rc = nxt_python_write(pctx, response); + nxt_unit_req_error(req, "Python failed to create arguments tuple"); - } else { - iterator = PyObject_GetIter(response); + rc = NXT_UNIT_ERROR; + goto done; + } - if (nxt_fast_path(iterator != NULL)) { - rc = NXT_UNIT_OK; + PyTuple_SET_ITEM(args, 0, environ); - while (pctx->bytes_sent < pctx->content_length) { - item = PyIter_Next(iterator); + Py_INCREF(pctx->start_resp); + PyTuple_SET_ITEM(args, 1, pctx->start_resp); - if (item == NULL) { - if (nxt_slow_path(PyErr_Occurred() != NULL)) { - nxt_unit_req_error(req, "Python failed to iterate over " - "the application response object"); - nxt_python_print_exception(); + response = PyObject_CallObject(target->application, args); - rc = NXT_UNIT_ERROR; - } + Py_DECREF(args); - break; - } + if (nxt_slow_path(response == NULL)) { + nxt_unit_req_error(req, "Python failed to call the application"); + nxt_python_print_exception(); - if (nxt_fast_path(PyBytes_Check(item))) { - rc = nxt_python_write(pctx, item); + rc = NXT_UNIT_ERROR; + goto done; + } - } else { - nxt_unit_req_error(req, "the application returned " - "not a bytestring object"); - rc = NXT_UNIT_ERROR; - } + /* Shortcut: avoid iterate over response string symbols. */ + if (PyBytes_Check(response)) { + rc = nxt_python_write(pctx, response); - Py_DECREF(item); + } else { + iterator = PyObject_GetIter(response); - if (nxt_slow_path(rc != NXT_UNIT_OK)) { - break; - } - } + if (nxt_fast_path(iterator != NULL)) { + rc = NXT_UNIT_OK; - Py_DECREF(iterator); + while (pctx->bytes_sent < pctx->content_length) { + item = PyIter_Next(iterator); - } else { - nxt_unit_req_error(req, - "the application returned not an iterable object"); + if (item == NULL) { + if (nxt_slow_path(PyErr_Occurred() != NULL)) { + nxt_unit_req_error(req, "Python failed to iterate over " + "the application response object"); nxt_python_print_exception(); rc = NXT_UNIT_ERROR; - } + } - close = PyObject_GetAttr(response, nxt_py_close_str); - - if (close != NULL) { - result = PyObject_CallFunction(close, NULL); - if (nxt_slow_path(result == NULL)) { - nxt_unit_req_error(req, "Python failed to call the close() " - "method of the application response"); - nxt_python_print_exception(); - - } else { - Py_DECREF(result); - } + break; + } - Py_DECREF(close); + if (nxt_fast_path(PyBytes_Check(item))) { + rc = nxt_python_write(pctx, item); } else { - PyErr_Clear(); + nxt_unit_req_error(req, "the application returned " + "not a bytestring object"); + rc = NXT_UNIT_ERROR; } - } - Py_DECREF(response); + Py_DECREF(item); -done: - - pctx->thread_state = PyEval_SaveThread(); - - pctx->req = NULL; - - nxt_unit_request_done(req, rc); - - if (nxt_fast_path(prepare_environ)) { - PyEval_RestoreThread(pctx->thread_state); - - pctx->environ = nxt_python_copy_environ(NULL); - - pctx->thread_state = PyEval_SaveThread(); - } -} - - -static PyObject * -nxt_python_create_environ(nxt_python_app_conf_t *c) -{ - PyObject *obj, *err, *environ; + if (nxt_slow_path(rc != NXT_UNIT_OK)) { + break; + } + } - environ = PyDict_New(); + Py_DECREF(iterator); - if (nxt_slow_path(environ == NULL)) { - nxt_unit_alert(NULL, - "Python failed to create the \"environ\" dictionary"); - return NULL; - } + } else { + nxt_unit_req_error(req, + "the application returned not an iterable object"); + nxt_python_print_exception(); - obj = PyString_FromStringAndSize((char *) nxt_server.start, - nxt_server.length); - if (nxt_slow_path(obj == NULL)) { - nxt_unit_alert(NULL, - "Python failed to create the \"SERVER_SOFTWARE\" environ value"); - goto fail; + rc = NXT_UNIT_ERROR; } - if (nxt_slow_path(PyDict_SetItemString(environ, "SERVER_SOFTWARE", obj) - != 0)) - { - nxt_unit_alert(NULL, - "Python failed to set the \"SERVER_SOFTWARE\" environ value"); - goto fail; - } + close = PyObject_GetAttr(response, nxt_py_close_str); - Py_DECREF(obj); + if (close != NULL) { + result = PyObject_CallFunction(close, NULL); + if (nxt_slow_path(result == NULL)) { + nxt_unit_req_error(req, "Python failed to call the close() " + "method of the application response"); + nxt_python_print_exception(); - obj = Py_BuildValue("(ii)", 1, 0); + } else { + Py_DECREF(result); + } - if (nxt_slow_path(obj == NULL)) { - nxt_unit_alert(NULL, - "Python failed to build the \"wsgi.version\" environ value"); - goto fail; - } + Py_DECREF(close); - if (nxt_slow_path(PyDict_SetItemString(environ, "wsgi.version", obj) != 0)) - { - nxt_unit_alert(NULL, - "Python failed to set the \"wsgi.version\" environ value"); - goto fail; + } else { + PyErr_Clear(); } + } - Py_DECREF(obj); - obj = NULL; + Py_DECREF(response); +done: - if (nxt_slow_path(PyDict_SetItemString(environ, "wsgi.multithread", - c->threads > 1 ? Py_True : Py_False) - != 0)) - { - nxt_unit_alert(NULL, - "Python failed to set the \"wsgi.multithread\" environ value"); - goto fail; - } - - if (nxt_slow_path(PyDict_SetItemString(environ, "wsgi.multiprocess", - Py_True) - != 0)) - { - nxt_unit_alert(NULL, - "Python failed to set the \"wsgi.multiprocess\" environ value"); - goto fail; - } + pctx->thread_state = PyEval_SaveThread(); - if (nxt_slow_path(PyDict_SetItemString(environ, "wsgi.run_once", - Py_False) - != 0)) - { - nxt_unit_alert(NULL, - "Python failed to set the \"wsgi.run_once\" environ value"); - goto fail; - } + pctx->req = NULL; + nxt_unit_request_done(req, rc); - if (nxt_slow_path(PyType_Ready(&nxt_py_input_type) != 0)) { - nxt_unit_alert(NULL, - "Python failed to initialize the \"wsgi.input\" type object"); - goto fail; - } + if (nxt_fast_path(prepare_environ)) { + PyEval_RestoreThread(pctx->thread_state); + pctx->environ = nxt_python_copy_environ(NULL); - err = PySys_GetObject((char *) "stderr"); + pctx->thread_state = PyEval_SaveThread(); + } +} - if (nxt_slow_path(err == NULL)) { - nxt_unit_alert(NULL, "Python failed to get \"sys.stderr\" object"); - goto fail; - } +static PyObject *nxt_python_create_environ(nxt_python_app_conf_t *c) { + PyObject *obj, *err, *environ; - if (nxt_slow_path(PyDict_SetItemString(environ, "wsgi.errors", err) != 0)) - { - nxt_unit_alert(NULL, - "Python failed to set the \"wsgi.errors\" environ value"); - goto fail; - } + environ = PyDict_New(); - return environ; + if (nxt_slow_path(environ == NULL)) { + nxt_unit_alert(NULL, "Python failed to create the \"environ\" dictionary"); + return NULL; + } + + obj = PyString_FromStringAndSize((char *)nxt_server.start, nxt_server.length); + if (nxt_slow_path(obj == NULL)) { + nxt_unit_alert( + NULL, "Python failed to create the \"SERVER_SOFTWARE\" environ value"); + goto fail; + } + + if (nxt_slow_path(PyDict_SetItemString(environ, "SERVER_SOFTWARE", obj) != + 0)) { + nxt_unit_alert( + NULL, "Python failed to set the \"SERVER_SOFTWARE\" environ value"); + goto fail; + } + + Py_DECREF(obj); + + obj = Py_BuildValue("(ii)", 1, 0); + + if (nxt_slow_path(obj == NULL)) { + nxt_unit_alert(NULL, + "Python failed to build the \"wsgi.version\" environ value"); + goto fail; + } + + if (nxt_slow_path(PyDict_SetItemString(environ, "wsgi.version", obj) != 0)) { + nxt_unit_alert(NULL, + "Python failed to set the \"wsgi.version\" environ value"); + goto fail; + } + + Py_DECREF(obj); + obj = NULL; + + if (nxt_slow_path(PyDict_SetItemString(environ, "wsgi.multithread", + c->threads > 1 ? Py_True : Py_False) != + 0)) { + nxt_unit_alert( + NULL, "Python failed to set the \"wsgi.multithread\" environ value"); + goto fail; + } + + if (nxt_slow_path( + PyDict_SetItemString(environ, "wsgi.multiprocess", Py_True) != 0)) { + nxt_unit_alert( + NULL, "Python failed to set the \"wsgi.multiprocess\" environ value"); + goto fail; + } + + if (nxt_slow_path(PyDict_SetItemString(environ, "wsgi.run_once", Py_False) != + 0)) { + nxt_unit_alert(NULL, + "Python failed to set the \"wsgi.run_once\" environ value"); + goto fail; + } + + if (nxt_slow_path(PyType_Ready(&nxt_py_input_type) != 0)) { + nxt_unit_alert( + NULL, "Python failed to initialize the \"wsgi.input\" type object"); + goto fail; + } + + err = PySys_GetObject((char *)"stderr"); + + if (nxt_slow_path(err == NULL)) { + nxt_unit_alert(NULL, "Python failed to get \"sys.stderr\" object"); + goto fail; + } + + if (nxt_slow_path(PyDict_SetItemString(environ, "wsgi.errors", err) != 0)) { + nxt_unit_alert(NULL, + "Python failed to set the \"wsgi.errors\" environ value"); + goto fail; + } + + return environ; fail: - Py_XDECREF(obj); - Py_DECREF(environ); + Py_XDECREF(obj); + Py_DECREF(environ); - return NULL; + return NULL; } +static PyObject *nxt_python_copy_environ(nxt_unit_request_info_t *req) { + PyObject *environ; -static PyObject * -nxt_python_copy_environ(nxt_unit_request_info_t *req) -{ - PyObject *environ; + environ = PyDict_Copy(nxt_py_environ_ptyp); - environ = PyDict_Copy(nxt_py_environ_ptyp); + if (nxt_slow_path(environ == NULL)) { + nxt_unit_req_alert(req, "Python failed to copy the \"environ\" dictionary"); + nxt_python_print_exception(); + } - if (nxt_slow_path(environ == NULL)) { - nxt_unit_req_alert(req, - "Python failed to copy the \"environ\" dictionary"); - nxt_python_print_exception(); - } - - return environ; + return environ; } - -static PyObject * -nxt_python_get_environ(nxt_python_ctx_t *pctx, - nxt_python_target_t *app_target) -{ - int rc; - char *path; - uint32_t i, j, vl, path_length; - PyObject *environ; - nxt_str_t prefix; - nxt_unit_field_t *f, *f2; - nxt_unit_request_t *r; - - r = pctx->req->request; - -#define RC(S) \ - do { \ - rc = (S); \ - if (nxt_slow_path(rc != NXT_UNIT_OK)) { \ - goto fail; \ - } \ - } while(0) - - RC(nxt_python_add_sptr(pctx, nxt_py_request_method_str, &r->method, - r->method_length)); - RC(nxt_python_add_sptr(pctx, nxt_py_request_uri_str, &r->target, - r->target_length)); - RC(nxt_python_add_sptr(pctx, nxt_py_query_string_str, &r->query, - r->query_length)); - - prefix = app_target->prefix; - path_length = r->path_length; - path = nxt_unit_sptr_get(&r->path); - if (prefix.length > 0 - && ((path_length > prefix.length && path[prefix.length] == '/') - || path_length == prefix.length) - && memcmp(prefix.start, path, prefix.length) == 0) - { - RC(nxt_python_add_py_string(pctx, nxt_py_script_name_str, - app_target->py_prefix)); - - path += prefix.length; - path_length -= prefix.length; - } - - RC(nxt_python_add_char(pctx, nxt_py_path_info_str, path, path_length)); - - RC(nxt_python_add_sptr(pctx, nxt_py_remote_addr_str, &r->remote, - r->remote_length)); - RC(nxt_python_add_sptr(pctx, nxt_py_server_addr_str, &r->local_addr, - r->local_addr_length)); - - if (r->tls) { - RC(nxt_python_add_obj(pctx, nxt_py_wsgi_uri_scheme_str, - nxt_py_https_str)); - } else { - RC(nxt_python_add_obj(pctx, nxt_py_wsgi_uri_scheme_str, - nxt_py_http_str)); - } - - RC(nxt_python_add_sptr(pctx, nxt_py_server_protocol_str, &r->version, - r->version_length)); - - RC(nxt_python_add_sptr(pctx, nxt_py_server_name_str, &r->server_name, - r->server_name_length)); - RC(nxt_python_add_obj(pctx, nxt_py_server_port_str, nxt_py_80_str)); - - nxt_unit_request_group_dup_fields(pctx->req); - - for (i = 0; i < r->fields_count;) { - f = r->fields + i; - vl = f->value_length; - - for (j = i + 1; j < r->fields_count; j++) { - f2 = r->fields + j; - - if (f2->hash != f->hash - || nxt_unit_sptr_get(&f2->name) != nxt_unit_sptr_get(&f->name)) - { - break; - } - - vl += 2 + f2->value_length; - } - - RC(nxt_python_add_field(pctx, f, j - i, vl)); - - i = j; - } - - if (r->content_length_field != NXT_UNIT_NONE_FIELD) { - f = r->fields + r->content_length_field; - - RC(nxt_python_add_sptr(pctx, nxt_py_content_length_str, &f->value, - f->value_length)); - } - - if (r->content_type_field != NXT_UNIT_NONE_FIELD) { - f = r->fields + r->content_type_field; - - RC(nxt_python_add_sptr(pctx, nxt_py_content_type_str, &f->value, - f->value_length)); - } +static PyObject *nxt_python_get_environ(nxt_python_ctx_t *pctx, + nxt_python_target_t *app_target) { + int rc; + char *path; + uint32_t i, j, vl, path_length; + PyObject *environ; + nxt_str_t prefix; + nxt_unit_field_t *f, *f2; + nxt_unit_request_t *r; + + r = pctx->req->request; + +#define RC(S) \ + do { \ + rc = (S); \ + if (nxt_slow_path(rc != NXT_UNIT_OK)) { \ + goto fail; \ + } \ + } while (0) + + RC(nxt_python_add_sptr(pctx, nxt_py_request_method_str, &r->method, + r->method_length)); + RC(nxt_python_add_sptr(pctx, nxt_py_request_uri_str, &r->target, + r->target_length)); + RC(nxt_python_add_sptr(pctx, nxt_py_query_string_str, &r->query, + r->query_length)); + + prefix = app_target->prefix; + path_length = r->path_length; + path = nxt_unit_sptr_get(&r->path); + if (prefix.length > 0 && + ((path_length > prefix.length && path[prefix.length] == '/') || + path_length == prefix.length) && + memcmp(prefix.start, path, prefix.length) == 0) { + RC(nxt_python_add_py_string(pctx, nxt_py_script_name_str, + app_target->py_prefix)); + + path += prefix.length; + path_length -= prefix.length; + } + + RC(nxt_python_add_char(pctx, nxt_py_path_info_str, path, path_length)); + + RC(nxt_python_add_sptr(pctx, nxt_py_remote_addr_str, &r->remote, + r->remote_length)); + RC(nxt_python_add_sptr(pctx, nxt_py_server_addr_str, &r->local_addr, + r->local_addr_length)); + + if (r->tls) { + RC(nxt_python_add_obj(pctx, nxt_py_wsgi_uri_scheme_str, nxt_py_https_str)); + } else { + RC(nxt_python_add_obj(pctx, nxt_py_wsgi_uri_scheme_str, nxt_py_http_str)); + } + + RC(nxt_python_add_sptr(pctx, nxt_py_server_protocol_str, &r->version, + r->version_length)); + + RC(nxt_python_add_sptr(pctx, nxt_py_server_name_str, &r->server_name, + r->server_name_length)); + RC(nxt_python_add_obj(pctx, nxt_py_server_port_str, nxt_py_80_str)); + + nxt_unit_request_group_dup_fields(pctx->req); + + for (i = 0; i < r->fields_count;) { + f = r->fields + i; + vl = f->value_length; + + for (j = i + 1; j < r->fields_count; j++) { + f2 = r->fields + j; + + if (f2->hash != f->hash || + nxt_unit_sptr_get(&f2->name) != nxt_unit_sptr_get(&f->name)) { + break; + } + + vl += 2 + f2->value_length; + } + + RC(nxt_python_add_field(pctx, f, j - i, vl)); + + i = j; + } + + if (r->content_length_field != NXT_UNIT_NONE_FIELD) { + f = r->fields + r->content_length_field; + + RC(nxt_python_add_sptr(pctx, nxt_py_content_length_str, &f->value, + f->value_length)); + } + + if (r->content_type_field != NXT_UNIT_NONE_FIELD) { + f = r->fields + r->content_type_field; + + RC(nxt_python_add_sptr(pctx, nxt_py_content_type_str, &f->value, + f->value_length)); + } #undef RC - if (nxt_slow_path(PyDict_SetItem(pctx->environ, nxt_py_wsgi_input_str, - (PyObject *) pctx) != 0)) - { - nxt_unit_req_error(pctx->req, + if (nxt_slow_path(PyDict_SetItem(pctx->environ, nxt_py_wsgi_input_str, + (PyObject *)pctx) != 0)) { + nxt_unit_req_error(pctx->req, "Python failed to set the \"wsgi.input\" environ value"); - goto fail; - } + goto fail; + } - environ = pctx->environ; - pctx->environ = NULL; + environ = pctx->environ; + pctx->environ = NULL; - return environ; + return environ; fail: - Py_DECREF(pctx->environ); - pctx->environ = NULL; + Py_DECREF(pctx->environ); + pctx->environ = NULL; - return NULL; + return NULL; } - -static int -nxt_python_add_sptr(nxt_python_ctx_t *pctx, PyObject *name, - nxt_unit_sptr_t *sptr, uint32_t size) -{ - return nxt_python_add_char(pctx, name, nxt_unit_sptr_get(sptr), size); +static int nxt_python_add_sptr(nxt_python_ctx_t *pctx, PyObject *name, + nxt_unit_sptr_t *sptr, uint32_t size) { + return nxt_python_add_char(pctx, name, nxt_unit_sptr_get(sptr), size); } +static int nxt_python_add_char(nxt_python_ctx_t *pctx, PyObject *name, + char *src, uint32_t size) { + int res; + PyObject *value; -static int -nxt_python_add_char(nxt_python_ctx_t *pctx, PyObject *name, - char *src, uint32_t size) -{ - int res; - PyObject *value; - - value = PyString_FromStringAndSize(src, size); - if (nxt_slow_path(value == NULL)) { - nxt_unit_req_error(pctx->req, - "Python failed to create value string \"%.*s\"", - (int) size, src); - nxt_python_print_exception(); + value = PyString_FromStringAndSize(src, size); + if (nxt_slow_path(value == NULL)) { + nxt_unit_req_error(pctx->req, + "Python failed to create value string \"%.*s\"", + (int)size, src); + nxt_python_print_exception(); - return NXT_UNIT_ERROR; - } + return NXT_UNIT_ERROR; + } - res = nxt_python_add_py_string(pctx, name, value); + res = nxt_python_add_py_string(pctx, name, value); - Py_DECREF(value); + Py_DECREF(value); - return res; + return res; } - static int nxt_python_add_py_string(nxt_python_ctx_t *pctx, PyObject *name, - PyObject *value) -{ - if (nxt_slow_path(PyDict_SetItem(pctx->environ, name, value) != 0)) { - nxt_unit_req_error(pctx->req, - "Python failed to set the \"%s\" environ value", - PyUnicode_AsUTF8(name)); - - return NXT_UNIT_ERROR; - } + PyObject *value) { + if (nxt_slow_path(PyDict_SetItem(pctx->environ, name, value) != 0)) { + nxt_unit_req_error(pctx->req, + "Python failed to set the \"%s\" environ value", + PyUnicode_AsUTF8(name)); - return NXT_UNIT_OK; -} + return NXT_UNIT_ERROR; + } + return NXT_UNIT_OK; +} -static int -nxt_python_add_field(nxt_python_ctx_t *pctx, nxt_unit_field_t *field, int n, - uint32_t vl) -{ - char *src; - PyObject *name, *value; +static int nxt_python_add_field(nxt_python_ctx_t *pctx, nxt_unit_field_t *field, + int n, uint32_t vl) { + char *src; + PyObject *name, *value; - src = nxt_unit_sptr_get(&field->name); + src = nxt_unit_sptr_get(&field->name); - name = nxt_python_field_name(src, field->name_length); - if (nxt_slow_path(name == NULL)) { - nxt_unit_req_error(pctx->req, - "Python failed to create name string \"%.*s\"", - (int) field->name_length, src); - nxt_python_print_exception(); + name = nxt_python_field_name(src, field->name_length); + if (nxt_slow_path(name == NULL)) { + nxt_unit_req_error(pctx->req, + "Python failed to create name string \"%.*s\"", + (int)field->name_length, src); + nxt_python_print_exception(); - return NXT_UNIT_ERROR; - } + return NXT_UNIT_ERROR; + } - value = nxt_python_field_value(field, n, vl); + value = nxt_python_field_value(field, n, vl); - if (nxt_slow_path(value == NULL)) { - nxt_unit_req_error(pctx->req, - "Python failed to create value string \"%.*s\"", - (int) field->value_length, - (char *) nxt_unit_sptr_get(&field->value)); - nxt_python_print_exception(); + if (nxt_slow_path(value == NULL)) { + nxt_unit_req_error( + pctx->req, "Python failed to create value string \"%.*s\"", + (int)field->value_length, (char *)nxt_unit_sptr_get(&field->value)); + nxt_python_print_exception(); - goto fail; - } + goto fail; + } - if (nxt_slow_path(PyDict_SetItem(pctx->environ, name, value) != 0)) { - nxt_unit_req_error(pctx->req, - "Python failed to set the \"%s\" environ value", - PyUnicode_AsUTF8(name)); - goto fail; - } + if (nxt_slow_path(PyDict_SetItem(pctx->environ, name, value) != 0)) { + nxt_unit_req_error(pctx->req, + "Python failed to set the \"%s\" environ value", + PyUnicode_AsUTF8(name)); + goto fail; + } - Py_DECREF(name); - Py_DECREF(value); + Py_DECREF(name); + Py_DECREF(value); - return NXT_UNIT_OK; + return NXT_UNIT_OK; fail: - Py_DECREF(name); - Py_XDECREF(value); + Py_DECREF(name); + Py_XDECREF(value); - return NXT_UNIT_ERROR; + return NXT_UNIT_ERROR; } - -static PyObject * -nxt_python_field_name(const char *name, uint8_t len) -{ - char *p, c; - uint8_t i; - PyObject *res; +static PyObject *nxt_python_field_name(const char *name, uint8_t len) { + char *p, c; + uint8_t i; + PyObject *res; #if PY_MAJOR_VERSION == 3 - res = PyUnicode_New(len + 5, 255); + res = PyUnicode_New(len + 5, 255); #else - res = PyString_FromStringAndSize(NULL, len + 5); + res = PyString_FromStringAndSize(NULL, len + 5); #endif - if (nxt_slow_path(res == NULL)) { - return NULL; - } - - p = PyString_AS_STRING(res); + if (nxt_slow_path(res == NULL)) { + return NULL; + } - p = nxt_cpymem(p, "HTTP_", 5); + p = PyString_AS_STRING(res); - for (i = 0; i < len; i++) { - c = name[i]; + p = nxt_cpymem(p, "HTTP_", 5); - if (c >= 'a' && c <= 'z') { - *p++ = (c & ~0x20); - continue; - } + for (i = 0; i < len; i++) { + c = name[i]; - if (c == '-') { - *p++ = '_'; - continue; - } + if (c >= 'a' && c <= 'z') { + *p++ = (c & ~0x20); + continue; + } - *p++ = c; + if (c == '-') { + *p++ = '_'; + continue; } - return res; -} + *p++ = c; + } + return res; +} -static PyObject * -nxt_python_field_value(nxt_unit_field_t *f, int n, uint32_t vl) -{ - int i; - char *p, *src; - PyObject *res; +static PyObject *nxt_python_field_value(nxt_unit_field_t *f, int n, + uint32_t vl) { + int i; + char *p, *src; + PyObject *res; - src = nxt_unit_sptr_get(&f->value); + src = nxt_unit_sptr_get(&f->value); #if PY_MAJOR_VERSION == 3 - if (nxt_slow_path(n > 1)) { - char *ptr; - - p = nxt_unit_malloc(NULL, vl + 1); - if (nxt_slow_path(p == NULL)) { - return NULL; - } - - ptr = p; - p = nxt_cpymem(p, src, f->value_length); - - for (i = 1; i < n; i++) { - p = nxt_cpymem(p, ", ", 2); - - src = nxt_unit_sptr_get(&f[i].value); - p = nxt_cpymem(p, src, f[i].value_length); - } - *p = '\0'; - - src = ptr; - } - - res = PyUnicode_DecodeCharmap(src, vl, NULL, NULL); + if (nxt_slow_path(n > 1)) { + char *ptr; - if (nxt_slow_path(n > 1)) { - nxt_unit_free(NULL, src); + p = nxt_unit_malloc(NULL, vl + 1); + if (nxt_slow_path(p == NULL)) { + return NULL; } -#else - res = PyString_FromStringAndSize(NULL, vl); - - if (nxt_slow_path(res == NULL)) { - return NULL; - } - - p = PyString_AS_STRING(res); + ptr = p; p = nxt_cpymem(p, src, f->value_length); for (i = 1; i < n; i++) { - p = nxt_cpymem(p, ", ", 2); - - src = nxt_unit_sptr_get(&f[i].value); - p = nxt_cpymem(p, src, f[i].value_length); - } -#endif - - return res; -} - - -static int -nxt_python_add_obj(nxt_python_ctx_t *pctx, PyObject *name, PyObject *value) -{ - if (nxt_slow_path(PyDict_SetItem(pctx->environ, name, value) != 0)) { - nxt_unit_req_error(pctx->req, - "Python failed to set the \"%s\" environ value", - PyUnicode_AsUTF8(name)); + p = nxt_cpymem(p, ", ", 2); - return NXT_UNIT_ERROR; + src = nxt_unit_sptr_get(&f[i].value); + p = nxt_cpymem(p, src, f[i].value_length); } + *p = '\0'; - return NXT_UNIT_OK; -} + src = ptr; + } + res = PyUnicode_DecodeCharmap(src, vl, NULL, NULL); -static PyObject * -nxt_py_start_resp(PyObject *self, PyObject *args) -{ - int rc, status; - char *status_str, *space_ptr; - uint32_t status_len; - PyObject *headers, *tuple, *string, *status_bytes; - Py_ssize_t i, n, fields_size, fields_count; - nxt_python_ctx_t *pctx; - - pctx = (nxt_python_ctx_t *) self; - if (nxt_slow_path(pctx->req == NULL)) { - return PyErr_Format(PyExc_RuntimeError, - "start_response() is called " - "outside of WSGI request processing"); - } + if (nxt_slow_path(n > 1)) { + nxt_unit_free(NULL, src); + } +#else + res = PyString_FromStringAndSize(NULL, vl); - n = PyTuple_GET_SIZE(args); + if (nxt_slow_path(res == NULL)) { + return NULL; + } - if (n < 2 || n > 3) { - return PyErr_Format(PyExc_TypeError, "invalid number of arguments"); - } + p = PyString_AS_STRING(res); - string = PyTuple_GET_ITEM(args, 0); - if (!PyBytes_Check(string) && !PyUnicode_Check(string)) { - return PyErr_Format(PyExc_TypeError, - "failed to write first argument (not a string?)"); - } + p = nxt_cpymem(p, src, f->value_length); - headers = PyTuple_GET_ITEM(args, 1); - if (!PyList_Check(headers)) { - return PyErr_Format(PyExc_TypeError, - "the second argument is not a response headers list"); - } + for (i = 1; i < n; i++) { + p = nxt_cpymem(p, ", ", 2); - fields_size = 0; - fields_count = PyList_GET_SIZE(headers); + src = nxt_unit_sptr_get(&f[i].value); + p = nxt_cpymem(p, src, f[i].value_length); + } +#endif - for (i = 0; i < fields_count; i++) { - tuple = PyList_GET_ITEM(headers, i); + return res; +} - if (!PyTuple_Check(tuple)) { - return PyErr_Format(PyExc_TypeError, - "the response headers must be a list of tuples"); - } +static int nxt_python_add_obj(nxt_python_ctx_t *pctx, PyObject *name, + PyObject *value) { + if (nxt_slow_path(PyDict_SetItem(pctx->environ, name, value) != 0)) { + nxt_unit_req_error(pctx->req, + "Python failed to set the \"%s\" environ value", + PyUnicode_AsUTF8(name)); - if (PyTuple_GET_SIZE(tuple) != 2) { - return PyErr_Format(PyExc_TypeError, - "each header must be a tuple of two items"); - } + return NXT_UNIT_ERROR; + } - string = PyTuple_GET_ITEM(tuple, 0); - if (PyBytes_Check(string)) { - fields_size += PyBytes_GET_SIZE(string); + return NXT_UNIT_OK; +} - } else if (PyUnicode_Check(string)) { - fields_size += PyUnicode_GET_LENGTH(string); +static PyObject *nxt_py_start_resp(PyObject *self, PyObject *args) { + int rc, status; + char *status_str, *space_ptr; + uint32_t status_len; + PyObject *headers, *tuple, *string, *status_bytes; + Py_ssize_t i, n, fields_size, fields_count; + nxt_python_ctx_t *pctx; - } else { - return PyErr_Format(PyExc_TypeError, - "header #%d name is not a string", (int) i); - } + pctx = (nxt_python_ctx_t *)self; + if (nxt_slow_path(pctx->req == NULL)) { + return PyErr_Format(PyExc_RuntimeError, + "start_response() is called " + "outside of WSGI request processing"); + } - string = PyTuple_GET_ITEM(tuple, 1); - if (PyBytes_Check(string)) { - fields_size += PyBytes_GET_SIZE(string); + n = PyTuple_GET_SIZE(args); - } else if (PyUnicode_Check(string)) { - fields_size += PyUnicode_GET_LENGTH(string); + if (n < 2 || n > 3) { + return PyErr_Format(PyExc_TypeError, "invalid number of arguments"); + } - } else { - return PyErr_Format(PyExc_TypeError, - "header #%d value is not a string", (int) i); - } - } + string = PyTuple_GET_ITEM(args, 0); + if (!PyBytes_Check(string) && !PyUnicode_Check(string)) { + return PyErr_Format(PyExc_TypeError, + "failed to write first argument (not a string?)"); + } - pctx->content_length = -1; + headers = PyTuple_GET_ITEM(args, 1); + if (!PyList_Check(headers)) { + return PyErr_Format(PyExc_TypeError, + "the second argument is not a response headers list"); + } - string = PyTuple_GET_ITEM(args, 0); - rc = nxt_python_str_buf(string, &status_str, &status_len, &status_bytes); - if (nxt_slow_path(rc != NXT_UNIT_OK)) { - return PyErr_Format(PyExc_TypeError, "status is not a string"); - } + fields_size = 0; + fields_count = PyList_GET_SIZE(headers); - space_ptr = memchr(status_str, ' ', status_len); - if (space_ptr != NULL) { - status_len = space_ptr - status_str; - } + for (i = 0; i < fields_count; i++) { + tuple = PyList_GET_ITEM(headers, i); - status = nxt_int_parse((u_char *) status_str, status_len); - if (nxt_slow_path(status < 0)) { - return PyErr_Format(PyExc_TypeError, "failed to parse status code"); + if (!PyTuple_Check(tuple)) { + return PyErr_Format(PyExc_TypeError, + "the response headers must be a list of tuples"); } - Py_XDECREF(status_bytes); - - /* - * PEP 3333: - * - * ... applications can replace their originally intended output with error - * output, up until the last possible moment. - */ - rc = nxt_unit_response_init(pctx->req, status, fields_count, fields_size); - if (nxt_slow_path(rc != NXT_UNIT_OK)) { - return PyErr_Format(PyExc_RuntimeError, - "failed to allocate response object"); + if (PyTuple_GET_SIZE(tuple) != 2) { + return PyErr_Format(PyExc_TypeError, + "each header must be a tuple of two items"); } - for (i = 0; i < fields_count; i++) { - tuple = PyList_GET_ITEM(headers, i); + string = PyTuple_GET_ITEM(tuple, 0); + if (PyBytes_Check(string)) { + fields_size += PyBytes_GET_SIZE(string); - rc = nxt_python_response_add_field(pctx, PyTuple_GET_ITEM(tuple, 0), - PyTuple_GET_ITEM(tuple, 1), i); - if (nxt_slow_path(rc != NXT_UNIT_OK)) { - return PyErr_Format(PyExc_RuntimeError, - "failed to add header #%d", (int) i); - } - } + } else if (PyUnicode_Check(string)) { + fields_size += PyUnicode_GET_LENGTH(string); - /* - * PEP 3333: - * - * However, the start_response callable must not actually transmit the - * response headers. Instead, it must store them for the server or gateway - * to transmit only after the first iteration of the application return - * value that yields a non-empty bytestring, or upon the application's - * first invocation of the write() callable. In other words, response - * headers must not be sent until there is actual body data available, or - * until the application's returned iterable is exhausted. (The only - * possible exception to this rule is if the response headers explicitly - * include a Content-Length of zero.) - */ - if (pctx->content_length == 0) { - rc = nxt_unit_response_send(pctx->req); - if (nxt_slow_path(rc != NXT_UNIT_OK)) { - return PyErr_Format(PyExc_RuntimeError, - "failed to send response headers"); - } + } else { + return PyErr_Format(PyExc_TypeError, "header #%d name is not a string", + (int)i); } - Py_INCREF(pctx->write); - return pctx->write; -} - + string = PyTuple_GET_ITEM(tuple, 1); + if (PyBytes_Check(string)) { + fields_size += PyBytes_GET_SIZE(string); -static int -nxt_python_response_add_field(nxt_python_ctx_t *pctx, PyObject *name, - PyObject *value, int i) -{ - int rc; - char *name_str, *value_str; - uint32_t name_length, value_length; - PyObject *name_bytes, *value_bytes; - nxt_off_t content_length; + } else if (PyUnicode_Check(string)) { + fields_size += PyUnicode_GET_LENGTH(string); - name_bytes = NULL; - value_bytes = NULL; - - rc = nxt_python_str_buf(name, &name_str, &name_length, &name_bytes); + } else { + return PyErr_Format(PyExc_TypeError, "header #%d value is not a string", + (int)i); + } + } + + pctx->content_length = -1; + + string = PyTuple_GET_ITEM(args, 0); + rc = nxt_python_str_buf(string, &status_str, &status_len, &status_bytes); + if (nxt_slow_path(rc != NXT_UNIT_OK)) { + return PyErr_Format(PyExc_TypeError, "status is not a string"); + } + + space_ptr = memchr(status_str, ' ', status_len); + if (space_ptr != NULL) { + status_len = space_ptr - status_str; + } + + status = nxt_int_parse((u_char *)status_str, status_len); + if (nxt_slow_path(status < 0)) { + return PyErr_Format(PyExc_TypeError, "failed to parse status code"); + } + + Py_XDECREF(status_bytes); + + /* + * PEP 3333: + * + * ... applications can replace their originally intended output with error + * output, up until the last possible moment. + */ + rc = nxt_unit_response_init(pctx->req, status, fields_count, fields_size); + if (nxt_slow_path(rc != NXT_UNIT_OK)) { + return PyErr_Format(PyExc_RuntimeError, + "failed to allocate response object"); + } + + for (i = 0; i < fields_count; i++) { + tuple = PyList_GET_ITEM(headers, i); + + rc = nxt_python_response_add_field(pctx, PyTuple_GET_ITEM(tuple, 0), + PyTuple_GET_ITEM(tuple, 1), i); if (nxt_slow_path(rc != NXT_UNIT_OK)) { - goto fail; - } - - rc = nxt_python_str_buf(value, &value_str, &value_length, &value_bytes); + return PyErr_Format(PyExc_RuntimeError, "failed to add header #%d", + (int)i); + } + } + + /* + * PEP 3333: + * + * However, the start_response callable must not actually transmit the + * response headers. Instead, it must store them for the server or gateway + * to transmit only after the first iteration of the application return + * value that yields a non-empty bytestring, or upon the application's + * first invocation of the write() callable. In other words, response + * headers must not be sent until there is actual body data available, or + * until the application's returned iterable is exhausted. (The only + * possible exception to this rule is if the response headers explicitly + * include a Content-Length of zero.) + */ + if (pctx->content_length == 0) { + rc = nxt_unit_response_send(pctx->req); if (nxt_slow_path(rc != NXT_UNIT_OK)) { - goto fail; + return PyErr_Format(PyExc_RuntimeError, + "failed to send response headers"); } + } - rc = nxt_unit_response_add_field(pctx->req, name_str, name_length, - value_str, value_length); - if (nxt_slow_path(rc != NXT_UNIT_OK)) { - goto fail; - } + Py_INCREF(pctx->write); + return pctx->write; +} - if (pctx->req->response->fields[i].hash == NXT_UNIT_HASH_CONTENT_LENGTH) { - content_length = nxt_off_t_parse((u_char *) value_str, value_length); - if (nxt_slow_path(content_length < 0)) { - nxt_unit_req_error(pctx->req, "failed to parse Content-Length " - "value %.*s", (int) value_length, value_str); +static int nxt_python_response_add_field(nxt_python_ctx_t *pctx, PyObject *name, + PyObject *value, int i) { + int rc; + char *name_str, *value_str; + uint32_t name_length, value_length; + PyObject *name_bytes, *value_bytes; + nxt_off_t content_length; + + name_bytes = NULL; + value_bytes = NULL; + + rc = nxt_python_str_buf(name, &name_str, &name_length, &name_bytes); + if (nxt_slow_path(rc != NXT_UNIT_OK)) { + goto fail; + } + + rc = nxt_python_str_buf(value, &value_str, &value_length, &value_bytes); + if (nxt_slow_path(rc != NXT_UNIT_OK)) { + goto fail; + } + + rc = nxt_unit_response_add_field(pctx->req, name_str, name_length, value_str, + value_length); + if (nxt_slow_path(rc != NXT_UNIT_OK)) { + goto fail; + } + + if (pctx->req->response->fields[i].hash == NXT_UNIT_HASH_CONTENT_LENGTH) { + content_length = nxt_off_t_parse((u_char *)value_str, value_length); + if (nxt_slow_path(content_length < 0)) { + nxt_unit_req_error(pctx->req, + "failed to parse Content-Length " + "value %.*s", + (int)value_length, value_str); - } else { - pctx->content_length = content_length; - } + } else { + pctx->content_length = content_length; } + } fail: - Py_XDECREF(name_bytes); - Py_XDECREF(value_bytes); + Py_XDECREF(name_bytes); + Py_XDECREF(value_bytes); - return rc; + return rc; } +static int nxt_python_str_buf(PyObject *str, char **buf, uint32_t *len, + PyObject **bytes) { + if (PyBytes_Check(str)) { + *buf = PyBytes_AS_STRING(str); + *len = PyBytes_GET_SIZE(str); + *bytes = NULL; -static int -nxt_python_str_buf(PyObject *str, char **buf, uint32_t *len, PyObject **bytes) -{ - if (PyBytes_Check(str)) { - *buf = PyBytes_AS_STRING(str); - *len = PyBytes_GET_SIZE(str); - *bytes = NULL; - - } else { - *bytes = PyUnicode_AsLatin1String(str); - if (nxt_slow_path(*bytes == NULL)) { - return NXT_UNIT_ERROR; - } - - *buf = PyBytes_AS_STRING(*bytes); - *len = PyBytes_GET_SIZE(*bytes); + } else { + *bytes = PyUnicode_AsLatin1String(str); + if (nxt_slow_path(*bytes == NULL)) { + return NXT_UNIT_ERROR; } - return NXT_UNIT_OK; -} - + *buf = PyBytes_AS_STRING(*bytes); + *len = PyBytes_GET_SIZE(*bytes); + } -static PyObject * -nxt_py_write(PyObject *self, PyObject *str) -{ - int rc; + return NXT_UNIT_OK; +} - if (nxt_fast_path(!PyBytes_Check(str))) { - return PyErr_Format(PyExc_TypeError, "the argument is not a %s", - NXT_PYTHON_BYTES_TYPE); - } +static PyObject *nxt_py_write(PyObject *self, PyObject *str) { + int rc; - rc = nxt_python_write((nxt_python_ctx_t *) self, str); - if (nxt_slow_path(rc != NXT_UNIT_OK)) { - return PyErr_Format(PyExc_RuntimeError, - "failed to write response value"); - } + if (nxt_fast_path(!PyBytes_Check(str))) { + return PyErr_Format(PyExc_TypeError, "the argument is not a %s", + NXT_PYTHON_BYTES_TYPE); + } - Py_RETURN_NONE; -} + rc = nxt_python_write((nxt_python_ctx_t *)self, str); + if (nxt_slow_path(rc != NXT_UNIT_OK)) { + return PyErr_Format(PyExc_RuntimeError, "failed to write response value"); + } - -static void -nxt_py_input_dealloc(nxt_python_ctx_t *self) -{ - PyObject_Del(self); + Py_RETURN_NONE; } +static void nxt_py_input_dealloc(nxt_python_ctx_t *self) { PyObject_Del(self); } -static PyObject * -nxt_py_input_read(nxt_python_ctx_t *pctx, PyObject *args) -{ - char *buf; - PyObject *content, *obj; - Py_ssize_t size, n; - - if (nxt_slow_path(pctx->req == NULL)) { - return PyErr_Format(PyExc_RuntimeError, - "wsgi.input.read() is called " - "outside of WSGI request processing"); - } +static PyObject *nxt_py_input_read(nxt_python_ctx_t *pctx, PyObject *args) { + char *buf; + PyObject *content, *obj; + Py_ssize_t size, n; - size = pctx->req->content_length; + if (nxt_slow_path(pctx->req == NULL)) { + return PyErr_Format(PyExc_RuntimeError, + "wsgi.input.read() is called " + "outside of WSGI request processing"); + } - n = PyTuple_GET_SIZE(args); + size = pctx->req->content_length; - if (n > 0) { - if (n != 1) { - return PyErr_Format(PyExc_TypeError, "invalid number of arguments"); - } + n = PyTuple_GET_SIZE(args); - obj = PyTuple_GET_ITEM(args, 0); + if (n > 0) { + if (n != 1) { + return PyErr_Format(PyExc_TypeError, "invalid number of arguments"); + } - size = PyNumber_AsSsize_t(obj, PyExc_OverflowError); + obj = PyTuple_GET_ITEM(args, 0); - if (nxt_slow_path(size < 0)) { - if (size == -1 && PyErr_Occurred()) { - return NULL; - } + size = PyNumber_AsSsize_t(obj, PyExc_OverflowError); - if (size != -1) { - return PyErr_Format(PyExc_ValueError, - "the read body size cannot be zero or less"); - } - } + if (nxt_slow_path(size < 0)) { + if (size == -1 && PyErr_Occurred()) { + return NULL; + } - if (size == -1 || size > (Py_ssize_t) pctx->req->content_length) { - size = pctx->req->content_length; - } + if (size != -1) { + return PyErr_Format(PyExc_ValueError, + "the read body size cannot be zero or less"); + } } - content = PyBytes_FromStringAndSize(NULL, size); - if (nxt_slow_path(content == NULL)) { - return NULL; + if (size == -1 || size > (Py_ssize_t)pctx->req->content_length) { + size = pctx->req->content_length; } + } - buf = PyBytes_AS_STRING(content); + content = PyBytes_FromStringAndSize(NULL, size); + if (nxt_slow_path(content == NULL)) { + return NULL; + } - size = nxt_unit_request_read(pctx->req, buf, size); + buf = PyBytes_AS_STRING(content); - return content; -} + size = nxt_unit_request_read(pctx->req, buf, size); + return content; +} -static PyObject * -nxt_py_input_readline(nxt_python_ctx_t *pctx, PyObject *args) -{ - ssize_t ssize; - PyObject *obj; - Py_ssize_t n; +static PyObject *nxt_py_input_readline(nxt_python_ctx_t *pctx, PyObject *args) { + ssize_t ssize; + PyObject *obj; + Py_ssize_t n; - if (nxt_slow_path(pctx->req == NULL)) { - return PyErr_Format(PyExc_RuntimeError, - "wsgi.input.readline() is called " - "outside of WSGI request processing"); - } + if (nxt_slow_path(pctx->req == NULL)) { + return PyErr_Format(PyExc_RuntimeError, + "wsgi.input.readline() is called " + "outside of WSGI request processing"); + } - n = PyTuple_GET_SIZE(args); + n = PyTuple_GET_SIZE(args); - if (n > 0) { - if (n != 1) { - return PyErr_Format(PyExc_TypeError, "invalid number of arguments"); - } + if (n > 0) { + if (n != 1) { + return PyErr_Format(PyExc_TypeError, "invalid number of arguments"); + } - obj = PyTuple_GET_ITEM(args, 0); + obj = PyTuple_GET_ITEM(args, 0); - ssize = PyNumber_AsSsize_t(obj, PyExc_OverflowError); + ssize = PyNumber_AsSsize_t(obj, PyExc_OverflowError); - if (nxt_fast_path(ssize > 0)) { - return nxt_py_input_getline(pctx, ssize); - } + if (nxt_fast_path(ssize > 0)) { + return nxt_py_input_getline(pctx, ssize); + } - if (ssize == 0) { - return PyBytes_FromStringAndSize("", 0); - } + if (ssize == 0) { + return PyBytes_FromStringAndSize("", 0); + } - if (ssize != -1) { - return PyErr_Format(PyExc_ValueError, - "the read line size cannot be zero or less"); - } + if (ssize != -1) { + return PyErr_Format(PyExc_ValueError, + "the read line size cannot be zero or less"); + } - if (PyErr_Occurred()) { - return NULL; - } + if (PyErr_Occurred()) { + return NULL; } + } - return nxt_py_input_getline(pctx, SSIZE_MAX); + return nxt_py_input_getline(pctx, SSIZE_MAX); } +static PyObject *nxt_py_input_getline(nxt_python_ctx_t *pctx, size_t size) { + void *buf; + ssize_t res; + PyObject *content; -static PyObject * -nxt_py_input_getline(nxt_python_ctx_t *pctx, size_t size) -{ - void *buf; - ssize_t res; - PyObject *content; - - res = nxt_unit_request_readline_size(pctx->req, size); - if (nxt_slow_path(res < 0)) { - return NULL; - } + res = nxt_unit_request_readline_size(pctx->req, size); + if (nxt_slow_path(res < 0)) { + return NULL; + } - if (res == 0) { - return PyBytes_FromStringAndSize("", 0); - } + if (res == 0) { + return PyBytes_FromStringAndSize("", 0); + } - content = PyBytes_FromStringAndSize(NULL, res); - if (nxt_slow_path(content == NULL)) { - return NULL; - } + content = PyBytes_FromStringAndSize(NULL, res); + if (nxt_slow_path(content == NULL)) { + return NULL; + } - buf = PyBytes_AS_STRING(content); + buf = PyBytes_AS_STRING(content); - res = nxt_unit_request_read(pctx->req, buf, res); + res = nxt_unit_request_read(pctx->req, buf, res); - return content; + return content; } +static PyObject *nxt_py_input_readlines(nxt_python_ctx_t *pctx, + PyObject *args) { + PyObject *res; -static PyObject * -nxt_py_input_readlines(nxt_python_ctx_t *pctx, PyObject *args) -{ - PyObject *res; + if (nxt_slow_path(pctx->req == NULL)) { + return PyErr_Format(PyExc_RuntimeError, + "wsgi.input.readlines() is called " + "outside of WSGI request processing"); + } - if (nxt_slow_path(pctx->req == NULL)) { - return PyErr_Format(PyExc_RuntimeError, - "wsgi.input.readlines() is called " - "outside of WSGI request processing"); - } + res = PyList_New(0); + if (nxt_slow_path(res == NULL)) { + return NULL; + } - res = PyList_New(0); - if (nxt_slow_path(res == NULL)) { - return NULL; + for (;;) { + PyObject *line = nxt_py_input_getline(pctx, SSIZE_MAX); + if (nxt_slow_path(line == NULL)) { + Py_DECREF(res); + return NULL; } - for ( ;; ) { - PyObject *line = nxt_py_input_getline(pctx, SSIZE_MAX); - if (nxt_slow_path(line == NULL)) { - Py_DECREF(res); - return NULL; - } - - if (PyBytes_GET_SIZE(line) == 0) { - Py_DECREF(line); - return res; - } - - PyList_Append(res, line); - Py_DECREF(line); + if (PyBytes_GET_SIZE(line) == 0) { + Py_DECREF(line); + return res; } - return res; -} + PyList_Append(res, line); + Py_DECREF(line); + } - -static PyObject * -nxt_py_input_iter(PyObject *self) -{ - Py_INCREF(self); - return self; + return res; } +static PyObject *nxt_py_input_iter(PyObject *self) { + Py_INCREF(self); + return self; +} -static PyObject * -nxt_py_input_next(PyObject *self) -{ - PyObject *line; - nxt_python_ctx_t *pctx; +static PyObject *nxt_py_input_next(PyObject *self) { + PyObject *line; + nxt_python_ctx_t *pctx; - pctx = (nxt_python_ctx_t *) self; - if (nxt_slow_path(pctx->req == NULL)) { - return PyErr_Format(PyExc_RuntimeError, - "wsgi.input.next() is called " - "outside of WSGI request processing"); - } + pctx = (nxt_python_ctx_t *)self; + if (nxt_slow_path(pctx->req == NULL)) { + return PyErr_Format(PyExc_RuntimeError, + "wsgi.input.next() is called " + "outside of WSGI request processing"); + } - line = nxt_py_input_getline(pctx, SSIZE_MAX); - if (nxt_slow_path(line == NULL)) { - return NULL; - } + line = nxt_py_input_getline(pctx, SSIZE_MAX); + if (nxt_slow_path(line == NULL)) { + return NULL; + } - if (PyBytes_GET_SIZE(line) == 0) { - Py_DECREF(line); - PyErr_SetNone(PyExc_StopIteration); - return NULL; - } + if (PyBytes_GET_SIZE(line) == 0) { + Py_DECREF(line); + PyErr_SetNone(PyExc_StopIteration); + return NULL; + } - return line; + return line; } +static int nxt_python_write(nxt_python_ctx_t *pctx, PyObject *bytes) { + int rc; + char *str_buf; + uint32_t str_length; -static int -nxt_python_write(nxt_python_ctx_t *pctx, PyObject *bytes) -{ - int rc; - char *str_buf; - uint32_t str_length; + str_buf = PyBytes_AS_STRING(bytes); + str_length = PyBytes_GET_SIZE(bytes); - str_buf = PyBytes_AS_STRING(bytes); - str_length = PyBytes_GET_SIZE(bytes); - - if (nxt_slow_path(str_length == 0)) { - return NXT_UNIT_OK; - } + if (nxt_slow_path(str_length == 0)) { + return NXT_UNIT_OK; + } + + /* + * PEP 3333: + * + * If the application supplies a Content-Length header, the server should + * not transmit more bytes to the client than the header allows, and should + * stop iterating over the response when enough data has been sent, or raise + * an error if the application tries to write() past that point. + */ + if (nxt_slow_path(str_length > pctx->content_length - pctx->bytes_sent)) { + nxt_unit_req_error(pctx->req, "content length %" PRIu64 " exceeded", + pctx->content_length); - /* - * PEP 3333: - * - * If the application supplies a Content-Length header, the server should - * not transmit more bytes to the client than the header allows, and should - * stop iterating over the response when enough data has been sent, or raise - * an error if the application tries to write() past that point. - */ - if (nxt_slow_path(str_length > pctx->content_length - pctx->bytes_sent)) { - nxt_unit_req_error(pctx->req, "content length %"PRIu64" exceeded", - pctx->content_length); - - return NXT_UNIT_ERROR; - } + return NXT_UNIT_ERROR; + } - rc = nxt_unit_response_write(pctx->req, str_buf, str_length); - if (nxt_fast_path(rc == NXT_UNIT_OK)) { - pctx->bytes_sent += str_length; - } + rc = nxt_unit_response_write(pctx->req, str_buf, str_length); + if (nxt_fast_path(rc == NXT_UNIT_OK)) { + pctx->bytes_sent += str_length; + } - return rc; + return rc; } diff --git a/src/ruby/nxt_ruby.c b/src/ruby/nxt_ruby.c index 27b868fed..8b140aefe 100644 --- a/src/ruby/nxt_ruby.c +++ b/src/ruby/nxt_ruby.c @@ -14,20 +14,16 @@ #include - -#define NXT_RUBY_RACK_API_VERSION_MAJOR 1 -#define NXT_RUBY_RACK_API_VERSION_MINOR 3 - +#define NXT_RUBY_RACK_API_VERSION_MAJOR 1 +#define NXT_RUBY_RACK_API_VERSION_MINOR 3 typedef struct { - nxt_task_t *task; - nxt_str_t *script; - nxt_ruby_ctx_t *rctx; + nxt_task_t *task; + nxt_str_t *script; + nxt_ruby_ctx_t *rctx; } nxt_ruby_rack_init_t; - -static nxt_int_t nxt_ruby_start(nxt_task_t *task, - nxt_process_data_t *data); +static nxt_int_t nxt_ruby_start(nxt_task_t *task, nxt_process_data_t *data); static VALUE nxt_ruby_init_basic(VALUE arg); static VALUE nxt_ruby_hook_procs_load(VALUE path); @@ -50,1461 +46,1307 @@ static VALUE nxt_ruby_thread_func(VALUE arg); static void *nxt_ruby_unit_run(void *ctx); static void nxt_ruby_ubf(void *ctx); static int nxt_ruby_init_threads(nxt_ruby_app_conf_t *c); -static void nxt_ruby_join_threads(nxt_unit_ctx_t *ctx, - nxt_ruby_app_conf_t *c); +static void nxt_ruby_join_threads(nxt_unit_ctx_t *ctx, nxt_ruby_app_conf_t *c); static VALUE nxt_ruby_rack_app_run(VALUE arg); static int nxt_ruby_read_request(nxt_unit_request_info_t *req, VALUE hash_env); nxt_inline void nxt_ruby_add_sptr(VALUE hash_env, VALUE name, - nxt_unit_sptr_t *sptr, uint32_t len); + nxt_unit_sptr_t *sptr, uint32_t len); static nxt_int_t nxt_ruby_rack_result_status(nxt_unit_request_info_t *req, - VALUE result); + VALUE result); static int nxt_ruby_rack_result_headers(nxt_unit_request_info_t *req, - VALUE result, nxt_int_t status); + VALUE result, nxt_int_t status); static int nxt_ruby_hash_info(VALUE r_key, VALUE r_value, VALUE arg); static int nxt_ruby_hash_add(VALUE r_key, VALUE r_value, VALUE arg); static int nxt_ruby_rack_result_body(nxt_unit_request_info_t *req, - VALUE result); + VALUE result); static int nxt_ruby_rack_result_body_file_write(nxt_unit_request_info_t *req, - VALUE filepath); + VALUE filepath); static void *nxt_ruby_response_write_cb(void *read_info); -static VALUE nxt_ruby_rack_result_body_each(VALUE body, VALUE arg, - int argc, const VALUE *argv, VALUE blockarg); +static VALUE nxt_ruby_rack_result_body_each(VALUE body, VALUE arg, int argc, + const VALUE *argv, VALUE blockarg); static void *nxt_ruby_response_write(void *body); -static void nxt_ruby_exception_log(nxt_unit_request_info_t *req, - uint32_t level, const char *desc); +static void nxt_ruby_exception_log(nxt_unit_request_info_t *req, uint32_t level, + const char *desc); static void nxt_ruby_ctx_done(nxt_ruby_ctx_t *rctx); static void nxt_ruby_atexit(void); - -static uint32_t compat[] = { - NXT_VERNUM, NXT_DEBUG, +static uint32_t compat[] = { + NXT_VERNUM, + NXT_DEBUG, }; -static VALUE nxt_ruby_hook_procs; -static VALUE nxt_ruby_rackup; -static VALUE nxt_ruby_call; - -static uint32_t nxt_ruby_threads; -static nxt_ruby_ctx_t *nxt_ruby_ctxs; - -NXT_EXPORT nxt_app_module_t nxt_app_module = { - sizeof(compat), - compat, - nxt_string("ruby"), - ruby_version, - nxt_ruby_mounts, - nxt_nitems(nxt_ruby_mounts), - NULL, - nxt_ruby_start, +static VALUE nxt_ruby_hook_procs; +static VALUE nxt_ruby_rackup; +static VALUE nxt_ruby_call; + +static uint32_t nxt_ruby_threads; +static nxt_ruby_ctx_t *nxt_ruby_ctxs; + +NXT_EXPORT nxt_app_module_t nxt_app_module = { + sizeof(compat), compat, nxt_string("ruby"), + ruby_version, nxt_ruby_mounts, nxt_nitems(nxt_ruby_mounts), + NULL, nxt_ruby_start, }; typedef struct { - nxt_str_t string; - VALUE *v; + nxt_str_t string; + VALUE *v; } nxt_ruby_string_t; -static VALUE nxt_rb_80_str; -static VALUE nxt_rb_content_length_str; -static VALUE nxt_rb_content_type_str; -static VALUE nxt_rb_http_str; -static VALUE nxt_rb_https_str; -static VALUE nxt_rb_path_info_str; -static VALUE nxt_rb_query_string_str; -static VALUE nxt_rb_rack_url_scheme_str; -static VALUE nxt_rb_remote_addr_str; -static VALUE nxt_rb_request_method_str; -static VALUE nxt_rb_request_uri_str; -static VALUE nxt_rb_server_addr_str; -static VALUE nxt_rb_server_name_str; -static VALUE nxt_rb_server_port_str; -static VALUE nxt_rb_server_protocol_str; -static VALUE nxt_rb_on_worker_boot; -static VALUE nxt_rb_on_worker_shutdown; -static VALUE nxt_rb_on_thread_boot; -static VALUE nxt_rb_on_thread_shutdown; +static VALUE nxt_rb_80_str; +static VALUE nxt_rb_content_length_str; +static VALUE nxt_rb_content_type_str; +static VALUE nxt_rb_http_str; +static VALUE nxt_rb_https_str; +static VALUE nxt_rb_path_info_str; +static VALUE nxt_rb_query_string_str; +static VALUE nxt_rb_rack_url_scheme_str; +static VALUE nxt_rb_remote_addr_str; +static VALUE nxt_rb_request_method_str; +static VALUE nxt_rb_request_uri_str; +static VALUE nxt_rb_server_addr_str; +static VALUE nxt_rb_server_name_str; +static VALUE nxt_rb_server_port_str; +static VALUE nxt_rb_server_protocol_str; +static VALUE nxt_rb_on_worker_boot; +static VALUE nxt_rb_on_worker_shutdown; +static VALUE nxt_rb_on_thread_boot; +static VALUE nxt_rb_on_thread_shutdown; static nxt_ruby_string_t nxt_rb_strings[] = { - { nxt_string("80"), &nxt_rb_80_str }, - { nxt_string("CONTENT_LENGTH"), &nxt_rb_content_length_str }, - { nxt_string("CONTENT_TYPE"), &nxt_rb_content_type_str }, - { nxt_string("http"), &nxt_rb_http_str }, - { nxt_string("https"), &nxt_rb_https_str }, - { nxt_string("PATH_INFO"), &nxt_rb_path_info_str }, - { nxt_string("QUERY_STRING"), &nxt_rb_query_string_str }, - { nxt_string("rack.url_scheme"), &nxt_rb_rack_url_scheme_str }, - { nxt_string("REMOTE_ADDR"), &nxt_rb_remote_addr_str }, - { nxt_string("REQUEST_METHOD"), &nxt_rb_request_method_str }, - { nxt_string("REQUEST_URI"), &nxt_rb_request_uri_str }, - { nxt_string("SERVER_ADDR"), &nxt_rb_server_addr_str }, - { nxt_string("SERVER_NAME"), &nxt_rb_server_name_str }, - { nxt_string("SERVER_PORT"), &nxt_rb_server_port_str }, - { nxt_string("SERVER_PROTOCOL"), &nxt_rb_server_protocol_str }, - { nxt_string("on_worker_boot"), &nxt_rb_on_worker_boot }, - { nxt_string("on_worker_shutdown"), &nxt_rb_on_worker_shutdown }, - { nxt_string("on_thread_boot"), &nxt_rb_on_thread_boot }, - { nxt_string("on_thread_shutdown"), &nxt_rb_on_thread_shutdown }, - { nxt_null_string, NULL }, + {nxt_string("80"), &nxt_rb_80_str}, + {nxt_string("CONTENT_LENGTH"), &nxt_rb_content_length_str}, + {nxt_string("CONTENT_TYPE"), &nxt_rb_content_type_str}, + {nxt_string("http"), &nxt_rb_http_str}, + {nxt_string("https"), &nxt_rb_https_str}, + {nxt_string("PATH_INFO"), &nxt_rb_path_info_str}, + {nxt_string("QUERY_STRING"), &nxt_rb_query_string_str}, + {nxt_string("rack.url_scheme"), &nxt_rb_rack_url_scheme_str}, + {nxt_string("REMOTE_ADDR"), &nxt_rb_remote_addr_str}, + {nxt_string("REQUEST_METHOD"), &nxt_rb_request_method_str}, + {nxt_string("REQUEST_URI"), &nxt_rb_request_uri_str}, + {nxt_string("SERVER_ADDR"), &nxt_rb_server_addr_str}, + {nxt_string("SERVER_NAME"), &nxt_rb_server_name_str}, + {nxt_string("SERVER_PORT"), &nxt_rb_server_port_str}, + {nxt_string("SERVER_PROTOCOL"), &nxt_rb_server_protocol_str}, + {nxt_string("on_worker_boot"), &nxt_rb_on_worker_boot}, + {nxt_string("on_worker_shutdown"), &nxt_rb_on_worker_shutdown}, + {nxt_string("on_thread_boot"), &nxt_rb_on_thread_boot}, + {nxt_string("on_thread_shutdown"), &nxt_rb_on_thread_shutdown}, + {nxt_null_string, NULL}, }; +static int nxt_ruby_init_strings(void) { + VALUE v; + nxt_ruby_string_t *pstr; -static int -nxt_ruby_init_strings(void) -{ - VALUE v; - nxt_ruby_string_t *pstr; - - pstr = nxt_rb_strings; + pstr = nxt_rb_strings; - while (pstr->string.start != NULL) { - v = rb_str_new_static((char *) pstr->string.start, pstr->string.length); + while (pstr->string.start != NULL) { + v = rb_str_new_static((char *)pstr->string.start, pstr->string.length); - if (nxt_slow_path(v == Qnil)) { - nxt_unit_alert(NULL, "Ruby: failed to create const string '%.*s'", - (int) pstr->string.length, - (char *) pstr->string.start); + if (nxt_slow_path(v == Qnil)) { + nxt_unit_alert(NULL, "Ruby: failed to create const string '%.*s'", + (int)pstr->string.length, (char *)pstr->string.start); - return NXT_UNIT_ERROR; - } + return NXT_UNIT_ERROR; + } - *pstr->v = v; + *pstr->v = v; - rb_gc_register_address(pstr->v); + rb_gc_register_address(pstr->v); - pstr++; - } + pstr++; + } - return NXT_UNIT_OK; + return NXT_UNIT_OK; } +static void nxt_ruby_done_strings(void) { + nxt_ruby_string_t *pstr; -static void -nxt_ruby_done_strings(void) -{ - nxt_ruby_string_t *pstr; + pstr = nxt_rb_strings; - pstr = nxt_rb_strings; + while (pstr->string.start != NULL) { + rb_gc_unregister_address(pstr->v); - while (pstr->string.start != NULL) { - rb_gc_unregister_address(pstr->v); + *pstr->v = Qnil; - *pstr->v = Qnil; - - pstr++; - } + pstr++; + } } +static VALUE nxt_ruby_hook_procs_load(VALUE path) { + VALUE module, file, file_obj; -static VALUE -nxt_ruby_hook_procs_load(VALUE path) -{ - VALUE module, file, file_obj; - - module = rb_define_module("Unit"); + module = rb_define_module("Unit"); - nxt_ruby_hook_procs = rb_hash_new(); + nxt_ruby_hook_procs = rb_hash_new(); - rb_gc_register_address(&nxt_ruby_hook_procs); + rb_gc_register_address(&nxt_ruby_hook_procs); - rb_define_module_function(module, "on_worker_boot", - &nxt_ruby_hook_register, 0); - rb_define_module_function(module, "on_worker_shutdown", - &nxt_ruby_hook_register, 0); - rb_define_module_function(module, "on_thread_boot", - &nxt_ruby_hook_register, 0); - rb_define_module_function(module, "on_thread_shutdown", - &nxt_ruby_hook_register, 0); + rb_define_module_function(module, "on_worker_boot", &nxt_ruby_hook_register, + 0); + rb_define_module_function(module, "on_worker_shutdown", + &nxt_ruby_hook_register, 0); + rb_define_module_function(module, "on_thread_boot", &nxt_ruby_hook_register, + 0); + rb_define_module_function(module, "on_thread_shutdown", + &nxt_ruby_hook_register, 0); - file = rb_const_get(rb_cObject, rb_intern("File")); - file_obj = rb_funcall(file, rb_intern("read"), 1, path); + file = rb_const_get(rb_cObject, rb_intern("File")); + file_obj = rb_funcall(file, rb_intern("read"), 1, path); - return rb_funcall(module, rb_intern("module_eval"), 3, file_obj, path, - INT2NUM(1)); + return rb_funcall(module, rb_intern("module_eval"), 3, file_obj, path, + INT2NUM(1)); } +static VALUE nxt_ruby_hook_register(VALUE arg) { + VALUE kernel, callee, callee_str; -static VALUE -nxt_ruby_hook_register(VALUE arg) -{ - VALUE kernel, callee, callee_str; + rb_need_block(); - rb_need_block(); + kernel = rb_const_get(rb_cObject, rb_intern("Kernel")); + callee = rb_funcall(kernel, rb_intern("__callee__"), 0); + callee_str = rb_funcall(callee, rb_intern("to_s"), 0); - kernel = rb_const_get(rb_cObject, rb_intern("Kernel")); - callee = rb_funcall(kernel, rb_intern("__callee__"), 0); - callee_str = rb_funcall(callee, rb_intern("to_s"), 0); + rb_hash_aset(nxt_ruby_hook_procs, callee_str, rb_block_proc()); - rb_hash_aset(nxt_ruby_hook_procs, callee_str, rb_block_proc()); - - return Qnil; + return Qnil; } +static VALUE nxt_ruby_hook_call(VALUE name) { + VALUE proc; -static VALUE -nxt_ruby_hook_call(VALUE name) -{ - VALUE proc; - - proc = rb_hash_lookup(nxt_ruby_hook_procs, name); - if (proc == Qnil) { - return Qnil; - } + proc = rb_hash_lookup(nxt_ruby_hook_procs, name); + if (proc == Qnil) { + return Qnil; + } - return rb_funcall(proc, rb_intern("call"), 0); + return rb_funcall(proc, rb_intern("call"), 0); } +static nxt_int_t nxt_ruby_start(nxt_task_t *task, nxt_process_data_t *data) { + int state, rc; + VALUE res, path; + nxt_ruby_ctx_t ruby_ctx; + nxt_unit_ctx_t *unit_ctx; + nxt_unit_init_t ruby_unit_init; + nxt_ruby_app_conf_t *c; + nxt_ruby_rack_init_t rack_init; + nxt_common_app_conf_t *conf; -static nxt_int_t -nxt_ruby_start(nxt_task_t *task, nxt_process_data_t *data) -{ - int state, rc; - VALUE res, path; - nxt_ruby_ctx_t ruby_ctx; - nxt_unit_ctx_t *unit_ctx; - nxt_unit_init_t ruby_unit_init; - nxt_ruby_app_conf_t *c; - nxt_ruby_rack_init_t rack_init; - nxt_common_app_conf_t *conf; - - static char *argv[2] = { (char *) "NGINX_Unit", (char *) "-e0" }; + static char *argv[2] = {(char *)"NGINX_Unit", (char *)"-e0"}; - signal(SIGINT, SIG_IGN); + signal(SIGINT, SIG_IGN); - conf = data->app; - c = &conf->u.ruby; + conf = data->app; + c = &conf->u.ruby; - nxt_ruby_threads = c->threads; + nxt_ruby_threads = c->threads; - setlocale(LC_CTYPE, ""); + setlocale(LC_CTYPE, ""); - RUBY_INIT_STACK - ruby_init(); - ruby_options(2, argv); - ruby_script("NGINX_Unit"); + RUBY_INIT_STACK + ruby_init(); + ruby_options(2, argv); + ruby_script("NGINX_Unit"); - ruby_ctx.env = Qnil; - ruby_ctx.io_input = Qnil; - ruby_ctx.io_error = Qnil; - ruby_ctx.thread = Qnil; - ruby_ctx.ctx = NULL; - ruby_ctx.req = NULL; + ruby_ctx.env = Qnil; + ruby_ctx.io_input = Qnil; + ruby_ctx.io_error = Qnil; + ruby_ctx.thread = Qnil; + ruby_ctx.ctx = NULL; + ruby_ctx.req = NULL; - rack_init.task = task; - rack_init.script = &c->script; - rack_init.rctx = &ruby_ctx; + rack_init.task = task; + rack_init.script = &c->script; + rack_init.rctx = &ruby_ctx; - nxt_ruby_init_strings(); + nxt_ruby_init_strings(); - res = rb_protect(nxt_ruby_init_basic, - (VALUE) (uintptr_t) &rack_init, &state); - if (nxt_slow_path(res == Qnil || state != 0)) { - nxt_ruby_exception_log(NULL, NXT_LOG_ALERT, - "Failed to init basic variables"); - return NXT_ERROR; - } + res = rb_protect(nxt_ruby_init_basic, (VALUE)(uintptr_t)&rack_init, &state); + if (nxt_slow_path(res == Qnil || state != 0)) { + nxt_ruby_exception_log(NULL, NXT_LOG_ALERT, + "Failed to init basic variables"); + return NXT_ERROR; + } - nxt_ruby_call = Qnil; - nxt_ruby_hook_procs = Qnil; + nxt_ruby_call = Qnil; + nxt_ruby_hook_procs = Qnil; - if (c->hooks.start != NULL) { - path = rb_str_new((const char *) c->hooks.start, - (long) c->hooks.length); + if (c->hooks.start != NULL) { + path = rb_str_new((const char *)c->hooks.start, (long)c->hooks.length); - rb_protect(nxt_ruby_hook_procs_load, path, &state); - rb_str_free(path); - if (nxt_slow_path(state != 0)) { - nxt_ruby_exception_log(NULL, NXT_LOG_ALERT, - "Failed to setup hooks"); - return NXT_ERROR; - } + rb_protect(nxt_ruby_hook_procs_load, path, &state); + rb_str_free(path); + if (nxt_slow_path(state != 0)) { + nxt_ruby_exception_log(NULL, NXT_LOG_ALERT, "Failed to setup hooks"); + return NXT_ERROR; } + } - if (nxt_ruby_hook_procs != Qnil) { - rb_protect(nxt_ruby_hook_call, nxt_rb_on_worker_boot, &state); - if (nxt_slow_path(state != 0)) { - nxt_ruby_exception_log(NULL, NXT_LOG_ERR, - "Failed to call on_worker_boot()"); - return NXT_ERROR; - } + if (nxt_ruby_hook_procs != Qnil) { + rb_protect(nxt_ruby_hook_call, nxt_rb_on_worker_boot, &state); + if (nxt_slow_path(state != 0)) { + nxt_ruby_exception_log(NULL, NXT_LOG_ERR, + "Failed to call on_worker_boot()"); + return NXT_ERROR; } + } - nxt_ruby_rackup = nxt_ruby_rack_init(&rack_init); - if (nxt_slow_path(nxt_ruby_rackup == Qnil)) { - return NXT_ERROR; - } + nxt_ruby_rackup = nxt_ruby_rack_init(&rack_init); + if (nxt_slow_path(nxt_ruby_rackup == Qnil)) { + return NXT_ERROR; + } - rb_gc_register_address(&nxt_ruby_rackup); + rb_gc_register_address(&nxt_ruby_rackup); - nxt_ruby_call = rb_intern("call"); - if (nxt_slow_path(nxt_ruby_call == Qnil)) { - nxt_alert(task, "Ruby: Unable to find rack entry point"); + nxt_ruby_call = rb_intern("call"); + if (nxt_slow_path(nxt_ruby_call == Qnil)) { + nxt_alert(task, "Ruby: Unable to find rack entry point"); - goto fail; - } + goto fail; + } - rb_gc_register_address(&nxt_ruby_call); + rb_gc_register_address(&nxt_ruby_call); - ruby_ctx.env = rb_protect(nxt_ruby_rack_env_create, - (VALUE) (uintptr_t) &ruby_ctx, &state); - if (nxt_slow_path(ruby_ctx.env == Qnil || state != 0)) { - nxt_ruby_exception_log(NULL, NXT_LOG_ALERT, - "Failed to create 'environ' variable"); - goto fail; - } + ruby_ctx.env = + rb_protect(nxt_ruby_rack_env_create, (VALUE)(uintptr_t)&ruby_ctx, &state); + if (nxt_slow_path(ruby_ctx.env == Qnil || state != 0)) { + nxt_ruby_exception_log(NULL, NXT_LOG_ALERT, + "Failed to create 'environ' variable"); + goto fail; + } - rc = nxt_ruby_init_threads(c); - if (nxt_slow_path(rc == NXT_UNIT_ERROR)) { - goto fail; - } + rc = nxt_ruby_init_threads(c); + if (nxt_slow_path(rc == NXT_UNIT_ERROR)) { + goto fail; + } - nxt_unit_default_init(task, &ruby_unit_init, conf); + nxt_unit_default_init(task, &ruby_unit_init, conf); - ruby_unit_init.callbacks.request_handler = nxt_ruby_request_handler; - ruby_unit_init.callbacks.ready_handler = nxt_ruby_ready_handler; - ruby_unit_init.data = c; - ruby_unit_init.ctx_data = &ruby_ctx; + ruby_unit_init.callbacks.request_handler = nxt_ruby_request_handler; + ruby_unit_init.callbacks.ready_handler = nxt_ruby_ready_handler; + ruby_unit_init.data = c; + ruby_unit_init.ctx_data = &ruby_ctx; - unit_ctx = nxt_unit_init(&ruby_unit_init); - if (nxt_slow_path(unit_ctx == NULL)) { - goto fail; - } + unit_ctx = nxt_unit_init(&ruby_unit_init); + if (nxt_slow_path(unit_ctx == NULL)) { + goto fail; + } - if (nxt_ruby_hook_procs != Qnil) { - rb_protect(nxt_ruby_hook_call, nxt_rb_on_thread_boot, &state); - if (nxt_slow_path(state != 0)) { - nxt_ruby_exception_log(NULL, NXT_LOG_ERR, - "Failed to call on_thread_boot()"); - } + if (nxt_ruby_hook_procs != Qnil) { + rb_protect(nxt_ruby_hook_call, nxt_rb_on_thread_boot, &state); + if (nxt_slow_path(state != 0)) { + nxt_ruby_exception_log(NULL, NXT_LOG_ERR, + "Failed to call on_thread_boot()"); } + } - rc = (intptr_t) rb_thread_call_without_gvl2(nxt_ruby_unit_run, unit_ctx, - nxt_ruby_ubf, unit_ctx); + rc = (intptr_t)rb_thread_call_without_gvl2(nxt_ruby_unit_run, unit_ctx, + nxt_ruby_ubf, unit_ctx); - if (nxt_ruby_hook_procs != Qnil) { - rb_protect(nxt_ruby_hook_call, nxt_rb_on_thread_shutdown, &state); - if (nxt_slow_path(state != 0)) { - nxt_ruby_exception_log(NULL, NXT_LOG_ERR, - "Failed to call on_thread_shutdown()"); - } + if (nxt_ruby_hook_procs != Qnil) { + rb_protect(nxt_ruby_hook_call, nxt_rb_on_thread_shutdown, &state); + if (nxt_slow_path(state != 0)) { + nxt_ruby_exception_log(NULL, NXT_LOG_ERR, + "Failed to call on_thread_shutdown()"); } + } - nxt_ruby_join_threads(unit_ctx, c); + nxt_ruby_join_threads(unit_ctx, c); - if (nxt_ruby_hook_procs != Qnil) { - rb_protect(nxt_ruby_hook_call, nxt_rb_on_worker_shutdown, &state); - if (nxt_slow_path(state != 0)) { - nxt_ruby_exception_log(NULL, NXT_LOG_ERR, - "Failed to call on_worker_shutdown()"); - } + if (nxt_ruby_hook_procs != Qnil) { + rb_protect(nxt_ruby_hook_call, nxt_rb_on_worker_shutdown, &state); + if (nxt_slow_path(state != 0)) { + nxt_ruby_exception_log(NULL, NXT_LOG_ERR, + "Failed to call on_worker_shutdown()"); } + } - nxt_unit_done(unit_ctx); + nxt_unit_done(unit_ctx); - nxt_ruby_ctx_done(&ruby_ctx); + nxt_ruby_ctx_done(&ruby_ctx); - nxt_ruby_atexit(); + nxt_ruby_atexit(); - exit(rc); + exit(rc); - return NXT_OK; + return NXT_OK; fail: - nxt_ruby_join_threads(NULL, c); + nxt_ruby_join_threads(NULL, c); - nxt_ruby_ctx_done(&ruby_ctx); + nxt_ruby_ctx_done(&ruby_ctx); - nxt_ruby_atexit(); + nxt_ruby_atexit(); - return NXT_ERROR; + return NXT_ERROR; } +static VALUE nxt_ruby_init_basic(VALUE arg) { + int state; + nxt_ruby_rack_init_t *rack_init; -static VALUE -nxt_ruby_init_basic(VALUE arg) -{ - int state; - nxt_ruby_rack_init_t *rack_init; - - rack_init = (nxt_ruby_rack_init_t *) (uintptr_t) arg; + rack_init = (nxt_ruby_rack_init_t *)(uintptr_t)arg; - state = rb_enc_find_index("encdb"); - if (nxt_slow_path(state == 0)) { - nxt_alert(rack_init->task, - "Ruby: Failed to find encoding index 'encdb'"); + state = rb_enc_find_index("encdb"); + if (nxt_slow_path(state == 0)) { + nxt_alert(rack_init->task, "Ruby: Failed to find encoding index 'encdb'"); - return Qnil; - } + return Qnil; + } - rb_funcall(rb_cObject, rb_intern("require"), 1, - rb_str_new2("enc/trans/transdb")); + rb_funcall(rb_cObject, rb_intern("require"), 1, + rb_str_new2("enc/trans/transdb")); - return arg; + return arg; } +static VALUE nxt_ruby_rack_init(nxt_ruby_rack_init_t *rack_init) { + int state; + VALUE rackup, err; -static VALUE -nxt_ruby_rack_init(nxt_ruby_rack_init_t *rack_init) -{ - int state; - VALUE rackup, err; - - rb_protect(nxt_ruby_require_rubygems, Qnil, &state); - if (nxt_slow_path(state != 0)) { - nxt_ruby_exception_log(NULL, NXT_LOG_ALERT, - "Failed to require 'rubygems' package"); - return Qnil; - } - - rb_protect(nxt_ruby_bundler_setup, Qnil, &state); - if (state != 0) { - err = rb_errinfo(); + rb_protect(nxt_ruby_require_rubygems, Qnil, &state); + if (nxt_slow_path(state != 0)) { + nxt_ruby_exception_log(NULL, NXT_LOG_ALERT, + "Failed to require 'rubygems' package"); + return Qnil; + } - if (rb_obj_is_kind_of(err, rb_eLoadError) == Qfalse) { - nxt_ruby_exception_log(NULL, NXT_LOG_ALERT, - "Failed to require 'bundler/setup' package"); - return Qnil; - } + rb_protect(nxt_ruby_bundler_setup, Qnil, &state); + if (state != 0) { + err = rb_errinfo(); - rb_set_errinfo(Qnil); + if (rb_obj_is_kind_of(err, rb_eLoadError) == Qfalse) { + nxt_ruby_exception_log(NULL, NXT_LOG_ALERT, + "Failed to require 'bundler/setup' package"); + return Qnil; } - rb_protect(nxt_ruby_require_rack, Qnil, &state); - if (nxt_slow_path(state != 0)) { - nxt_ruby_exception_log(NULL, NXT_LOG_ALERT, - "Failed to require 'rack' package"); - return Qnil; - } + rb_set_errinfo(Qnil); + } - rackup = rb_protect(nxt_ruby_rack_parse_script, - (VALUE) (uintptr_t) rack_init, &state); + rb_protect(nxt_ruby_require_rack, Qnil, &state); + if (nxt_slow_path(state != 0)) { + nxt_ruby_exception_log(NULL, NXT_LOG_ALERT, + "Failed to require 'rack' package"); + return Qnil; + } - if (nxt_slow_path(state != 0)) { - nxt_ruby_exception_log(NULL, NXT_LOG_ALERT, - "Failed to parse rack script"); - return Qnil; - } + rackup = rb_protect(nxt_ruby_rack_parse_script, (VALUE)(uintptr_t)rack_init, + &state); - if (TYPE(rackup) != T_ARRAY) { - return rackup; - } - - if (nxt_slow_path(RARRAY_LEN(rackup) < 1)) { - nxt_ruby_exception_log(NULL, NXT_LOG_ALERT, "Invalid rack config file"); - return Qnil; - } + if (nxt_slow_path(state != 0)) { + nxt_ruby_exception_log(NULL, NXT_LOG_ALERT, "Failed to parse rack script"); + return Qnil; + } - return RARRAY_PTR(rackup)[0]; -} + if (TYPE(rackup) != T_ARRAY) { + return rackup; + } + if (nxt_slow_path(RARRAY_LEN(rackup) < 1)) { + nxt_ruby_exception_log(NULL, NXT_LOG_ALERT, "Invalid rack config file"); + return Qnil; + } -static VALUE -nxt_ruby_require_rubygems(VALUE arg) -{ - return rb_funcall(rb_cObject, rb_intern("require"), 1, - rb_str_new2("rubygems")); + return RARRAY_PTR(rackup)[0]; } - -static VALUE -nxt_ruby_bundler_setup(VALUE arg) -{ - return rb_funcall(rb_cObject, rb_intern("require"), 1, - rb_str_new2("bundler/setup")); +static VALUE nxt_ruby_require_rubygems(VALUE arg) { + return rb_funcall(rb_cObject, rb_intern("require"), 1, + rb_str_new2("rubygems")); } - -static VALUE -nxt_ruby_require_rack(VALUE arg) -{ - return rb_funcall(rb_cObject, rb_intern("require"), 1, rb_str_new2("rack")); +static VALUE nxt_ruby_bundler_setup(VALUE arg) { + return rb_funcall(rb_cObject, rb_intern("require"), 1, + rb_str_new2("bundler/setup")); } +static VALUE nxt_ruby_require_rack(VALUE arg) { + return rb_funcall(rb_cObject, rb_intern("require"), 1, rb_str_new2("rack")); +} -static VALUE -nxt_ruby_rack_parse_script(VALUE ctx) -{ - VALUE script, res, rack, builder; - nxt_ruby_rack_init_t *rack_init; +static VALUE nxt_ruby_rack_parse_script(VALUE ctx) { + VALUE script, res, rack, builder; + nxt_ruby_rack_init_t *rack_init; - rack_init = (nxt_ruby_rack_init_t *) (uintptr_t) ctx; + rack_init = (nxt_ruby_rack_init_t *)(uintptr_t)ctx; - rack = rb_const_get(rb_cObject, rb_intern("Rack")); - builder = rb_const_get(rack, rb_intern("Builder")); + rack = rb_const_get(rb_cObject, rb_intern("Rack")); + builder = rb_const_get(rack, rb_intern("Builder")); - script = rb_str_new((const char *) rack_init->script->start, - (long) rack_init->script->length); + script = rb_str_new((const char *)rack_init->script->start, + (long)rack_init->script->length); - res = rb_funcall(builder, rb_intern("parse_file"), 1, script); + res = rb_funcall(builder, rb_intern("parse_file"), 1, script); - rb_str_free(script); + rb_str_free(script); - return res; + return res; } +static VALUE nxt_ruby_rack_env_create(VALUE arg) { + int rc; + VALUE hash_env, version; + nxt_ruby_ctx_t *rctx; -static VALUE -nxt_ruby_rack_env_create(VALUE arg) -{ - int rc; - VALUE hash_env, version; - nxt_ruby_ctx_t *rctx; - - rctx = (nxt_ruby_ctx_t *) (uintptr_t) arg; + rctx = (nxt_ruby_ctx_t *)(uintptr_t)arg; - rc = nxt_ruby_init_io(rctx); - if (nxt_slow_path(rc != NXT_UNIT_OK)) { - return Qnil; - } + rc = nxt_ruby_init_io(rctx); + if (nxt_slow_path(rc != NXT_UNIT_OK)) { + return Qnil; + } - hash_env = rb_hash_new(); + hash_env = rb_hash_new(); - rb_hash_aset(hash_env, rb_str_new2("SERVER_SOFTWARE"), - rb_str_new((const char *) nxt_server.start, - (long) nxt_server.length)); + rb_hash_aset( + hash_env, rb_str_new2("SERVER_SOFTWARE"), + rb_str_new((const char *)nxt_server.start, (long)nxt_server.length)); - version = rb_ary_new(); + version = rb_ary_new(); - rb_ary_push(version, UINT2NUM(NXT_RUBY_RACK_API_VERSION_MAJOR)); - rb_ary_push(version, UINT2NUM(NXT_RUBY_RACK_API_VERSION_MINOR)); + rb_ary_push(version, UINT2NUM(NXT_RUBY_RACK_API_VERSION_MAJOR)); + rb_ary_push(version, UINT2NUM(NXT_RUBY_RACK_API_VERSION_MINOR)); - rb_hash_aset(hash_env, rb_str_new2("SCRIPT_NAME"), rb_str_new("", 0)); - rb_hash_aset(hash_env, rb_str_new2("rack.version"), version); - rb_hash_aset(hash_env, rb_str_new2("rack.input"), rctx->io_input); - rb_hash_aset(hash_env, rb_str_new2("rack.errors"), rctx->io_error); - rb_hash_aset(hash_env, rb_str_new2("rack.multithread"), - nxt_ruby_threads > 1 ? Qtrue : Qfalse); - rb_hash_aset(hash_env, rb_str_new2("rack.multiprocess"), Qtrue); - rb_hash_aset(hash_env, rb_str_new2("rack.run_once"), Qfalse); - rb_hash_aset(hash_env, rb_str_new2("rack.hijack?"), Qfalse); - rb_hash_aset(hash_env, rb_str_new2("rack.hijack"), Qnil); - rb_hash_aset(hash_env, rb_str_new2("rack.hijack_io"), Qnil); + rb_hash_aset(hash_env, rb_str_new2("SCRIPT_NAME"), rb_str_new("", 0)); + rb_hash_aset(hash_env, rb_str_new2("rack.version"), version); + rb_hash_aset(hash_env, rb_str_new2("rack.input"), rctx->io_input); + rb_hash_aset(hash_env, rb_str_new2("rack.errors"), rctx->io_error); + rb_hash_aset(hash_env, rb_str_new2("rack.multithread"), + nxt_ruby_threads > 1 ? Qtrue : Qfalse); + rb_hash_aset(hash_env, rb_str_new2("rack.multiprocess"), Qtrue); + rb_hash_aset(hash_env, rb_str_new2("rack.run_once"), Qfalse); + rb_hash_aset(hash_env, rb_str_new2("rack.hijack?"), Qfalse); + rb_hash_aset(hash_env, rb_str_new2("rack.hijack"), Qnil); + rb_hash_aset(hash_env, rb_str_new2("rack.hijack_io"), Qnil); - rctx->env = hash_env; + rctx->env = hash_env; - rb_gc_register_address(&rctx->env); + rb_gc_register_address(&rctx->env); - return hash_env; + return hash_env; } +static int nxt_ruby_init_io(nxt_ruby_ctx_t *rctx) { + VALUE io_input, io_error; -static int -nxt_ruby_init_io(nxt_ruby_ctx_t *rctx) -{ - VALUE io_input, io_error; - - io_input = nxt_ruby_stream_io_input_init(); + io_input = nxt_ruby_stream_io_input_init(); - rctx->io_input = rb_funcall(io_input, rb_intern("new"), 1, - (VALUE) (uintptr_t) rctx); - if (nxt_slow_path(rctx->io_input == Qnil)) { - nxt_unit_alert(NULL, - "Ruby: Failed to create environment 'rack.input' var"); + rctx->io_input = + rb_funcall(io_input, rb_intern("new"), 1, (VALUE)(uintptr_t)rctx); + if (nxt_slow_path(rctx->io_input == Qnil)) { + nxt_unit_alert(NULL, "Ruby: Failed to create environment 'rack.input' var"); - return NXT_UNIT_ERROR; - } + return NXT_UNIT_ERROR; + } - rb_gc_register_address(&rctx->io_input); + rb_gc_register_address(&rctx->io_input); - io_error = nxt_ruby_stream_io_error_init(); + io_error = nxt_ruby_stream_io_error_init(); - rctx->io_error = rb_funcall(io_error, rb_intern("new"), 1, - (VALUE) (uintptr_t) rctx); - if (nxt_slow_path(rctx->io_error == Qnil)) { - nxt_unit_alert(NULL, - "Ruby: Failed to create environment 'rack.error' var"); + rctx->io_error = + rb_funcall(io_error, rb_intern("new"), 1, (VALUE)(uintptr_t)rctx); + if (nxt_slow_path(rctx->io_error == Qnil)) { + nxt_unit_alert(NULL, "Ruby: Failed to create environment 'rack.error' var"); - return NXT_UNIT_ERROR; - } + return NXT_UNIT_ERROR; + } - rb_gc_register_address(&rctx->io_error); + rb_gc_register_address(&rctx->io_error); - return NXT_UNIT_OK; + return NXT_UNIT_OK; } - -static void -nxt_ruby_request_handler(nxt_unit_request_info_t *req) -{ - (void) rb_thread_call_with_gvl(nxt_ruby_request_handler_gvl, req); +static void nxt_ruby_request_handler(nxt_unit_request_info_t *req) { + (void)rb_thread_call_with_gvl(nxt_ruby_request_handler_gvl, req); } +static void *nxt_ruby_request_handler_gvl(void *data) { + int state; + VALUE res; + nxt_ruby_ctx_t *rctx; + nxt_unit_request_info_t *req; -static void * -nxt_ruby_request_handler_gvl(void *data) -{ - int state; - VALUE res; - nxt_ruby_ctx_t *rctx; - nxt_unit_request_info_t *req; + req = data; - req = data; + rctx = req->ctx->data; + rctx->req = req; - rctx = req->ctx->data; - rctx->req = req; + res = rb_protect(nxt_ruby_rack_app_run, (VALUE)(uintptr_t)req, &state); + if (nxt_slow_path(res == Qnil || state != 0)) { + nxt_ruby_exception_log(req, NXT_LOG_ERR, "Failed to run ruby script"); - res = rb_protect(nxt_ruby_rack_app_run, (VALUE) (uintptr_t) req, &state); - if (nxt_slow_path(res == Qnil || state != 0)) { - nxt_ruby_exception_log(req, NXT_LOG_ERR, - "Failed to run ruby script"); + nxt_unit_request_done(req, NXT_UNIT_ERROR); - nxt_unit_request_done(req, NXT_UNIT_ERROR); - - } else { - nxt_unit_request_done(req, NXT_UNIT_OK); - } + } else { + nxt_unit_request_done(req, NXT_UNIT_OK); + } - rctx->req = NULL; + rctx->req = NULL; - return NULL; + return NULL; } +static VALUE nxt_ruby_rack_app_run(VALUE arg) { + int rc; + VALUE env, result; + nxt_int_t status; + nxt_ruby_ctx_t *rctx; + nxt_unit_request_info_t *req; -static VALUE -nxt_ruby_rack_app_run(VALUE arg) -{ - int rc; - VALUE env, result; - nxt_int_t status; - nxt_ruby_ctx_t *rctx; - nxt_unit_request_info_t *req; + req = (nxt_unit_request_info_t *)arg; - req = (nxt_unit_request_info_t *) arg; + rctx = req->ctx->data; - rctx = req->ctx->data; + env = rb_hash_dup(rctx->env); - env = rb_hash_dup(rctx->env); + rc = nxt_ruby_read_request(req, env); + if (nxt_slow_path(rc != NXT_UNIT_OK)) { + nxt_unit_req_alert(req, "Ruby: Failed to process incoming request"); - rc = nxt_ruby_read_request(req, env); - if (nxt_slow_path(rc != NXT_UNIT_OK)) { - nxt_unit_req_alert(req, - "Ruby: Failed to process incoming request"); + goto fail; + } - goto fail; - } + result = rb_funcall(nxt_ruby_rackup, nxt_ruby_call, 1, env); + if (nxt_slow_path(TYPE(result) != T_ARRAY)) { + nxt_unit_req_error(req, "Ruby: Invalid response format from application"); - result = rb_funcall(nxt_ruby_rackup, nxt_ruby_call, 1, env); - if (nxt_slow_path(TYPE(result) != T_ARRAY)) { - nxt_unit_req_error(req, - "Ruby: Invalid response format from application"); + goto fail; + } - goto fail; - } + if (nxt_slow_path(RARRAY_LEN(result) != 3)) { + nxt_unit_req_error(req, "Ruby: Invalid response format from application. " + "Need 3 entries [Status, Headers, Body]"); - if (nxt_slow_path(RARRAY_LEN(result) != 3)) { - nxt_unit_req_error(req, - "Ruby: Invalid response format from application. " - "Need 3 entries [Status, Headers, Body]"); + goto fail; + } - goto fail; - } + status = nxt_ruby_rack_result_status(req, result); + if (nxt_slow_path(status < 0)) { + nxt_unit_req_error(req, "Ruby: Invalid response status from application."); - status = nxt_ruby_rack_result_status(req, result); - if (nxt_slow_path(status < 0)) { - nxt_unit_req_error(req, - "Ruby: Invalid response status from application."); + goto fail; + } - goto fail; - } + rc = nxt_ruby_rack_result_headers(req, result, status); + if (nxt_slow_path(rc != NXT_UNIT_OK)) { + goto fail; + } - rc = nxt_ruby_rack_result_headers(req, result, status); - if (nxt_slow_path(rc != NXT_UNIT_OK)) { - goto fail; - } + rc = nxt_ruby_rack_result_body(req, result); + if (nxt_slow_path(rc != NXT_UNIT_OK)) { + goto fail; + } - rc = nxt_ruby_rack_result_body(req, result); - if (nxt_slow_path(rc != NXT_UNIT_OK)) { - goto fail; - } - - rb_hash_delete(env, rb_obj_id(env)); + rb_hash_delete(env, rb_obj_id(env)); - return result; + return result; fail: - rb_hash_delete(env, rb_obj_id(env)); + rb_hash_delete(env, rb_obj_id(env)); - return Qnil; + return Qnil; } +static int nxt_ruby_read_request(nxt_unit_request_info_t *req, VALUE hash_env) { + VALUE name; + uint32_t i; + nxt_unit_field_t *f; + nxt_unit_request_t *r; -static int -nxt_ruby_read_request(nxt_unit_request_info_t *req, VALUE hash_env) -{ - VALUE name; - uint32_t i; - nxt_unit_field_t *f; - nxt_unit_request_t *r; + r = req->request; - r = req->request; + nxt_ruby_add_sptr(hash_env, nxt_rb_request_method_str, &r->method, + r->method_length); + nxt_ruby_add_sptr(hash_env, nxt_rb_request_uri_str, &r->target, + r->target_length); + nxt_ruby_add_sptr(hash_env, nxt_rb_path_info_str, &r->path, r->path_length); + nxt_ruby_add_sptr(hash_env, nxt_rb_query_string_str, &r->query, + r->query_length); + nxt_ruby_add_sptr(hash_env, nxt_rb_server_protocol_str, &r->version, + r->version_length); + nxt_ruby_add_sptr(hash_env, nxt_rb_remote_addr_str, &r->remote, + r->remote_length); + nxt_ruby_add_sptr(hash_env, nxt_rb_server_addr_str, &r->local_addr, + r->local_addr_length); + nxt_ruby_add_sptr(hash_env, nxt_rb_server_name_str, &r->server_name, + r->server_name_length); - nxt_ruby_add_sptr(hash_env, nxt_rb_request_method_str, &r->method, - r->method_length); - nxt_ruby_add_sptr(hash_env, nxt_rb_request_uri_str, &r->target, - r->target_length); - nxt_ruby_add_sptr(hash_env, nxt_rb_path_info_str, &r->path, r->path_length); - nxt_ruby_add_sptr(hash_env, nxt_rb_query_string_str, &r->query, - r->query_length); - nxt_ruby_add_sptr(hash_env, nxt_rb_server_protocol_str, &r->version, - r->version_length); - nxt_ruby_add_sptr(hash_env, nxt_rb_remote_addr_str, &r->remote, - r->remote_length); - nxt_ruby_add_sptr(hash_env, nxt_rb_server_addr_str, &r->local_addr, - r->local_addr_length); - nxt_ruby_add_sptr(hash_env, nxt_rb_server_name_str, &r->server_name, - r->server_name_length); + rb_hash_aset(hash_env, nxt_rb_server_port_str, nxt_rb_80_str); - rb_hash_aset(hash_env, nxt_rb_server_port_str, nxt_rb_80_str); + rb_hash_aset(hash_env, nxt_rb_rack_url_scheme_str, + r->tls ? nxt_rb_https_str : nxt_rb_http_str); - rb_hash_aset(hash_env, nxt_rb_rack_url_scheme_str, - r->tls ? nxt_rb_https_str : nxt_rb_http_str); + for (i = 0; i < r->fields_count; i++) { + f = r->fields + i; - for (i = 0; i < r->fields_count; i++) { - f = r->fields + i; + name = rb_str_new(nxt_unit_sptr_get(&f->name), f->name_length); - name = rb_str_new(nxt_unit_sptr_get(&f->name), f->name_length); + nxt_ruby_add_sptr(hash_env, name, &f->value, f->value_length); + } - nxt_ruby_add_sptr(hash_env, name, &f->value, f->value_length); - } + if (r->content_length_field != NXT_UNIT_NONE_FIELD) { + f = r->fields + r->content_length_field; - if (r->content_length_field != NXT_UNIT_NONE_FIELD) { - f = r->fields + r->content_length_field; + nxt_ruby_add_sptr(hash_env, nxt_rb_content_length_str, &f->value, + f->value_length); + } - nxt_ruby_add_sptr(hash_env, nxt_rb_content_length_str, - &f->value, f->value_length); - } + if (r->content_type_field != NXT_UNIT_NONE_FIELD) { + f = r->fields + r->content_type_field; - if (r->content_type_field != NXT_UNIT_NONE_FIELD) { - f = r->fields + r->content_type_field; + nxt_ruby_add_sptr(hash_env, nxt_rb_content_type_str, &f->value, + f->value_length); + } - nxt_ruby_add_sptr(hash_env, nxt_rb_content_type_str, - &f->value, f->value_length); - } - - return NXT_UNIT_OK; + return NXT_UNIT_OK; } +nxt_inline void nxt_ruby_add_sptr(VALUE hash_env, VALUE name, + nxt_unit_sptr_t *sptr, uint32_t len) { + char *str; -nxt_inline void -nxt_ruby_add_sptr(VALUE hash_env, VALUE name, - nxt_unit_sptr_t *sptr, uint32_t len) -{ - char *str; - - str = nxt_unit_sptr_get(sptr); + str = nxt_unit_sptr_get(sptr); - rb_hash_aset(hash_env, name, rb_str_new(str, len)); + rb_hash_aset(hash_env, name, rb_str_new(str, len)); } +static nxt_int_t nxt_ruby_rack_result_status(nxt_unit_request_info_t *req, + VALUE result) { + VALUE status; -static nxt_int_t -nxt_ruby_rack_result_status(nxt_unit_request_info_t *req, VALUE result) -{ - VALUE status; - - status = rb_ary_entry(result, 0); + status = rb_ary_entry(result, 0); - if (TYPE(status) == T_FIXNUM) { - return FIX2INT(status); - } + if (TYPE(status) == T_FIXNUM) { + return FIX2INT(status); + } - if (TYPE(status) == T_STRING) { - return nxt_int_parse((u_char *) RSTRING_PTR(status), - RSTRING_LEN(status)); - } + if (TYPE(status) == T_STRING) { + return nxt_int_parse((u_char *)RSTRING_PTR(status), RSTRING_LEN(status)); + } - nxt_unit_req_error(req, "Ruby: Invalid response 'status' " - "format from application"); + nxt_unit_req_error(req, "Ruby: Invalid response 'status' " + "format from application"); - return -2; + return -2; } - typedef struct { - int rc; - uint32_t fields; - uint32_t size; - nxt_unit_request_info_t *req; + int rc; + uint32_t fields; + uint32_t size; + nxt_unit_request_info_t *req; } nxt_ruby_headers_info_t; +static int nxt_ruby_rack_result_headers(nxt_unit_request_info_t *req, + VALUE result, nxt_int_t status) { + int rc; + VALUE headers; + nxt_ruby_headers_info_t headers_info; + + headers = rb_ary_entry(result, 1); + if (nxt_slow_path(TYPE(headers) != T_HASH)) { + nxt_unit_req_error(req, "Ruby: Invalid response 'headers' format from " + "application"); + + return NXT_UNIT_ERROR; + } + + rc = NXT_UNIT_OK; + + headers_info.rc = NXT_UNIT_OK; + headers_info.fields = 0; + headers_info.size = 0; + headers_info.req = req; + + rb_hash_foreach(headers, nxt_ruby_hash_info, (VALUE)(uintptr_t)&headers_info); + if (nxt_slow_path(headers_info.rc != NXT_UNIT_OK)) { + return headers_info.rc; + } + + rc = nxt_unit_response_init(req, status, headers_info.fields, + headers_info.size); + if (nxt_slow_path(rc != NXT_UNIT_OK)) { + return rc; + } -static int -nxt_ruby_rack_result_headers(nxt_unit_request_info_t *req, VALUE result, - nxt_int_t status) -{ - int rc; - VALUE headers; - nxt_ruby_headers_info_t headers_info; - - headers = rb_ary_entry(result, 1); - if (nxt_slow_path(TYPE(headers) != T_HASH)) { - nxt_unit_req_error(req, - "Ruby: Invalid response 'headers' format from " - "application"); - - return NXT_UNIT_ERROR; - } + rb_hash_foreach(headers, nxt_ruby_hash_add, (VALUE)(uintptr_t)&headers_info); - rc = NXT_UNIT_OK; + return rc; +} - headers_info.rc = NXT_UNIT_OK; - headers_info.fields = 0; - headers_info.size = 0; - headers_info.req = req; +static int nxt_ruby_hash_info(VALUE r_key, VALUE r_value, VALUE arg) { + const char *value, *value_end, *pos; + nxt_ruby_headers_info_t *headers_info; - rb_hash_foreach(headers, nxt_ruby_hash_info, - (VALUE) (uintptr_t) &headers_info); - if (nxt_slow_path(headers_info.rc != NXT_UNIT_OK)) { - return headers_info.rc; - } + headers_info = (void *)(uintptr_t)arg; - rc = nxt_unit_response_init(req, status, - headers_info.fields, headers_info.size); - if (nxt_slow_path(rc != NXT_UNIT_OK)) { - return rc; - } + if (nxt_slow_path(TYPE(r_key) != T_STRING)) { + nxt_unit_req_error(headers_info->req, + "Ruby: Wrong header entry 'key' from application"); - rb_hash_foreach(headers, nxt_ruby_hash_add, - (VALUE) (uintptr_t) &headers_info); - - return rc; -} + goto fail; + } + if (nxt_slow_path(TYPE(r_value) != T_STRING && TYPE(r_value) != T_ARRAY)) { + nxt_unit_req_error(headers_info->req, + "Ruby: Wrong header entry 'value' from application"); -static int -nxt_ruby_hash_info(VALUE r_key, VALUE r_value, VALUE arg) -{ - const char *value, *value_end, *pos; - nxt_ruby_headers_info_t *headers_info; + goto fail; + } - headers_info = (void *) (uintptr_t) arg; + if (TYPE(r_value) == T_ARRAY) { + int i; + int arr_len = RARRAY_LEN(r_value); + VALUE item; + size_t len = 0; - if (nxt_slow_path(TYPE(r_key) != T_STRING)) { + for (i = 0; i < arr_len; i++) { + item = rb_ary_entry(r_value, i); + if (TYPE(item) != T_STRING) { nxt_unit_req_error(headers_info->req, - "Ruby: Wrong header entry 'key' from application"); - + "Ruby: Wrong header entry in 'value' array " + "from application"); goto fail; - } + } - if (nxt_slow_path(TYPE(r_value) != T_STRING && TYPE(r_value) != T_ARRAY)) { - nxt_unit_req_error(headers_info->req, - "Ruby: Wrong header entry 'value' from application"); + len += RSTRING_LEN(item) + 2; /* +2 for '; ' */ + } - goto fail; + if (arr_len > 0) { + len -= 2; } - if (TYPE(r_value) == T_ARRAY) { - int i; - int arr_len = RARRAY_LEN(r_value); - VALUE item; - size_t len = 0; + headers_info->fields++; + headers_info->size += RSTRING_LEN(r_key) + len; - for (i = 0; i < arr_len; i++) { - item = rb_ary_entry(r_value, i); - if (TYPE(item) != T_STRING) { - nxt_unit_req_error(headers_info->req, - "Ruby: Wrong header entry in 'value' array " - "from application"); - goto fail; - } + return ST_CONTINUE; + } - len += RSTRING_LEN(item) + 2; /* +2 for '; ' */ - } + value = RSTRING_PTR(r_value); + value_end = value + RSTRING_LEN(r_value); - if (arr_len > 0) { - len -= 2; - } + pos = value; - headers_info->fields++; - headers_info->size += RSTRING_LEN(r_key) + len; + for (;;) { + pos = strchr(pos, '\n'); - return ST_CONTINUE; + if (pos == NULL) { + break; } - value = RSTRING_PTR(r_value); - value_end = value + RSTRING_LEN(r_value); + headers_info->fields++; + headers_info->size += RSTRING_LEN(r_key) + (pos - value); - pos = value; + pos++; + value = pos; + } - for ( ;; ) { - pos = strchr(pos, '\n'); + if (value <= value_end) { + headers_info->fields++; + headers_info->size += RSTRING_LEN(r_key) + (value_end - value); + } - if (pos == NULL) { - break; - } - - headers_info->fields++; - headers_info->size += RSTRING_LEN(r_key) + (pos - value); - - pos++; - value = pos; - } - - if (value <= value_end) { - headers_info->fields++; - headers_info->size += RSTRING_LEN(r_key) + (value_end - value); - } - - return ST_CONTINUE; + return ST_CONTINUE; fail: - headers_info->rc = NXT_UNIT_ERROR; + headers_info->rc = NXT_UNIT_ERROR; - return ST_STOP; + return ST_STOP; } +static int nxt_ruby_hash_add(VALUE r_key, VALUE r_value, VALUE arg) { + int *rc; + uint32_t key_len; + const char *value, *value_end, *pos; + nxt_ruby_headers_info_t *headers_info; -static int -nxt_ruby_hash_add(VALUE r_key, VALUE r_value, VALUE arg) -{ - int *rc; - uint32_t key_len; - const char *value, *value_end, *pos; - nxt_ruby_headers_info_t *headers_info; - - headers_info = (void *) (uintptr_t) arg; - rc = &headers_info->rc; - - key_len = RSTRING_LEN(r_key); + headers_info = (void *)(uintptr_t)arg; + rc = &headers_info->rc; - if (TYPE(r_value) == T_ARRAY) { - int i; - int arr_len = RARRAY_LEN(r_value); - char *field, *p; - VALUE item; - size_t len = 0; + key_len = RSTRING_LEN(r_key); - for (i = 0; i < arr_len; i++) { - item = rb_ary_entry(r_value, i); + if (TYPE(r_value) == T_ARRAY) { + int i; + int arr_len = RARRAY_LEN(r_value); + char *field, *p; + VALUE item; + size_t len = 0; - len += RSTRING_LEN(item) + 2; /* +2 for '; ' */ - } + for (i = 0; i < arr_len; i++) { + item = rb_ary_entry(r_value, i); - field = nxt_unit_malloc(NULL, len); - if (field == NULL) { - goto fail; - } + len += RSTRING_LEN(item) + 2; /* +2 for '; ' */ + } - p = field; + field = nxt_unit_malloc(NULL, len); + if (field == NULL) { + goto fail; + } - for (i = 0; i < arr_len; i++) { - item = rb_ary_entry(r_value, i); + p = field; - p = nxt_cpymem(p, RSTRING_PTR(item), RSTRING_LEN(item)); - p = nxt_cpymem(p, "; ", 2); - } + for (i = 0; i < arr_len; i++) { + item = rb_ary_entry(r_value, i); - if (arr_len > 0) { - len -= 2; - } + p = nxt_cpymem(p, RSTRING_PTR(item), RSTRING_LEN(item)); + p = nxt_cpymem(p, "; ", 2); + } - *rc = nxt_unit_response_add_field(headers_info->req, - RSTRING_PTR(r_key), key_len, - field, len); - nxt_unit_free(NULL, field); + if (arr_len > 0) { + len -= 2; + } - if (nxt_slow_path(*rc != NXT_UNIT_OK)) { - goto fail; - } + *rc = nxt_unit_response_add_field(headers_info->req, RSTRING_PTR(r_key), + key_len, field, len); + nxt_unit_free(NULL, field); - return ST_CONTINUE; + if (nxt_slow_path(*rc != NXT_UNIT_OK)) { + goto fail; } - value = RSTRING_PTR(r_value); - value_end = value + RSTRING_LEN(r_value); + return ST_CONTINUE; + } - pos = value; + value = RSTRING_PTR(r_value); + value_end = value + RSTRING_LEN(r_value); - for ( ;; ) { - pos = strchr(pos, '\n'); + pos = value; - if (pos == NULL) { - break; - } + for (;;) { + pos = strchr(pos, '\n'); - *rc = nxt_unit_response_add_field(headers_info->req, - RSTRING_PTR(r_key), key_len, - value, pos - value); - if (nxt_slow_path(*rc != NXT_UNIT_OK)) { - goto fail; - } + if (pos == NULL) { + break; + } - pos++; - value = pos; + *rc = nxt_unit_response_add_field(headers_info->req, RSTRING_PTR(r_key), + key_len, value, pos - value); + if (nxt_slow_path(*rc != NXT_UNIT_OK)) { + goto fail; } - if (value <= value_end) { - *rc = nxt_unit_response_add_field(headers_info->req, - RSTRING_PTR(r_key), key_len, - value, value_end - value); - if (nxt_slow_path(*rc != NXT_UNIT_OK)) { - goto fail; - } + pos++; + value = pos; + } + + if (value <= value_end) { + *rc = nxt_unit_response_add_field(headers_info->req, RSTRING_PTR(r_key), + key_len, value, value_end - value); + if (nxt_slow_path(*rc != NXT_UNIT_OK)) { + goto fail; } + } - return ST_CONTINUE; + return ST_CONTINUE; fail: - *rc = NXT_UNIT_ERROR; + *rc = NXT_UNIT_ERROR; - return ST_STOP; + return ST_STOP; } +static int nxt_ruby_rack_result_body(nxt_unit_request_info_t *req, + VALUE result) { + int rc; + VALUE fn, body; -static int -nxt_ruby_rack_result_body(nxt_unit_request_info_t *req, VALUE result) -{ - int rc; - VALUE fn, body; - - body = rb_ary_entry(result, 2); + body = rb_ary_entry(result, 2); - if (rb_respond_to(body, rb_intern("to_path"))) { + if (rb_respond_to(body, rb_intern("to_path"))) { - fn = rb_funcall(body, rb_intern("to_path"), 0); - if (nxt_slow_path(TYPE(fn) != T_STRING)) { - nxt_unit_req_error(req, - "Ruby: Failed to get 'body' file path from " - "application"); + fn = rb_funcall(body, rb_intern("to_path"), 0); + if (nxt_slow_path(TYPE(fn) != T_STRING)) { + nxt_unit_req_error(req, "Ruby: Failed to get 'body' file path from " + "application"); - return NXT_UNIT_ERROR; - } + return NXT_UNIT_ERROR; + } - rc = nxt_ruby_rack_result_body_file_write(req, fn); - if (nxt_slow_path(rc != NXT_UNIT_OK)) { - return rc; - } + rc = nxt_ruby_rack_result_body_file_write(req, fn); + if (nxt_slow_path(rc != NXT_UNIT_OK)) { + return rc; + } - } else if (rb_respond_to(body, rb_intern("each"))) { - rb_block_call(body, rb_intern("each"), 0, 0, - nxt_ruby_rack_result_body_each, (VALUE) (uintptr_t) req); + } else if (rb_respond_to(body, rb_intern("each"))) { + rb_block_call(body, rb_intern("each"), 0, 0, nxt_ruby_rack_result_body_each, + (VALUE)(uintptr_t)req); - } else { - nxt_unit_req_error(req, - "Ruby: Invalid response 'body' format " - "from application"); + } else { + nxt_unit_req_error(req, "Ruby: Invalid response 'body' format " + "from application"); - return NXT_UNIT_ERROR; - } + return NXT_UNIT_ERROR; + } - if (rb_respond_to(body, rb_intern("close"))) { - rb_funcall(body, rb_intern("close"), 0); - } + if (rb_respond_to(body, rb_intern("close"))) { + rb_funcall(body, rb_intern("close"), 0); + } - return NXT_UNIT_OK; + return NXT_UNIT_OK; } - typedef struct { - int fd; - off_t pos; - off_t rest; + int fd; + off_t pos; + off_t rest; } nxt_ruby_rack_file_t; +static ssize_t nxt_ruby_rack_file_read(nxt_unit_read_info_t *read_info, + void *dst, size_t size) { + ssize_t res; + nxt_ruby_rack_file_t *file; -static ssize_t -nxt_ruby_rack_file_read(nxt_unit_read_info_t *read_info, void *dst, size_t size) -{ - ssize_t res; - nxt_ruby_rack_file_t *file; - - file = read_info->data; + file = read_info->data; - size = nxt_min(size, (size_t) file->rest); + size = nxt_min(size, (size_t)file->rest); - res = pread(file->fd, dst, size, file->pos); + res = pread(file->fd, dst, size, file->pos); - if (res >= 0) { - file->pos += res; - file->rest -= res; + if (res >= 0) { + file->pos += res; + file->rest -= res; - if (size > (size_t) res) { - file->rest = 0; - } + if (size > (size_t)res) { + file->rest = 0; } + } - read_info->eof = file->rest == 0; + read_info->eof = file->rest == 0; - return res; + return res; } - typedef struct { - nxt_unit_read_info_t read_info; - nxt_unit_request_info_t *req; + nxt_unit_read_info_t read_info; + nxt_unit_request_info_t *req; } nxt_ruby_read_info_t; +static int nxt_ruby_rack_result_body_file_write(nxt_unit_request_info_t *req, + VALUE filepath) { + int fd, rc; + struct stat finfo; + nxt_ruby_rack_file_t ruby_file; + nxt_ruby_read_info_t ri; -static int -nxt_ruby_rack_result_body_file_write(nxt_unit_request_info_t *req, - VALUE filepath) -{ - int fd, rc; - struct stat finfo; - nxt_ruby_rack_file_t ruby_file; - nxt_ruby_read_info_t ri; + fd = open(RSTRING_PTR(filepath), O_RDONLY, 0); + if (nxt_slow_path(fd == -1)) { + nxt_unit_req_error(req, "Ruby: Failed to open content file \"%s\": %s (%d)", + RSTRING_PTR(filepath), strerror(errno), errno); - fd = open(RSTRING_PTR(filepath), O_RDONLY, 0); - if (nxt_slow_path(fd == -1)) { - nxt_unit_req_error(req, - "Ruby: Failed to open content file \"%s\": %s (%d)", - RSTRING_PTR(filepath), strerror(errno), errno); + return NXT_UNIT_ERROR; + } - return NXT_UNIT_ERROR; - } + rc = fstat(fd, &finfo); + if (nxt_slow_path(rc == -1)) { + nxt_unit_req_error(req, "Ruby: Content file fstat(\"%s\") failed: %s (%d)", + RSTRING_PTR(filepath), strerror(errno), errno); - rc = fstat(fd, &finfo); - if (nxt_slow_path(rc == -1)) { - nxt_unit_req_error(req, - "Ruby: Content file fstat(\"%s\") failed: %s (%d)", - RSTRING_PTR(filepath), strerror(errno), errno); + close(fd); - close(fd); + return NXT_UNIT_ERROR; + } - return NXT_UNIT_ERROR; - } + ruby_file.fd = fd; + ruby_file.pos = 0; + ruby_file.rest = finfo.st_size; - ruby_file.fd = fd; - ruby_file.pos = 0; - ruby_file.rest = finfo.st_size; + ri.read_info.read = nxt_ruby_rack_file_read; + ri.read_info.eof = ruby_file.rest == 0; + ri.read_info.buf_size = ruby_file.rest; + ri.read_info.data = &ruby_file; + ri.req = req; - ri.read_info.read = nxt_ruby_rack_file_read; - ri.read_info.eof = ruby_file.rest == 0; - ri.read_info.buf_size = ruby_file.rest; - ri.read_info.data = &ruby_file; - ri.req = req; + rc = (intptr_t)rb_thread_call_without_gvl(nxt_ruby_response_write_cb, &ri, + nxt_ruby_ubf, req->ctx); - rc = (intptr_t) rb_thread_call_without_gvl(nxt_ruby_response_write_cb, - &ri, - nxt_ruby_ubf, - req->ctx); + close(fd); - close(fd); - - return rc; + return rc; } +static void *nxt_ruby_response_write_cb(void *data) { + int rc; + nxt_ruby_read_info_t *ri; -static void * -nxt_ruby_response_write_cb(void *data) -{ - int rc; - nxt_ruby_read_info_t *ri; + ri = data; - ri = data; + rc = nxt_unit_response_write_cb(ri->req, &ri->read_info); + if (nxt_slow_path(rc != NXT_UNIT_OK)) { + nxt_unit_req_error(ri->req, "Ruby: Failed to write content file."); + } - rc = nxt_unit_response_write_cb(ri->req, &ri->read_info); - if (nxt_slow_path(rc != NXT_UNIT_OK)) { - nxt_unit_req_error(ri->req, "Ruby: Failed to write content file."); - } - - return (void *) (intptr_t) rc; + return (void *)(intptr_t)rc; } - typedef struct { - VALUE body; - nxt_unit_request_info_t *req; + VALUE body; + nxt_unit_request_info_t *req; } nxt_ruby_write_info_t; +static VALUE nxt_ruby_rack_result_body_each(VALUE body, VALUE arg, int argc, + const VALUE *argv, VALUE blockarg) { + nxt_ruby_write_info_t wi; -static VALUE -nxt_ruby_rack_result_body_each(VALUE body, VALUE arg, int argc, - const VALUE *argv, VALUE blockarg) -{ - nxt_ruby_write_info_t wi; - - if (TYPE(body) != T_STRING) { - return Qnil; - } + if (TYPE(body) != T_STRING) { + return Qnil; + } - wi.body = body; - wi.req = (void *) (uintptr_t) arg; + wi.body = body; + wi.req = (void *)(uintptr_t)arg; - (void) rb_thread_call_without_gvl(nxt_ruby_response_write, - (void *) (uintptr_t) &wi, - nxt_ruby_ubf, wi.req->ctx); + (void)rb_thread_call_without_gvl(nxt_ruby_response_write, + (void *)(uintptr_t)&wi, nxt_ruby_ubf, + wi.req->ctx); - return Qnil; + return Qnil; } +static void *nxt_ruby_response_write(void *data) { + int rc; + nxt_ruby_write_info_t *wi; -static void * -nxt_ruby_response_write(void *data) -{ - int rc; - nxt_ruby_write_info_t *wi; + wi = data; - wi = data; - - rc = nxt_unit_response_write(wi->req, RSTRING_PTR(wi->body), - RSTRING_LEN(wi->body)); - if (nxt_slow_path(rc != NXT_UNIT_OK)) { - nxt_unit_req_error(wi->req, - "Ruby: Failed to write 'body' from application"); - } + rc = nxt_unit_response_write(wi->req, RSTRING_PTR(wi->body), + RSTRING_LEN(wi->body)); + if (nxt_slow_path(rc != NXT_UNIT_OK)) { + nxt_unit_req_error(wi->req, + "Ruby: Failed to write 'body' from application"); + } - return (void *) (intptr_t) rc; + return (void *)(intptr_t)rc; } +static void nxt_ruby_exception_log(nxt_unit_request_info_t *req, uint32_t level, + const char *desc) { + int i; + VALUE err, ary, eclass, msg; -static void -nxt_ruby_exception_log(nxt_unit_request_info_t *req, uint32_t level, - const char *desc) -{ - int i; - VALUE err, ary, eclass, msg; + nxt_unit_req_log(req, level, "Ruby: %s", desc); - nxt_unit_req_log(req, level, "Ruby: %s", desc); + err = rb_errinfo(); + if (nxt_slow_path(err == Qnil)) { + return; + } - err = rb_errinfo(); - if (nxt_slow_path(err == Qnil)) { - return; - } + eclass = rb_class_name(rb_class_of(err)); - eclass = rb_class_name(rb_class_of(err)); + msg = rb_funcall(err, rb_intern("message"), 0); + ary = rb_funcall(err, rb_intern("backtrace"), 0); - msg = rb_funcall(err, rb_intern("message"), 0); - ary = rb_funcall(err, rb_intern("backtrace"), 0); + if (RARRAY_LEN(ary) == 0) { + nxt_unit_req_log(req, level, "Ruby: %s (%s)", RSTRING_PTR(msg), + RSTRING_PTR(eclass)); - if (RARRAY_LEN(ary) == 0) { - nxt_unit_req_log(req, level, "Ruby: %s (%s)", RSTRING_PTR(msg), - RSTRING_PTR(eclass)); - - return; - } + return; + } - nxt_unit_req_log(req, level, "Ruby: %s: %s (%s)", - RSTRING_PTR(RARRAY_PTR(ary)[0]), - RSTRING_PTR(msg), RSTRING_PTR(eclass)); + nxt_unit_req_log(req, level, "Ruby: %s: %s (%s)", + RSTRING_PTR(RARRAY_PTR(ary)[0]), RSTRING_PTR(msg), + RSTRING_PTR(eclass)); - for (i = 1; i < RARRAY_LEN(ary); i++) { - nxt_unit_req_log(req, level, "from %s", - RSTRING_PTR(RARRAY_PTR(ary)[i])); - } + for (i = 1; i < RARRAY_LEN(ary); i++) { + nxt_unit_req_log(req, level, "from %s", RSTRING_PTR(RARRAY_PTR(ary)[i])); + } } +static void nxt_ruby_ctx_done(nxt_ruby_ctx_t *rctx) { + if (rctx->io_input != Qnil) { + rb_gc_unregister_address(&rctx->io_input); + } -static void -nxt_ruby_ctx_done(nxt_ruby_ctx_t *rctx) -{ - if (rctx->io_input != Qnil) { - rb_gc_unregister_address(&rctx->io_input); - } + if (rctx->io_error != Qnil) { + rb_gc_unregister_address(&rctx->io_error); + } - if (rctx->io_error != Qnil) { - rb_gc_unregister_address(&rctx->io_error); - } - - if (rctx->env != Qnil) { - rb_gc_unregister_address(&rctx->env); - } + if (rctx->env != Qnil) { + rb_gc_unregister_address(&rctx->env); + } } +static void nxt_ruby_atexit(void) { + if (nxt_ruby_rackup != Qnil) { + rb_gc_unregister_address(&nxt_ruby_rackup); + } -static void -nxt_ruby_atexit(void) -{ - if (nxt_ruby_rackup != Qnil) { - rb_gc_unregister_address(&nxt_ruby_rackup); - } - - if (nxt_ruby_call != Qnil) { - rb_gc_unregister_address(&nxt_ruby_call); - } + if (nxt_ruby_call != Qnil) { + rb_gc_unregister_address(&nxt_ruby_call); + } - if (nxt_ruby_hook_procs != Qnil) { - rb_gc_unregister_address(&nxt_ruby_hook_procs); - } + if (nxt_ruby_hook_procs != Qnil) { + rb_gc_unregister_address(&nxt_ruby_hook_procs); + } - nxt_ruby_done_strings(); + nxt_ruby_done_strings(); - ruby_cleanup(0); + ruby_cleanup(0); } +static int nxt_ruby_ready_handler(nxt_unit_ctx_t *ctx) { + VALUE res; + uint32_t i; + nxt_ruby_ctx_t *rctx; + nxt_ruby_app_conf_t *c; -static int -nxt_ruby_ready_handler(nxt_unit_ctx_t *ctx) -{ - VALUE res; - uint32_t i; - nxt_ruby_ctx_t *rctx; - nxt_ruby_app_conf_t *c; + c = ctx->unit->data; - c = ctx->unit->data; - - if (c->threads <= 1) { - return NXT_UNIT_OK; - } + if (c->threads <= 1) { + return NXT_UNIT_OK; + } - for (i = 0; i < c->threads - 1; i++) { - rctx = &nxt_ruby_ctxs[i]; + for (i = 0; i < c->threads - 1; i++) { + rctx = &nxt_ruby_ctxs[i]; - rctx->ctx = ctx; + rctx->ctx = ctx; - res = (VALUE) rb_thread_call_with_gvl(nxt_ruby_thread_create_gvl, rctx); + res = (VALUE)rb_thread_call_with_gvl(nxt_ruby_thread_create_gvl, rctx); - if (nxt_fast_path(res != Qnil)) { - nxt_unit_debug(ctx, "thread #%d created", (int) (i + 1)); + if (nxt_fast_path(res != Qnil)) { + nxt_unit_debug(ctx, "thread #%d created", (int)(i + 1)); - rctx->thread = res; + rctx->thread = res; - } else { - nxt_unit_alert(ctx, "thread #%d create failed", (int) (i + 1)); + } else { + nxt_unit_alert(ctx, "thread #%d create failed", (int)(i + 1)); - return NXT_UNIT_ERROR; - } + return NXT_UNIT_ERROR; } + } - return NXT_UNIT_OK; + return NXT_UNIT_OK; } +static void *nxt_ruby_thread_create_gvl(void *rctx) { + VALUE res; -static void * -nxt_ruby_thread_create_gvl(void *rctx) -{ - VALUE res; - - res = rb_thread_create(RUBY_METHOD_FUNC(nxt_ruby_thread_func), rctx); + res = rb_thread_create(RUBY_METHOD_FUNC(nxt_ruby_thread_func), rctx); - return (void *) (uintptr_t) res; + return (void *)(uintptr_t)res; } +static VALUE nxt_ruby_thread_func(VALUE arg) { + int state; + nxt_unit_ctx_t *ctx; + nxt_ruby_ctx_t *rctx; -static VALUE -nxt_ruby_thread_func(VALUE arg) -{ - int state; - nxt_unit_ctx_t *ctx; - nxt_ruby_ctx_t *rctx; + rctx = (nxt_ruby_ctx_t *)(uintptr_t)arg; - rctx = (nxt_ruby_ctx_t *) (uintptr_t) arg; + nxt_unit_debug(rctx->ctx, "worker thread start"); - nxt_unit_debug(rctx->ctx, "worker thread start"); + ctx = nxt_unit_ctx_alloc(rctx->ctx, rctx); + if (nxt_slow_path(ctx == NULL)) { + goto fail; + } - ctx = nxt_unit_ctx_alloc(rctx->ctx, rctx); - if (nxt_slow_path(ctx == NULL)) { - goto fail; - } - - if (nxt_ruby_hook_procs != Qnil) { - rb_protect(nxt_ruby_hook_call, nxt_rb_on_thread_boot, &state); - if (nxt_slow_path(state != 0)) { - nxt_ruby_exception_log(NULL, NXT_LOG_ERR, - "Failed to call on_thread_boot()"); - } + if (nxt_ruby_hook_procs != Qnil) { + rb_protect(nxt_ruby_hook_call, nxt_rb_on_thread_boot, &state); + if (nxt_slow_path(state != 0)) { + nxt_ruby_exception_log(NULL, NXT_LOG_ERR, + "Failed to call on_thread_boot()"); } + } - (void) rb_thread_call_without_gvl(nxt_ruby_unit_run, ctx, - nxt_ruby_ubf, ctx); + (void)rb_thread_call_without_gvl(nxt_ruby_unit_run, ctx, nxt_ruby_ubf, ctx); - if (nxt_ruby_hook_procs != Qnil) { - rb_protect(nxt_ruby_hook_call, nxt_rb_on_thread_shutdown, &state); - if (nxt_slow_path(state != 0)) { - nxt_ruby_exception_log(NULL, NXT_LOG_ERR, - "Failed to call on_thread_shutdown()"); - } + if (nxt_ruby_hook_procs != Qnil) { + rb_protect(nxt_ruby_hook_call, nxt_rb_on_thread_shutdown, &state); + if (nxt_slow_path(state != 0)) { + nxt_ruby_exception_log(NULL, NXT_LOG_ERR, + "Failed to call on_thread_shutdown()"); } + } - nxt_unit_done(ctx); + nxt_unit_done(ctx); fail: - nxt_unit_debug(NULL, "worker thread end"); + nxt_unit_debug(NULL, "worker thread end"); - return Qnil; + return Qnil; } - -static void * -nxt_ruby_unit_run(void *ctx) -{ - return (void *) (intptr_t) nxt_unit_run(ctx); +static void *nxt_ruby_unit_run(void *ctx) { + return (void *)(intptr_t)nxt_unit_run(ctx); } +static void nxt_ruby_ubf(void *ctx) { nxt_unit_warn(ctx, "Ruby: UBF"); } -static void -nxt_ruby_ubf(void *ctx) -{ - nxt_unit_warn(ctx, "Ruby: UBF"); -} - - -static int -nxt_ruby_init_threads(nxt_ruby_app_conf_t *c) -{ - int state; - uint32_t i; - nxt_ruby_ctx_t *rctx; +static int nxt_ruby_init_threads(nxt_ruby_app_conf_t *c) { + int state; + uint32_t i; + nxt_ruby_ctx_t *rctx; - if (c->threads <= 1) { - return NXT_UNIT_OK; - } + if (c->threads <= 1) { + return NXT_UNIT_OK; + } - nxt_ruby_ctxs = nxt_unit_malloc(NULL, sizeof(nxt_ruby_ctx_t) - * (c->threads - 1)); - if (nxt_slow_path(nxt_ruby_ctxs == NULL)) { - nxt_unit_alert(NULL, "Failed to allocate run contexts array"); + nxt_ruby_ctxs = + nxt_unit_malloc(NULL, sizeof(nxt_ruby_ctx_t) * (c->threads - 1)); + if (nxt_slow_path(nxt_ruby_ctxs == NULL)) { + nxt_unit_alert(NULL, "Failed to allocate run contexts array"); - return NXT_UNIT_ERROR; - } + return NXT_UNIT_ERROR; + } - for (i = 0; i < c->threads - 1; i++) { - rctx = &nxt_ruby_ctxs[i]; + for (i = 0; i < c->threads - 1; i++) { + rctx = &nxt_ruby_ctxs[i]; - rctx->env = Qnil; - rctx->io_input = Qnil; - rctx->io_error = Qnil; - rctx->thread = Qnil; - } + rctx->env = Qnil; + rctx->io_input = Qnil; + rctx->io_error = Qnil; + rctx->thread = Qnil; + } - for (i = 0; i < c->threads - 1; i++) { - rctx = &nxt_ruby_ctxs[i]; + for (i = 0; i < c->threads - 1; i++) { + rctx = &nxt_ruby_ctxs[i]; - rctx->env = rb_protect(nxt_ruby_rack_env_create, - (VALUE) (uintptr_t) rctx, &state); - if (nxt_slow_path(rctx->env == Qnil || state != 0)) { - nxt_ruby_exception_log(NULL, NXT_LOG_ALERT, - "Failed to create 'environ' variable"); - return NXT_UNIT_ERROR; - } + rctx->env = + rb_protect(nxt_ruby_rack_env_create, (VALUE)(uintptr_t)rctx, &state); + if (nxt_slow_path(rctx->env == Qnil || state != 0)) { + nxt_ruby_exception_log(NULL, NXT_LOG_ALERT, + "Failed to create 'environ' variable"); + return NXT_UNIT_ERROR; } + } - return NXT_UNIT_OK; + return NXT_UNIT_OK; } +static void nxt_ruby_join_threads(nxt_unit_ctx_t *ctx, nxt_ruby_app_conf_t *c) { + uint32_t i; + nxt_ruby_ctx_t *rctx; -static void -nxt_ruby_join_threads(nxt_unit_ctx_t *ctx, nxt_ruby_app_conf_t *c) -{ - uint32_t i; - nxt_ruby_ctx_t *rctx; - - if (nxt_ruby_ctxs == NULL) { - return; - } + if (nxt_ruby_ctxs == NULL) { + return; + } - for (i = 0; i < c->threads - 1; i++) { - rctx = &nxt_ruby_ctxs[i]; + for (i = 0; i < c->threads - 1; i++) { + rctx = &nxt_ruby_ctxs[i]; - if (rctx->thread != Qnil) { - rb_funcall(rctx->thread, rb_intern("join"), 0); + if (rctx->thread != Qnil) { + rb_funcall(rctx->thread, rb_intern("join"), 0); - nxt_unit_debug(ctx, "thread #%d joined", (int) (i + 1)); + nxt_unit_debug(ctx, "thread #%d joined", (int)(i + 1)); - } else { - nxt_unit_debug(ctx, "thread #%d not started", (int) (i + 1)); - } + } else { + nxt_unit_debug(ctx, "thread #%d not started", (int)(i + 1)); } + } - for (i = 0; i < c->threads - 1; i++) { - nxt_ruby_ctx_done(&nxt_ruby_ctxs[i]); - } + for (i = 0; i < c->threads - 1; i++) { + nxt_ruby_ctx_done(&nxt_ruby_ctxs[i]); + } - nxt_unit_free(ctx, nxt_ruby_ctxs); + nxt_unit_free(ctx, nxt_ruby_ctxs); } diff --git a/src/ruby/nxt_ruby.h b/src/ruby/nxt_ruby.h index 264300213..57aafc3af 100644 --- a/src/ruby/nxt_ruby.h +++ b/src/ruby/nxt_ruby.h @@ -7,7 +7,6 @@ #ifndef _NXT_RUBY_H_INCLUDED_ #define _NXT_RUBY_H_INCLUDED_ - #include #include #include @@ -19,17 +18,15 @@ #include #include - typedef struct { - VALUE env; - VALUE io_input; - VALUE io_error; - VALUE thread; - nxt_unit_ctx_t *ctx; - nxt_unit_request_info_t *req; + VALUE env; + VALUE io_input; + VALUE io_error; + VALUE thread; + nxt_unit_ctx_t *ctx; + nxt_unit_request_info_t *req; } nxt_ruby_ctx_t; - VALUE nxt_ruby_stream_io_input_init(void); VALUE nxt_ruby_stream_io_error_init(void); diff --git a/src/ruby/nxt_ruby_stream_io.c b/src/ruby/nxt_ruby_stream_io.c index 4ef69cee1..1bb9072f8 100644 --- a/src/ruby/nxt_ruby_stream_io.c +++ b/src/ruby/nxt_ruby_stream_io.c @@ -7,7 +7,6 @@ #include #include - static VALUE nxt_ruby_stream_io_new(VALUE class, VALUE arg); static VALUE nxt_ruby_stream_io_initialize(int argc, VALUE *argv, VALUE self); static VALUE nxt_ruby_stream_io_gets(VALUE obj); @@ -20,250 +19,205 @@ nxt_inline long nxt_ruby_stream_io_s_write(nxt_ruby_ctx_t *rctx, VALUE val); static VALUE nxt_ruby_stream_io_flush(VALUE obj); static VALUE nxt_ruby_stream_io_close(VALUE obj); - VALUE -nxt_ruby_stream_io_input_init(void) -{ - VALUE stream_io; +nxt_ruby_stream_io_input_init(void) { + VALUE stream_io; - stream_io = rb_define_class("NGINX_Unit_Stream_IO_Read", rb_cObject); + stream_io = rb_define_class("NGINX_Unit_Stream_IO_Read", rb_cObject); - rb_undef_alloc_func(stream_io); + rb_undef_alloc_func(stream_io); - rb_gc_register_address(&stream_io); + rb_gc_register_address(&stream_io); - rb_define_singleton_method(stream_io, "new", nxt_ruby_stream_io_new, 1); - rb_define_method(stream_io, "initialize", - nxt_ruby_stream_io_initialize, -1); - rb_define_method(stream_io, "gets", nxt_ruby_stream_io_gets, 0); - rb_define_method(stream_io, "each", nxt_ruby_stream_io_each, 0); - rb_define_method(stream_io, "read", nxt_ruby_stream_io_read, -2); - rb_define_method(stream_io, "rewind", nxt_ruby_stream_io_rewind, 0); - rb_define_method(stream_io, "close", nxt_ruby_stream_io_close, 0); + rb_define_singleton_method(stream_io, "new", nxt_ruby_stream_io_new, 1); + rb_define_method(stream_io, "initialize", nxt_ruby_stream_io_initialize, -1); + rb_define_method(stream_io, "gets", nxt_ruby_stream_io_gets, 0); + rb_define_method(stream_io, "each", nxt_ruby_stream_io_each, 0); + rb_define_method(stream_io, "read", nxt_ruby_stream_io_read, -2); + rb_define_method(stream_io, "rewind", nxt_ruby_stream_io_rewind, 0); + rb_define_method(stream_io, "close", nxt_ruby_stream_io_close, 0); - return stream_io; + return stream_io; } - VALUE -nxt_ruby_stream_io_error_init(void) -{ - VALUE stream_io; +nxt_ruby_stream_io_error_init(void) { + VALUE stream_io; - stream_io = rb_define_class("NGINX_Unit_Stream_IO_Error", rb_cObject); + stream_io = rb_define_class("NGINX_Unit_Stream_IO_Error", rb_cObject); - rb_undef_alloc_func(stream_io); + rb_undef_alloc_func(stream_io); - rb_gc_register_address(&stream_io); + rb_gc_register_address(&stream_io); - rb_define_singleton_method(stream_io, "new", nxt_ruby_stream_io_new, 1); - rb_define_method(stream_io, "initialize", - nxt_ruby_stream_io_initialize, -1); - rb_define_method(stream_io, "puts", nxt_ruby_stream_io_puts, -2); - rb_define_method(stream_io, "write", nxt_ruby_stream_io_write, -2); - rb_define_method(stream_io, "flush", nxt_ruby_stream_io_flush, 0); - rb_define_method(stream_io, "close", nxt_ruby_stream_io_close, 0); + rb_define_singleton_method(stream_io, "new", nxt_ruby_stream_io_new, 1); + rb_define_method(stream_io, "initialize", nxt_ruby_stream_io_initialize, -1); + rb_define_method(stream_io, "puts", nxt_ruby_stream_io_puts, -2); + rb_define_method(stream_io, "write", nxt_ruby_stream_io_write, -2); + rb_define_method(stream_io, "flush", nxt_ruby_stream_io_flush, 0); + rb_define_method(stream_io, "close", nxt_ruby_stream_io_close, 0); - return stream_io; + return stream_io; } +static VALUE nxt_ruby_stream_io_new(VALUE class, VALUE arg) { + VALUE self; -static VALUE -nxt_ruby_stream_io_new(VALUE class, VALUE arg) -{ - VALUE self; + self = Data_Wrap_Struct(class, 0, 0, (void *)(uintptr_t)arg); - self = Data_Wrap_Struct(class, 0, 0, (void *) (uintptr_t) arg); + rb_obj_call_init(self, 0, NULL); - rb_obj_call_init(self, 0, NULL); - - return self; + return self; } - -static VALUE -nxt_ruby_stream_io_initialize(int argc, VALUE *argv, VALUE self) -{ - return self; +static VALUE nxt_ruby_stream_io_initialize(int argc, VALUE *argv, VALUE self) { + return self; } +static VALUE nxt_ruby_stream_io_gets(VALUE obj) { + VALUE buf; + ssize_t res; + nxt_ruby_ctx_t *rctx; + nxt_unit_request_info_t *req; -static VALUE -nxt_ruby_stream_io_gets(VALUE obj) -{ - VALUE buf; - ssize_t res; - nxt_ruby_ctx_t *rctx; - nxt_unit_request_info_t *req; + Data_Get_Struct(obj, nxt_ruby_ctx_t, rctx); + req = rctx->req; - Data_Get_Struct(obj, nxt_ruby_ctx_t, rctx); - req = rctx->req; - - if (req->content_length == 0) { - return Qnil; - } + if (req->content_length == 0) { + return Qnil; + } - res = nxt_unit_request_readline_size(req, SSIZE_MAX); - if (nxt_slow_path(res < 0)) { - return Qnil; - } + res = nxt_unit_request_readline_size(req, SSIZE_MAX); + if (nxt_slow_path(res < 0)) { + return Qnil; + } - buf = rb_str_buf_new(res); + buf = rb_str_buf_new(res); - if (nxt_slow_path(buf == Qnil)) { - return Qnil; - } + if (nxt_slow_path(buf == Qnil)) { + return Qnil; + } - res = nxt_unit_request_read(req, RSTRING_PTR(buf), res); + res = nxt_unit_request_read(req, RSTRING_PTR(buf), res); - rb_str_set_len(buf, res); + rb_str_set_len(buf, res); - return buf; + return buf; } +static VALUE nxt_ruby_stream_io_each(VALUE obj) { + VALUE chunk; -static VALUE -nxt_ruby_stream_io_each(VALUE obj) -{ - VALUE chunk; - - if (rb_block_given_p() == 0) { - rb_raise(rb_eArgError, "Expected block on rack.input 'each' method"); - } - - for ( ;; ) { - chunk = nxt_ruby_stream_io_gets(obj); + if (rb_block_given_p() == 0) { + rb_raise(rb_eArgError, "Expected block on rack.input 'each' method"); + } - if (chunk == Qnil) { - return Qnil; - } + for (;;) { + chunk = nxt_ruby_stream_io_gets(obj); - rb_yield(chunk); + if (chunk == Qnil) { + return Qnil; } - return Qnil; -} - + rb_yield(chunk); + } -static VALUE -nxt_ruby_stream_io_read(VALUE obj, VALUE args) -{ - VALUE buf; - long copy_size, u_size; - nxt_ruby_ctx_t *rctx; + return Qnil; +} - Data_Get_Struct(obj, nxt_ruby_ctx_t, rctx); +static VALUE nxt_ruby_stream_io_read(VALUE obj, VALUE args) { + VALUE buf; + long copy_size, u_size; + nxt_ruby_ctx_t *rctx; - copy_size = rctx->req->content_length; + Data_Get_Struct(obj, nxt_ruby_ctx_t, rctx); - if (RARRAY_LEN(args) > 0 && TYPE(RARRAY_PTR(args)[0]) == T_FIXNUM) { - u_size = NUM2LONG(RARRAY_PTR(args)[0]); + copy_size = rctx->req->content_length; - if (u_size < 0 || copy_size == 0) { - return Qnil; - } + if (RARRAY_LEN(args) > 0 && TYPE(RARRAY_PTR(args)[0]) == T_FIXNUM) { + u_size = NUM2LONG(RARRAY_PTR(args)[0]); - if (copy_size > u_size) { - copy_size = u_size; - } + if (u_size < 0 || copy_size == 0) { + return Qnil; } - if (copy_size == 0) { - return rb_str_new_cstr(""); + if (copy_size > u_size) { + copy_size = u_size; } + } - buf = rb_str_buf_new(copy_size); + if (copy_size == 0) { + return rb_str_new_cstr(""); + } - if (nxt_slow_path(buf == Qnil)) { - return Qnil; - } + buf = rb_str_buf_new(copy_size); - copy_size = nxt_unit_request_read(rctx->req, RSTRING_PTR(buf), copy_size); + if (nxt_slow_path(buf == Qnil)) { + return Qnil; + } - if (RARRAY_LEN(args) > 1 && TYPE(RARRAY_PTR(args)[1]) == T_STRING) { + copy_size = nxt_unit_request_read(rctx->req, RSTRING_PTR(buf), copy_size); - rb_str_set_len(RARRAY_PTR(args)[1], 0); - rb_str_cat(RARRAY_PTR(args)[1], RSTRING_PTR(buf), copy_size); - } + if (RARRAY_LEN(args) > 1 && TYPE(RARRAY_PTR(args)[1]) == T_STRING) { - rb_str_set_len(buf, copy_size); + rb_str_set_len(RARRAY_PTR(args)[1], 0); + rb_str_cat(RARRAY_PTR(args)[1], RSTRING_PTR(buf), copy_size); + } - return buf; -} + rb_str_set_len(buf, copy_size); - -static VALUE -nxt_ruby_stream_io_rewind(VALUE obj) -{ - return Qnil; + return buf; } +static VALUE nxt_ruby_stream_io_rewind(VALUE obj) { return Qnil; } -static VALUE -nxt_ruby_stream_io_puts(VALUE obj, VALUE args) -{ - nxt_ruby_ctx_t *rctx; +static VALUE nxt_ruby_stream_io_puts(VALUE obj, VALUE args) { + nxt_ruby_ctx_t *rctx; - if (RARRAY_LEN(args) != 1) { - return Qnil; - } + if (RARRAY_LEN(args) != 1) { + return Qnil; + } - Data_Get_Struct(obj, nxt_ruby_ctx_t, rctx); + Data_Get_Struct(obj, nxt_ruby_ctx_t, rctx); - nxt_ruby_stream_io_s_write(rctx, RARRAY_PTR(args)[0]); + nxt_ruby_stream_io_s_write(rctx, RARRAY_PTR(args)[0]); - return Qnil; + return Qnil; } +static VALUE nxt_ruby_stream_io_write(VALUE obj, VALUE args) { + long len; + nxt_ruby_ctx_t *rctx; -static VALUE -nxt_ruby_stream_io_write(VALUE obj, VALUE args) -{ - long len; - nxt_ruby_ctx_t *rctx; - - if (RARRAY_LEN(args) != 1) { - return Qnil; - } + if (RARRAY_LEN(args) != 1) { + return Qnil; + } - Data_Get_Struct(obj, nxt_ruby_ctx_t, rctx); + Data_Get_Struct(obj, nxt_ruby_ctx_t, rctx); - len = nxt_ruby_stream_io_s_write(rctx, RARRAY_PTR(args)[0]); + len = nxt_ruby_stream_io_s_write(rctx, RARRAY_PTR(args)[0]); - return LONG2FIX(len); + return LONG2FIX(len); } +nxt_inline long nxt_ruby_stream_io_s_write(nxt_ruby_ctx_t *rctx, VALUE val) { + if (nxt_slow_path(val == Qnil)) { + return 0; + } -nxt_inline long -nxt_ruby_stream_io_s_write(nxt_ruby_ctx_t *rctx, VALUE val) -{ - if (nxt_slow_path(val == Qnil)) { - return 0; - } + if (TYPE(val) != T_STRING) { + val = rb_funcall(val, rb_intern("to_s"), 0); if (TYPE(val) != T_STRING) { - val = rb_funcall(val, rb_intern("to_s"), 0); - - if (TYPE(val) != T_STRING) { - return 0; - } + return 0; } + } - nxt_unit_req_error(rctx->req, "Ruby: %s", RSTRING_PTR(val)); + nxt_unit_req_error(rctx->req, "Ruby: %s", RSTRING_PTR(val)); - return RSTRING_LEN(val); + return RSTRING_LEN(val); } +static VALUE nxt_ruby_stream_io_flush(VALUE obj) { return Qnil; } -static VALUE -nxt_ruby_stream_io_flush(VALUE obj) -{ - return Qnil; -} - - -static VALUE -nxt_ruby_stream_io_close(VALUE obj) -{ - return Qnil; -} +static VALUE nxt_ruby_stream_io_close(VALUE obj) { return Qnil; } diff --git a/src/test/nxt_base64_test.c b/src/test/nxt_base64_test.c index 13a772b69..9de69d121 100644 --- a/src/test/nxt_base64_test.c +++ b/src/test/nxt_base64_test.c @@ -6,93 +6,75 @@ #include #include "nxt_tests.h" +nxt_int_t nxt_base64_test(nxt_thread_t *thr) { + ssize_t ret; + nxt_uint_t i; + + static struct { + nxt_str_t enc; + nxt_str_t dec; + + } tests[] = { + {nxt_string("ABCDEFGHIJKLMNOPQRSTUVWXYZ" + "abcdefghijklmnopqrstuvwxyz" + "0123456789+//+9876543210" + "zyxwvutsrqponmlkjihgfedcba" + "ZYXWVUTSRQPONMLKJIHGFEDCBA"), + nxt_string("\x00\x10\x83\x10\x51\x87\x20\x92\x8b\x30\xd3\x8f" + "\x41\x14\x93\x51\x55\x97\x61\x96\x9b\x71\xd7\x9f" + "\x82\x18\xa3\x92\x59\xa7\xa2\x9a\xab\xb2\xdb\xaf" + "\xc3\x1c\xb3\xd3\x5d\xb7\xe3\x9e\xbb\xf3\xdf\xbf" + "\xff\xef\x7c\xef\xae\x78\xdf\x6d\x74\xcf\x2c\x70" + "\xbe\xeb\x6c\xae\xaa\x68\x9e\x69\x64\x8e\x28\x60" + "\x7d\xe7\x5c\x6d\xa6\x58\x5d\x65\x54\x4d\x24\x50" + "\x3c\xe3\x4c\x2c\xa2\x48\x1c\x61\x44\x0c\x20\x40")}, + + {nxt_string("Aa=="), nxt_string("\x01")}, + {nxt_string("0Z"), nxt_string("\xd1")}, + {nxt_string("0aA="), nxt_string("\xd1\xa0")}, + {nxt_string("z/+"), nxt_string("\xcf\xff")}, + {nxt_string("z9+Npe=="), nxt_string("\xcf\xdf\x8d\xa5")}, + {nxt_string("/+98765"), nxt_string("\xff\xef\x7c\xef\xae")}, + + {nxt_string("aBc_"), nxt_null_string}, + {nxt_string("5"), nxt_null_string}, + {nxt_string("M==="), nxt_null_string}, + {nxt_string("===="), nxt_null_string}, + {nxt_string("Ab="), nxt_null_string}, + {nxt_string("00=0"), nxt_null_string}, + {nxt_string("\0"), nxt_null_string}, + {nxt_string("\r\naaaa"), nxt_null_string}, + {nxt_string("=0000"), nxt_null_string}, + }; + + u_char buf[96]; + + nxt_thread_time_update(thr); + + for (i = 0; i < nxt_nitems(tests); i++) { + ret = nxt_base64_decode(NULL, tests[i].enc.start, tests[i].enc.length); + + if (ret == NXT_ERROR && tests[i].dec.start == NULL) { + continue; + } + + if ((size_t)ret != tests[i].dec.length) { + nxt_log_alert(thr->log, + "nxt_base64_decode() test \"%V\" failed: incorrect " + "length of decoded string %z, expected %uz", + &tests[i].enc, ret, tests[i].dec.length); + return NXT_ERROR; + } + + ret = nxt_base64_decode(buf, tests[i].enc.start, tests[i].enc.length); -nxt_int_t -nxt_base64_test(nxt_thread_t *thr) -{ - ssize_t ret; - nxt_uint_t i; - - static struct { - nxt_str_t enc; - nxt_str_t dec; - - } tests[] = { - { nxt_string("ABCDEFGHIJKLMNOPQRSTUVWXYZ" - "abcdefghijklmnopqrstuvwxyz" - "0123456789+//+9876543210" - "zyxwvutsrqponmlkjihgfedcba" - "ZYXWVUTSRQPONMLKJIHGFEDCBA"), - nxt_string("\x00\x10\x83\x10\x51\x87\x20\x92\x8b\x30\xd3\x8f" - "\x41\x14\x93\x51\x55\x97\x61\x96\x9b\x71\xd7\x9f" - "\x82\x18\xa3\x92\x59\xa7\xa2\x9a\xab\xb2\xdb\xaf" - "\xc3\x1c\xb3\xd3\x5d\xb7\xe3\x9e\xbb\xf3\xdf\xbf" - "\xff\xef\x7c\xef\xae\x78\xdf\x6d\x74\xcf\x2c\x70" - "\xbe\xeb\x6c\xae\xaa\x68\x9e\x69\x64\x8e\x28\x60" - "\x7d\xe7\x5c\x6d\xa6\x58\x5d\x65\x54\x4d\x24\x50" - "\x3c\xe3\x4c\x2c\xa2\x48\x1c\x61\x44\x0c\x20\x40") }, - - { nxt_string("Aa=="), - nxt_string("\x01") }, - { nxt_string("0Z"), - nxt_string("\xd1") }, - { nxt_string("0aA="), - nxt_string("\xd1\xa0") }, - { nxt_string("z/+"), - nxt_string("\xcf\xff") }, - { nxt_string("z9+Npe=="), - nxt_string("\xcf\xdf\x8d\xa5") }, - { nxt_string("/+98765"), - nxt_string("\xff\xef\x7c\xef\xae") }, - - { nxt_string("aBc_"), - nxt_null_string }, - { nxt_string("5"), - nxt_null_string }, - { nxt_string("M==="), - nxt_null_string }, - { nxt_string("===="), - nxt_null_string }, - { nxt_string("Ab="), - nxt_null_string }, - { nxt_string("00=0"), - nxt_null_string }, - { nxt_string("\0"), - nxt_null_string }, - { nxt_string("\r\naaaa"), - nxt_null_string }, - { nxt_string("=0000"), - nxt_null_string }, - }; - - u_char buf[96]; - - nxt_thread_time_update(thr); - - for (i = 0; i < nxt_nitems(tests); i++) { - ret = nxt_base64_decode(NULL, tests[i].enc.start, tests[i].enc.length); - - if (ret == NXT_ERROR && tests[i].dec.start == NULL) { - continue; - } - - if ((size_t) ret != tests[i].dec.length) { - nxt_log_alert(thr->log, - "nxt_base64_decode() test \"%V\" failed: incorrect " - "length of decoded string %z, expected %uz", - &tests[i].enc, ret, tests[i].dec.length); - return NXT_ERROR; - } - - ret = nxt_base64_decode(buf, tests[i].enc.start, tests[i].enc.length); - - if (!nxt_str_eq(&tests[i].dec, buf, (size_t) ret)) { - nxt_log_alert(thr->log, "nxt_base64_decode() test \"%V\" failed"); - return NXT_ERROR; - } + if (!nxt_str_eq(&tests[i].dec, buf, (size_t)ret)) { + nxt_log_alert(thr->log, "nxt_base64_decode() test \"%V\" failed"); + return NXT_ERROR; } + } - nxt_log_error(NXT_LOG_NOTICE, thr->log, "nxt_base64_decode() test passed"); + nxt_log_error(NXT_LOG_NOTICE, thr->log, "nxt_base64_decode() test passed"); - return NXT_OK; + return NXT_OK; } diff --git a/src/test/nxt_clone_test.c b/src/test/nxt_clone_test.c index 1a864f0e0..b49ce4b8a 100644 --- a/src/test/nxt_clone_test.c +++ b/src/test/nxt_clone_test.c @@ -7,321 +7,294 @@ #include #include "nxt_tests.h" - #define UIDMAP 1 #define GIDMAP 2 - typedef struct { - nxt_int_t map_type; - nxt_str_t map_data; - nxt_int_t setid; - nxt_credential_t creds; - nxt_uid_t unit_euid; - nxt_gid_t unit_egid; - nxt_int_t result; - nxt_str_t errmsg; + nxt_int_t map_type; + nxt_str_t map_data; + nxt_int_t setid; + nxt_credential_t creds; + nxt_uid_t unit_euid; + nxt_gid_t unit_egid; + nxt_int_t result; + nxt_str_t errmsg; } nxt_clone_creds_testcase_t; typedef struct { - nxt_clone_creds_testcase_t *tc; + nxt_clone_creds_testcase_t *tc; } nxt_clone_creds_ctx_t; - nxt_int_t nxt_clone_test_mappings(nxt_task_t *task, nxt_mp_t *mp, - nxt_clone_creds_ctx_t *ctx, nxt_clone_creds_testcase_t *tc); + nxt_clone_creds_ctx_t *ctx, + nxt_clone_creds_testcase_t *tc); void nxt_cdecl nxt_clone_test_log_handler(nxt_uint_t level, nxt_log_t *log, - const char *fmt, ...); + const char *fmt, ...); nxt_int_t nxt_clone_test_map_assert(nxt_task_t *task, - nxt_clone_creds_testcase_t *tc, nxt_clone_credential_map_t *map); -static nxt_int_t nxt_clone_test_parse_map(nxt_task_t *task, - nxt_str_t *map_str, nxt_clone_credential_map_t *map); - + nxt_clone_creds_testcase_t *tc, + nxt_clone_credential_map_t *map); +static nxt_int_t nxt_clone_test_parse_map(nxt_task_t *task, nxt_str_t *map_str, + nxt_clone_credential_map_t *map); nxt_log_t *test_log; static nxt_gid_t gids[] = {1000, 10000, 60000}; static nxt_clone_creds_testcase_t testcases[] = { - { - /* - * Unprivileged unit - * - * if no uid mapping and app creds and unit creds are the same, - * then we automatically add a map for the creds->uid. - * Then, child process can safely setuid(creds->uid) in - * the new namespace. - */ - UIDMAP, - nxt_string(""), - 0, - {"nobody", 65534, 65534, 0, NULL}, - 1000, 1000, - NXT_OK, - nxt_string("") - }, - { - UIDMAP, - nxt_string(""), - 0, - {"johndoe", 10000, 10000, 0, NULL}, - 1000, 1000, - NXT_OK, - nxt_string("") - }, - { - UIDMAP, - nxt_string("[{\"container\": 1000, \"host\": 1000, \"size\": 1}]"), - 0, - {"johndoe", 1000, 1000, 0, NULL}, - 1000, 1000, - NXT_OK, - nxt_string("") - }, - { - UIDMAP, - nxt_string("[{\"container\": 0, \"host\": 1000, \"size\": 1}]"), - 0, - {"root", 0, 0, 0, NULL}, - 1000, 1000, - NXT_OK, - nxt_string("") - }, - { - UIDMAP, - nxt_string("[{\"container\": 65534, \"host\": 1000, \"size\": 1}]"), - 0, - {"nobody", 65534, 0, 0, NULL}, - 1000, 1000, - NXT_OK, - nxt_string("") - }, - { - UIDMAP, - nxt_string("[{\"container\": 0, \"host\": 1000, \"size\": 1}," - " {\"container\": 1000, \"host\": 2000, \"size\": 1}]"), - 0, - {"root", 0, 0, 0, NULL}, - 1000, 1000, - NXT_ERROR, - nxt_string("\"uidmap\" field has 2 entries but unprivileged unit has " - "a maximum of 1 map.") - }, - { - UIDMAP, - nxt_string("[{\"container\": 0, \"host\": 1000, \"size\": 1}," - " {\"container\": 1000, \"host\": 2000, \"size\": 1}]"), - 1, /* privileged */ - {"root", 0, 0, 0, NULL}, - 1000, 1000, - NXT_OK, - nxt_string("") - }, - { - UIDMAP, - nxt_string("[{\"container\": 0, \"host\": 1000, \"size\": 1000}," - " {\"container\": 1000, \"host\": 2000, \"size\": 1000}]"), - 1, /* privileged */ - {"johndoe", 500, 0, 0, NULL}, - 1000, 1000, - NXT_OK, - nxt_string("") - }, - { - UIDMAP, - nxt_string("[{\"container\": 0, \"host\": 1000, \"size\": 1000}," - " {\"container\": 1000, \"host\": 2000, \"size\": 1000}]"), - 1, /* privileged */ - {"johndoe", 1000, 0, 0, NULL}, - 1000, 1000, - NXT_OK, - nxt_string("") - }, - { - UIDMAP, - nxt_string("[{\"container\": 0, \"host\": 1000, \"size\": 1000}," - " {\"container\": 1000, \"host\": 2000, \"size\": 1000}]"), - 1, /* privileged */ - {"johndoe", 1500, 0, 0, NULL}, - 1000, 1000, - NXT_OK, - nxt_string("") - }, - { - UIDMAP, - nxt_string("[{\"container\": 0, \"host\": 1000, \"size\": 1000}," - " {\"container\": 1000, \"host\": 2000, \"size\": 1000}]"), - 1, /* privileged */ - {"johndoe", 1999, 0, 0, NULL}, - 1000, 1000, - NXT_OK, - nxt_string("") - }, - { - UIDMAP, - nxt_string("[{\"container\": 0, \"host\": 1000, \"size\": 1000}," - " {\"container\": 1000, \"host\": 2000, \"size\": 1000}]"), - 1, /* privileged */ - {"johndoe", 2000, 0, 0, NULL}, - 1000, 1000, - NXT_ERROR, - nxt_string("\"uidmap\" field has no \"container\" entry for user " - "\"johndoe\" (uid 2000)") - }, - { - /* - * Unprivileged unit - * - * if no gid mapping and app creds and unit creds are the same, - * then we automatically add a map for the creds->base_gid. - * Then, child process can safely setgid(creds->base_gid) in - * the new namespace. - */ - GIDMAP, - nxt_string("[]"), - 0, - {"nobody", 65534, 65534, 0, NULL}, - 1000, 1000, - NXT_OK, - nxt_string("") - }, - { - /* - * Unprivileged unit - * - * Inside the new namespace, we can have any gid but it - * should map to parent gid (in this case 1000) in parent - * namespace. - */ - GIDMAP, - nxt_string("[{\"container\": 0, \"host\": 1000, \"size\": 1}]"), - 0, - {"root", 0, 0, 0, NULL}, - 1000, 1000, - NXT_OK, - nxt_string("") - }, - { - GIDMAP, - nxt_string("[{\"container\": 65534, \"host\": 1000, \"size\": 1}]"), - 0, - {"nobody", 65534, 65534, 0, NULL}, - 1000, 1000, - NXT_OK, - nxt_string("") - }, - { - /* - * Unprivileged unit - * - * There's no mapping for "johndoe" (gid 1000) inside the namespace. - */ - GIDMAP, - nxt_string("[{\"container\": 65535, \"host\": 1000, \"size\": 1}]"), - 0, - {"johndoe", 1000, 1000, 0, NULL}, - 1000, 1000, - NXT_ERROR, - nxt_string("\"gidmap\" field has no \"container\" entry for " - "gid 1000.") - }, - { - GIDMAP, - nxt_string("[{\"container\": 1000, \"host\": 1000, \"size\": 2}]"), - 0, - {"johndoe", 1000, 1000, 0, NULL}, - 1000, 1000, - NXT_ERROR, - nxt_string("\"gidmap\" field has an entry with \"size\": 2, but " - "for unprivileged unit it must be 1.") - }, - { - GIDMAP, - nxt_string("[{\"container\": 1000, \"host\": 1001, \"size\": 1}]"), - 0, - {"johndoe", 1000, 1000, 0, NULL}, - 1000, 1000, - NXT_ERROR, - nxt_string("\"gidmap\" field has an entry for host gid 1001 but " - "unprivileged unit can only map itself (gid 1000) " - "into child namespaces.") - }, - { - GIDMAP, - nxt_string("[{\"container\": 1000, \"host\": 1000, \"size\": 1}]"), - 0, - {"johndoe", 1000, 1000, 3, gids}, - 1000, 1000, - NXT_ERROR, - nxt_string("unprivileged unit disallow supplementary groups for " - "new namespace (user \"johndoe\" has 3 groups).") - }, + {/* + * Unprivileged unit + * + * if no uid mapping and app creds and unit creds are the same, + * then we automatically add a map for the creds->uid. + * Then, child process can safely setuid(creds->uid) in + * the new namespace. + */ + UIDMAP, + nxt_string(""), + 0, + {"nobody", 65534, 65534, 0, NULL}, + 1000, + 1000, + NXT_OK, + nxt_string("")}, + {UIDMAP, + nxt_string(""), + 0, + {"johndoe", 10000, 10000, 0, NULL}, + 1000, + 1000, + NXT_OK, + nxt_string("")}, + {UIDMAP, + nxt_string("[{\"container\": 1000, \"host\": 1000, \"size\": 1}]"), + 0, + {"johndoe", 1000, 1000, 0, NULL}, + 1000, + 1000, + NXT_OK, + nxt_string("")}, + {UIDMAP, + nxt_string("[{\"container\": 0, \"host\": 1000, \"size\": 1}]"), + 0, + {"root", 0, 0, 0, NULL}, + 1000, + 1000, + NXT_OK, + nxt_string("")}, + {UIDMAP, + nxt_string("[{\"container\": 65534, \"host\": 1000, \"size\": 1}]"), + 0, + {"nobody", 65534, 0, 0, NULL}, + 1000, + 1000, + NXT_OK, + nxt_string("")}, + {UIDMAP, + nxt_string("[{\"container\": 0, \"host\": 1000, \"size\": 1}," + " {\"container\": 1000, \"host\": 2000, \"size\": 1}]"), + 0, + {"root", 0, 0, 0, NULL}, + 1000, + 1000, + NXT_ERROR, + nxt_string("\"uidmap\" field has 2 entries but unprivileged unit has " + "a maximum of 1 map.")}, + {UIDMAP, + nxt_string("[{\"container\": 0, \"host\": 1000, \"size\": 1}," + " {\"container\": 1000, \"host\": 2000, \"size\": 1}]"), + 1, /* privileged */ + {"root", 0, 0, 0, NULL}, + 1000, + 1000, + NXT_OK, + nxt_string("")}, + {UIDMAP, + nxt_string("[{\"container\": 0, \"host\": 1000, \"size\": 1000}," + " {\"container\": 1000, \"host\": 2000, \"size\": 1000}]"), + 1, /* privileged */ + {"johndoe", 500, 0, 0, NULL}, + 1000, + 1000, + NXT_OK, + nxt_string("")}, + {UIDMAP, + nxt_string("[{\"container\": 0, \"host\": 1000, \"size\": 1000}," + " {\"container\": 1000, \"host\": 2000, \"size\": 1000}]"), + 1, /* privileged */ + {"johndoe", 1000, 0, 0, NULL}, + 1000, + 1000, + NXT_OK, + nxt_string("")}, + {UIDMAP, + nxt_string("[{\"container\": 0, \"host\": 1000, \"size\": 1000}," + " {\"container\": 1000, \"host\": 2000, \"size\": 1000}]"), + 1, /* privileged */ + {"johndoe", 1500, 0, 0, NULL}, + 1000, + 1000, + NXT_OK, + nxt_string("")}, + {UIDMAP, + nxt_string("[{\"container\": 0, \"host\": 1000, \"size\": 1000}," + " {\"container\": 1000, \"host\": 2000, \"size\": 1000}]"), + 1, /* privileged */ + {"johndoe", 1999, 0, 0, NULL}, + 1000, + 1000, + NXT_OK, + nxt_string("")}, + {UIDMAP, + nxt_string("[{\"container\": 0, \"host\": 1000, \"size\": 1000}," + " {\"container\": 1000, \"host\": 2000, \"size\": 1000}]"), + 1, /* privileged */ + {"johndoe", 2000, 0, 0, NULL}, + 1000, + 1000, + NXT_ERROR, + nxt_string("\"uidmap\" field has no \"container\" entry for user " + "\"johndoe\" (uid 2000)")}, + {/* + * Unprivileged unit + * + * if no gid mapping and app creds and unit creds are the same, + * then we automatically add a map for the creds->base_gid. + * Then, child process can safely setgid(creds->base_gid) in + * the new namespace. + */ + GIDMAP, + nxt_string("[]"), + 0, + {"nobody", 65534, 65534, 0, NULL}, + 1000, + 1000, + NXT_OK, + nxt_string("")}, + {/* + * Unprivileged unit + * + * Inside the new namespace, we can have any gid but it + * should map to parent gid (in this case 1000) in parent + * namespace. + */ + GIDMAP, + nxt_string("[{\"container\": 0, \"host\": 1000, \"size\": 1}]"), + 0, + {"root", 0, 0, 0, NULL}, + 1000, + 1000, + NXT_OK, + nxt_string("")}, + {GIDMAP, + nxt_string("[{\"container\": 65534, \"host\": 1000, \"size\": 1}]"), + 0, + {"nobody", 65534, 65534, 0, NULL}, + 1000, + 1000, + NXT_OK, + nxt_string("")}, + {/* + * Unprivileged unit + * + * There's no mapping for "johndoe" (gid 1000) inside the namespace. + */ + GIDMAP, + nxt_string("[{\"container\": 65535, \"host\": 1000, \"size\": 1}]"), + 0, + {"johndoe", 1000, 1000, 0, NULL}, + 1000, + 1000, + NXT_ERROR, + nxt_string("\"gidmap\" field has no \"container\" entry for " + "gid 1000.")}, + {GIDMAP, + nxt_string("[{\"container\": 1000, \"host\": 1000, \"size\": 2}]"), + 0, + {"johndoe", 1000, 1000, 0, NULL}, + 1000, + 1000, + NXT_ERROR, + nxt_string("\"gidmap\" field has an entry with \"size\": 2, but " + "for unprivileged unit it must be 1.")}, + {GIDMAP, + nxt_string("[{\"container\": 1000, \"host\": 1001, \"size\": 1}]"), + 0, + {"johndoe", 1000, 1000, 0, NULL}, + 1000, + 1000, + NXT_ERROR, + nxt_string("\"gidmap\" field has an entry for host gid 1001 but " + "unprivileged unit can only map itself (gid 1000) " + "into child namespaces.")}, + {GIDMAP, + nxt_string("[{\"container\": 1000, \"host\": 1000, \"size\": 1}]"), + 0, + {"johndoe", 1000, 1000, 3, gids}, + 1000, + 1000, + NXT_ERROR, + nxt_string("unprivileged unit disallow supplementary groups for " + "new namespace (user \"johndoe\" has 3 groups).")}, /* privileged unit */ /* not root with capabilities */ - { - GIDMAP, - nxt_string("[]"), - 1, - {"johndoe", 1000, 1000, 0, NULL}, - 1000, 1000, - NXT_OK, - nxt_string("") - }, - { - GIDMAP, - nxt_string(""), - 1, - {"johndoe", 1000, 1000, 0, NULL}, - 1000, 1000, - NXT_OK, - nxt_string("") - }, - { - /* missing gid of {"user": "nobody"} */ - GIDMAP, - nxt_string("[{\"container\": 0, \"host\": 1000, \"size\": 1}]"), - 1, - {"nobody", 65534, 65534, 0, NULL}, - 1000, 1000, - NXT_ERROR, - nxt_string("\"gidmap\" field has no \"container\" entry for " - "gid 65534.") - }, - { - /* solves the previous by mapping 65534 gids */ - GIDMAP, - nxt_string("[{\"container\": 0, \"host\": 1000, \"size\": 65535}]"), - 1, - {"nobody", 65534, 65534, 0, NULL}, - 1000, 1000, - NXT_OK, - nxt_string("") - }, - { - /* solves by adding a separate mapping */ - GIDMAP, - nxt_string("[{\"container\": 0, \"host\": 1000, \"size\": 1}," - " {\"container\": 65534, \"host\": 1000, \"size\": 1}]"), - 1, - {"nobody", 65534, 65534, 0, NULL}, - 1000, 1000, - NXT_OK, - nxt_string("") - }, - { - /* - * Map a big range - */ - GIDMAP, - nxt_string("[{\"container\": 0, \"host\": 0, \"size\": 200000}]"), - 1, - {"johndoe", 100000, 100000, 0, NULL}, - 1000, 1000, - NXT_OK, - nxt_string("") - }, + {GIDMAP, + nxt_string("[]"), + 1, + {"johndoe", 1000, 1000, 0, NULL}, + 1000, + 1000, + NXT_OK, + nxt_string("")}, + {GIDMAP, + nxt_string(""), + 1, + {"johndoe", 1000, 1000, 0, NULL}, + 1000, + 1000, + NXT_OK, + nxt_string("")}, + {/* missing gid of {"user": "nobody"} */ + GIDMAP, + nxt_string("[{\"container\": 0, \"host\": 1000, \"size\": 1}]"), + 1, + {"nobody", 65534, 65534, 0, NULL}, + 1000, + 1000, + NXT_ERROR, + nxt_string("\"gidmap\" field has no \"container\" entry for " + "gid 65534.")}, + {/* solves the previous by mapping 65534 gids */ + GIDMAP, + nxt_string("[{\"container\": 0, \"host\": 1000, \"size\": 65535}]"), + 1, + {"nobody", 65534, 65534, 0, NULL}, + 1000, + 1000, + NXT_OK, + nxt_string("")}, + {/* solves by adding a separate mapping */ + GIDMAP, + nxt_string("[{\"container\": 0, \"host\": 1000, \"size\": 1}," + " {\"container\": 65534, \"host\": 1000, \"size\": 1}]"), + 1, + {"nobody", 65534, 65534, 0, NULL}, + 1000, + 1000, + NXT_OK, + nxt_string("")}, + {/* + * Map a big range + */ + GIDMAP, + nxt_string("[{\"container\": 0, \"host\": 0, \"size\": 200000}]"), + 1, + {"johndoe", 100000, 100000, 0, NULL}, + 1000, + 1000, + NXT_OK, + nxt_string("")}, { /* * Validate if supplementary groups are mapped @@ -330,7 +303,8 @@ static nxt_clone_creds_testcase_t testcases[] = { nxt_string("[]"), 1, {"johndoe", 1000, 1000, 3, gids}, - 1000, 1000, + 1000, + 1000, NXT_ERROR, nxt_string("\"gidmap\" field has no entries but user \"johndoe\" " "has 3 suplementary groups."), @@ -340,7 +314,8 @@ static nxt_clone_creds_testcase_t testcases[] = { nxt_string("[{\"container\": 0, \"host\": 0, \"size\": 1}]"), 1, {"johndoe", 1000, 1000, 3, gids}, - 1000, 1000, + 1000, + 1000, NXT_ERROR, nxt_string("\"gidmap\" field has no \"container\" entry for " "gid 1000."), @@ -350,7 +325,8 @@ static nxt_clone_creds_testcase_t testcases[] = { nxt_string("[{\"container\": 1000, \"host\": 0, \"size\": 1}]"), 1, {"johndoe", 1000, 1000, 3, gids}, - 1000, 1000, + 1000, + 1000, NXT_ERROR, nxt_string("\"gidmap\" field has missing suplementary gid mappings " "(found 1 out of 3)."), @@ -361,7 +337,8 @@ static nxt_clone_creds_testcase_t testcases[] = { " {\"container\": 10000, \"host\": 10000, \"size\": 1}]"), 1, {"johndoe", 1000, 1000, 3, gids}, - 1000, 1000, + 1000, + 1000, NXT_ERROR, nxt_string("\"gidmap\" field has missing suplementary gid mappings " "(found 2 out of 3)."), @@ -376,226 +353,209 @@ static nxt_clone_creds_testcase_t testcases[] = { " {\"container\": 60000, \"host\": 60000, \"size\": 1}]"), 1, {"johndoe", 1000, 1000, 3, gids}, - 1000, 1000, + 1000, + 1000, NXT_OK, nxt_string(""), }, }; - -void nxt_cdecl -nxt_clone_test_log_handler(nxt_uint_t level, nxt_log_t *log, - const char *fmt, ...) -{ - u_char *p, *end; - va_list args; - nxt_clone_creds_ctx_t *ctx; - nxt_clone_creds_testcase_t *tc; - u_char msg[NXT_MAX_ERROR_STR]; - - p = msg; - end = msg + NXT_MAX_ERROR_STR; - - ctx = log->ctx; - tc = ctx->tc; - - va_start(args, fmt); - p = nxt_vsprintf(p, end, fmt, args); - va_end(args); - - *p++ = '\0'; - - if (tc->result == NXT_OK && level == NXT_LOG_DEBUG) { - return; - } - - if (tc->errmsg.length == 0) { - nxt_log_error(NXT_LOG_ERR, &nxt_main_log, "unexpected log: %s", msg); - return; - } - - if (!nxt_str_eq(&tc->errmsg, msg, (nxt_uint_t) (p - msg - 1))) { - nxt_log_error(NXT_LOG_ERR, &nxt_main_log, - "error log mismatch: got [%s] but wants [%V]", - msg, &tc->errmsg); - return; - } +void nxt_cdecl nxt_clone_test_log_handler(nxt_uint_t level, nxt_log_t *log, + const char *fmt, ...) { + u_char *p, *end; + va_list args; + nxt_clone_creds_ctx_t *ctx; + nxt_clone_creds_testcase_t *tc; + u_char msg[NXT_MAX_ERROR_STR]; + + p = msg; + end = msg + NXT_MAX_ERROR_STR; + + ctx = log->ctx; + tc = ctx->tc; + + va_start(args, fmt); + p = nxt_vsprintf(p, end, fmt, args); + va_end(args); + + *p++ = '\0'; + + if (tc->result == NXT_OK && level == NXT_LOG_DEBUG) { + return; + } + + if (tc->errmsg.length == 0) { + nxt_log_error(NXT_LOG_ERR, &nxt_main_log, "unexpected log: %s", msg); + return; + } + + if (!nxt_str_eq(&tc->errmsg, msg, (nxt_uint_t)(p - msg - 1))) { + nxt_log_error(NXT_LOG_ERR, &nxt_main_log, + "error log mismatch: got [%s] but wants [%V]", msg, + &tc->errmsg); + return; + } } +nxt_int_t nxt_clone_creds_test(nxt_thread_t *thr) { + nxt_mp_t *mp; + nxt_int_t ret; + nxt_uint_t count, i; + nxt_task_t *task; + nxt_runtime_t rt; + nxt_clone_creds_ctx_t ctx; -nxt_int_t -nxt_clone_creds_test(nxt_thread_t *thr) -{ - nxt_mp_t *mp; - nxt_int_t ret; - nxt_uint_t count, i; - nxt_task_t *task; - nxt_runtime_t rt; - nxt_clone_creds_ctx_t ctx; + nxt_log_t nxt_clone_creds_log = {NXT_LOG_INFO, 0, nxt_clone_test_log_handler, + NULL, &ctx}; - nxt_log_t nxt_clone_creds_log = { - NXT_LOG_INFO, - 0, - nxt_clone_test_log_handler, - NULL, - &ctx - }; + nxt_thread_time_update(thr); - nxt_thread_time_update(thr); + thr->runtime = &rt; - thr->runtime = &rt; + task = thr->task; - task = thr->task; + mp = nxt_mp_create(1024, 128, 256, 32); + if (mp == NULL) { + return NXT_ERROR; + } - mp = nxt_mp_create(1024, 128, 256, 32); - if (mp == NULL) { - return NXT_ERROR; - } - - rt.mem_pool = mp; + rt.mem_pool = mp; - test_log = task->log; - task->log = &nxt_clone_creds_log; - task->thread = thr; + test_log = task->log; + task->log = &nxt_clone_creds_log; + task->thread = thr; - count = sizeof(testcases)/sizeof(nxt_clone_creds_testcase_t); + count = sizeof(testcases) / sizeof(nxt_clone_creds_testcase_t); - for (i = 0; i < count; i++) { - ret = nxt_clone_test_mappings(task, mp, &ctx, &testcases[i]); + for (i = 0; i < count; i++) { + ret = nxt_clone_test_mappings(task, mp, &ctx, &testcases[i]); - if (ret != NXT_OK) { - goto fail; - } + if (ret != NXT_OK) { + goto fail; } + } - ret = NXT_OK; + ret = NXT_OK; - nxt_log_error(NXT_LOG_NOTICE, test_log, "clone creds test passed"); + nxt_log_error(NXT_LOG_NOTICE, test_log, "clone creds test passed"); fail: - task->log = test_log; - nxt_mp_destroy(mp); + task->log = test_log; + nxt_mp_destroy(mp); - return ret; + return ret; } +nxt_int_t nxt_clone_test_mappings(nxt_task_t *task, nxt_mp_t *mp, + nxt_clone_creds_ctx_t *ctx, + nxt_clone_creds_testcase_t *tc) { + nxt_int_t ret; + nxt_runtime_t *rt; + nxt_clone_credential_map_t map; -nxt_int_t -nxt_clone_test_mappings(nxt_task_t *task, nxt_mp_t *mp, - nxt_clone_creds_ctx_t *ctx, nxt_clone_creds_testcase_t *tc) -{ - nxt_int_t ret; - nxt_runtime_t *rt; - nxt_clone_credential_map_t map; - - rt = task->thread->runtime; + rt = task->thread->runtime; - map.size = 0; + map.size = 0; - if (tc->map_data.length > 0) { - ret = nxt_clone_test_parse_map(task, &tc->map_data, &map); - if (ret != NXT_OK) { - return NXT_ERROR; - } + if (tc->map_data.length > 0) { + ret = nxt_clone_test_parse_map(task, &tc->map_data, &map); + if (ret != NXT_OK) { + return NXT_ERROR; } + } - rt->capabilities.setid = tc->setid; + rt->capabilities.setid = tc->setid; - nxt_euid = tc->unit_euid; - nxt_egid = tc->unit_egid; + nxt_euid = tc->unit_euid; + nxt_egid = tc->unit_egid; - ctx->tc = tc; + ctx->tc = tc; - if (nxt_clone_test_map_assert(task, tc, &map) != NXT_OK) { - return NXT_ERROR; - } + if (nxt_clone_test_map_assert(task, tc, &map) != NXT_OK) { + return NXT_ERROR; + } - if (tc->setid && nxt_euid != 0) { - /* - * Running as root should have the same behavior as - * passing Linux capabilities. - */ + if (tc->setid && nxt_euid != 0) { + /* + * Running as root should have the same behavior as + * passing Linux capabilities. + */ - nxt_euid = 0; - nxt_egid = 0; + nxt_euid = 0; + nxt_egid = 0; - if (nxt_clone_test_map_assert(task, tc, &map) != NXT_OK) { - return NXT_ERROR; - } + if (nxt_clone_test_map_assert(task, tc, &map) != NXT_OK) { + return NXT_ERROR; } + } - return NXT_OK; + return NXT_OK; } +nxt_int_t nxt_clone_test_map_assert(nxt_task_t *task, + nxt_clone_creds_testcase_t *tc, + nxt_clone_credential_map_t *map) { + nxt_int_t ret; -nxt_int_t -nxt_clone_test_map_assert(nxt_task_t *task, nxt_clone_creds_testcase_t *tc, - nxt_clone_credential_map_t *map) -{ - nxt_int_t ret; - - if (tc->map_type == UIDMAP) { - ret = nxt_clone_vldt_credential_uidmap(task, map, &tc->creds); - } else { - ret = nxt_clone_vldt_credential_gidmap(task, map, &tc->creds); - } + if (tc->map_type == UIDMAP) { + ret = nxt_clone_vldt_credential_uidmap(task, map, &tc->creds); + } else { + ret = nxt_clone_vldt_credential_gidmap(task, map, &tc->creds); + } - if (ret != tc->result) { - nxt_log_error(NXT_LOG_ERR, &nxt_main_log, - "return %d instead of %d (map: %V)", ret, tc->result, - &tc->map_data); + if (ret != tc->result) { + nxt_log_error(NXT_LOG_ERR, &nxt_main_log, + "return %d instead of %d (map: %V)", ret, tc->result, + &tc->map_data); - return NXT_ERROR; - } + return NXT_ERROR; + } - return NXT_OK; + return NXT_OK; } +static nxt_int_t nxt_clone_test_parse_map(nxt_task_t *task, nxt_str_t *map_str, + nxt_clone_credential_map_t *map) { + nxt_uint_t i; + nxt_runtime_t *rt; + nxt_conf_value_t *array, *obj, *value; -static nxt_int_t -nxt_clone_test_parse_map(nxt_task_t *task, nxt_str_t *map_str, - nxt_clone_credential_map_t *map) -{ - nxt_uint_t i; - nxt_runtime_t *rt; - nxt_conf_value_t *array, *obj, *value; + static const nxt_str_t host_name = nxt_string("host"); + static const nxt_str_t cont_name = nxt_string("container"); + static const nxt_str_t size_name = nxt_string("size"); - static const nxt_str_t host_name = nxt_string("host"); - static const nxt_str_t cont_name = nxt_string("container"); - static const nxt_str_t size_name = nxt_string("size"); + rt = task->thread->runtime; - rt = task->thread->runtime; + array = nxt_conf_json_parse_str(rt->mem_pool, map_str); + if (array == NULL) { + return NXT_ERROR; + } - array = nxt_conf_json_parse_str(rt->mem_pool, map_str); - if (array == NULL) { - return NXT_ERROR; - } + map->size = nxt_conf_array_elements_count(array); - map->size = nxt_conf_array_elements_count(array); - - if (map->size == 0) { - return NXT_OK; - } + if (map->size == 0) { + return NXT_OK; + } - map->map = nxt_mp_alloc(rt->mem_pool, - map->size * sizeof(nxt_clone_map_entry_t)); + map->map = + nxt_mp_alloc(rt->mem_pool, map->size * sizeof(nxt_clone_map_entry_t)); - if (map->map == NULL) { - return NXT_ERROR; - } + if (map->map == NULL) { + return NXT_ERROR; + } - for (i = 0; i < map->size; i++) { - obj = nxt_conf_get_array_element(array, i); + for (i = 0; i < map->size; i++) { + obj = nxt_conf_get_array_element(array, i); - value = nxt_conf_get_object_member(obj, &host_name, NULL); - map->map[i].host = nxt_conf_get_number(value); + value = nxt_conf_get_object_member(obj, &host_name, NULL); + map->map[i].host = nxt_conf_get_number(value); - value = nxt_conf_get_object_member(obj, &cont_name, NULL); - map->map[i].container = nxt_conf_get_number(value); + value = nxt_conf_get_object_member(obj, &cont_name, NULL); + map->map[i].container = nxt_conf_get_number(value); - value = nxt_conf_get_object_member(obj, &size_name, NULL); - map->map[i].size = nxt_conf_get_number(value); - } + value = nxt_conf_get_object_member(obj, &size_name, NULL); + map->map[i].size = nxt_conf_get_number(value); + } - return NXT_OK; + return NXT_OK; } diff --git a/src/test/nxt_cq_test.c b/src/test/nxt_cq_test.c index ae69505a3..81e47b100 100644 --- a/src/test/nxt_cq_test.c +++ b/src/test/nxt_cq_test.c @@ -8,10 +8,10 @@ #include #ifndef NXT_NCQ_TEST -#define NXT_NCQ_TEST 1 +#define NXT_NCQ_TEST 1 #endif -#define NXT_QTEST_USE_THREAD 0 +#define NXT_QTEST_USE_THREAD 0 #if NXT_NCQ_TEST #include @@ -19,28 +19,24 @@ #include #endif +#define MAX_ITER 20 +#define STAT_ITER 5 +#define MIN_COV 0.02 -#define MAX_ITER 20 -#define STAT_ITER 5 -#define MIN_COV 0.02 - -extern char **environ; +extern char **environ; static uintptr_t nops = 10000000; -static uintptr_t nprocs_enq = 0; -static uintptr_t nprocs_deq = 0; -static uintptr_t nprocs_wenq = 0; -static uintptr_t nprocs_wdeq = 0; +static uintptr_t nprocs_enq = 0; +static uintptr_t nprocs_deq = 0; +static uintptr_t nprocs_wenq = 0; +static uintptr_t nprocs_wdeq = 0; static uintptr_t nprocs_enq_deq = 0; -static uintptr_t nprocs_cas = 0; -static uintptr_t nprocs_faa = 0; +static uintptr_t nprocs_cas = 0; +static uintptr_t nprocs_faa = 0; static uintptr_t nprocs = 1; - -static size_t -elapsed_time(size_t us) -{ +static size_t elapsed_time(size_t us) { struct timeval t; gettimeofday(&t, NULL); @@ -48,531 +44,494 @@ elapsed_time(size_t us) return t.tv_sec * 1000000 + t.tv_usec - us; } +static double mean(const double *times, int n) { + int i; + double sum; -static double -mean(const double *times, int n) -{ - int i; - double sum; - - sum = 0; + sum = 0; - for (i = 0; i < n; i++) { - sum += times[i]; - } + for (i = 0; i < n; i++) { + sum += times[i]; + } - return sum / n; + return sum / n; } +static double cov(const double *times, double mean, int n) { + int i; + double variance; -static double -cov(const double *times, double mean, int n) -{ - int i; - double variance; - - variance = 0; + variance = 0; - for (i = 0; i < n; i++) { - variance += (times[i] - mean) * (times[i] - mean); - } + for (i = 0; i < n; i++) { + variance += (times[i] - mean) * (times[i] - mean); + } - variance /= n; + variance /= n; - return sqrt(variance) / mean; + return sqrt(variance) / mean; } typedef struct { #if NXT_NCQ_TEST - nxt_nncq_t free_queue; - nxt_nncq_t active_queue; + nxt_nncq_t free_queue; + nxt_nncq_t active_queue; #else - nxt_nvbcq_t free_queue; - nxt_nvbcq_t active_queue; + nxt_nvbcq_t free_queue; + nxt_nvbcq_t active_queue; #endif - uint32_t counter; + uint32_t counter; } nxt_cq_t; - -static nxt_cq_t *pgq; - +static nxt_cq_t *pgq; #if NXT_NCQ_TEST -#define nxt_cq_enqueue nxt_nncq_enqueue -#define nxt_cq_dequeue nxt_nncq_dequeue -#define nxt_cq_empty nxt_nncq_empty -#define nxt_cq_init nxt_nncq_init -#define NXT_CQ_SIZE NXT_NNCQ_SIZE +#define nxt_cq_enqueue nxt_nncq_enqueue +#define nxt_cq_dequeue nxt_nncq_dequeue +#define nxt_cq_empty nxt_nncq_empty +#define nxt_cq_init nxt_nncq_init +#define NXT_CQ_SIZE NXT_NNCQ_SIZE #else -#define nxt_cq_enqueue nxt_nvbcq_enqueue -#define nxt_cq_dequeue nxt_nvbcq_dequeue -#define nxt_cq_empty nxt_nvbcq_empty -#define nxt_cq_init nxt_nvbcq_init -#define NXT_CQ_SIZE NXT_NVBCQ_SIZE +#define nxt_cq_enqueue nxt_nvbcq_enqueue +#define nxt_cq_dequeue nxt_nvbcq_dequeue +#define nxt_cq_empty nxt_nvbcq_empty +#define nxt_cq_init nxt_nvbcq_init +#define NXT_CQ_SIZE NXT_NVBCQ_SIZE #endif typedef struct { - int id; - uint64_t enq; - uint64_t deq; - uint64_t wait_enq; - uint64_t wait_deq; - uint64_t own_res; - uint64_t cas; - uint64_t faa; + int id; + uint64_t enq; + uint64_t deq; + uint64_t wait_enq; + uint64_t wait_deq; + uint64_t own_res; + uint64_t cas; + uint64_t faa; #if NXT_QTEST_USE_THREAD - nxt_thread_handle_t handle; + nxt_thread_handle_t handle; #else - nxt_pid_t pid; - int status; + nxt_pid_t pid; + int status; #endif } nxt_worker_info_t; +static void cas_worker(void *p) { + nxt_cq_t *q; + uint32_t c; + uintptr_t i; + nxt_worker_info_t *wi; -static void -cas_worker(void *p) -{ - nxt_cq_t *q; - uint32_t c; - uintptr_t i; - nxt_worker_info_t *wi; - - q = pgq; - wi = p; + q = pgq; + wi = p; - for (i = 0; i < nops / nprocs_cas; i++) { - c = q->counter; + for (i = 0; i < nops / nprocs_cas; i++) { + c = q->counter; - if (nxt_atomic_cmp_set(&q->counter, c, c + 1)) { - ++wi->cas; - } + if (nxt_atomic_cmp_set(&q->counter, c, c + 1)) { + ++wi->cas; } + } } +static void faa_worker(void *p) { + nxt_cq_t *q; + uintptr_t i; + nxt_worker_info_t *wi; -static void -faa_worker(void *p) -{ - nxt_cq_t *q; - uintptr_t i; - nxt_worker_info_t *wi; - - q = pgq; - wi = p; + q = pgq; + wi = p; - for (i = 0; i < nops / nprocs_faa; i++) { - nxt_atomic_fetch_add(&q->counter, 1); - wi->faa++; - } + for (i = 0; i < nops / nprocs_faa; i++) { + nxt_atomic_fetch_add(&q->counter, 1); + wi->faa++; + } } +static void enq_deq_worker(void *p) { + nxt_cq_t *q; + uintptr_t i, v; + nxt_worker_info_t *wi; -static void -enq_deq_worker(void *p) -{ - nxt_cq_t *q; - uintptr_t i, v; - nxt_worker_info_t *wi; + q = pgq; + wi = p; - q = pgq; - wi = p; + for (i = 0; i < nops / nprocs_enq_deq; i++) { + v = nxt_cq_dequeue(&q->free_queue); - for (i = 0; i < nops / nprocs_enq_deq; i++) { - v = nxt_cq_dequeue(&q->free_queue); - - if (v != nxt_cq_empty(&q->free_queue)) { - nxt_cq_enqueue(&q->active_queue, wi->id); - wi->enq++; - } + if (v != nxt_cq_empty(&q->free_queue)) { + nxt_cq_enqueue(&q->active_queue, wi->id); + wi->enq++; + } - v = nxt_cq_dequeue(&q->active_queue); + v = nxt_cq_dequeue(&q->active_queue); - if (v != nxt_cq_empty(&q->active_queue)) { - nxt_cq_enqueue(&q->free_queue, v); - wi->deq++; + if (v != nxt_cq_empty(&q->active_queue)) { + nxt_cq_enqueue(&q->free_queue, v); + wi->deq++; - if ((int) v == wi->id) { - wi->own_res++; - } - } + if ((int)v == wi->id) { + wi->own_res++; + } } + } } +static void enq_worker(void *p) { + nxt_cq_t *q; + uintptr_t i, v; + nxt_worker_info_t *wi; -static void -enq_worker(void *p) -{ - nxt_cq_t *q; - uintptr_t i, v; - nxt_worker_info_t *wi; - - q = pgq; - wi = p; + q = pgq; + wi = p; - for (i = 0; i < nops / nprocs_enq; i++) { - v = nxt_cq_dequeue(&q->free_queue); + for (i = 0; i < nops / nprocs_enq; i++) { + v = nxt_cq_dequeue(&q->free_queue); - if (v != nxt_cq_empty(&q->free_queue)) { - nxt_cq_enqueue(&q->active_queue, v); - wi->enq++; - } + if (v != nxt_cq_empty(&q->free_queue)) { + nxt_cq_enqueue(&q->active_queue, v); + wi->enq++; } + } } +static void deq_worker(void *p) { + nxt_cq_t *q; + uintptr_t i, v; + nxt_worker_info_t *wi; -static void -deq_worker(void *p) -{ - nxt_cq_t *q; - uintptr_t i, v; - nxt_worker_info_t *wi; + q = pgq; + wi = p; - q = pgq; - wi = p; + for (i = 0; i < nops / nprocs_deq; i++) { + v = nxt_cq_dequeue(&q->active_queue); - for (i = 0; i < nops / nprocs_deq; i++) { - v = nxt_cq_dequeue(&q->active_queue); - - if (v != nxt_cq_empty(&q->active_queue)) { - nxt_cq_enqueue(&q->free_queue, v); - ++wi->deq; - } + if (v != nxt_cq_empty(&q->active_queue)) { + nxt_cq_enqueue(&q->free_queue, v); + ++wi->deq; } + } } +static void wenq_worker(void *p) { + nxt_cq_t *q; + uintptr_t i, v; + nxt_worker_info_t *wi; -static void -wenq_worker(void *p) -{ - nxt_cq_t *q; - uintptr_t i, v; - nxt_worker_info_t *wi; - - q = pgq; - wi = p; + q = pgq; + wi = p; - for (i = 0; i < nops / nprocs_wenq; i++) { + for (i = 0; i < nops / nprocs_wenq; i++) { - do { - wi->wait_enq++; - v = nxt_cq_dequeue(&q->free_queue); - } while (v == nxt_cq_empty(&q->free_queue)); + do { + wi->wait_enq++; + v = nxt_cq_dequeue(&q->free_queue); + } while (v == nxt_cq_empty(&q->free_queue)); - nxt_cq_enqueue(&q->active_queue, v); + nxt_cq_enqueue(&q->active_queue, v); - wi->enq++; - wi->wait_enq--; - } + wi->enq++; + wi->wait_enq--; + } } +static void wdeq_worker(void *p) { + nxt_cq_t *q; + uintptr_t i, v; + nxt_worker_info_t *wi; -static void -wdeq_worker(void *p) -{ - nxt_cq_t *q; - uintptr_t i, v; - nxt_worker_info_t *wi; - - q = pgq; - wi = p; + q = pgq; + wi = p; - for (i = 0; i < nops / nprocs_wdeq; i++) { + for (i = 0; i < nops / nprocs_wdeq; i++) { - do { - wi->wait_deq++; - v = nxt_cq_dequeue(&q->active_queue); - } while (v == nxt_cq_empty(&q->active_queue)); + do { + wi->wait_deq++; + v = nxt_cq_dequeue(&q->active_queue); + } while (v == nxt_cq_empty(&q->active_queue)); - nxt_cq_enqueue(&q->free_queue, v); + nxt_cq_enqueue(&q->free_queue, v); - wi->deq++; - wi->wait_deq--; - } + wi->deq++; + wi->wait_deq--; + } } - -static nxt_int_t -worker_create(nxt_worker_info_t *wi, int id, nxt_thread_start_t start) -{ - wi->id = id; +static nxt_int_t worker_create(nxt_worker_info_t *wi, int id, + nxt_thread_start_t start) { + wi->id = id; #if NXT_QTEST_USE_THREAD - nxt_thread_link_t *link; + nxt_thread_link_t *link; - link = nxt_zalloc(sizeof(nxt_thread_link_t)); + link = nxt_zalloc(sizeof(nxt_thread_link_t)); - link->start = start; - link->work.data = wi; + link->start = start; + link->work.data = wi; - return nxt_thread_create(&wi->handle, link); + return nxt_thread_create(&wi->handle, link); #else - pid_t pid = fork(); + pid_t pid = fork(); - if (pid == 0) { - start(wi); - exit(0); + if (pid == 0) { + start(wi); + exit(0); - } else { - wi->pid = pid; - } + } else { + wi->pid = pid; + } - return NXT_OK; + return NXT_OK; #endif } - -static void -worker_wait(nxt_worker_info_t *wi) -{ +static void worker_wait(nxt_worker_info_t *wi) { #if NXT_QTEST_USE_THREAD - pthread_join(wi->handle, NULL); + pthread_join(wi->handle, NULL); #else - waitpid(wi->pid, &wi->status, 0); + waitpid(wi->pid, &wi->status, 0); #endif } +int nxt_cdecl main(int argc, char **argv) { + int i, k, id, verbose, objective, rk; + char *a; + size_t start, elapsed; + double *stats, m, c; + uint64_t total_ops; + uintptr_t j; + nxt_task_t task; + nxt_thread_t *thr; + nxt_worker_info_t *wi; + double times[MAX_ITER], mopsec[MAX_ITER]; + + verbose = 0; + objective = 0; + + for (i = 1; i < argc; i++) { + a = argv[i]; + + if (strcmp(a, "-v") == 0) { + verbose++; + continue; + } -int nxt_cdecl -main(int argc, char **argv) -{ - int i, k, id, verbose, objective, rk; - char *a; - size_t start, elapsed; - double *stats, m, c; - uint64_t total_ops; - uintptr_t j; - nxt_task_t task; - nxt_thread_t *thr; - nxt_worker_info_t *wi; - double times[MAX_ITER], mopsec[MAX_ITER]; - - verbose = 0; - objective = 0; - - for (i = 1; i < argc; i++) { - a = argv[i]; - - if (strcmp(a, "-v") == 0) { - verbose++; - continue; - } + if (strcmp(a, "-n") == 0 && (i + 1) < argc) { + nops = atoi(argv[++i]); + continue; + } - if (strcmp(a, "-n") == 0 && (i + 1) < argc) { - nops = atoi(argv[++i]); - continue; - } + if (strcmp(a, "--enq") == 0 && (i + 1) < argc) { + nprocs_enq = atoi(argv[++i]); + continue; + } - if (strcmp(a, "--enq") == 0 && (i + 1) < argc) { - nprocs_enq = atoi(argv[++i]); - continue; - } + if (strcmp(a, "--deq") == 0 && (i + 1) < argc) { + nprocs_deq = atoi(argv[++i]); + continue; + } - if (strcmp(a, "--deq") == 0 && (i + 1) < argc) { - nprocs_deq = atoi(argv[++i]); - continue; - } + if (strcmp(a, "--wenq") == 0 && (i + 1) < argc) { + nprocs_wenq = atoi(argv[++i]); + continue; + } - if (strcmp(a, "--wenq") == 0 && (i + 1) < argc) { - nprocs_wenq = atoi(argv[++i]); - continue; - } + if (strcmp(a, "--wdeq") == 0 && (i + 1) < argc) { + nprocs_wdeq = atoi(argv[++i]); + continue; + } - if (strcmp(a, "--wdeq") == 0 && (i + 1) < argc) { - nprocs_wdeq = atoi(argv[++i]); - continue; - } + if (strcmp(a, "--ed") == 0 && (i + 1) < argc) { + nprocs_enq_deq = atoi(argv[++i]); + continue; + } - if (strcmp(a, "--ed") == 0 && (i + 1) < argc) { - nprocs_enq_deq = atoi(argv[++i]); - continue; - } + if (strcmp(a, "--cas") == 0 && (i + 1) < argc) { + nprocs_cas = atoi(argv[++i]); + continue; + } - if (strcmp(a, "--cas") == 0 && (i + 1) < argc) { - nprocs_cas = atoi(argv[++i]); - continue; - } + if (strcmp(a, "--faa") == 0 && (i + 1) < argc) { + nprocs_faa = atoi(argv[++i]); + continue; + } - if (strcmp(a, "--faa") == 0 && (i + 1) < argc) { - nprocs_faa = atoi(argv[++i]); - continue; - } + if (strcmp(a, "--obj") == 0 && (i + 1) < argc) { + objective = atoi(argv[++i]); + continue; + } - if (strcmp(a, "--obj") == 0 && (i + 1) < argc) { - objective = atoi(argv[++i]); - continue; - } + printf("unknown option %s", a); - printf("unknown option %s", a); + return 1; + } - return 1; - } + if (nxt_lib_start("ncq_test", argv, &environ) != NXT_OK) { + return 1; + } - if (nxt_lib_start("ncq_test", argv, &environ) != NXT_OK) { - return 1; - } + nprocs = nprocs_enq + nprocs_deq + nprocs_wenq + nprocs_wdeq + + nprocs_enq_deq + nprocs_cas + nprocs_faa; - nprocs = nprocs_enq + nprocs_deq + nprocs_wenq + nprocs_wdeq - + nprocs_enq_deq + nprocs_cas + nprocs_faa; + if (nprocs == 0) { + return 0; + } - if (nprocs == 0) { - return 0; - } + nxt_main_log.level = NXT_LOG_INFO; + task.log = &nxt_main_log; - nxt_main_log.level = NXT_LOG_INFO; - task.log = &nxt_main_log; + thr = nxt_thread(); + thr->task = &task; - thr = nxt_thread(); - thr->task = &task; + pgq = mmap(NULL, sizeof(nxt_cq_t), PROT_READ | PROT_WRITE, + MAP_ANON | MAP_SHARED, -1, 0); + if (pgq == MAP_FAILED) { + return 2; + } - pgq = mmap(NULL, sizeof(nxt_cq_t), PROT_READ | PROT_WRITE, - MAP_ANON | MAP_SHARED, -1, 0); - if (pgq == MAP_FAILED) { - return 2; - } + nxt_cq_init(&pgq->free_queue); + nxt_cq_init(&pgq->active_queue); + + for (i = 0; i < NXT_CQ_SIZE; i++) { + nxt_cq_enqueue(&pgq->free_queue, i); + } + + if (verbose >= 1) { + printf("number of workers: %d\n", (int)nprocs); + printf("number of ops: %d\n", (int)nops); + } + + wi = mmap(NULL, nprocs * sizeof(nxt_worker_info_t), PROT_READ | PROT_WRITE, + MAP_ANON | MAP_SHARED, -1, 0); + if (wi == MAP_FAILED) { + return 3; + } + + for (k = 0; k < MAX_ITER; k++) { + nxt_memzero(wi, nprocs * sizeof(nxt_worker_info_t)); nxt_cq_init(&pgq->free_queue); nxt_cq_init(&pgq->active_queue); - for(i = 0; i < NXT_CQ_SIZE; i++) { - nxt_cq_enqueue(&pgq->free_queue, i); + for (i = 0; i < NXT_CQ_SIZE; i++) { + nxt_cq_enqueue(&pgq->free_queue, i); } - if (verbose >= 1) { - printf("number of workers: %d\n", (int) nprocs); - printf("number of ops: %d\n", (int) nops); + start = elapsed_time(0); + + id = 0; + + for (j = 0; j < nprocs_enq; j++, id++) { + worker_create(wi + id, id, enq_worker); } - wi = mmap(NULL, nprocs * sizeof(nxt_worker_info_t), PROT_READ | PROT_WRITE, - MAP_ANON | MAP_SHARED, -1, 0); - if (wi == MAP_FAILED) { - return 3; + for (j = 0; j < nprocs_deq; j++, id++) { + worker_create(wi + id, id, deq_worker); } - for (k = 0; k < MAX_ITER; k++) { - nxt_memzero(wi, nprocs * sizeof(nxt_worker_info_t)); + for (j = 0; j < nprocs_wenq; j++, id++) { + worker_create(wi + id, id, wenq_worker); + } - nxt_cq_init(&pgq->free_queue); - nxt_cq_init(&pgq->active_queue); + for (j = 0; j < nprocs_wdeq; j++, id++) { + worker_create(wi + id, id, wdeq_worker); + } - for(i = 0; i < NXT_CQ_SIZE; i++) { - nxt_cq_enqueue(&pgq->free_queue, i); - } + for (j = 0; j < nprocs_enq_deq; j++, id++) { + worker_create(wi + id, id, enq_deq_worker); + } - start = elapsed_time(0); + for (j = 0; j < nprocs_cas; j++, id++) { + worker_create(wi + id, id, cas_worker); + } - id = 0; + for (j = 0; j < nprocs_faa; j++, id++) { + worker_create(wi + id, id, faa_worker); + } - for (j = 0; j < nprocs_enq; j++, id++) { - worker_create(wi + id, id, enq_worker); - } + for (j = 0; j < nprocs; j++) { + worker_wait(wi + j); + } - for (j = 0; j < nprocs_deq; j++, id++) { - worker_create(wi + id, id, deq_worker); - } + elapsed = elapsed_time(start); - for (j = 0; j < nprocs_wenq; j++, id++) { - worker_create(wi + id, id, wenq_worker); - } + for (j = 1; j < nprocs; j++) { + wi[0].enq += wi[j].enq; + wi[0].deq += wi[j].deq; + wi[0].wait_enq += wi[j].wait_enq; + wi[0].wait_deq += wi[j].wait_deq; + wi[0].own_res += wi[j].own_res; + wi[0].cas += wi[j].cas; + wi[0].faa += wi[j].faa; + } - for (j = 0; j < nprocs_wdeq; j++, id++) { - worker_create(wi + id, id, wdeq_worker); - } + total_ops = wi[0].enq + wi[0].deq + wi[0].cas + wi[0].faa; - for (j = 0; j < nprocs_enq_deq; j++, id++) { - worker_create(wi + id, id, enq_deq_worker); - } + if (total_ops == 0) { + total_ops = nops; + } - for (j = 0; j < nprocs_cas; j++, id++) { - worker_create(wi + id, id, cas_worker); - } + times[k] = elapsed / 1000.0; + mopsec[k] = (double)total_ops / elapsed; + + if (verbose >= 2) { + printf("enq %10" PRIu64 "\n", wi[0].enq); + printf("deq %10" PRIu64 "\n", wi[0].deq); + printf("wait_enq %10" PRIu64 "\n", wi[0].wait_enq); + printf("wait_deq %10" PRIu64 "\n", wi[0].wait_deq); + printf("own_res %10" PRIu64 "\n", wi[0].own_res); + printf("cas %10" PRIu64 "\n", wi[0].cas); + printf("faa %10" PRIu64 "\n", wi[0].faa); + printf("total ops %10" PRIu64 "\n", total_ops); + printf("Mops/sec %13.2f\n", mopsec[k]); + + printf("elapsed %10d us\n", (int)elapsed); + printf("per op %10d ns\n", (int)((1000 * elapsed) / total_ops)); + } - for (j = 0; j < nprocs_faa; j++, id++) { - worker_create(wi + id, id, faa_worker); - } + if (k >= STAT_ITER) { + stats = (objective == 0) ? times : mopsec; - for (j = 0; j < nprocs; j++) { - worker_wait(wi + j); - } + m = mean(stats + k - STAT_ITER, STAT_ITER); + c = cov(stats + k - STAT_ITER, m, STAT_ITER); - elapsed = elapsed_time(start); + if (verbose >= 1) { + if (objective == 0) { + printf(" #%02d elapsed time: %.2f ms; Mops/sec %.2f; " + "mean time %.2f ms; cov %.4f\n", + (int)k + 1, times[k], mopsec[k], m, c); - for (j = 1; j < nprocs; j++) { - wi[0].enq += wi[j].enq; - wi[0].deq += wi[j].deq; - wi[0].wait_enq += wi[j].wait_enq; - wi[0].wait_deq += wi[j].wait_deq; - wi[0].own_res += wi[j].own_res; - wi[0].cas += wi[j].cas; - wi[0].faa += wi[j].faa; + } else { + printf(" #%02d elapsed time: %.2f ms; Mops/sec %.2f; " + "mean Mop/sec %.2f; cov %.4f\n", + (int)k + 1, times[k], mopsec[k], m, c); } + } - total_ops = wi[0].enq + wi[0].deq + wi[0].cas + wi[0].faa; - - if (total_ops == 0) { - total_ops = nops; - } + if (c < MIN_COV) { + rk = k - STAT_ITER; - times[k] = elapsed / 1000.0; - mopsec[k] = (double) total_ops / elapsed; - - if (verbose >= 2) { - printf("enq %10"PRIu64"\n", wi[0].enq); - printf("deq %10"PRIu64"\n", wi[0].deq); - printf("wait_enq %10"PRIu64"\n", wi[0].wait_enq); - printf("wait_deq %10"PRIu64"\n", wi[0].wait_deq); - printf("own_res %10"PRIu64"\n", wi[0].own_res); - printf("cas %10"PRIu64"\n", wi[0].cas); - printf("faa %10"PRIu64"\n", wi[0].faa); - printf("total ops %10"PRIu64"\n", total_ops); - printf("Mops/sec %13.2f\n", mopsec[k]); - - printf("elapsed %10d us\n", (int) elapsed); - printf("per op %10d ns\n", (int) ((1000 * elapsed) / total_ops)); + for (i = rk + 1; i <= k; i++) { + if (fabs(stats[i] - m) < fabs(stats[rk] - m)) { + rk = i; + } } - if (k >= STAT_ITER) { - stats = (objective == 0) ? times : mopsec; + printf("#%d %.2f ms; %.2f\n", rk, times[rk], mopsec[rk]); - m = mean(stats + k - STAT_ITER, STAT_ITER); - c = cov(stats + k - STAT_ITER, m, STAT_ITER); - - if (verbose >= 1) { - if (objective == 0) { - printf(" #%02d elapsed time: %.2f ms; Mops/sec %.2f; " - "mean time %.2f ms; cov %.4f\n", - (int) k + 1, times[k], mopsec[k], m, c); - - } else { - printf(" #%02d elapsed time: %.2f ms; Mops/sec %.2f; " - "mean Mop/sec %.2f; cov %.4f\n", - (int) k + 1, times[k], mopsec[k], m, c); - } - } - - if (c < MIN_COV) { - rk = k - STAT_ITER; - - for (i = rk + 1; i <= k; i++) { - if (fabs(stats[i] - m) < fabs(stats[rk] - m)) { - rk = i; - } - } - - printf("#%d %.2f ms; %.2f\n", rk, times[rk], mopsec[rk]); - - return 0; - } + return 0; + } - } else { - if (verbose >= 1) { - printf(" #%02d elapsed time: %.2f ms; Mops/sec %.2f\n", - (int) k + 1, times[k], mopsec[k]); - } - } + } else { + if (verbose >= 1) { + printf(" #%02d elapsed time: %.2f ms; Mops/sec %.2f\n", (int)k + 1, + times[k], mopsec[k]); + } } + } - return 0; + return 0; } diff --git a/src/test/nxt_gmtime_test.c b/src/test/nxt_gmtime_test.c index cec81ab45..e3ca7f11e 100644 --- a/src/test/nxt_gmtime_test.c +++ b/src/test/nxt_gmtime_test.c @@ -7,78 +7,67 @@ #include #include "nxt_tests.h" - #if (NXT_TIME_T_SIZE == 4) /* A 86400-fold number below 2^31. */ -#define NXT_GMTIME_MAX 2147472000 +#define NXT_GMTIME_MAX 2147472000 #else /* * March 19, 29398 is maximum valid data if nxt_uint_t * is 4 bytes size whilst nxt_time_t is 8 bytes size. */ -#define NXT_GMTIME_MAX 865550793600 +#define NXT_GMTIME_MAX 865550793600 #endif +nxt_int_t nxt_gmtime_test(nxt_thread_t *thr) { + struct tm tm0, *tm1; + nxt_time_t s; + nxt_nsec_t start, end; -nxt_int_t -nxt_gmtime_test(nxt_thread_t *thr) -{ - struct tm tm0, *tm1; - nxt_time_t s; - nxt_nsec_t start, end; - - nxt_thread_time_update(thr); - nxt_log_error(NXT_LOG_NOTICE, thr->log, "gmtime test started"); - - for (s = 0; s < NXT_GMTIME_MAX; s += 86400) { - - nxt_gmtime(s, &tm0); - tm1 = gmtime(&s); - - if (tm0.tm_mday != tm1->tm_mday - || tm0.tm_mon != tm1->tm_mon - || tm0.tm_year != tm1->tm_year - || tm0.tm_yday != tm1->tm_yday - || tm0.tm_wday != tm1->tm_wday) - { - nxt_log_alert(thr->log, - "gmtime test failed: %T @ %02d.%02d.%d", - s, tm1->tm_mday, tm1->tm_mon + 1, - tm1->tm_year + 1900); - return NXT_ERROR; - } - } + nxt_thread_time_update(thr); + nxt_log_error(NXT_LOG_NOTICE, thr->log, "gmtime test started"); + for (s = 0; s < NXT_GMTIME_MAX; s += 86400) { - nxt_thread_time_update(thr); - start = nxt_thread_monotonic_time(thr); + nxt_gmtime(s, &tm0); + tm1 = gmtime(&s); - for (s = 0; s < 10000000; s++) { - nxt_gmtime(s, &tm0); + if (tm0.tm_mday != tm1->tm_mday || tm0.tm_mon != tm1->tm_mon || + tm0.tm_year != tm1->tm_year || tm0.tm_yday != tm1->tm_yday || + tm0.tm_wday != tm1->tm_wday) { + nxt_log_alert(thr->log, "gmtime test failed: %T @ %02d.%02d.%d", s, + tm1->tm_mday, tm1->tm_mon + 1, tm1->tm_year + 1900); + return NXT_ERROR; } + } - nxt_thread_time_update(thr); - end = nxt_thread_monotonic_time(thr); + nxt_thread_time_update(thr); + start = nxt_thread_monotonic_time(thr); - nxt_log_error(NXT_LOG_NOTICE, thr->log, "nxt_gmtime(): %0.1fns", - (end - start) / 10000000.0); + for (s = 0; s < 10000000; s++) { + nxt_gmtime(s, &tm0); + } + nxt_thread_time_update(thr); + end = nxt_thread_monotonic_time(thr); - nxt_thread_time_update(thr); - start = nxt_thread_monotonic_time(thr); + nxt_log_error(NXT_LOG_NOTICE, thr->log, "nxt_gmtime(): %0.1fns", + (end - start) / 10000000.0); - for (s = 0; s < 10000000; s++) { - (void) gmtime(&s); - } + nxt_thread_time_update(thr); + start = nxt_thread_monotonic_time(thr); + + for (s = 0; s < 10000000; s++) { + (void)gmtime(&s); + } - nxt_thread_time_update(thr); - end = nxt_thread_monotonic_time(thr); + nxt_thread_time_update(thr); + end = nxt_thread_monotonic_time(thr); - nxt_log_error(NXT_LOG_NOTICE, thr->log, "gmtime(): %0.1fns", - (end - start) / 10000000.0); + nxt_log_error(NXT_LOG_NOTICE, thr->log, "gmtime(): %0.1fns", + (end - start) / 10000000.0); - nxt_log_error(NXT_LOG_NOTICE, thr->log, "gmtime test passed"); - return NXT_OK; + nxt_log_error(NXT_LOG_NOTICE, thr->log, "gmtime test passed"); + return NXT_OK; } diff --git a/src/test/nxt_http_parse_test.c b/src/test/nxt_http_parse_test.c index 474b3f8d2..4ed65cdec 100644 --- a/src/test/nxt_http_parse_test.c +++ b/src/test/nxt_http_parse_test.c @@ -7,776 +7,608 @@ #include #include "nxt_tests.h" - typedef struct { - nxt_str_t method; - nxt_str_t target; - nxt_str_t args; - u_char version[8]; - - /* target with "/." */ - unsigned complex_target:1; - /* target with "%" */ - unsigned quoted_target:1; - /* target with " " */ - unsigned space_in_target:1; + nxt_str_t method; + nxt_str_t target; + nxt_str_t args; + u_char version[8]; + + /* target with "/." */ + unsigned complex_target : 1; + /* target with "%" */ + unsigned quoted_target : 1; + /* target with " " */ + unsigned space_in_target : 1; } nxt_http_parse_test_request_line_t; - typedef struct { - nxt_int_t result; - unsigned discard_unsafe_fields:1; + nxt_int_t result; + unsigned discard_unsafe_fields : 1; } nxt_http_parse_test_fields_t; - typedef union { - void *pointer; - nxt_http_parse_test_fields_t fields; - nxt_http_parse_test_request_line_t request_line; + void *pointer; + nxt_http_parse_test_fields_t fields; + nxt_http_parse_test_request_line_t request_line; } nxt_http_parse_test_data_t; - typedef struct { - nxt_str_t request; - nxt_int_t result; - nxt_int_t (*handler)(nxt_http_request_parse_t *rp, - nxt_http_parse_test_data_t *data, - nxt_str_t *request, nxt_log_t *log); + nxt_str_t request; + nxt_int_t result; + nxt_int_t (*handler)(nxt_http_request_parse_t *rp, + nxt_http_parse_test_data_t *data, nxt_str_t *request, + nxt_log_t *log); - nxt_http_parse_test_data_t data; + nxt_http_parse_test_data_t data; } nxt_http_parse_test_case_t; - static nxt_int_t nxt_http_parse_test_run(nxt_http_request_parse_t *rp, - nxt_str_t *request); + nxt_str_t *request); static nxt_int_t nxt_http_parse_test_bench(nxt_thread_t *thr, - nxt_str_t *request, nxt_lvlhsh_t *hash, const char *name, nxt_uint_t n); -static nxt_int_t nxt_http_parse_test_request_line(nxt_http_request_parse_t *rp, - nxt_http_parse_test_data_t *data, - nxt_str_t *request, nxt_log_t *log); + nxt_str_t *request, + nxt_lvlhsh_t *hash, const char *name, + nxt_uint_t n); +static nxt_int_t +nxt_http_parse_test_request_line(nxt_http_request_parse_t *rp, + nxt_http_parse_test_data_t *data, + nxt_str_t *request, nxt_log_t *log); static nxt_int_t nxt_http_parse_test_fields(nxt_http_request_parse_t *rp, - nxt_http_parse_test_data_t *data, nxt_str_t *request, nxt_log_t *log); - + nxt_http_parse_test_data_t *data, + nxt_str_t *request, nxt_log_t *log); static nxt_int_t nxt_http_test_header_return(void *ctx, nxt_http_field_t *field, - uintptr_t data); - - -static nxt_http_parse_test_case_t nxt_http_test_cases[] = { - { - nxt_string("GET / HTTP/1.0\r\n\r\n"), - NXT_DONE, - &nxt_http_parse_test_request_line, - { .request_line = { - nxt_string("GET"), - nxt_string("/"), - nxt_null_string, - "HTTP/1.0", - 0, 0, 0 - }} - }, - { - nxt_string("XXX-METHOD /d.ir/fi+le.ext?key=val HTTP/1.2\n\n"), - NXT_DONE, - &nxt_http_parse_test_request_line, - { .request_line = { - nxt_string("XXX-METHOD"), - nxt_string("/d.ir/fi+le.ext?key=val"), - nxt_string("key=val"), - "HTTP/1.2", - 0, 0, 0 - }} - }, - { - nxt_string("GET /di.r/? HTTP/1.0\r\n\r\n"), - NXT_DONE, - &nxt_http_parse_test_request_line, - { .request_line = { - nxt_string("GET"), - nxt_string("/di.r/?"), - nxt_string(""), - "HTTP/1.0", - 0, 0, 0 - }} - }, - { - nxt_string("GEt / HTTP/1.0\r\n\r\n"), - NXT_HTTP_PARSE_INVALID, - NULL, { NULL } - }, - { - nxt_string("GET /\0 HTTP/1.0\r\n\r\n"), - NXT_HTTP_PARSE_INVALID, - NULL, { NULL } - }, - { - nxt_string("GET /\r HTTP/1.0\r\n\r\n"), - NXT_HTTP_PARSE_INVALID, - NULL, { NULL } - }, - { - nxt_string("GET /\n HTTP/1.0\r\n\r\n"), - NXT_HTTP_PARSE_INVALID, - NULL, { NULL } - }, - { - nxt_string("GET / HTTP/1.0\r\r\n"), - NXT_HTTP_PARSE_INVALID, - NULL, { NULL } - }, - { - nxt_string("GET / HTTP/2.0\r\n"), - NXT_HTTP_PARSE_UNSUPPORTED_VERSION, - NULL, { NULL } - }, - { - nxt_string("GET /. HTTP/1.0\r\n\r\n"), - NXT_DONE, - &nxt_http_parse_test_request_line, - { .request_line = { - nxt_string("GET"), - nxt_string("/."), - nxt_null_string, - "HTTP/1.0", - 1, 0, 0 - }} - }, - { - nxt_string("GET /# HTTP/1.0\r\n\r\n"), - NXT_DONE, - &nxt_http_parse_test_request_line, - { .request_line = { - nxt_string("GET"), - nxt_string("/#"), - nxt_null_string, - "HTTP/1.0", - 1, 0, 0 - }} - }, - { - nxt_string("GET /?# HTTP/1.0\r\n\r\n"), - NXT_DONE, - &nxt_http_parse_test_request_line, - { .request_line = { - nxt_string("GET"), - nxt_string("/?#"), - nxt_string(""), - "HTTP/1.0", - 1, 0, 0 - }} - }, - { - nxt_string("GET // HTTP/1.0\r\n\r\n"), - NXT_DONE, - &nxt_http_parse_test_request_line, - { .request_line = { - nxt_string("GET"), - nxt_string("//"), - nxt_null_string, - "HTTP/1.0", - 1, 0, 0 - }} - }, - { - nxt_string("GET /%20 HTTP/1.0\r\n\r\n"), - NXT_DONE, - &nxt_http_parse_test_request_line, - { .request_line = { - nxt_string("GET"), - nxt_string("/%20"), - nxt_null_string, - "HTTP/1.0", - 0, 1, 0 - }} - }, - { - nxt_string("GET / a HTTP/1.0\r\n\r\n"), - NXT_DONE, - &nxt_http_parse_test_request_line, - { .request_line = { - nxt_string("GET"), - nxt_string("/ a"), - nxt_null_string, - "HTTP/1.0", - 0, 0, 1 - }} - }, - { - nxt_string("GET /na %20me.ext?args HTTP/1.0\r\n\r\n"), - NXT_DONE, - &nxt_http_parse_test_request_line, - { .request_line = { - nxt_string("GET"), - nxt_string("/na %20me.ext?args"), - nxt_string("args"), - "HTTP/1.0", - 0, 1, 1 - }} - }, - { - nxt_string("GET / HTTP/1.0 HTTP/1.1\r\n\r\n"), - NXT_DONE, - &nxt_http_parse_test_request_line, - { .request_line = { - nxt_string("GET"), - nxt_string("/ HTTP/1.0"), - nxt_null_string, - "HTTP/1.1", - 0, 0, 1 - }} - }, - { - nxt_string("GET / HTTP/1.1\r\n" - "Host: example.com\r\n\r\n"), - NXT_DONE, - NULL, { NULL } - }, - { - nxt_string("GET / HTTP/1.1\r\n" - "Host:example.com \r\n\r\n"), - NXT_DONE, - NULL, { NULL } - }, - { - nxt_string("GET / HTTP/1.1\r\n" - "Host:\r\n\r\n"), - NXT_DONE, - NULL, { NULL } - }, - { - nxt_string("GET / HTTP/1.1\r\n" - "Host example.com\r\n\r\n"), - NXT_HTTP_PARSE_INVALID, - NULL, { NULL } - }, - { - nxt_string("GET / HTTP/1.1\r\n" - ":Host: example.com\r\n\r\n"), - NXT_HTTP_PARSE_INVALID, - NULL, { NULL } - }, - { - nxt_string("GET / HTTP/1.1\r\n" - "Ho_st: example.com\r\n\r\n"), - NXT_DONE, - NULL, { NULL } - }, - { - nxt_string("GET / HTTP/1.1\r\n" - "Ho\0st: example.com\r\n\r\n"), - NXT_HTTP_PARSE_INVALID, - NULL, { NULL } - }, - { - nxt_string("GET / HTTP/1.1\r\n" - "Ho\rst: example.com\r\n\r\n"), - NXT_HTTP_PARSE_INVALID, - NULL, { NULL } - }, - { - nxt_string("GET / HTTP/1.1\r\n" - "Ho\nst: example.com\r\n\r\n"), - NXT_HTTP_PARSE_INVALID, - NULL, { NULL } - }, - { - nxt_string("GET / HTTP/1.1\r\n" - "Host : example.com\r\n\r\n"), - NXT_HTTP_PARSE_INVALID, - NULL, { NULL } - }, - { - nxt_string("GET / HTTP/1.1\r\n" - "Host: exa\0mple.com\r\n\r\n"), - NXT_HTTP_PARSE_INVALID, - NULL, { NULL } - }, - { - nxt_string("GET / HTTP/1.1\r\n" - "Host: exa\rmple.com\r\n\r\n"), - NXT_HTTP_PARSE_INVALID, - NULL, { NULL } - }, - { - nxt_string("GET / HTTP/1.1\r\n" - "Host: exa\bmple.com\r\n\r\n"), - NXT_HTTP_PARSE_INVALID, - NULL, { NULL } - }, - { - nxt_string("GET / HTTP/1.1\r\n" - "Host: пример.испытание\r\n\r\n"), - NXT_DONE, - NULL, { NULL } - }, - { - nxt_string("GET / HTTP/1.1\r\n" - "Host: xn--e1afmkfd.xn--80akhbyknj4f\r\n\r\n"), - NXT_DONE, - NULL, { NULL } - }, - { - nxt_string("GET / HTTP/1.1\r\n" - "Host: exa\nmple.com\r\n\r\n"), - NXT_HTTP_PARSE_INVALID, - NULL, { NULL } - }, - { - nxt_string("GET / HTTP/1.1\r\n" - "Host: exa\tmple.com\r\n\r\n"), - NXT_DONE, - NULL, { NULL } - }, - { - nxt_string("GET / HTTP/1.1\r\n" - "X-Unknown-Header: value\r\n" - "X-Good-Header: value\r\n" - "!#$%&'*+.^_`|~: skipped\r\n\r\n"), - NXT_DONE, - &nxt_http_parse_test_fields, - { .fields = { NXT_OK, 1 } } - }, - { - nxt_string("GET / HTTP/1.1\r\n" - "X-Good-Header: value\r\n" - "X-Unknown-Header: value\r\n" - "X-Bad-Header: value\r\n\r\n"), - NXT_DONE, - &nxt_http_parse_test_fields, - { .fields = { NXT_ERROR, 1 } } - }, - { - nxt_string("GET / HTTP/1.1\r\n" - "!#$%&'*+.^_`|~: allowed\r\n\r\n"), - NXT_DONE, - &nxt_http_parse_test_fields, - { .fields = { NXT_ERROR, 0 } } - }, + uintptr_t data); + +static nxt_http_parse_test_case_t nxt_http_test_cases[] = { + {nxt_string("GET / HTTP/1.0\r\n\r\n"), + NXT_DONE, + &nxt_http_parse_test_request_line, + {.request_line = {nxt_string("GET"), nxt_string("/"), nxt_null_string, + "HTTP/1.0", 0, 0, 0}}}, + {nxt_string("XXX-METHOD /d.ir/fi+le.ext?key=val HTTP/1.2\n\n"), + NXT_DONE, + &nxt_http_parse_test_request_line, + {.request_line = {nxt_string("XXX-METHOD"), + nxt_string("/d.ir/fi+le.ext?key=val"), + nxt_string("key=val"), "HTTP/1.2", 0, 0, 0}}}, + {nxt_string("GET /di.r/? HTTP/1.0\r\n\r\n"), + NXT_DONE, + &nxt_http_parse_test_request_line, + {.request_line = {nxt_string("GET"), nxt_string("/di.r/?"), nxt_string(""), + "HTTP/1.0", 0, 0, 0}}}, + {nxt_string("GEt / HTTP/1.0\r\n\r\n"), + NXT_HTTP_PARSE_INVALID, + NULL, + {NULL}}, + {nxt_string("GET /\0 HTTP/1.0\r\n\r\n"), + NXT_HTTP_PARSE_INVALID, + NULL, + {NULL}}, + {nxt_string("GET /\r HTTP/1.0\r\n\r\n"), + NXT_HTTP_PARSE_INVALID, + NULL, + {NULL}}, + {nxt_string("GET /\n HTTP/1.0\r\n\r\n"), + NXT_HTTP_PARSE_INVALID, + NULL, + {NULL}}, + {nxt_string("GET / HTTP/1.0\r\r\n"), NXT_HTTP_PARSE_INVALID, NULL, {NULL}}, + {nxt_string("GET / HTTP/2.0\r\n"), + NXT_HTTP_PARSE_UNSUPPORTED_VERSION, + NULL, + {NULL}}, + {nxt_string("GET /. HTTP/1.0\r\n\r\n"), + NXT_DONE, + &nxt_http_parse_test_request_line, + {.request_line = {nxt_string("GET"), nxt_string("/."), nxt_null_string, + "HTTP/1.0", 1, 0, 0}}}, + {nxt_string("GET /# HTTP/1.0\r\n\r\n"), + NXT_DONE, + &nxt_http_parse_test_request_line, + {.request_line = {nxt_string("GET"), nxt_string("/#"), nxt_null_string, + "HTTP/1.0", 1, 0, 0}}}, + {nxt_string("GET /?# HTTP/1.0\r\n\r\n"), + NXT_DONE, + &nxt_http_parse_test_request_line, + {.request_line = {nxt_string("GET"), nxt_string("/?#"), nxt_string(""), + "HTTP/1.0", 1, 0, 0}}}, + {nxt_string("GET // HTTP/1.0\r\n\r\n"), + NXT_DONE, + &nxt_http_parse_test_request_line, + {.request_line = {nxt_string("GET"), nxt_string("//"), nxt_null_string, + "HTTP/1.0", 1, 0, 0}}}, + {nxt_string("GET /%20 HTTP/1.0\r\n\r\n"), + NXT_DONE, + &nxt_http_parse_test_request_line, + {.request_line = {nxt_string("GET"), nxt_string("/%20"), nxt_null_string, + "HTTP/1.0", 0, 1, 0}}}, + {nxt_string("GET / a HTTP/1.0\r\n\r\n"), + NXT_DONE, + &nxt_http_parse_test_request_line, + {.request_line = {nxt_string("GET"), nxt_string("/ a"), nxt_null_string, + "HTTP/1.0", 0, 0, 1}}}, + {nxt_string("GET /na %20me.ext?args HTTP/1.0\r\n\r\n"), + NXT_DONE, + &nxt_http_parse_test_request_line, + {.request_line = {nxt_string("GET"), nxt_string("/na %20me.ext?args"), + nxt_string("args"), "HTTP/1.0", 0, 1, 1}}}, + {nxt_string("GET / HTTP/1.0 HTTP/1.1\r\n\r\n"), + NXT_DONE, + &nxt_http_parse_test_request_line, + {.request_line = {nxt_string("GET"), nxt_string("/ HTTP/1.0"), + nxt_null_string, "HTTP/1.1", 0, 0, 1}}}, + {nxt_string("GET / HTTP/1.1\r\n" + "Host: example.com\r\n\r\n"), + NXT_DONE, + NULL, + {NULL}}, + {nxt_string("GET / HTTP/1.1\r\n" + "Host:example.com \r\n\r\n"), + NXT_DONE, + NULL, + {NULL}}, + {nxt_string("GET / HTTP/1.1\r\n" + "Host:\r\n\r\n"), + NXT_DONE, + NULL, + {NULL}}, + {nxt_string("GET / HTTP/1.1\r\n" + "Host example.com\r\n\r\n"), + NXT_HTTP_PARSE_INVALID, + NULL, + {NULL}}, + {nxt_string("GET / HTTP/1.1\r\n" + ":Host: example.com\r\n\r\n"), + NXT_HTTP_PARSE_INVALID, + NULL, + {NULL}}, + {nxt_string("GET / HTTP/1.1\r\n" + "Ho_st: example.com\r\n\r\n"), + NXT_DONE, + NULL, + {NULL}}, + {nxt_string("GET / HTTP/1.1\r\n" + "Ho\0st: example.com\r\n\r\n"), + NXT_HTTP_PARSE_INVALID, + NULL, + {NULL}}, + {nxt_string("GET / HTTP/1.1\r\n" + "Ho\rst: example.com\r\n\r\n"), + NXT_HTTP_PARSE_INVALID, + NULL, + {NULL}}, + {nxt_string("GET / HTTP/1.1\r\n" + "Ho\nst: example.com\r\n\r\n"), + NXT_HTTP_PARSE_INVALID, + NULL, + {NULL}}, + {nxt_string("GET / HTTP/1.1\r\n" + "Host : example.com\r\n\r\n"), + NXT_HTTP_PARSE_INVALID, + NULL, + {NULL}}, + {nxt_string("GET / HTTP/1.1\r\n" + "Host: exa\0mple.com\r\n\r\n"), + NXT_HTTP_PARSE_INVALID, + NULL, + {NULL}}, + {nxt_string("GET / HTTP/1.1\r\n" + "Host: exa\rmple.com\r\n\r\n"), + NXT_HTTP_PARSE_INVALID, + NULL, + {NULL}}, + {nxt_string("GET / HTTP/1.1\r\n" + "Host: exa\bmple.com\r\n\r\n"), + NXT_HTTP_PARSE_INVALID, + NULL, + {NULL}}, + {nxt_string("GET / HTTP/1.1\r\n" + "Host: пример.испытание\r\n\r\n"), + NXT_DONE, + NULL, + {NULL}}, + {nxt_string("GET / HTTP/1.1\r\n" + "Host: xn--e1afmkfd.xn--80akhbyknj4f\r\n\r\n"), + NXT_DONE, + NULL, + {NULL}}, + {nxt_string("GET / HTTP/1.1\r\n" + "Host: exa\nmple.com\r\n\r\n"), + NXT_HTTP_PARSE_INVALID, + NULL, + {NULL}}, + {nxt_string("GET / HTTP/1.1\r\n" + "Host: exa\tmple.com\r\n\r\n"), + NXT_DONE, + NULL, + {NULL}}, + {nxt_string("GET / HTTP/1.1\r\n" + "X-Unknown-Header: value\r\n" + "X-Good-Header: value\r\n" + "!#$%&'*+.^_`|~: skipped\r\n\r\n"), + NXT_DONE, + &nxt_http_parse_test_fields, + {.fields = {NXT_OK, 1}}}, + {nxt_string("GET / HTTP/1.1\r\n" + "X-Good-Header: value\r\n" + "X-Unknown-Header: value\r\n" + "X-Bad-Header: value\r\n\r\n"), + NXT_DONE, + &nxt_http_parse_test_fields, + {.fields = {NXT_ERROR, 1}}}, + {nxt_string("GET / HTTP/1.1\r\n" + "!#$%&'*+.^_`|~: allowed\r\n\r\n"), + NXT_DONE, + &nxt_http_parse_test_fields, + {.fields = {NXT_ERROR, 0}}}, }; +static nxt_http_field_proc_t nxt_http_test_fields[] = { + {nxt_string("X-Bad-Header"), &nxt_http_test_header_return, NXT_ERROR}, -static nxt_http_field_proc_t nxt_http_test_fields[] = { - { nxt_string("X-Bad-Header"), - &nxt_http_test_header_return, - NXT_ERROR }, - - { nxt_string("X-Good-Header"), - &nxt_http_test_header_return, - NXT_OK }, + {nxt_string("X-Good-Header"), &nxt_http_test_header_return, NXT_OK}, - { nxt_string("!#$%&'*+.^_`|~"), - &nxt_http_test_header_return, - NXT_ERROR }, + {nxt_string("!#$%&'*+.^_`|~"), &nxt_http_test_header_return, NXT_ERROR}, }; - -static nxt_lvlhsh_t nxt_http_test_fields_hash; - - -static nxt_http_field_proc_t nxt_http_test_bench_fields[] = { - { nxt_string("Host"), - &nxt_http_test_header_return, NXT_OK }, - { nxt_string("User-Agent"), - &nxt_http_test_header_return, NXT_OK }, - { nxt_string("Accept"), - &nxt_http_test_header_return, NXT_OK }, - { nxt_string("Accept-Encoding"), - &nxt_http_test_header_return, NXT_OK }, - { nxt_string("Accept-Language"), - &nxt_http_test_header_return, NXT_OK }, - { nxt_string("Connection"), - &nxt_http_test_header_return, NXT_OK }, - { nxt_string("Content-Length"), - &nxt_http_test_header_return, NXT_OK }, - { nxt_string("Content-Range"), - &nxt_http_test_header_return, NXT_OK }, - { nxt_string("Content-Type"), - &nxt_http_test_header_return, NXT_OK }, - { nxt_string("Cookie"), - &nxt_http_test_header_return, NXT_OK }, - { nxt_string("Range"), - &nxt_http_test_header_return, NXT_OK }, - { nxt_string("If-Range"), - &nxt_http_test_header_return, NXT_OK }, - { nxt_string("Transfer-Encoding"), - &nxt_http_test_header_return, NXT_OK }, - { nxt_string("Expect"), - &nxt_http_test_header_return, NXT_OK }, - { nxt_string("Via"), - &nxt_http_test_header_return, NXT_OK }, - { nxt_string("If-Modified-Since"), - &nxt_http_test_header_return, NXT_OK }, - { nxt_string("If-Unmodified-Since"), - &nxt_http_test_header_return, NXT_OK }, - { nxt_string("If-Match"), - &nxt_http_test_header_return, NXT_OK }, - { nxt_string("If-None-Match"), - &nxt_http_test_header_return, NXT_OK }, - { nxt_string("Referer"), - &nxt_http_test_header_return, NXT_OK }, - { nxt_string("Date"), - &nxt_http_test_header_return, NXT_OK }, - { nxt_string("Upgrade"), - &nxt_http_test_header_return, NXT_OK }, - { nxt_string("Authorization"), - &nxt_http_test_header_return, NXT_OK }, - { nxt_string("Keep-Alive"), - &nxt_http_test_header_return, NXT_OK }, - { nxt_string("X-Forwarded-For"), - &nxt_http_test_header_return, NXT_OK }, - { nxt_string("X-Forwarded-Host"), - &nxt_http_test_header_return, NXT_OK }, - { nxt_string("X-Forwarded-Proto"), - &nxt_http_test_header_return, NXT_OK }, - { nxt_string("X-Http-Method-Override"), - &nxt_http_test_header_return, NXT_OK }, - { nxt_string("X-Real-IP"), - &nxt_http_test_header_return, NXT_OK }, - { nxt_string("X-Request-ID"), - &nxt_http_test_header_return, NXT_OK }, - { nxt_string("TE"), - &nxt_http_test_header_return, NXT_OK }, - { nxt_string("Pragma"), - &nxt_http_test_header_return, NXT_OK }, - { nxt_string("Cache-Control"), - &nxt_http_test_header_return, NXT_OK }, - { nxt_string("Origin"), - &nxt_http_test_header_return, NXT_OK }, - { nxt_string("Upgrade-Insecure-Requests"), - &nxt_http_test_header_return, NXT_OK }, +static nxt_lvlhsh_t nxt_http_test_fields_hash; + +static nxt_http_field_proc_t nxt_http_test_bench_fields[] = { + {nxt_string("Host"), &nxt_http_test_header_return, NXT_OK}, + {nxt_string("User-Agent"), &nxt_http_test_header_return, NXT_OK}, + {nxt_string("Accept"), &nxt_http_test_header_return, NXT_OK}, + {nxt_string("Accept-Encoding"), &nxt_http_test_header_return, NXT_OK}, + {nxt_string("Accept-Language"), &nxt_http_test_header_return, NXT_OK}, + {nxt_string("Connection"), &nxt_http_test_header_return, NXT_OK}, + {nxt_string("Content-Length"), &nxt_http_test_header_return, NXT_OK}, + {nxt_string("Content-Range"), &nxt_http_test_header_return, NXT_OK}, + {nxt_string("Content-Type"), &nxt_http_test_header_return, NXT_OK}, + {nxt_string("Cookie"), &nxt_http_test_header_return, NXT_OK}, + {nxt_string("Range"), &nxt_http_test_header_return, NXT_OK}, + {nxt_string("If-Range"), &nxt_http_test_header_return, NXT_OK}, + {nxt_string("Transfer-Encoding"), &nxt_http_test_header_return, NXT_OK}, + {nxt_string("Expect"), &nxt_http_test_header_return, NXT_OK}, + {nxt_string("Via"), &nxt_http_test_header_return, NXT_OK}, + {nxt_string("If-Modified-Since"), &nxt_http_test_header_return, NXT_OK}, + {nxt_string("If-Unmodified-Since"), &nxt_http_test_header_return, NXT_OK}, + {nxt_string("If-Match"), &nxt_http_test_header_return, NXT_OK}, + {nxt_string("If-None-Match"), &nxt_http_test_header_return, NXT_OK}, + {nxt_string("Referer"), &nxt_http_test_header_return, NXT_OK}, + {nxt_string("Date"), &nxt_http_test_header_return, NXT_OK}, + {nxt_string("Upgrade"), &nxt_http_test_header_return, NXT_OK}, + {nxt_string("Authorization"), &nxt_http_test_header_return, NXT_OK}, + {nxt_string("Keep-Alive"), &nxt_http_test_header_return, NXT_OK}, + {nxt_string("X-Forwarded-For"), &nxt_http_test_header_return, NXT_OK}, + {nxt_string("X-Forwarded-Host"), &nxt_http_test_header_return, NXT_OK}, + {nxt_string("X-Forwarded-Proto"), &nxt_http_test_header_return, NXT_OK}, + {nxt_string("X-Http-Method-Override"), &nxt_http_test_header_return, + NXT_OK}, + {nxt_string("X-Real-IP"), &nxt_http_test_header_return, NXT_OK}, + {nxt_string("X-Request-ID"), &nxt_http_test_header_return, NXT_OK}, + {nxt_string("TE"), &nxt_http_test_header_return, NXT_OK}, + {nxt_string("Pragma"), &nxt_http_test_header_return, NXT_OK}, + {nxt_string("Cache-Control"), &nxt_http_test_header_return, NXT_OK}, + {nxt_string("Origin"), &nxt_http_test_header_return, NXT_OK}, + {nxt_string("Upgrade-Insecure-Requests"), &nxt_http_test_header_return, + NXT_OK}, }; - -static nxt_str_t nxt_http_test_simple_request = nxt_string( - "GET /page HTTP/1.1\r\n" - "Host: example.com\r\n\r\n" -); - +static nxt_str_t nxt_http_test_simple_request = + nxt_string("GET /page HTTP/1.1\r\n" + "Host: example.com\r\n\r\n"); static nxt_str_t nxt_http_test_big_request = nxt_string( "POST /path/to/very/interesting/article/on.this.site?arg1=value&arg2=value" - "2&very_big_arg=even_bigger_value HTTP/1.1\r\n" + "2&very_big_arg=even_bigger_value HTTP/1.1\r\n" "Host: www.example.com\r\n" "User-Agent: Mozilla/5.0 (X11; Gentoo Linux x86_64; rv:42.0) Firefox/42.0" - "\r\n" + "\r\n" "Accept: text/html,application/json,application/xml;q=0.9,*/*;q=0.8\r\n" "Accept-Language: ru-RU,ru;q=0.8,en-US;q=0.6,en;q=0.4\r\n" "Accept-Encoding: gzip, deflate, br\r\n" "If-Modified-Since: Wed, 31 Dec 1986 16:00:00 GMT\r\n" "Referer: https://example.org/path/to/not-interesting/article.html\r\n" "Cookie: name=value; name2=value2; some_big_cookie=iVBORw0KGgoAAAANSUhEUgA" - "AAEAAAABACAMAAACdt4HsAAAABGdBTUEAALGPC/xhBQAAAAFzUkdCAK7OHOkAAABmelRY" - "dFJhdyBwcm9maWxlIHR5cGUgZXhpZgAAeNptitsJgEAMBP9ThSWsZy6PcvKhcB1YvjEni" - "ODAwjAs7ec4aCmkEXc1cREk7OwtUgyTFRA3BU+vFPjS7gUI/p46Q0u2fP/1B7oA1Scbwk" - "nkf9gAAAAJcEhZcwAADsMAAA7DAcdvqGQAAACfUExURQwMDDw8PFBQUAICAhQUFAcHBxs" - "bGxEREQkJCTk5OTU1NSAgIFRUVB8fH0xMTCUlJVtbW0pKSikpKS8vL0BAQEZGRjMzM2Bg" - "YL6+vsDAwLS0tF1dXXJycrGxsWVlZWhoaKenp29vb6urq8TExHp6epSUlLu7u66urqOjo" - "5ycnH9/f4CAgJOTk5qamo6OjoWFhYiIiHd3d8nJyc/Pz9LS0ojXP1QAAAihSURBVFjDZV" - "eHdqM6EBUYEEh0EM3gCu41+/7/294dCSfZsxOHeM8yV3f6iGVGYohNEtJPGEjPiSLpMTz" - "zokg8DmGOCOm/P0I6MTPaBGDPCGEYV3kEzchjzPOSPIkk8BzuM8fSCOFfALER+6MdpnaV" - "55FMoOP7UliioK8QzpiT0Qv0Fl4lDJvFPwChETuHFjhw7vhRVcGAXDqcfhhnRaZUWeJTW" - "pYVCBEYAJihtCsUpIhyq6win3ueDCoRBIknJRwACtz3AJhDYBhESsmyEjhaKv0MRJIIFR" - "d4XyYqC1RWwQFeBF2CcApCmEFI2KwHTRIrsMq8UnYcRUkehKtlaGeq8BjowKHEQf7oEgH" - "JcKRWpSeZpTIrs5dKlGX9fF7GfrtdWqDAuce1IyOtLbWyRKRYIIIPBo63gswO07q20/p6" - "2txvj+flvUZUZeQ4IODBGDoYivoReREzugaAJKuX637dP0/DbnMGwuWyTTNlBYX0ItL3E" - "q2ptUmYZi9+ANLt9r2+nrqmORKD1/W9Xi3hirisEumQOz+qRv5hUL/H1bg7tG0znKbHCy" - "Zs16u6TgmiQH5rLW2Ltslhf6kjO1bjOJ4PTfu1PwDgeR0BsF6BBCBQIThee+P78QvAQNS" - "X17mD/tfXYaMBejAAhWWahqoiB5q8dmYQ9rc+AF7Trmn2BLC7vy4XQ0ADpHZmJRQPznVO" - "0YcABJRnBwBg+Tofm3a//2q7zYREIAAyAQRQQKqAJ/ksH4CPC4wJy9uma2eA2+syjtsVn" - "LicKzDTRYaqMgi/AQyHQNSPY0uyb7vdHVEcezDQBhAHJXLPqLOZxN8+CLJVehmapoUX2u" - "54okzsIXACucAOYyunov62AUDiN0IQd69+dyAf7PfdsLlRGAGwXekowIgySRzoMzZzcAj" - "gpxIs9Ti+TsTghLMvV1Lfbvt+vbTR9ZAJtlWoXxSIwaxuohCUt8Pp3LTd+XHt01KF9XZL" - "iRhXkSwKCzYg7X2NwGYYJsRvCHU6nndNO3SH4TauV9v3OK7rUKHnUJaiTxRl4XODwD8mC" - "Gptn0Q8j1e4oOmmfi0iZY/naRuWaIyiNI1bxDljs/7M4Hcxlta9fzTd/qubrrdYpNZ2GL" - "ZxgJboFkmFVhGLLPE/6ubPp5nNTphOAGj/QHavtZ292t3KLouiQocqbXhRKOlr+/9hoA0" - "og/d+dzi0/+2b7nTr60vXbtZhJkQZx2GaLsNMxZ8ozk5gphN/M4i79nBo/uwHdJPn1Db7" - "c40aUgoDRVdTmhn3awbsXxOs4PZfc2i+vrrTNCEe+/0JnTmkoZOiJcT2co4i5z9hnHu6Z" - "bxoT7sWAM3mfp9O7Vd7rnUV6E8ap2lk/MdmJzD2eyRohKrf4+DmON2ej6HZ31epnnqpLg" - "ZV8dmFMw6fB0vww0Gs903ToJaviOifdnrXS6SxhgjjxNEF9BH6VlUVMKqf+STqPTLpeHr" - "0l2HYHaYeHohVZiOIYUYjhjHfx0cLAHI96Qrzi4BXeYxiRi94PjeH4/k8xshgO8u0HYoI" - "EIDvQgzEPOJIaGAlSSQQye54nzbH3Wb3wFSJ9SJAi0XAZ33NwXUXC5dJFIRHvZo7n0Z3J" - "oDNaYef0zVd2bFZJjDzEmhByWfQ8bi/gDDpuz7NCa4RidhivT90w7B51tfXpV+F2CVEqd" - "eamC+gj5cYznSYawCYwSPvEIbP3ArqXXdeXze3MUUNBJbSAGHgGuOZ7maazAfAoXnnaP8" - "yN9kdj8fhjPY8TNt6FWchDTbsVB4s196jANI3XwNQPPXM9LSLmZ/Ae0f8nuGC2lhPK5md" - "++zbh76B8V0Wmaz0aOB7epHy5XA4b3ZIgt1puvYYrCkaQZyhCrjZ1ehw+B//An2skMYLh" - "GDCXB3b43Q6dhSL+7NHQ0YZYW3yyVfgyUwoOI1WABje3IkkBRMHRPmmPWxupyM4nF/jek" - "mrp8pSSSqap++aSADA1ZuTtsLTewPgKmfadx2q8YwNZVwhDzJVZnbGfEcDOB8A/Y1wDAV" - "iRxtHVLF321EiTJf3u0b+osLgglyTximcUQr6NJ2ZvwDAxwa9ejg8l7wcDsOAZLptwzgr" - "LUXLdOC5nF5yPi6giFAYsbTwbwQHcRCejFCHA/lwwoZFZRBjvZlbGJ4mGylj8E27giJDo" - "SQCsvJyR702xwGz8X5dp7qSMuy7lGcmhBrB13XxC8Asw7zIueBJ/brvEINHvzRLeSmS3C" - "SfTgHDwaXKIOd5c4/RoYzrRHiOtbpOm8391dNuhXW3rECBzwC+qWQS+IAZABSBE+VoJzV" - "6P+e5Wl9u9wlZRJtNjEXTLq1INwHdhvxZH9GkcFI8HFqAsWDLhYw5k0W8Hl8Y0fUSFxBs" - "9CquLGFKQBfcDODPrQGPnPpRlADAiZEMCVb1/r0lAkjD0kq9xSJnmj/7NoEiYUxAElOOA" - "SMoFgwAUhbKpnmANhTTFSXD+x6jEjJm+CaUXIdfJhFuN3RLy3GbcBcqYjJPKH8QwGWdod" - "nbEgqOMQD6xpXQJ/fjelXlgKU9vghk4S0KwZIC15YSvXjZ15awslAHzP00008iUEE7oC4" - "r7nKHerJAl18gGRGPAMwzez2GVpmFFhEAAKOe5CN6ZL6v0znPpVcluBMyj2ZDHhWLhciT" - "Ctq4UKb9uIIfV3ChqzvJpxvpWBIeAOheSXQ8ZEEig2DhyjyqSqVoJ9j2W0y2knLW16dCd" - "6EjyQ0a/E23IDDwowJ5IFJsMzJaRAEoxOFy1S+tXDAAcMdlxoP4w7UtnABQe0nhUa1HES" - "5kVennooC/WWEpANRLK4mYjplkcy/ViU+n627I8gjXIJ9L5APiCDYiqFD7IIYLWKoKySj" - "lUXleNM9TzcSfdxRGqlKijGALtTVJA7bgi0RVRaByyhjqP1S73BxPyjoeM47LPRqvVInU" - "cvGoCit3GRpZ5VC0XZ1zpg6pb1AqLAhDD8L/AcHH1p8sEFAHAAAAAElFTkSuQmCC\r\n" + "AAEAAAABACAMAAACdt4HsAAAABGdBTUEAALGPC/xhBQAAAAFzUkdCAK7OHOkAAABmelRY" + "dFJhdyBwcm9maWxlIHR5cGUgZXhpZgAAeNptitsJgEAMBP9ThSWsZy6PcvKhcB1YvjEni" + "ODAwjAs7ec4aCmkEXc1cREk7OwtUgyTFRA3BU+vFPjS7gUI/p46Q0u2fP/1B7oA1Scbwk" + "nkf9gAAAAJcEhZcwAADsMAAA7DAcdvqGQAAACfUExURQwMDDw8PFBQUAICAhQUFAcHBxs" + "bGxEREQkJCTk5OTU1NSAgIFRUVB8fH0xMTCUlJVtbW0pKSikpKS8vL0BAQEZGRjMzM2Bg" + "YL6+vsDAwLS0tF1dXXJycrGxsWVlZWhoaKenp29vb6urq8TExHp6epSUlLu7u66urqOjo" + "5ycnH9/f4CAgJOTk5qamo6OjoWFhYiIiHd3d8nJyc/Pz9LS0ojXP1QAAAihSURBVFjDZV" + "eHdqM6EBUYEEh0EM3gCu41+/7/294dCSfZsxOHeM8yV3f6iGVGYohNEtJPGEjPiSLpMTz" + "zokg8DmGOCOm/P0I6MTPaBGDPCGEYV3kEzchjzPOSPIkk8BzuM8fSCOFfALER+6MdpnaV" + "55FMoOP7UliioK8QzpiT0Qv0Fl4lDJvFPwChETuHFjhw7vhRVcGAXDqcfhhnRaZUWeJTW" + "pYVCBEYAJihtCsUpIhyq6win3ueDCoRBIknJRwACtz3AJhDYBhESsmyEjhaKv0MRJIIFR" + "d4XyYqC1RWwQFeBF2CcApCmEFI2KwHTRIrsMq8UnYcRUkehKtlaGeq8BjowKHEQf7oEgH" + "JcKRWpSeZpTIrs5dKlGX9fF7GfrtdWqDAuce1IyOtLbWyRKRYIIIPBo63gswO07q20/p6" + "2txvj+flvUZUZeQ4IODBGDoYivoReREzugaAJKuX637dP0/DbnMGwuWyTTNlBYX0ItL3E" + "q2ptUmYZi9+ANLt9r2+nrqmORKD1/W9Xi3hirisEumQOz+qRv5hUL/H1bg7tG0znKbHCy" + "Zs16u6TgmiQH5rLW2Ltslhf6kjO1bjOJ4PTfu1PwDgeR0BsF6BBCBQIThee+P78QvAQNS" + "X17mD/tfXYaMBejAAhWWahqoiB5q8dmYQ9rc+AF7Trmn2BLC7vy4XQ0ADpHZmJRQPznVO" + "0YcABJRnBwBg+Tofm3a//2q7zYREIAAyAQRQQKqAJ/ksH4CPC4wJy9uma2eA2+syjtsVn" + "LicKzDTRYaqMgi/AQyHQNSPY0uyb7vdHVEcezDQBhAHJXLPqLOZxN8+CLJVehmapoUX2u" + "54okzsIXACucAOYyunov62AUDiN0IQd69+dyAf7PfdsLlRGAGwXekowIgySRzoMzZzcAj" + "gpxIs9Ti+TsTghLMvV1Lfbvt+vbTR9ZAJtlWoXxSIwaxuohCUt8Pp3LTd+XHt01KF9XZL" + "iRhXkSwKCzYg7X2NwGYYJsRvCHU6nndNO3SH4TauV9v3OK7rUKHnUJaiTxRl4XODwD8mC" + "Gptn0Q8j1e4oOmmfi0iZY/naRuWaIyiNI1bxDljs/7M4Hcxlta9fzTd/qubrrdYpNZ2GL" + "ZxgJboFkmFVhGLLPE/6ubPp5nNTphOAGj/QHavtZ292t3KLouiQocqbXhRKOlr+/9hoA0" + "og/d+dzi0/+2b7nTr60vXbtZhJkQZx2GaLsNMxZ8ozk5gphN/M4i79nBo/uwHdJPn1Db7" + "c40aUgoDRVdTmhn3awbsXxOs4PZfc2i+vrrTNCEe+/0JnTmkoZOiJcT2co4i5z9hnHu6Z" + "bxoT7sWAM3mfp9O7Vd7rnUV6E8ap2lk/MdmJzD2eyRohKrf4+DmON2ej6HZ31epnnqpLg" + "ZV8dmFMw6fB0vww0Gs903ToJaviOifdnrXS6SxhgjjxNEF9BH6VlUVMKqf+STqPTLpeHr" + "0l2HYHaYeHohVZiOIYUYjhjHfx0cLAHI96Qrzi4BXeYxiRi94PjeH4/k8xshgO8u0HYoI" + "EIDvQgzEPOJIaGAlSSQQye54nzbH3Wb3wFSJ9SJAi0XAZ33NwXUXC5dJFIRHvZo7n0Z3J" + "oDNaYef0zVd2bFZJjDzEmhByWfQ8bi/gDDpuz7NCa4RidhivT90w7B51tfXpV+F2CVEqd" + "eamC+gj5cYznSYawCYwSPvEIbP3ArqXXdeXze3MUUNBJbSAGHgGuOZ7maazAfAoXnnaP8" + "yN9kdj8fhjPY8TNt6FWchDTbsVB4s196jANI3XwNQPPXM9LSLmZ/Ae0f8nuGC2lhPK5md" + "++zbh76B8V0Wmaz0aOB7epHy5XA4b3ZIgt1puvYYrCkaQZyhCrjZ1ehw+B//An2skMYLh" + "GDCXB3b43Q6dhSL+7NHQ0YZYW3yyVfgyUwoOI1WABje3IkkBRMHRPmmPWxupyM4nF/jek" + "mrp8pSSSqap++aSADA1ZuTtsLTewPgKmfadx2q8YwNZVwhDzJVZnbGfEcDOB8A/Y1wDAV" + "iRxtHVLF321EiTJf3u0b+osLgglyTximcUQr6NJ2ZvwDAxwa9ejg8l7wcDsOAZLptwzgr" + "LUXLdOC5nF5yPi6giFAYsbTwbwQHcRCejFCHA/lwwoZFZRBjvZlbGJ4mGylj8E27giJDo" + "SQCsvJyR702xwGz8X5dp7qSMuy7lGcmhBrB13XxC8Asw7zIueBJ/brvEINHvzRLeSmS3C" + "SfTgHDwaXKIOd5c4/RoYzrRHiOtbpOm8391dNuhXW3rECBzwC+qWQS+IAZABSBE+VoJzV" + "6P+e5Wl9u9wlZRJtNjEXTLq1INwHdhvxZH9GkcFI8HFqAsWDLhYw5k0W8Hl8Y0fUSFxBs" + "9CquLGFKQBfcDODPrQGPnPpRlADAiZEMCVb1/r0lAkjD0kq9xSJnmj/7NoEiYUxAElOOA" + "SMoFgwAUhbKpnmANhTTFSXD+x6jEjJm+CaUXIdfJhFuN3RLy3GbcBcqYjJPKH8QwGWdod" + "nbEgqOMQD6xpXQJ/fjelXlgKU9vghk4S0KwZIC15YSvXjZ15awslAHzP00008iUEE7oC4" + "r7nKHerJAl18gGRGPAMwzez2GVpmFFhEAAKOe5CN6ZL6v0znPpVcluBMyj2ZDHhWLhciT" + "Ctq4UKb9uIIfV3ChqzvJpxvpWBIeAOheSXQ8ZEEig2DhyjyqSqVoJ9j2W0y2knLW16dCd" + "6EjyQ0a/E23IDDwowJ5IFJsMzJaRAEoxOFy1S+tXDAAcMdlxoP4w7UtnABQe0nhUa1HES" + "5kVennooC/WWEpANRLK4mYjplkcy/ViU+n627I8gjXIJ9L5APiCDYiqFD7IIYLWKoKySj" + "lUXleNM9TzcSfdxRGqlKijGALtTVJA7bgi0RVRaByyhjqP1S73BxPyjoeM47LPRqvVInU" + "cvGoCit3GRpZ5VC0XZ1zpg6pb1AqLAhDD8L/AcHH1p8sEFAHAAAAAElFTkSuQmCC\r\n" "Connection: keep-alive\r\n" "Content-Length: 0\r\n" "Upgrade-Insecure-Requests: 1\r\n" "Pragma: no-cache\r\n" "Cache-Control: no-cache\r\n" "X-Forwarded-For: 192.0.2.0, 198.51.100.0, 203.0.113.0\r\n" - "\r\n" -); - - -nxt_int_t -nxt_http_parse_test(nxt_thread_t *thr) -{ - nxt_mp_t *mp_temp; - nxt_int_t rc; - nxt_uint_t i, colls, lvl_colls; - nxt_lvlhsh_t hash; - nxt_http_request_parse_t rp; - nxt_http_parse_test_case_t *test; - - nxt_thread_time_update(thr); - - rc = nxt_http_fields_hash(&nxt_http_test_fields_hash, - nxt_http_test_fields, - nxt_nitems(nxt_http_test_fields)); - if (rc != NXT_OK) { - return NXT_ERROR; - } - - for (i = 0; i < nxt_nitems(nxt_http_test_cases); i++) { - test = &nxt_http_test_cases[i]; + "\r\n"); - nxt_memzero(&rp, sizeof(nxt_http_request_parse_t)); +nxt_int_t nxt_http_parse_test(nxt_thread_t *thr) { + nxt_mp_t *mp_temp; + nxt_int_t rc; + nxt_uint_t i, colls, lvl_colls; + nxt_lvlhsh_t hash; + nxt_http_request_parse_t rp; + nxt_http_parse_test_case_t *test; - mp_temp = nxt_mp_create(1024, 128, 256, 32); - if (mp_temp == NULL) { - return NXT_ERROR; - } + nxt_thread_time_update(thr); - if (nxt_http_parse_request_init(&rp, mp_temp) != NXT_OK) { - return NXT_ERROR; - } + rc = nxt_http_fields_hash(&nxt_http_test_fields_hash, nxt_http_test_fields, + nxt_nitems(nxt_http_test_fields)); + if (rc != NXT_OK) { + return NXT_ERROR; + } - if (test->handler == &nxt_http_parse_test_fields) { - rp.discard_unsafe_fields = test->data.fields.discard_unsafe_fields; - } + for (i = 0; i < nxt_nitems(nxt_http_test_cases); i++) { + test = &nxt_http_test_cases[i]; - rc = nxt_http_parse_test_run(&rp, &test->request); + nxt_memzero(&rp, sizeof(nxt_http_request_parse_t)); - if (rc != test->result) { - nxt_log_alert(thr->log, "http parse test case failed:\n" - " - request:\n\"%V\"\n" - " - result: %i (expected: %i)", - &test->request, rc, test->result); - return NXT_ERROR; - } - - if (test->handler != NULL - && test->handler(&rp, &test->data, &test->request, thr->log) - != NXT_OK) - { - return NXT_ERROR; - } - - nxt_mp_destroy(mp_temp); + mp_temp = nxt_mp_create(1024, 128, 256, 32); + if (mp_temp == NULL) { + return NXT_ERROR; } - nxt_log_error(NXT_LOG_NOTICE, thr->log, "http parse test passed"); - - nxt_memzero(&hash, sizeof(nxt_lvlhsh_t)); - - colls = nxt_http_fields_hash_collisions(&hash, - nxt_http_test_bench_fields, - nxt_nitems(nxt_http_test_bench_fields), - 0); - - nxt_memzero(&hash, sizeof(nxt_lvlhsh_t)); - - lvl_colls = nxt_http_fields_hash_collisions(&hash, - nxt_http_test_bench_fields, - nxt_nitems(nxt_http_test_bench_fields), - 1); - - nxt_log_error(NXT_LOG_NOTICE, thr->log, - "http parse test hash collisions %ui out of %uz, level: %ui", - colls, nxt_nitems(nxt_http_test_bench_fields), lvl_colls); - - nxt_memzero(&hash, sizeof(nxt_lvlhsh_t)); + if (nxt_http_parse_request_init(&rp, mp_temp) != NXT_OK) { + return NXT_ERROR; + } - rc = nxt_http_fields_hash(&hash, nxt_http_test_bench_fields, - nxt_nitems(nxt_http_test_bench_fields)); - if (rc != NXT_OK) { - return NXT_ERROR; + if (test->handler == &nxt_http_parse_test_fields) { + rp.discard_unsafe_fields = test->data.fields.discard_unsafe_fields; } - if (nxt_http_parse_test_bench(thr, &nxt_http_test_simple_request, - &hash, "simple", 1000000) - != NXT_OK) - { - return NXT_ERROR; + rc = nxt_http_parse_test_run(&rp, &test->request); + + if (rc != test->result) { + nxt_log_alert(thr->log, + "http parse test case failed:\n" + " - request:\n\"%V\"\n" + " - result: %i (expected: %i)", + &test->request, rc, test->result); + return NXT_ERROR; } - if (nxt_http_parse_test_bench(thr, &nxt_http_test_big_request, - &hash, "big", 100000) - != NXT_OK) - { - return NXT_ERROR; + if (test->handler != NULL && + test->handler(&rp, &test->data, &test->request, thr->log) != NXT_OK) { + return NXT_ERROR; } - return NXT_OK; -} + nxt_mp_destroy(mp_temp); + } + nxt_log_error(NXT_LOG_NOTICE, thr->log, "http parse test passed"); -static nxt_int_t -nxt_http_parse_test_run(nxt_http_request_parse_t *rp, nxt_str_t *request) -{ - nxt_int_t rc; - nxt_buf_mem_t buf; + nxt_memzero(&hash, sizeof(nxt_lvlhsh_t)); - buf.start = request->start; - buf.end = request->start + request->length; + colls = nxt_http_fields_hash_collisions( + &hash, nxt_http_test_bench_fields, nxt_nitems(nxt_http_test_bench_fields), + 0); - buf.pos = buf.start; - buf.free = buf.pos + 1; + nxt_memzero(&hash, sizeof(nxt_lvlhsh_t)); - do { - buf.free++; - rc = nxt_http_parse_request(rp, &buf); - } while (buf.free < buf.end && rc == NXT_AGAIN); + lvl_colls = nxt_http_fields_hash_collisions( + &hash, nxt_http_test_bench_fields, nxt_nitems(nxt_http_test_bench_fields), + 1); - return rc; -} + nxt_log_error(NXT_LOG_NOTICE, thr->log, + "http parse test hash collisions %ui out of %uz, level: %ui", + colls, nxt_nitems(nxt_http_test_bench_fields), lvl_colls); + nxt_memzero(&hash, sizeof(nxt_lvlhsh_t)); -static nxt_int_t -nxt_http_parse_test_bench(nxt_thread_t *thr, nxt_str_t *request, - nxt_lvlhsh_t *hash, const char *name, nxt_uint_t n) -{ - nxt_mp_t *mp; - nxt_nsec_t start, end; - nxt_uint_t i; - nxt_buf_mem_t buf; - nxt_http_request_parse_t rp; - - nxt_log_error(NXT_LOG_NOTICE, thr->log, - "http parse %s request bench started: %uz bytes, %ui runs", - name, request->length, n); - - buf.start = request->start; - buf.end = request->start + request->length; - - nxt_thread_time_update(thr); - start = nxt_thread_monotonic_time(thr); - - for (i = 0; nxt_fast_path(i < n); i++) { - nxt_memzero(&rp, sizeof(nxt_http_request_parse_t)); - - mp = nxt_mp_create(1024, 128, 256, 32); - if (nxt_slow_path(mp == NULL)) { - return NXT_ERROR; - } - - if (nxt_slow_path(nxt_http_parse_request_init(&rp, mp) != NXT_OK)) { - return NXT_ERROR; - } - - buf.pos = buf.start; - buf.free = buf.end; - - if (nxt_slow_path(nxt_http_parse_request(&rp, &buf) != NXT_DONE)) { - nxt_log_alert(thr->log, "http parse %s request bench failed " - "while parsing", name); - return NXT_ERROR; - } - - if (nxt_slow_path(nxt_http_fields_process(rp.fields, hash, NULL) - != NXT_OK)) - { - nxt_log_alert(thr->log, "http parse %s request bench failed " - "while fields processing", name); - return NXT_ERROR; - } - - nxt_mp_destroy(mp); - } + rc = nxt_http_fields_hash(&hash, nxt_http_test_bench_fields, + nxt_nitems(nxt_http_test_bench_fields)); + if (rc != NXT_OK) { + return NXT_ERROR; + } - nxt_thread_time_update(thr); - end = nxt_thread_monotonic_time(thr); + if (nxt_http_parse_test_bench(thr, &nxt_http_test_simple_request, &hash, + "simple", 1000000) != NXT_OK) { + return NXT_ERROR; + } - nxt_log_error(NXT_LOG_NOTICE, thr->log, - "http parse %s request bench: %0.3fs", - name, (end - start) / 1000000000.0); + if (nxt_http_parse_test_bench(thr, &nxt_http_test_big_request, &hash, "big", + 100000) != NXT_OK) { + return NXT_ERROR; + } - return NXT_OK; + return NXT_OK; } +static nxt_int_t nxt_http_parse_test_run(nxt_http_request_parse_t *rp, + nxt_str_t *request) { + nxt_int_t rc; + nxt_buf_mem_t buf; -static nxt_int_t -nxt_http_parse_test_request_line(nxt_http_request_parse_t *rp, - nxt_http_parse_test_data_t *data, nxt_str_t *request, nxt_log_t *log) -{ - nxt_str_t str; + buf.start = request->start; + buf.end = request->start + request->length; - nxt_http_parse_test_request_line_t *test = &data->request_line; + buf.pos = buf.start; + buf.free = buf.pos + 1; - if (rp->method.start != test->method.start - && !nxt_strstr_eq(&rp->method, &test->method)) - { - nxt_log_alert(log, "http parse test case failed:\n" - " - request:\n\"%V\"\n" - " - method: \"%V\" (expected: \"%V\")", - request, &rp->method, &test->method); - return NXT_ERROR; - } + do { + buf.free++; + rc = nxt_http_parse_request(rp, &buf); + } while (buf.free < buf.end && rc == NXT_AGAIN); - str.length = rp->target_end - rp->target_start; - str.start = rp->target_start; + return rc; +} - if (str.start != test->target.start - && !nxt_strstr_eq(&str, &test->target)) - { - nxt_log_alert(log, "http parse test case failed:\n" - " - request:\n\"%V\"\n" - " - target: \"%V\" (expected: \"%V\")", - request, &str, &test->target); - return NXT_ERROR; +static nxt_int_t nxt_http_parse_test_bench(nxt_thread_t *thr, + nxt_str_t *request, + nxt_lvlhsh_t *hash, const char *name, + nxt_uint_t n) { + nxt_mp_t *mp; + nxt_nsec_t start, end; + nxt_uint_t i; + nxt_buf_mem_t buf; + nxt_http_request_parse_t rp; + + nxt_log_error(NXT_LOG_NOTICE, thr->log, + "http parse %s request bench started: %uz bytes, %ui runs", + name, request->length, n); + + buf.start = request->start; + buf.end = request->start + request->length; + + nxt_thread_time_update(thr); + start = nxt_thread_monotonic_time(thr); + + for (i = 0; nxt_fast_path(i < n); i++) { + nxt_memzero(&rp, sizeof(nxt_http_request_parse_t)); + + mp = nxt_mp_create(1024, 128, 256, 32); + if (nxt_slow_path(mp == NULL)) { + return NXT_ERROR; } - if (rp->args.start != test->args.start - && !nxt_strstr_eq(&rp->args, &test->args)) - { - nxt_log_alert(log, "http parse test case failed:\n" - " - request:\n\"%V\"\n" - " - args: \"%V\" (expected: \"%V\")", - request, &rp->args, &test->args); - return NXT_ERROR; + if (nxt_slow_path(nxt_http_parse_request_init(&rp, mp) != NXT_OK)) { + return NXT_ERROR; } - if (memcmp(rp->version.str, test->version, 8) != 0) { - nxt_log_alert(log, "http parse test case failed:\n" - " - request:\n\"%V\"\n" - " - version: \"%*s\" (expected: \"%*s\")", request, - (size_t) 8, rp->version.str, - (size_t) 8, test->version); - return NXT_ERROR; + buf.pos = buf.start; + buf.free = buf.end; + + if (nxt_slow_path(nxt_http_parse_request(&rp, &buf) != NXT_DONE)) { + nxt_log_alert(thr->log, + "http parse %s request bench failed " + "while parsing", + name); + return NXT_ERROR; } - if (rp->complex_target != test->complex_target) { - nxt_log_alert(log, "http parse test case failed:\n" - " - request:\n\"%V\"\n" - " - complex_target: %d (expected: %d)", - request, rp->complex_target, test->complex_target); - return NXT_ERROR; + if (nxt_slow_path(nxt_http_fields_process(rp.fields, hash, NULL) != + NXT_OK)) { + nxt_log_alert(thr->log, + "http parse %s request bench failed " + "while fields processing", + name); + return NXT_ERROR; } - if (rp->quoted_target != test->quoted_target) { - nxt_log_alert(log, "http parse test case failed:\n" - " - request:\n\"%V\"\n" - " - quoted_target: %d (expected: %d)", - request, rp->quoted_target, test->quoted_target); - return NXT_ERROR; - } + nxt_mp_destroy(mp); + } + + nxt_thread_time_update(thr); + end = nxt_thread_monotonic_time(thr); + + nxt_log_error(NXT_LOG_NOTICE, thr->log, "http parse %s request bench: %0.3fs", + name, (end - start) / 1000000000.0); + + return NXT_OK; +} + +static nxt_int_t +nxt_http_parse_test_request_line(nxt_http_request_parse_t *rp, + nxt_http_parse_test_data_t *data, + nxt_str_t *request, nxt_log_t *log) { + nxt_str_t str; + + nxt_http_parse_test_request_line_t *test = &data->request_line; + + if (rp->method.start != test->method.start && + !nxt_strstr_eq(&rp->method, &test->method)) { + nxt_log_alert(log, + "http parse test case failed:\n" + " - request:\n\"%V\"\n" + " - method: \"%V\" (expected: \"%V\")", + request, &rp->method, &test->method); + return NXT_ERROR; + } + + str.length = rp->target_end - rp->target_start; + str.start = rp->target_start; + + if (str.start != test->target.start && !nxt_strstr_eq(&str, &test->target)) { + nxt_log_alert(log, + "http parse test case failed:\n" + " - request:\n\"%V\"\n" + " - target: \"%V\" (expected: \"%V\")", + request, &str, &test->target); + return NXT_ERROR; + } + + if (rp->args.start != test->args.start && + !nxt_strstr_eq(&rp->args, &test->args)) { + nxt_log_alert(log, + "http parse test case failed:\n" + " - request:\n\"%V\"\n" + " - args: \"%V\" (expected: \"%V\")", + request, &rp->args, &test->args); + return NXT_ERROR; + } + + if (memcmp(rp->version.str, test->version, 8) != 0) { + nxt_log_alert(log, + "http parse test case failed:\n" + " - request:\n\"%V\"\n" + " - version: \"%*s\" (expected: \"%*s\")", + request, (size_t)8, rp->version.str, (size_t)8, + test->version); + return NXT_ERROR; + } + + if (rp->complex_target != test->complex_target) { + nxt_log_alert(log, + "http parse test case failed:\n" + " - request:\n\"%V\"\n" + " - complex_target: %d (expected: %d)", + request, rp->complex_target, test->complex_target); + return NXT_ERROR; + } + + if (rp->quoted_target != test->quoted_target) { + nxt_log_alert(log, + "http parse test case failed:\n" + " - request:\n\"%V\"\n" + " - quoted_target: %d (expected: %d)", + request, rp->quoted_target, test->quoted_target); + return NXT_ERROR; + } #if 0 if (rp->space_in_target != test->space_in_target) { @@ -788,32 +620,30 @@ nxt_http_parse_test_request_line(nxt_http_request_parse_t *rp, } #endif - return NXT_OK; + return NXT_OK; } - -static nxt_int_t -nxt_http_parse_test_fields(nxt_http_request_parse_t *rp, - nxt_http_parse_test_data_t *data, nxt_str_t *request, nxt_log_t *log) -{ - nxt_int_t rc; - - rc = nxt_http_fields_process(rp->fields, &nxt_http_test_fields_hash, NULL); - - if (rc != data->fields.result) { - nxt_log_alert(log, "http parse test hash failed:\n" - " - request:\n\"%V\"\n" - " - result: %i (expected: %i)", - request, rc, data->fields.result); - return NXT_ERROR; - } - - return NXT_OK; +static nxt_int_t nxt_http_parse_test_fields(nxt_http_request_parse_t *rp, + nxt_http_parse_test_data_t *data, + nxt_str_t *request, + nxt_log_t *log) { + nxt_int_t rc; + + rc = nxt_http_fields_process(rp->fields, &nxt_http_test_fields_hash, NULL); + + if (rc != data->fields.result) { + nxt_log_alert(log, + "http parse test hash failed:\n" + " - request:\n\"%V\"\n" + " - result: %i (expected: %i)", + request, rc, data->fields.result); + return NXT_ERROR; + } + + return NXT_OK; } - -static nxt_int_t -nxt_http_test_header_return(void *ctx, nxt_http_field_t *field, uintptr_t data) -{ - return data; +static nxt_int_t nxt_http_test_header_return(void *ctx, nxt_http_field_t *field, + uintptr_t data) { + return data; } diff --git a/src/test/nxt_lvlhsh_test.c b/src/test/nxt_lvlhsh_test.c index baa6d0e1e..da79e4e66 100644 --- a/src/test/nxt_lvlhsh_test.c +++ b/src/test/nxt_lvlhsh_test.c @@ -7,257 +7,246 @@ #include #include "nxt_tests.h" +static nxt_int_t nxt_lvlhsh_test_key_test(nxt_lvlhsh_query_t *lhq, void *data) { + if (*(uintptr_t *)lhq->key.start == (uintptr_t)data) { + return NXT_OK; + } -static nxt_int_t -nxt_lvlhsh_test_key_test(nxt_lvlhsh_query_t *lhq, void *data) -{ - if (*(uintptr_t *) lhq->key.start == (uintptr_t) data) { - return NXT_OK; - } - - return NXT_DECLINED; + return NXT_DECLINED; } - -static const nxt_lvlhsh_proto_t malloc_proto nxt_aligned(64) = { - //NXT_LVLHSH_LARGE_MEMALIGN, +static const nxt_lvlhsh_proto_t malloc_proto nxt_aligned(64) = { + // NXT_LVLHSH_LARGE_MEMALIGN, NXT_LVLHSH_DEFAULT, nxt_lvlhsh_test_key_test, nxt_lvlhsh_alloc, nxt_lvlhsh_free, }; -static const nxt_lvlhsh_proto_t pool_proto nxt_aligned(64) = { +static const nxt_lvlhsh_proto_t pool_proto nxt_aligned(64) = { NXT_LVLHSH_LARGE_SLAB, nxt_lvlhsh_test_key_test, nxt_mp_lvlhsh_alloc, nxt_mp_lvlhsh_free, }; +static nxt_int_t nxt_lvlhsh_test_add(nxt_lvlhsh_t *lh, + const nxt_lvlhsh_proto_t *proto, + void *pool, uintptr_t key) { + nxt_lvlhsh_query_t lhq; -static nxt_int_t -nxt_lvlhsh_test_add(nxt_lvlhsh_t *lh, const nxt_lvlhsh_proto_t *proto, - void *pool, uintptr_t key) -{ - nxt_lvlhsh_query_t lhq; + lhq.key_hash = key; + lhq.replace = 0; + lhq.key.length = sizeof(uintptr_t); + lhq.key.start = (u_char *)&key; + lhq.value = (void *)key; + lhq.proto = proto; + lhq.pool = pool; - lhq.key_hash = key; - lhq.replace = 0; - lhq.key.length = sizeof(uintptr_t); - lhq.key.start = (u_char *) &key; - lhq.value = (void *) key; - lhq.proto = proto; - lhq.pool = pool; + switch (nxt_lvlhsh_insert(lh, &lhq)) { - switch (nxt_lvlhsh_insert(lh, &lhq)) { - - case NXT_OK: - return NXT_OK; + case NXT_OK: + return NXT_OK; - case NXT_DECLINED: - nxt_thread_log_alert("lvlhsh test failed: " - "key %p is already in hash", key); - /* Fall through. */ - default: - return NXT_ERROR; - } + case NXT_DECLINED: + nxt_thread_log_alert("lvlhsh test failed: " + "key %p is already in hash", + key); + /* Fall through. */ + default: + return NXT_ERROR; + } } +static nxt_int_t nxt_lvlhsh_test_get(nxt_lvlhsh_t *lh, + const nxt_lvlhsh_proto_t *proto, + uintptr_t key) { + nxt_lvlhsh_query_t lhq; -static nxt_int_t -nxt_lvlhsh_test_get(nxt_lvlhsh_t *lh, const nxt_lvlhsh_proto_t *proto, - uintptr_t key) -{ - nxt_lvlhsh_query_t lhq; - - lhq.key_hash = key; - lhq.key.length = sizeof(uintptr_t); - lhq.key.start = (u_char *) &key; - lhq.proto = proto; + lhq.key_hash = key; + lhq.key.length = sizeof(uintptr_t); + lhq.key.start = (u_char *)&key; + lhq.proto = proto; - if (nxt_lvlhsh_find(lh, &lhq) == NXT_OK) { + if (nxt_lvlhsh_find(lh, &lhq) == NXT_OK) { - if (key == (uintptr_t) lhq.value) { - return NXT_OK; - } + if (key == (uintptr_t)lhq.value) { + return NXT_OK; } + } - nxt_thread_log_alert("lvlhsh test failed: " - "key %p not found in hash", key); + nxt_thread_log_alert("lvlhsh test failed: " + "key %p not found in hash", + key); - return NXT_ERROR; + return NXT_ERROR; } +static nxt_int_t nxt_lvlhsh_test_delete(nxt_lvlhsh_t *lh, + const nxt_lvlhsh_proto_t *proto, + void *pool, uintptr_t key) { + nxt_int_t ret; + nxt_lvlhsh_query_t lhq; -static nxt_int_t -nxt_lvlhsh_test_delete(nxt_lvlhsh_t *lh, const nxt_lvlhsh_proto_t *proto, - void *pool, uintptr_t key) -{ - nxt_int_t ret; - nxt_lvlhsh_query_t lhq; + lhq.key_hash = key; + lhq.key.length = sizeof(uintptr_t); + lhq.key.start = (u_char *)&key; + lhq.proto = proto; + lhq.pool = pool; - lhq.key_hash = key; - lhq.key.length = sizeof(uintptr_t); - lhq.key.start = (u_char *) &key; - lhq.proto = proto; - lhq.pool = pool; + ret = nxt_lvlhsh_delete(lh, &lhq); - ret = nxt_lvlhsh_delete(lh, &lhq); - - if (ret != NXT_OK) { - nxt_thread_log_alert("lvlhsh test failed: " - "key %p not found in hash", key); - } + if (ret != NXT_OK) { + nxt_thread_log_alert("lvlhsh test failed: " + "key %p not found in hash", + key); + } - return ret; + return ret; } +nxt_int_t nxt_lvlhsh_test(nxt_thread_t *thr, nxt_uint_t n, + nxt_bool_t use_pool) { + void *value; + uint32_t key; + nxt_mp_t *mp; + nxt_nsec_t start, end; + nxt_uint_t i; + nxt_lvlhsh_t lh; + nxt_lvlhsh_each_t lhe; + const nxt_lvlhsh_proto_t *proto; + + const size_t min_chunk_size = 32; + const size_t page_size = 1024; + const size_t page_alignment = 128; + const size_t cluster_size = 4096; -nxt_int_t -nxt_lvlhsh_test(nxt_thread_t *thr, nxt_uint_t n, nxt_bool_t use_pool) -{ - void *value; - uint32_t key; - nxt_mp_t *mp; - nxt_nsec_t start, end; - nxt_uint_t i; - nxt_lvlhsh_t lh; - nxt_lvlhsh_each_t lhe; - const nxt_lvlhsh_proto_t *proto; - - const size_t min_chunk_size = 32; - const size_t page_size = 1024; - const size_t page_alignment = 128; - const size_t cluster_size = 4096; - - nxt_thread_time_update(thr); - start = nxt_thread_monotonic_time(thr); - - if (use_pool) { - mp = nxt_mp_create(cluster_size, page_alignment, page_size, - min_chunk_size); - if (mp == NULL) { - return NXT_ERROR; - } - - nxt_log_error(NXT_LOG_NOTICE, thr->log, - "lvlhsh test started: %uD pool", n); - proto = &pool_proto; - - } else { - nxt_log_error(NXT_LOG_NOTICE, thr->log, - "lvlhsh test started: %uD malloc", n); - proto = &malloc_proto; - mp = NULL; + nxt_thread_time_update(thr); + start = nxt_thread_monotonic_time(thr); + + if (use_pool) { + mp = nxt_mp_create(cluster_size, page_alignment, page_size, min_chunk_size); + if (mp == NULL) { + return NXT_ERROR; } - nxt_memzero(&lh, sizeof(nxt_lvlhsh_t)); + nxt_log_error(NXT_LOG_NOTICE, thr->log, "lvlhsh test started: %uD pool", n); + proto = &pool_proto; - key = 0; - for (i = 0; i < n; i++) { - key = nxt_murmur_hash2(&key, sizeof(uint32_t)); + } else { + nxt_log_error(NXT_LOG_NOTICE, thr->log, "lvlhsh test started: %uD malloc", + n); + proto = &malloc_proto; + mp = NULL; + } - if (nxt_lvlhsh_test_add(&lh, proto, mp, key) != NXT_OK) { - nxt_log_error(NXT_LOG_NOTICE, thr->log, - "lvlhsh add test failed at %ui", i); - return NXT_ERROR; - } - } + nxt_memzero(&lh, sizeof(nxt_lvlhsh_t)); - key = 0; - for (i = 0; i < n; i++) { - key = nxt_murmur_hash2(&key, sizeof(uint32_t)); + key = 0; + for (i = 0; i < n; i++) { + key = nxt_murmur_hash2(&key, sizeof(uint32_t)); - if (nxt_lvlhsh_test_get(&lh, proto, key) != NXT_OK) { - return NXT_ERROR; - } + if (nxt_lvlhsh_test_add(&lh, proto, mp, key) != NXT_OK) { + nxt_log_error(NXT_LOG_NOTICE, thr->log, "lvlhsh add test failed at %ui", + i); + return NXT_ERROR; } + } - nxt_lvlhsh_each_init(&lhe, proto); + key = 0; + for (i = 0; i < n; i++) { + key = nxt_murmur_hash2(&key, sizeof(uint32_t)); - for (i = 0; i < n + 1; i++) { - if (nxt_lvlhsh_each(&lh, &lhe) == NULL) { - break; - } + if (nxt_lvlhsh_test_get(&lh, proto, key) != NXT_OK) { + return NXT_ERROR; } + } - if (i != n) { - nxt_log_error(NXT_LOG_NOTICE, thr->log, - "lvlhsh each test failed at %ui of %ui", i, n); - return NXT_ERROR; - } + nxt_lvlhsh_each_init(&lhe, proto); - for (i = 0; i < n; i++) { - value = nxt_lvlhsh_peek(&lh, proto); + for (i = 0; i < n + 1; i++) { + if (nxt_lvlhsh_each(&lh, &lhe) == NULL) { + break; + } + } - if (value == NULL) { - break; - } + if (i != n) { + nxt_log_error(NXT_LOG_NOTICE, thr->log, + "lvlhsh each test failed at %ui of %ui", i, n); + return NXT_ERROR; + } - key = (uintptr_t) value; + for (i = 0; i < n; i++) { + value = nxt_lvlhsh_peek(&lh, proto); - if (nxt_lvlhsh_test_delete(&lh, proto, mp, key) != NXT_OK) { - return NXT_ERROR; - } + if (value == NULL) { + break; } - if (i != n) { - nxt_log_error(NXT_LOG_NOTICE, thr->log, - "lvlhsh peek test failed at %ui of %ui", i, n); - return NXT_ERROR; - } + key = (uintptr_t)value; - if (!nxt_lvlhsh_is_empty(&lh)) { - nxt_log_error(NXT_LOG_NOTICE, thr->log, - "lvlhsh is not empty after deletion"); - return NXT_ERROR; + if (nxt_lvlhsh_test_delete(&lh, proto, mp, key) != NXT_OK) { + return NXT_ERROR; } + } - key = 0; - for (i = 0; i < n; i++) { - key = nxt_murmur_hash2(&key, sizeof(uint32_t)); + if (i != n) { + nxt_log_error(NXT_LOG_NOTICE, thr->log, + "lvlhsh peek test failed at %ui of %ui", i, n); + return NXT_ERROR; + } - if (nxt_lvlhsh_test_add(&lh, proto, mp, key) != NXT_OK) { - nxt_log_error(NXT_LOG_NOTICE, thr->log, - "lvlhsh add test failed at %ui", i); - return NXT_ERROR; - } - } + if (!nxt_lvlhsh_is_empty(&lh)) { + nxt_log_error(NXT_LOG_NOTICE, thr->log, + "lvlhsh is not empty after deletion"); + return NXT_ERROR; + } - for (i = 0; i < n; i++) { - value = nxt_lvlhsh_retrieve(&lh, proto, mp); + key = 0; + for (i = 0; i < n; i++) { + key = nxt_murmur_hash2(&key, sizeof(uint32_t)); - if (value == NULL) { - break; - } + if (nxt_lvlhsh_test_add(&lh, proto, mp, key) != NXT_OK) { + nxt_log_error(NXT_LOG_NOTICE, thr->log, "lvlhsh add test failed at %ui", + i); + return NXT_ERROR; } + } - if (i != n) { - nxt_log_error(NXT_LOG_NOTICE, thr->log, - "lvlhsh retrieve test failed at %ui of %ui", i, n); - return NXT_ERROR; - } + for (i = 0; i < n; i++) { + value = nxt_lvlhsh_retrieve(&lh, proto, mp); - if (!nxt_lvlhsh_is_empty(&lh)) { - nxt_log_error(NXT_LOG_NOTICE, thr->log, - "lvlhsh is not empty after retrieving"); - return NXT_ERROR; + if (value == NULL) { + break; } + } - if (mp != NULL) { - if (!nxt_mp_is_empty(mp)) { - nxt_log_error(NXT_LOG_NOTICE, thr->log, "mem pool is not empty"); - return NXT_ERROR; - } + if (i != n) { + nxt_log_error(NXT_LOG_NOTICE, thr->log, + "lvlhsh retrieve test failed at %ui of %ui", i, n); + return NXT_ERROR; + } - nxt_mp_destroy(mp); + if (!nxt_lvlhsh_is_empty(&lh)) { + nxt_log_error(NXT_LOG_NOTICE, thr->log, + "lvlhsh is not empty after retrieving"); + return NXT_ERROR; + } + + if (mp != NULL) { + if (!nxt_mp_is_empty(mp)) { + nxt_log_error(NXT_LOG_NOTICE, thr->log, "mem pool is not empty"); + return NXT_ERROR; } - nxt_thread_time_update(thr); - end = nxt_thread_monotonic_time(thr); + nxt_mp_destroy(mp); + } - nxt_log_error(NXT_LOG_NOTICE, thr->log, "lvlhsh test passed: %0.3fs", - (end - start) / 1000000000.0); + nxt_thread_time_update(thr); + end = nxt_thread_monotonic_time(thr); - return NXT_OK; + nxt_log_error(NXT_LOG_NOTICE, thr->log, "lvlhsh test passed: %0.3fs", + (end - start) / 1000000000.0); + + return NXT_OK; } diff --git a/src/test/nxt_malloc_test.c b/src/test/nxt_malloc_test.c index daa609b14..61a5576a5 100644 --- a/src/test/nxt_malloc_test.c +++ b/src/test/nxt_malloc_test.c @@ -7,117 +7,109 @@ #include #include "nxt_tests.h" - -#define TIMES 1000 - +#define TIMES 1000 typedef struct { - size_t size; - size_t alignment; - nxt_bool_t tight; + size_t size; + size_t alignment; + nxt_bool_t tight; } nxt_malloc_size_t; +static nxt_malloc_size_t *nxt_malloc_run_test(nxt_thread_t *thr, + nxt_malloc_size_t *last, + size_t size, nxt_uint_t times) { + size_t a, s, alignment; + uintptr_t n; + nxt_uint_t i, tight; + static u_char *p[TIMES + 1]; -static nxt_malloc_size_t * -nxt_malloc_run_test(nxt_thread_t *thr, nxt_malloc_size_t *last, size_t size, - nxt_uint_t times) -{ - size_t a, s, alignment; - uintptr_t n; - nxt_uint_t i, tight; - static u_char *p[TIMES + 1]; - - alignment = (size_t) -1; - tight = 0; + alignment = (size_t)-1; + tight = 0; - for (i = 1; i < times; i++) { + for (i = 1; i < times; i++) { - p[i] = nxt_malloc(size); - if (p[i] == NULL) { - return NULL; - } - - n = (uintptr_t) p[i]; - a = 0; + p[i] = nxt_malloc(size); + if (p[i] == NULL) { + return NULL; + } - while ((n & 1) == 0) { - a++; - n >>= 1; - } + n = (uintptr_t)p[i]; + a = 0; - alignment = nxt_min(alignment, a); + while ((n & 1) == 0) { + a++; + n >>= 1; } + alignment = nxt_min(alignment, a); + } - for (i = 1; i < times; i++) { - s = size; - nxt_malloc_usable_size(p[i], s); - - if (p[i - 1] + s == p[i] || p[i - 1] == p[i] + s) { - tight++; - } + for (i = 1; i < times; i++) { + s = size; + nxt_malloc_usable_size(p[i], s); - nxt_free(p[i]); + if (p[i - 1] + s == p[i] || p[i - 1] == p[i] + s) { + tight++; } - alignment = 1 << alignment; + nxt_free(p[i]); + } + + alignment = 1 << alignment; #if 0 nxt_log_error(NXT_LOG_NOTICE, thr->log, "malloc: %uz, %uz, %ui", size, alignment, tight); #endif - while (last->alignment >= alignment) { - last--; - } + while (last->alignment >= alignment) { + last--; + } - last++; + last++; - last->size = size; - last->alignment = alignment; - last->tight = times * 9 / 10 < tight; + last->size = size; + last->alignment = alignment; + last->tight = times * 9 / 10 < tight; - return last; + return last; } +nxt_int_t nxt_malloc_test(nxt_thread_t *thr) { + size_t size; + nxt_malloc_size_t *last, *s; + static nxt_malloc_size_t sizes[100]; -nxt_int_t -nxt_malloc_test(nxt_thread_t *thr) -{ - size_t size; - nxt_malloc_size_t *last, *s; - static nxt_malloc_size_t sizes[100]; - - nxt_log_error(NXT_LOG_NOTICE, thr->log, "malloc test started"); + nxt_log_error(NXT_LOG_NOTICE, thr->log, "malloc test started"); - last = &sizes[0]; + last = &sizes[0]; - for (size = 1; size < 64; size++) { - last = nxt_malloc_run_test(thr, last, size, TIMES); - if (last == NULL) { - return NXT_ERROR; - } + for (size = 1; size < 64; size++) { + last = nxt_malloc_run_test(thr, last, size, TIMES); + if (last == NULL) { + return NXT_ERROR; } + } - for (size = 64; size < 16384; size += 8) { - last = nxt_malloc_run_test(thr, last, size, TIMES / 4); - if (last == NULL) { - return NXT_ERROR; - } + for (size = 64; size < 16384; size += 8) { + last = nxt_malloc_run_test(thr, last, size, TIMES / 4); + if (last == NULL) { + return NXT_ERROR; } + } - for (size = 16384; size < 512 * 1024 + 129; size += 128) { - last = nxt_malloc_run_test(thr, last, size, TIMES / 16); - if (last == NULL) { - return NXT_ERROR; - } + for (size = 16384; size < 512 * 1024 + 129; size += 128) { + last = nxt_malloc_run_test(thr, last, size, TIMES / 16); + if (last == NULL) { + return NXT_ERROR; } + } - for (s = &sizes[1]; s <= last; s++) { - nxt_log_error(NXT_LOG_NOTICE, thr->log, - "malloc sizes: %uz-%uz alignment:%uz tight:%ui", - s[-1].size + 1, s->size, s->alignment, s->tight); - } + for (s = &sizes[1]; s <= last; s++) { + nxt_log_error(NXT_LOG_NOTICE, thr->log, + "malloc sizes: %uz-%uz alignment:%uz tight:%ui", + s[-1].size + 1, s->size, s->alignment, s->tight); + } - return NXT_OK; + return NXT_OK; } diff --git a/src/test/nxt_mem_zone_test.c b/src/test/nxt_mem_zone_test.c index faf0feee6..7245ec5d1 100644 --- a/src/test/nxt_mem_zone_test.c +++ b/src/test/nxt_mem_zone_test.c @@ -7,68 +7,65 @@ #include #include "nxt_tests.h" +nxt_int_t nxt_mem_zone_test(nxt_thread_t *thr, nxt_uint_t runs, + nxt_uint_t nblocks, size_t max_size) { + void *start, **blocks; + size_t total, zone_size; + uint32_t size; + nxt_uint_t i, n; + nxt_mem_zone_t *zone; + const size_t page_size = 4096; -nxt_int_t -nxt_mem_zone_test(nxt_thread_t *thr, nxt_uint_t runs, nxt_uint_t nblocks, - size_t max_size) -{ - void *start, **blocks; - size_t total, zone_size; - uint32_t size; - nxt_uint_t i, n; - nxt_mem_zone_t *zone; - const size_t page_size = 4096; - - nxt_thread_time_update(thr); - nxt_log_error(NXT_LOG_NOTICE, thr->log, - "mem zone test started, max:%uz", max_size); - - zone_size = (max_size + 1) * nblocks; - - start = nxt_memalign(page_size, zone_size); - if (start == NULL) { - return NXT_ERROR; - } + nxt_thread_time_update(thr); + nxt_log_error(NXT_LOG_NOTICE, thr->log, "mem zone test started, max:%uz", + max_size); - zone = nxt_mem_zone_init(start, zone_size, page_size); - if (zone == NULL) { - return NXT_ERROR; - } + zone_size = (max_size + 1) * nblocks; - blocks = nxt_malloc(nblocks * sizeof(void *)); - if (blocks == NULL) { - return NXT_ERROR; - } + start = nxt_memalign(page_size, zone_size); + if (start == NULL) { + return NXT_ERROR; + } + + zone = nxt_mem_zone_init(start, zone_size, page_size); + if (zone == NULL) { + return NXT_ERROR; + } + + blocks = nxt_malloc(nblocks * sizeof(void *)); + if (blocks == NULL) { + return NXT_ERROR; + } - size = 0; + size = 0; - for (i = 0; i < runs; i++) { + for (i = 0; i < runs; i++) { - total = 0; + total = 0; - for (n = 0; n < nblocks; n++) { - size = nxt_murmur_hash2(&size, sizeof(uint32_t)); + for (n = 0; n < nblocks; n++) { + size = nxt_murmur_hash2(&size, sizeof(uint32_t)); - total += size & max_size; - blocks[n] = nxt_mem_zone_alloc(zone, size & max_size); + total += size & max_size; + blocks[n] = nxt_mem_zone_alloc(zone, size & max_size); - if (blocks[n] == NULL) { - nxt_log_error(NXT_LOG_NOTICE, thr->log, - "mem zone test failed: %uz", total); - return NXT_ERROR; - } - } + if (blocks[n] == NULL) { + nxt_log_error(NXT_LOG_NOTICE, thr->log, "mem zone test failed: %uz", + total); + return NXT_ERROR; + } + } - for (n = 0; n < nblocks; n++) { - nxt_mem_zone_free(zone, blocks[n]); - } + for (n = 0; n < nblocks; n++) { + nxt_mem_zone_free(zone, blocks[n]); } + } - nxt_free(blocks); - nxt_free(zone); + nxt_free(blocks); + nxt_free(zone); - nxt_thread_time_update(thr); - nxt_log_error(NXT_LOG_NOTICE, thr->log, "mem zone test passed"); + nxt_thread_time_update(thr); + nxt_log_error(NXT_LOG_NOTICE, thr->log, "mem zone test passed"); - return NXT_OK; + return NXT_OK; } diff --git a/src/test/nxt_mp_test.c b/src/test/nxt_mp_test.c index 39aa939da..398fa17b4 100644 --- a/src/test/nxt_mp_test.c +++ b/src/test/nxt_mp_test.c @@ -7,84 +7,81 @@ #include #include "nxt_tests.h" +nxt_int_t nxt_mp_test(nxt_thread_t *thr, nxt_uint_t runs, nxt_uint_t nblocks, + size_t max_size) { + void **blocks; + size_t total; + uint32_t value, size; + nxt_mp_t *mp; + nxt_bool_t valid; + nxt_uint_t i, n; -nxt_int_t -nxt_mp_test(nxt_thread_t *thr, nxt_uint_t runs, nxt_uint_t nblocks, - size_t max_size) -{ - void **blocks; - size_t total; - uint32_t value, size; - nxt_mp_t *mp; - nxt_bool_t valid; - nxt_uint_t i, n; - - const size_t min_chunk_size = 16; - const size_t page_size = 128; - const size_t page_alignment = 128; - const size_t cluster_size = page_size * 8; - - nxt_thread_time_update(thr); - nxt_log_error(NXT_LOG_NOTICE, thr->log, - "mem pool test started, max:%uz", max_size); - - blocks = nxt_malloc(nblocks * sizeof(void *)); - if (blocks == NULL) { - return NXT_ERROR; - } + const size_t min_chunk_size = 16; + const size_t page_size = 128; + const size_t page_alignment = 128; + const size_t cluster_size = page_size * 8; - valid = nxt_mp_test_sizes(cluster_size, page_alignment, page_size, - min_chunk_size); - if (!valid) { - return NXT_ERROR; - } + nxt_thread_time_update(thr); + nxt_log_error(NXT_LOG_NOTICE, thr->log, "mem pool test started, max:%uz", + max_size); - mp = nxt_mp_create(cluster_size, page_alignment, page_size, min_chunk_size); - if (mp == NULL) { - return NXT_ERROR; - } + blocks = nxt_malloc(nblocks * sizeof(void *)); + if (blocks == NULL) { + return NXT_ERROR; + } - value = 0; + valid = nxt_mp_test_sizes(cluster_size, page_alignment, page_size, + min_chunk_size); + if (!valid) { + return NXT_ERROR; + } - for (i = 0; i < runs; i++) { + mp = nxt_mp_create(cluster_size, page_alignment, page_size, min_chunk_size); + if (mp == NULL) { + return NXT_ERROR; + } - total = 0; + value = 0; - for (n = 0; n < nblocks; n++) { - value = nxt_murmur_hash2(&value, sizeof(uint32_t)); + for (i = 0; i < runs; i++) { - size = value & max_size; + total = 0; - if (size == 0) { - size++; - } + for (n = 0; n < nblocks; n++) { + value = nxt_murmur_hash2(&value, sizeof(uint32_t)); - total += size; - blocks[n] = nxt_mp_alloc(mp, size); + size = value & max_size; - if (blocks[n] == NULL) { - nxt_log_error(NXT_LOG_NOTICE, thr->log, - "mem pool test failed: %uz", total); - return NXT_ERROR; - } - } + if (size == 0) { + size++; + } - for (n = 0; n < nblocks; n++) { - nxt_mp_free(mp, blocks[n]); - } - } + total += size; + blocks[n] = nxt_mp_alloc(mp, size); - if (!nxt_mp_is_empty(mp)) { - nxt_log_error(NXT_LOG_NOTICE, thr->log, "mem pool is not empty"); + if (blocks[n] == NULL) { + nxt_log_error(NXT_LOG_NOTICE, thr->log, "mem pool test failed: %uz", + total); return NXT_ERROR; + } } - nxt_mp_destroy(mp); + for (n = 0; n < nblocks; n++) { + nxt_mp_free(mp, blocks[n]); + } + } + + if (!nxt_mp_is_empty(mp)) { + nxt_log_error(NXT_LOG_NOTICE, thr->log, "mem pool is not empty"); + return NXT_ERROR; + } + + nxt_mp_destroy(mp); - nxt_free(blocks); + nxt_free(blocks); - nxt_thread_time_update(thr); - nxt_log_error(NXT_LOG_NOTICE, thr->log, "mem pool test passed"); + nxt_thread_time_update(thr); + nxt_log_error(NXT_LOG_NOTICE, thr->log, "mem pool test passed"); - return NXT_OK; + return NXT_OK; } diff --git a/src/test/nxt_msec_diff_test.c b/src/test/nxt_msec_diff_test.c index 0059b2464..953c5b5ad 100644 --- a/src/test/nxt_msec_diff_test.c +++ b/src/test/nxt_msec_diff_test.c @@ -7,40 +7,31 @@ #include #include "nxt_tests.h" +static const nxt_msec_t pairs[] = { -static const nxt_msec_t pairs[] = { + 0x00000000, 0x00000001, 0x00000000, 0x7FFFFFFF, - 0x00000000, 0x00000001, - 0x00000000, 0x7FFFFFFF, + 0x7FFFFFFF, 0x80000000, 0x7FFFFFFF, 0x80000001, - 0x7FFFFFFF, 0x80000000, - 0x7FFFFFFF, 0x80000001, + 0x80000000, 0x80000001, 0x80000000, 0xFFFFFFFF, - 0x80000000, 0x80000001, - 0x80000000, 0xFFFFFFFF, - - 0xFFFFFFFF, 0x00000000, - 0xFFFFFFFF, 0x00000001, + 0xFFFFFFFF, 0x00000000, 0xFFFFFFFF, 0x00000001, }; +nxt_int_t nxt_msec_diff_test(nxt_thread_t *thr, nxt_msec_less_t less) { + nxt_uint_t i; -nxt_int_t -nxt_msec_diff_test(nxt_thread_t *thr, nxt_msec_less_t less) -{ - nxt_uint_t i; - - nxt_thread_time_update(thr); + nxt_thread_time_update(thr); - for (i = 0; i < nxt_nitems(pairs); i += 2) { + for (i = 0; i < nxt_nitems(pairs); i += 2) { - if (!less(pairs[i], pairs[i + 1])) { - nxt_log_alert(thr->log, - "msec diff test failed: 0x%08XM 0x%08XM", - pairs[i], pairs[i + 1]); - return NXT_ERROR; - } + if (!less(pairs[i], pairs[i + 1])) { + nxt_log_alert(thr->log, "msec diff test failed: 0x%08XM 0x%08XM", + pairs[i], pairs[i + 1]); + return NXT_ERROR; } + } - nxt_log_error(NXT_LOG_NOTICE, thr->log, "msec diff test passed"); - return NXT_OK; + nxt_log_error(NXT_LOG_NOTICE, thr->log, "msec diff test passed"); + return NXT_OK; } diff --git a/src/test/nxt_rbtree1.c b/src/test/nxt_rbtree1.c index ec0248586..c8a97425b 100644 --- a/src/test/nxt_rbtree1.c +++ b/src/test/nxt_rbtree1.c @@ -4,379 +4,362 @@ * Copyright (C) NGINX, Inc. */ - #include #include "nxt_rbtree1.h" - /* * The red-black tree code is based on the algorithm described in * the "Introduction to Algorithms" by Cormen, Leiserson and Rivest. */ - nxt_inline void nxt_rbtree1_left_rotate(nxt_rbtree1_node_t **root, - nxt_rbtree1_node_t *sentinel, nxt_rbtree1_node_t *node); + nxt_rbtree1_node_t *sentinel, + nxt_rbtree1_node_t *node); nxt_inline void nxt_rbtree1_right_rotate(nxt_rbtree1_node_t **root, - nxt_rbtree1_node_t *sentinel, nxt_rbtree1_node_t *node); - - -void -nxt_rbtree1_insert(nxt_rbtree1_t *tree, nxt_rbtree1_node_t *node) -{ - nxt_rbtree1_node_t **root, *temp, *sentinel; + nxt_rbtree1_node_t *sentinel, + nxt_rbtree1_node_t *node); - /* a binary tree insert */ +void nxt_rbtree1_insert(nxt_rbtree1_t *tree, nxt_rbtree1_node_t *node) { + nxt_rbtree1_node_t **root, *temp, *sentinel; - root = (nxt_rbtree1_node_t **) &tree->root; - sentinel = tree->sentinel; + /* a binary tree insert */ - if (*root == sentinel) { - node->parent = NULL; - node->left = sentinel; - node->right = sentinel; - nxt_rbtree1_black(node); - *root = node; + root = (nxt_rbtree1_node_t **)&tree->root; + sentinel = tree->sentinel; - return; - } + if (*root == sentinel) { + node->parent = NULL; + node->left = sentinel; + node->right = sentinel; + nxt_rbtree1_black(node); + *root = node; - tree->insert(*root, node, sentinel); + return; + } - /* re-balance tree */ + tree->insert(*root, node, sentinel); - while (node != *root && nxt_rbtree1_is_red(node->parent)) { + /* re-balance tree */ - if (node->parent == node->parent->parent->left) { - temp = node->parent->parent->right; + while (node != *root && nxt_rbtree1_is_red(node->parent)) { - if (nxt_rbtree1_is_red(temp)) { - nxt_rbtree1_black(node->parent); - nxt_rbtree1_black(temp); - nxt_rbtree1_red(node->parent->parent); - node = node->parent->parent; + if (node->parent == node->parent->parent->left) { + temp = node->parent->parent->right; - } else { - if (node == node->parent->right) { - node = node->parent; - nxt_rbtree1_left_rotate(root, sentinel, node); - } + if (nxt_rbtree1_is_red(temp)) { + nxt_rbtree1_black(node->parent); + nxt_rbtree1_black(temp); + nxt_rbtree1_red(node->parent->parent); + node = node->parent->parent; - nxt_rbtree1_black(node->parent); - nxt_rbtree1_red(node->parent->parent); - nxt_rbtree1_right_rotate(root, sentinel, node->parent->parent); - } + } else { + if (node == node->parent->right) { + node = node->parent; + nxt_rbtree1_left_rotate(root, sentinel, node); + } - } else { - temp = node->parent->parent->left; + nxt_rbtree1_black(node->parent); + nxt_rbtree1_red(node->parent->parent); + nxt_rbtree1_right_rotate(root, sentinel, node->parent->parent); + } - if (nxt_rbtree1_is_red(temp)) { - nxt_rbtree1_black(node->parent); - nxt_rbtree1_black(temp); - nxt_rbtree1_red(node->parent->parent); - node = node->parent->parent; + } else { + temp = node->parent->parent->left; - } else { - if (node == node->parent->left) { - node = node->parent; - nxt_rbtree1_right_rotate(root, sentinel, node); - } + if (nxt_rbtree1_is_red(temp)) { + nxt_rbtree1_black(node->parent); + nxt_rbtree1_black(temp); + nxt_rbtree1_red(node->parent->parent); + node = node->parent->parent; - nxt_rbtree1_black(node->parent); - nxt_rbtree1_red(node->parent->parent); - nxt_rbtree1_left_rotate(root, sentinel, node->parent->parent); - } + } else { + if (node == node->parent->left) { + node = node->parent; + nxt_rbtree1_right_rotate(root, sentinel, node); } + + nxt_rbtree1_black(node->parent); + nxt_rbtree1_red(node->parent->parent); + nxt_rbtree1_left_rotate(root, sentinel, node->parent->parent); + } } + } - nxt_rbtree1_black(*root); + nxt_rbtree1_black(*root); } +void nxt_rbtree1_insert_value(nxt_rbtree1_node_t *temp, + nxt_rbtree1_node_t *node, + nxt_rbtree1_node_t *sentinel) { + nxt_rbtree1_node_t **p; -void -nxt_rbtree1_insert_value(nxt_rbtree1_node_t *temp, nxt_rbtree1_node_t *node, - nxt_rbtree1_node_t *sentinel) -{ - nxt_rbtree1_node_t **p; - - for ( ;; ) { + for (;;) { - p = (node->key < temp->key) ? &temp->left : &temp->right; + p = (node->key < temp->key) ? &temp->left : &temp->right; - if (*p == sentinel) { - break; - } - - temp = *p; + if (*p == sentinel) { + break; } - *p = node; - node->parent = temp; - node->left = sentinel; - node->right = sentinel; - nxt_rbtree1_red(node); -} - + temp = *p; + } -void -nxt_rbtree1_insert_timer_value(nxt_rbtree1_node_t *temp, - nxt_rbtree1_node_t *node, nxt_rbtree1_node_t *sentinel) -{ - nxt_rbtree1_node_t **p; + *p = node; + node->parent = temp; + node->left = sentinel; + node->right = sentinel; + nxt_rbtree1_red(node); +} - for ( ;; ) { +void nxt_rbtree1_insert_timer_value(nxt_rbtree1_node_t *temp, + nxt_rbtree1_node_t *node, + nxt_rbtree1_node_t *sentinel) { + nxt_rbtree1_node_t **p; - /* - * Timer values - * 1) are spread in small range, usually several minutes, - * 2) and overflow each 49 days, if milliseconds are stored in 32 bits. - * The comparison takes into account that overflow. - */ + for (;;) { - /* node->key < temp->key */ + /* + * Timer values + * 1) are spread in small range, usually several minutes, + * 2) and overflow each 49 days, if milliseconds are stored in 32 bits. + * The comparison takes into account that overflow. + */ - p = ((nxt_rbtree1_key_int_t) (node->key - temp->key) < 0) - ? &temp->left : &temp->right; + /* node->key < temp->key */ - if (*p == sentinel) { - break; - } + p = ((nxt_rbtree1_key_int_t)(node->key - temp->key) < 0) ? &temp->left + : &temp->right; - temp = *p; + if (*p == sentinel) { + break; } - *p = node; - node->parent = temp; - node->left = sentinel; - node->right = sentinel; - nxt_rbtree1_red(node); + temp = *p; + } + + *p = node; + node->parent = temp; + node->left = sentinel; + node->right = sentinel; + nxt_rbtree1_red(node); } +void nxt_rbtree1_delete(nxt_rbtree1_t *tree, nxt_rbtree1_node_t *node) { + nxt_uint_t red; + nxt_rbtree1_node_t **root, *sentinel, *subst, *temp, *w; -void -nxt_rbtree1_delete(nxt_rbtree1_t *tree, nxt_rbtree1_node_t *node) -{ - nxt_uint_t red; - nxt_rbtree1_node_t **root, *sentinel, *subst, *temp, *w; + /* a binary tree delete */ - /* a binary tree delete */ + root = (nxt_rbtree1_node_t **)&tree->root; + sentinel = tree->sentinel; - root = (nxt_rbtree1_node_t **) &tree->root; - sentinel = tree->sentinel; + if (node->left == sentinel) { + temp = node->right; + subst = node; - if (node->left == sentinel) { - temp = node->right; - subst = node; + } else if (node->right == sentinel) { + temp = node->left; + subst = node; - } else if (node->right == sentinel) { - temp = node->left; - subst = node; + } else { + subst = nxt_rbtree1_min(node->right, sentinel); + if (subst->left != sentinel) { + temp = subst->left; } else { - subst = nxt_rbtree1_min(node->right, sentinel); - - if (subst->left != sentinel) { - temp = subst->left; - } else { - temp = subst->right; - } + temp = subst->right; } + } - if (subst == *root) { - *root = temp; - nxt_rbtree1_black(temp); - - /* DEBUG stuff */ - node->left = NULL; - node->right = NULL; - node->parent = NULL; - node->key = 0; - - return; - } + if (subst == *root) { + *root = temp; + nxt_rbtree1_black(temp); - red = nxt_rbtree1_is_red(subst); + /* DEBUG stuff */ + node->left = NULL; + node->right = NULL; + node->parent = NULL; + node->key = 0; - if (subst == subst->parent->left) { - subst->parent->left = temp; + return; + } - } else { - subst->parent->right = temp; - } + red = nxt_rbtree1_is_red(subst); - if (subst == node) { + if (subst == subst->parent->left) { + subst->parent->left = temp; - temp->parent = subst->parent; + } else { + subst->parent->right = temp; + } - } else { + if (subst == node) { - if (subst->parent == node) { - temp->parent = subst; + temp->parent = subst->parent; - } else { - temp->parent = subst->parent; - } + } else { - subst->left = node->left; - subst->right = node->right; - subst->parent = node->parent; - nxt_rbtree1_copy_color(subst, node); + if (subst->parent == node) { + temp->parent = subst; - if (node == *root) { - *root = subst; + } else { + temp->parent = subst->parent; + } - } else { - if (node == node->parent->left) { - node->parent->left = subst; - } else { - node->parent->right = subst; - } - } + subst->left = node->left; + subst->right = node->right; + subst->parent = node->parent; + nxt_rbtree1_copy_color(subst, node); - if (subst->left != sentinel) { - subst->left->parent = subst; - } + if (node == *root) { + *root = subst; - if (subst->right != sentinel) { - subst->right->parent = subst; - } + } else { + if (node == node->parent->left) { + node->parent->left = subst; + } else { + node->parent->right = subst; + } } - /* DEBUG stuff */ - node->left = NULL; - node->right = NULL; - node->parent = NULL; - node->key = 0; + if (subst->left != sentinel) { + subst->left->parent = subst; + } - if (red) { - return; + if (subst->right != sentinel) { + subst->right->parent = subst; } + } + + /* DEBUG stuff */ + node->left = NULL; + node->right = NULL; + node->parent = NULL; + node->key = 0; + + if (red) { + return; + } + + /* a delete fixup */ + + while (temp != *root && nxt_rbtree1_is_black(temp)) { + + if (temp == temp->parent->left) { + w = temp->parent->right; + + if (nxt_rbtree1_is_red(w)) { + nxt_rbtree1_black(w); + nxt_rbtree1_red(temp->parent); + nxt_rbtree1_left_rotate(root, sentinel, temp->parent); + w = temp->parent->right; + } + + if (nxt_rbtree1_is_black(w->left) && nxt_rbtree1_is_black(w->right)) { + nxt_rbtree1_red(w); + temp = temp->parent; + + } else { + if (nxt_rbtree1_is_black(w->right)) { + nxt_rbtree1_black(w->left); + nxt_rbtree1_red(w); + nxt_rbtree1_right_rotate(root, sentinel, w); + w = temp->parent->right; + } + + nxt_rbtree1_copy_color(w, temp->parent); + nxt_rbtree1_black(temp->parent); + nxt_rbtree1_black(w->right); + nxt_rbtree1_left_rotate(root, sentinel, temp->parent); + temp = *root; + } - /* a delete fixup */ - - while (temp != *root && nxt_rbtree1_is_black(temp)) { - - if (temp == temp->parent->left) { - w = temp->parent->right; - - if (nxt_rbtree1_is_red(w)) { - nxt_rbtree1_black(w); - nxt_rbtree1_red(temp->parent); - nxt_rbtree1_left_rotate(root, sentinel, temp->parent); - w = temp->parent->right; - } - - if (nxt_rbtree1_is_black(w->left) && nxt_rbtree1_is_black(w->right)) - { - nxt_rbtree1_red(w); - temp = temp->parent; - - } else { - if (nxt_rbtree1_is_black(w->right)) { - nxt_rbtree1_black(w->left); - nxt_rbtree1_red(w); - nxt_rbtree1_right_rotate(root, sentinel, w); - w = temp->parent->right; - } - - nxt_rbtree1_copy_color(w, temp->parent); - nxt_rbtree1_black(temp->parent); - nxt_rbtree1_black(w->right); - nxt_rbtree1_left_rotate(root, sentinel, temp->parent); - temp = *root; - } - - } else { - w = temp->parent->left; - - if (nxt_rbtree1_is_red(w)) { - nxt_rbtree1_black(w); - nxt_rbtree1_red(temp->parent); - nxt_rbtree1_right_rotate(root, sentinel, temp->parent); - w = temp->parent->left; - } - - if (nxt_rbtree1_is_black(w->left) && nxt_rbtree1_is_black(w->right)) - { - nxt_rbtree1_red(w); - temp = temp->parent; - - } else { - if (nxt_rbtree1_is_black(w->left)) { - nxt_rbtree1_black(w->right); - nxt_rbtree1_red(w); - nxt_rbtree1_left_rotate(root, sentinel, w); - w = temp->parent->left; - } - - nxt_rbtree1_copy_color(w, temp->parent); - nxt_rbtree1_black(temp->parent); - nxt_rbtree1_black(w->left); - nxt_rbtree1_right_rotate(root, sentinel, temp->parent); - temp = *root; - } + } else { + w = temp->parent->left; + + if (nxt_rbtree1_is_red(w)) { + nxt_rbtree1_black(w); + nxt_rbtree1_red(temp->parent); + nxt_rbtree1_right_rotate(root, sentinel, temp->parent); + w = temp->parent->left; + } + + if (nxt_rbtree1_is_black(w->left) && nxt_rbtree1_is_black(w->right)) { + nxt_rbtree1_red(w); + temp = temp->parent; + + } else { + if (nxt_rbtree1_is_black(w->left)) { + nxt_rbtree1_black(w->right); + nxt_rbtree1_red(w); + nxt_rbtree1_left_rotate(root, sentinel, w); + w = temp->parent->left; } + + nxt_rbtree1_copy_color(w, temp->parent); + nxt_rbtree1_black(temp->parent); + nxt_rbtree1_black(w->left); + nxt_rbtree1_right_rotate(root, sentinel, temp->parent); + temp = *root; + } } + } - nxt_rbtree1_black(temp); + nxt_rbtree1_black(temp); } +nxt_inline void nxt_rbtree1_left_rotate(nxt_rbtree1_node_t **root, + nxt_rbtree1_node_t *sentinel, + nxt_rbtree1_node_t *node) { + nxt_rbtree1_node_t *temp; -nxt_inline void -nxt_rbtree1_left_rotate(nxt_rbtree1_node_t **root, nxt_rbtree1_node_t *sentinel, - nxt_rbtree1_node_t *node) -{ - nxt_rbtree1_node_t *temp; + temp = node->right; + node->right = temp->left; - temp = node->right; - node->right = temp->left; + if (temp->left != sentinel) { + temp->left->parent = node; + } - if (temp->left != sentinel) { - temp->left->parent = node; - } + temp->parent = node->parent; - temp->parent = node->parent; + if (node == *root) { + *root = temp; - if (node == *root) { - *root = temp; + } else if (node == node->parent->left) { + node->parent->left = temp; - } else if (node == node->parent->left) { - node->parent->left = temp; + } else { + node->parent->right = temp; + } - } else { - node->parent->right = temp; - } - - temp->left = node; - node->parent = temp; + temp->left = node; + node->parent = temp; } +nxt_inline void nxt_rbtree1_right_rotate(nxt_rbtree1_node_t **root, + nxt_rbtree1_node_t *sentinel, + nxt_rbtree1_node_t *node) { + nxt_rbtree1_node_t *temp; -nxt_inline void -nxt_rbtree1_right_rotate(nxt_rbtree1_node_t **root, - nxt_rbtree1_node_t *sentinel, nxt_rbtree1_node_t *node) -{ - nxt_rbtree1_node_t *temp; + temp = node->left; + node->left = temp->right; - temp = node->left; - node->left = temp->right; + if (temp->right != sentinel) { + temp->right->parent = node; + } - if (temp->right != sentinel) { - temp->right->parent = node; - } + temp->parent = node->parent; - temp->parent = node->parent; + if (node == *root) { + *root = temp; - if (node == *root) { - *root = temp; - - } else if (node == node->parent->right) { - node->parent->right = temp; + } else if (node == node->parent->right) { + node->parent->right = temp; - } else { - node->parent->left = temp; - } + } else { + node->parent->left = temp; + } - temp->right = node; - node->parent = temp; + temp->right = node; + node->parent = temp; } diff --git a/src/test/nxt_rbtree1.h b/src/test/nxt_rbtree1.h index d6230ab0c..6ccd9cd0b 100644 --- a/src/test/nxt_rbtree1.h +++ b/src/test/nxt_rbtree1.h @@ -4,70 +4,64 @@ * Copyright (C) NGINX, Inc. */ +typedef nxt_uint_t nxt_rbtree1_key_t; +typedef nxt_int_t nxt_rbtree1_key_int_t; -typedef nxt_uint_t nxt_rbtree1_key_t; -typedef nxt_int_t nxt_rbtree1_key_int_t; - - -typedef struct nxt_rbtree1_node_s nxt_rbtree1_node_t; +typedef struct nxt_rbtree1_node_s nxt_rbtree1_node_t; struct nxt_rbtree1_node_s { - nxt_rbtree1_key_t key; - nxt_rbtree1_node_t *left; - nxt_rbtree1_node_t *right; - nxt_rbtree1_node_t *parent; - u_char color; - u_char data; + nxt_rbtree1_key_t key; + nxt_rbtree1_node_t *left; + nxt_rbtree1_node_t *right; + nxt_rbtree1_node_t *parent; + u_char color; + u_char data; }; +typedef struct nxt_rbtree1_s nxt_rbtree1_t; -typedef struct nxt_rbtree1_s nxt_rbtree1_t; - -typedef void (*nxt_rbtree1_insert_pt) (nxt_rbtree1_node_t *root, - nxt_rbtree1_node_t *node, nxt_rbtree1_node_t *sentinel); +typedef void (*nxt_rbtree1_insert_pt)(nxt_rbtree1_node_t *root, + nxt_rbtree1_node_t *node, + nxt_rbtree1_node_t *sentinel); struct nxt_rbtree1_s { - nxt_rbtree1_node_t *root; - nxt_rbtree1_node_t *sentinel; - nxt_rbtree1_insert_pt insert; + nxt_rbtree1_node_t *root; + nxt_rbtree1_node_t *sentinel; + nxt_rbtree1_insert_pt insert; }; - -#define nxt_rbtree1_init(tree, s, i) \ - nxt_rbtree1_sentinel_init(s); \ - (tree)->root = s; \ - (tree)->sentinel = s; \ - (tree)->insert = i - +#define nxt_rbtree1_init(tree, s, i) \ + nxt_rbtree1_sentinel_init(s); \ + (tree)->root = s; \ + (tree)->sentinel = s; \ + (tree)->insert = i NXT_EXPORT void nxt_rbtree1_insert(nxt_rbtree1_t *tree, - nxt_rbtree1_node_t *node); + nxt_rbtree1_node_t *node); NXT_EXPORT void nxt_rbtree1_delete(nxt_rbtree1_t *tree, - nxt_rbtree1_node_t *node); + nxt_rbtree1_node_t *node); NXT_EXPORT void nxt_rbtree1_insert_value(nxt_rbtree1_node_t *root, - nxt_rbtree1_node_t *node, nxt_rbtree1_node_t *sentinel); + nxt_rbtree1_node_t *node, + nxt_rbtree1_node_t *sentinel); NXT_EXPORT void nxt_rbtree1_insert_timer_value(nxt_rbtree1_node_t *root, - nxt_rbtree1_node_t *node, nxt_rbtree1_node_t *sentinel); - - -#define nxt_rbtree1_red(node) ((node)->color = 1) -#define nxt_rbtree1_black(node) ((node)->color = 0) -#define nxt_rbtree1_is_red(node) ((node)->color) -#define nxt_rbtree1_is_black(node) (!nxt_rbtree1_is_red(node)) -#define nxt_rbtree1_copy_color(n1, n2) (n1->color = n2->color) + nxt_rbtree1_node_t *node, + nxt_rbtree1_node_t *sentinel); +#define nxt_rbtree1_red(node) ((node)->color = 1) +#define nxt_rbtree1_black(node) ((node)->color = 0) +#define nxt_rbtree1_is_red(node) ((node)->color) +#define nxt_rbtree1_is_black(node) (!nxt_rbtree1_is_red(node)) +#define nxt_rbtree1_copy_color(n1, n2) (n1->color = n2->color) /* a sentinel must be black */ -#define nxt_rbtree1_sentinel_init(node) nxt_rbtree1_black(node) - +#define nxt_rbtree1_sentinel_init(node) nxt_rbtree1_black(node) -nxt_inline nxt_rbtree1_node_t * -nxt_rbtree1_min(nxt_rbtree1_node_t *node, nxt_rbtree1_node_t *sentinel) -{ - while (node->left != sentinel) { - node = node->left; - } +nxt_inline nxt_rbtree1_node_t *nxt_rbtree1_min(nxt_rbtree1_node_t *node, + nxt_rbtree1_node_t *sentinel) { + while (node->left != sentinel) { + node = node->left; + } - return node; + return node; } diff --git a/src/test/nxt_rbtree1_test.c b/src/test/nxt_rbtree1_test.c index 1f23998c8..2b83972c9 100644 --- a/src/test/nxt_rbtree1_test.c +++ b/src/test/nxt_rbtree1_test.c @@ -8,178 +8,166 @@ #include "nxt_tests.h" #include "nxt_rbtree1.h" +#define nxt_rbtree1_is_empty(tree) (((tree)->root) == (tree)->sentinel) -#define nxt_rbtree1_is_empty(tree) \ - (((tree)->root) == (tree)->sentinel) - - -#define nxt_rbtree1_is_there_successor(tree, node) \ - ((node) != (tree)->sentinel) - +#define nxt_rbtree1_is_there_successor(tree, node) ((node) != (tree)->sentinel) nxt_inline nxt_rbtree1_node_t * -nxt_rbtree1_node_successor(nxt_rbtree1_t *tree, nxt_rbtree1_node_t *node) -{ - nxt_rbtree1_node_t *parent; +nxt_rbtree1_node_successor(nxt_rbtree1_t *tree, nxt_rbtree1_node_t *node) { + nxt_rbtree1_node_t *parent; - if (node->right != tree->sentinel) { - return nxt_rbtree1_min(node->right, tree->sentinel); - } - - for ( ;; ) { - parent = node->parent; + if (node->right != tree->sentinel) { + return nxt_rbtree1_min(node->right, tree->sentinel); + } - if (parent == NULL) { - return tree->sentinel; - } + for (;;) { + parent = node->parent; - if (node == parent->left) { - return parent; - } + if (parent == NULL) { + return tree->sentinel; + } - node = parent; + if (node == parent->left) { + return parent; } -} + node = parent; + } +} static void nxt_rbtree1_test_insert_value(nxt_rbtree1_node_t *temp, - nxt_rbtree1_node_t *node, nxt_rbtree1_node_t *sentinel); + nxt_rbtree1_node_t *node, + nxt_rbtree1_node_t *sentinel); static nxt_int_t nxt_rbtree1_test_compare(nxt_rbtree1_node_t *node1, - nxt_rbtree1_node_t *node2); + nxt_rbtree1_node_t *node2); static int nxt_cdecl nxt_rbtree1_test_sort_cmp(const void *one, - const void *two); + const void *two); static nxt_rbtree1_node_t *nxt_rbtree1_test_find(nxt_rbtree1_t *tree, - nxt_rbtree1_node_t *node); - + nxt_rbtree1_node_t *node); -nxt_int_t -nxt_rbtree1_test(nxt_thread_t *thr, nxt_uint_t n) -{ - uint32_t key, *keys; - nxt_uint_t i; - nxt_nsec_t start, end; - nxt_rbtree1_t tree; - nxt_rbtree1_node_t *node, *nodes, sentinel; +nxt_int_t nxt_rbtree1_test(nxt_thread_t *thr, nxt_uint_t n) { + uint32_t key, *keys; + nxt_uint_t i; + nxt_nsec_t start, end; + nxt_rbtree1_t tree; + nxt_rbtree1_node_t *node, *nodes, sentinel; - nxt_thread_time_update(thr); + nxt_thread_time_update(thr); - nxt_log_error(NXT_LOG_NOTICE, thr->log, "rbtree1 test started: %ui", n); + nxt_log_error(NXT_LOG_NOTICE, thr->log, "rbtree1 test started: %ui", n); - nxt_rbtree1_init(&tree, &sentinel, nxt_rbtree1_test_insert_value); + nxt_rbtree1_init(&tree, &sentinel, nxt_rbtree1_test_insert_value); - nodes = nxt_malloc(n * sizeof(nxt_rbtree1_node_t)); - if (nodes == NULL) { - return NXT_ERROR; - } + nodes = nxt_malloc(n * sizeof(nxt_rbtree1_node_t)); + if (nodes == NULL) { + return NXT_ERROR; + } - keys = nxt_malloc(n * sizeof(uint32_t)); - if (keys == NULL) { - nxt_free(keys); - return NXT_ERROR; - } + keys = nxt_malloc(n * sizeof(uint32_t)); + if (keys == NULL) { + nxt_free(keys); + return NXT_ERROR; + } - key = 0; + key = 0; - for (i = 0; i < n; i++) { - key = nxt_murmur_hash2(&key, sizeof(uint32_t)); + for (i = 0; i < n; i++) { + key = nxt_murmur_hash2(&key, sizeof(uint32_t)); - keys[i] = key; - nodes[i].key = key; - } + keys[i] = key; + nodes[i].key = key; + } - nxt_qsort(keys, n, sizeof(uint32_t), nxt_rbtree1_test_sort_cmp); + nxt_qsort(keys, n, sizeof(uint32_t), nxt_rbtree1_test_sort_cmp); - nxt_thread_time_update(thr); - start = nxt_thread_monotonic_time(thr); + nxt_thread_time_update(thr); + start = nxt_thread_monotonic_time(thr); - for (i = 0; i < n; i++) { - nxt_rbtree1_insert(&tree, &nodes[i]); - } + for (i = 0; i < n; i++) { + nxt_rbtree1_insert(&tree, &nodes[i]); + } - for (i = 0; i < n; i++) { - if (nxt_rbtree1_test_find(&tree, &nodes[i]) != &nodes[i]) { - nxt_log_alert(thr->log, "rbtree1 test failed: %08XD not found", - nodes[i].key); - goto fail; - } + for (i = 0; i < n; i++) { + if (nxt_rbtree1_test_find(&tree, &nodes[i]) != &nodes[i]) { + nxt_log_alert(thr->log, "rbtree1 test failed: %08XD not found", + nodes[i].key); + goto fail; } + } - i = 0; - node = nxt_rbtree1_min(tree.root, tree.sentinel); - - while (nxt_rbtree1_is_there_successor(&tree, node)) { + i = 0; + node = nxt_rbtree1_min(tree.root, tree.sentinel); - if (keys[i] != node->key) { - nxt_log_alert(thr->log, "rbtree1 test failed: %i: %08XD %08XD", - i, keys[i], node->key); - goto fail; - } + while (nxt_rbtree1_is_there_successor(&tree, node)) { - i++; - node = nxt_rbtree1_node_successor(&tree, node); + if (keys[i] != node->key) { + nxt_log_alert(thr->log, "rbtree1 test failed: %i: %08XD %08XD", i, + keys[i], node->key); + goto fail; } - if (i != n) { - nxt_log_alert(thr->log, "rbtree1 test failed: %ui", i); - goto fail; - } + i++; + node = nxt_rbtree1_node_successor(&tree, node); + } - for (i = 0; i < n; i++) { - nxt_rbtree1_delete(&tree, &nodes[i]); - nxt_memset(&nodes[i], 0xA5, sizeof(nxt_rbtree1_node_t)); - } + if (i != n) { + nxt_log_alert(thr->log, "rbtree1 test failed: %ui", i); + goto fail; + } - nxt_thread_time_update(thr); - end = nxt_thread_monotonic_time(thr); + for (i = 0; i < n; i++) { + nxt_rbtree1_delete(&tree, &nodes[i]); + nxt_memset(&nodes[i], 0xA5, sizeof(nxt_rbtree1_node_t)); + } - if (!nxt_rbtree1_is_empty(&tree)) { - nxt_log_alert(thr->log, "rbtree1 test failed: tree is not empty"); - goto fail; - } + nxt_thread_time_update(thr); + end = nxt_thread_monotonic_time(thr); - nxt_free(keys); - nxt_free(nodes); + if (!nxt_rbtree1_is_empty(&tree)) { + nxt_log_alert(thr->log, "rbtree1 test failed: tree is not empty"); + goto fail; + } - nxt_log_error(NXT_LOG_NOTICE, thr->log, "rbtree1 test passed %0.3fs", - (end - start) / 1000000000.0); + nxt_free(keys); + nxt_free(nodes); - return NXT_OK; + nxt_log_error(NXT_LOG_NOTICE, thr->log, "rbtree1 test passed %0.3fs", + (end - start) / 1000000000.0); + + return NXT_OK; fail: - nxt_free(keys); - nxt_free(nodes); + nxt_free(keys); + nxt_free(nodes); - return NXT_ERROR; + return NXT_ERROR; } +static void nxt_rbtree1_test_insert_value(nxt_rbtree1_node_t *temp, + nxt_rbtree1_node_t *node, + nxt_rbtree1_node_t *sentinel) { + nxt_rbtree1_node_t **p; -static void -nxt_rbtree1_test_insert_value(nxt_rbtree1_node_t *temp, - nxt_rbtree1_node_t *node, nxt_rbtree1_node_t *sentinel) -{ - nxt_rbtree1_node_t **p; - - for ( ;; ) { - nxt_prefetch(temp->left); - nxt_prefetch(temp->right); - - p = (node->key < temp->key) ? &temp->left : &temp->right; + for (;;) { + nxt_prefetch(temp->left); + nxt_prefetch(temp->right); - if (*p == sentinel) { - break; - } + p = (node->key < temp->key) ? &temp->left : &temp->right; - temp = *p; + if (*p == sentinel) { + break; } - *p = node; - node->parent = temp; - node->left = sentinel; - node->right = sentinel; - nxt_rbtree1_red(node); -} + temp = *p; + } + *p = node; + node->parent = temp; + node->left = sentinel; + node->right = sentinel; + nxt_rbtree1_red(node); +} /* * Subtraction cannot be used in these comparison functions because the key @@ -187,155 +175,140 @@ nxt_rbtree1_test_insert_value(nxt_rbtree1_node_t *temp, * around some value as timeout values are. */ -nxt_inline nxt_int_t -nxt_rbtree1_test_compare(nxt_rbtree1_node_t *node1, nxt_rbtree1_node_t *node2) -{ - if (node1->key < node2->key) { - return -1; - } +nxt_inline nxt_int_t nxt_rbtree1_test_compare(nxt_rbtree1_node_t *node1, + nxt_rbtree1_node_t *node2) { + if (node1->key < node2->key) { + return -1; + } - if (node1->key == node2->key) { - return 0; - } + if (node1->key == node2->key) { + return 0; + } - return 1; + return 1; } +static int nxt_cdecl nxt_rbtree1_test_sort_cmp(const void *one, + const void *two) { + const uint32_t *first, *second; -static int nxt_cdecl -nxt_rbtree1_test_sort_cmp(const void *one, const void *two) -{ - const uint32_t *first, *second; - - first = one; - second = two; + first = one; + second = two; - if (*first < *second) { - return -1; - } + if (*first < *second) { + return -1; + } - if (*first == *second) { - return 0; - } + if (*first == *second) { + return 0; + } - return 1; + return 1; } +static nxt_rbtree1_node_t *nxt_rbtree1_test_find(nxt_rbtree1_t *tree, + nxt_rbtree1_node_t *node) { + nxt_int_t n; + nxt_rbtree1_node_t *next, *sentinel; -static nxt_rbtree1_node_t * -nxt_rbtree1_test_find(nxt_rbtree1_t *tree, nxt_rbtree1_node_t *node) -{ - nxt_int_t n; - nxt_rbtree1_node_t *next, *sentinel; - - next = tree->root; - sentinel = tree->sentinel; + next = tree->root; + sentinel = tree->sentinel; - while (next != sentinel) { - nxt_prefetch(next->left); - nxt_prefetch(next->right); + while (next != sentinel) { + nxt_prefetch(next->left); + nxt_prefetch(next->right); - n = nxt_rbtree1_test_compare(node, next); + n = nxt_rbtree1_test_compare(node, next); - if (n < 0) { - next = next->left; + if (n < 0) { + next = next->left; - } else if (n > 0) { - next = next->right; + } else if (n > 0) { + next = next->right; - } else { - return next; - } + } else { + return next; } + } - return NULL; + return NULL; } - #if (NXT_TEST_RTDTSC) -#define NXT_RBT_STEP (21 * nxt_pagesize / 10 / sizeof(nxt_rbtree1_node_t)) - -static nxt_rbtree1_t mb_tree; -static nxt_rbtree1_node_t mb_sentinel; -static nxt_rbtree1_node_t *mb_nodes; +#define NXT_RBT_STEP (21 * nxt_pagesize / 10 / sizeof(nxt_rbtree1_node_t)) +static nxt_rbtree1_t mb_tree; +static nxt_rbtree1_node_t mb_sentinel; +static nxt_rbtree1_node_t *mb_nodes; -nxt_int_t -nxt_rbtree1_mb_start(nxt_thread_t *thr) -{ - uint32_t key; - uint64_t start, end; - nxt_uint_t i, n; +nxt_int_t nxt_rbtree1_mb_start(nxt_thread_t *thr) { + uint32_t key; + uint64_t start, end; + nxt_uint_t i, n; - n = NXT_RBT_STEP; + n = NXT_RBT_STEP; - mb_nodes = nxt_malloc(NXT_RBT_NODES * n * sizeof(nxt_rbtree1_node_t)); - if (mb_nodes == NULL) { - return NXT_ERROR; - } + mb_nodes = nxt_malloc(NXT_RBT_NODES * n * sizeof(nxt_rbtree1_node_t)); + if (mb_nodes == NULL) { + return NXT_ERROR; + } - nxt_rbtree1_init(&mb_tree, &mb_sentinel, nxt_rbtree1_test_insert_value); + nxt_rbtree1_init(&mb_tree, &mb_sentinel, nxt_rbtree1_test_insert_value); - key = 0; + key = 0; - for (i = 0; i < NXT_RBT_NODES; i++) { - key = nxt_murmur_hash2(&key, sizeof(uint32_t)); - mb_nodes[n * i].key = key; - } + for (i = 0; i < NXT_RBT_NODES; i++) { + key = nxt_murmur_hash2(&key, sizeof(uint32_t)); + mb_nodes[n * i].key = key; + } - for (i = 0; i < NXT_RBT_NODES - 2; i++) { - nxt_rbtree1_insert(&mb_tree, &mb_nodes[n * i]); - } + for (i = 0; i < NXT_RBT_NODES - 2; i++) { + nxt_rbtree1_insert(&mb_tree, &mb_nodes[n * i]); + } - n *= (NXT_RBT_NODES - 2); + n *= (NXT_RBT_NODES - 2); - start = nxt_rdtsc(); - nxt_rbtree1_insert(&mb_tree, &mb_nodes[n]); - end = nxt_rdtsc(); + start = nxt_rdtsc(); + nxt_rbtree1_insert(&mb_tree, &mb_nodes[n]); + end = nxt_rdtsc(); - nxt_log_error(NXT_LOG_NOTICE, thr->log, - "rbtree1 mb cached insert: %L cycles", end - start); + nxt_log_error(NXT_LOG_NOTICE, thr->log, "rbtree1 mb cached insert: %L cycles", + end - start); - return NXT_OK; + return NXT_OK; } +void nxt_rbtree1_mb_insert(nxt_thread_t *thr) { + uint64_t start, end; + nxt_uint_t n; -void -nxt_rbtree1_mb_insert(nxt_thread_t *thr) -{ - uint64_t start, end; - nxt_uint_t n; + n = NXT_RBT_STEP; + n *= (NXT_RBT_NODES - 1); - n = NXT_RBT_STEP; - n *= (NXT_RBT_NODES - 1); + start = nxt_rdtsc(); + nxt_rbtree1_insert(&mb_tree, &mb_nodes[n]); + end = nxt_rdtsc(); - start = nxt_rdtsc(); - nxt_rbtree1_insert(&mb_tree, &mb_nodes[n]); - end = nxt_rdtsc(); - - nxt_log_error(NXT_LOG_NOTICE, thr->log, - "rbtree1 mb insert: %L cycles", end - start); + nxt_log_error(NXT_LOG_NOTICE, thr->log, "rbtree1 mb insert: %L cycles", + end - start); } +void nxt_rbtree1_mb_delete(nxt_thread_t *thr) { + uint64_t start, end; + nxt_uint_t n; -void -nxt_rbtree1_mb_delete(nxt_thread_t *thr) -{ - uint64_t start, end; - nxt_uint_t n; - - n = NXT_RBT_STEP; - n *= (NXT_RBT_NODES / 4 + 1); + n = NXT_RBT_STEP; + n *= (NXT_RBT_NODES / 4 + 1); - start = nxt_rdtsc(); - nxt_rbtree1_delete(&mb_tree, &mb_nodes[n]); - end = nxt_rdtsc(); + start = nxt_rdtsc(); + nxt_rbtree1_delete(&mb_tree, &mb_nodes[n]); + end = nxt_rdtsc(); - nxt_log_error(NXT_LOG_NOTICE, thr->log, - "rbtree1 mb delete: %L cycles", end - start); + nxt_log_error(NXT_LOG_NOTICE, thr->log, "rbtree1 mb delete: %L cycles", + end - start); - nxt_free(mb_nodes); + nxt_free(mb_nodes); } #endif diff --git a/src/test/nxt_rbtree_test.c b/src/test/nxt_rbtree_test.c index 41375d920..e8b435830 100644 --- a/src/test/nxt_rbtree_test.c +++ b/src/test/nxt_rbtree_test.c @@ -7,273 +7,250 @@ #include #include "nxt_tests.h" - typedef struct { - NXT_RBTREE_NODE (node); - uint32_t key; + NXT_RBTREE_NODE(node); + uint32_t key; } nxt_rbtree_test_t; - static intptr_t nxt_rbtree_test_comparison(nxt_rbtree_node_t *node1, - nxt_rbtree_node_t *node2); + nxt_rbtree_node_t *node2); static nxt_int_t nxt_rbtree_test_compare(uint32_t key1, uint32_t key2); static int nxt_cdecl nxt_rbtree_test_sort_cmp(const void *one, const void *two); +nxt_int_t nxt_rbtree_test(nxt_thread_t *thr, nxt_uint_t n) { + void *mark; + uint32_t key, *keys; + nxt_uint_t i; + nxt_nsec_t start, end; + nxt_rbtree_t tree; + nxt_rbtree_node_t *node; + nxt_rbtree_test_t *items, *item; -nxt_int_t -nxt_rbtree_test(nxt_thread_t *thr, nxt_uint_t n) -{ - void *mark; - uint32_t key, *keys; - nxt_uint_t i; - nxt_nsec_t start, end; - nxt_rbtree_t tree; - nxt_rbtree_node_t *node; - nxt_rbtree_test_t *items, *item; - - nxt_thread_time_update(thr); + nxt_thread_time_update(thr); - nxt_log_error(NXT_LOG_NOTICE, thr->log, "rbtree test started: %ui", n); + nxt_log_error(NXT_LOG_NOTICE, thr->log, "rbtree test started: %ui", n); - nxt_rbtree_init(&tree, nxt_rbtree_test_comparison); + nxt_rbtree_init(&tree, nxt_rbtree_test_comparison); - mark = tree.sentinel.right; + mark = tree.sentinel.right; - items = nxt_malloc(n * sizeof(nxt_rbtree_test_t)); - if (items == NULL) { - return NXT_ERROR; - } + items = nxt_malloc(n * sizeof(nxt_rbtree_test_t)); + if (items == NULL) { + return NXT_ERROR; + } - keys = nxt_malloc(n * sizeof(uint32_t)); - if (keys == NULL) { - nxt_free(keys); - return NXT_ERROR; - } + keys = nxt_malloc(n * sizeof(uint32_t)); + if (keys == NULL) { + nxt_free(keys); + return NXT_ERROR; + } - key = 0; + key = 0; - for (i = 0; i < n; i++) { - key = nxt_murmur_hash2(&key, sizeof(uint32_t)); + for (i = 0; i < n; i++) { + key = nxt_murmur_hash2(&key, sizeof(uint32_t)); - keys[i] = key; - items[i].key = key; - } + keys[i] = key; + items[i].key = key; + } - nxt_qsort(keys, n, sizeof(uint32_t), nxt_rbtree_test_sort_cmp); + nxt_qsort(keys, n, sizeof(uint32_t), nxt_rbtree_test_sort_cmp); - nxt_thread_time_update(thr); - start = nxt_thread_monotonic_time(thr); + nxt_thread_time_update(thr); + start = nxt_thread_monotonic_time(thr); - for (i = 0; i < n; i++) { - nxt_rbtree_insert(&tree, &items[i].node); - } + for (i = 0; i < n; i++) { + nxt_rbtree_insert(&tree, &items[i].node); + } - for (i = 0; i < n; i++) { - node = nxt_rbtree_find(&tree, &items[i].node); + for (i = 0; i < n; i++) { + node = nxt_rbtree_find(&tree, &items[i].node); - if (node != (nxt_rbtree_node_t *) &items[i].node) { - nxt_log_alert(thr->log, "rbtree test failed: %08XD not found", - items[i].key); - goto fail; - } + if (node != (nxt_rbtree_node_t *)&items[i].node) { + nxt_log_alert(thr->log, "rbtree test failed: %08XD not found", + items[i].key); + goto fail; } + } - i = 0; - node = nxt_rbtree_min(&tree); - - while (nxt_rbtree_is_there_successor(&tree, node)) { + i = 0; + node = nxt_rbtree_min(&tree); - item = (nxt_rbtree_test_t *) node; + while (nxt_rbtree_is_there_successor(&tree, node)) { - if (keys[i] != item->key) { - nxt_log_alert(thr->log, "rbtree test failed: %i: %08XD %08XD", - i, keys[i], item->key); - goto fail; - } + item = (nxt_rbtree_test_t *)node; - i++; - node = nxt_rbtree_node_successor(&tree, node); + if (keys[i] != item->key) { + nxt_log_alert(thr->log, "rbtree test failed: %i: %08XD %08XD", i, keys[i], + item->key); + goto fail; } - if (i != n) { - nxt_log_alert(thr->log, "rbtree test failed: %ui", i); - goto fail; - } + i++; + node = nxt_rbtree_node_successor(&tree, node); + } - for (i = 0; i < n; i++) { - nxt_rbtree_delete(&tree, &items[i].node); - nxt_memset(&items[i], 0xA5, sizeof(nxt_rbtree_test_t)); - } + if (i != n) { + nxt_log_alert(thr->log, "rbtree test failed: %ui", i); + goto fail; + } - nxt_thread_time_update(thr); - end = nxt_thread_monotonic_time(thr); + for (i = 0; i < n; i++) { + nxt_rbtree_delete(&tree, &items[i].node); + nxt_memset(&items[i], 0xA5, sizeof(nxt_rbtree_test_t)); + } - if (!nxt_rbtree_is_empty(&tree)) { - nxt_log_alert(thr->log, "rbtree test failed: tree is not empty"); - goto fail; - } + nxt_thread_time_update(thr); + end = nxt_thread_monotonic_time(thr); - /* Check that the sentinel callback was not modified. */ + if (!nxt_rbtree_is_empty(&tree)) { + nxt_log_alert(thr->log, "rbtree test failed: tree is not empty"); + goto fail; + } - if (mark != tree.sentinel.right) { - nxt_log_alert(thr->log, "rbtree sentinel test failed"); - goto fail; - } + /* Check that the sentinel callback was not modified. */ - nxt_free(keys); - nxt_free(items); + if (mark != tree.sentinel.right) { + nxt_log_alert(thr->log, "rbtree sentinel test failed"); + goto fail; + } - nxt_log_error(NXT_LOG_NOTICE, thr->log, "rbtree test passed %0.3fs", - (end - start) / 1000000000.0); + nxt_free(keys); + nxt_free(items); - return NXT_OK; + nxt_log_error(NXT_LOG_NOTICE, thr->log, "rbtree test passed %0.3fs", + (end - start) / 1000000000.0); + + return NXT_OK; fail: - nxt_free(keys); - nxt_free(items); + nxt_free(keys); + nxt_free(items); - return NXT_ERROR; + return NXT_ERROR; } +static intptr_t nxt_rbtree_test_comparison(nxt_rbtree_node_t *node1, + nxt_rbtree_node_t *node2) { + nxt_rbtree_test_t *item1, *item2; -static intptr_t -nxt_rbtree_test_comparison(nxt_rbtree_node_t *node1, - nxt_rbtree_node_t *node2) -{ - nxt_rbtree_test_t *item1, *item2; - - item1 = (nxt_rbtree_test_t *) node1; - item2 = (nxt_rbtree_test_t *) node2; + item1 = (nxt_rbtree_test_t *)node1; + item2 = (nxt_rbtree_test_t *)node2; - return nxt_rbtree_test_compare(item1->key, item2->key); + return nxt_rbtree_test_compare(item1->key, item2->key); } - /* * Subtraction cannot be used in these comparison functions because * the key values are spread uniform in whole 0 .. 2^32 range but are * not grouped around some value as timeout values are. */ -static nxt_int_t -nxt_rbtree_test_compare(uint32_t key1, uint32_t key2) -{ - if (key1 < key2) { - return -1; - } +static nxt_int_t nxt_rbtree_test_compare(uint32_t key1, uint32_t key2) { + if (key1 < key2) { + return -1; + } - if (key1 == key2) { - return 0; - } + if (key1 == key2) { + return 0; + } - return 1; + return 1; } +static int nxt_cdecl nxt_rbtree_test_sort_cmp(const void *one, + const void *two) { + const uint32_t *first, *second; -static int nxt_cdecl -nxt_rbtree_test_sort_cmp(const void *one, const void *two) -{ - const uint32_t *first, *second; - - first = one; - second = two; + first = one; + second = two; - if (*first < *second) { - return -1; - } + if (*first < *second) { + return -1; + } - if (*first == *second) { - return 0; - } + if (*first == *second) { + return 0; + } - return 1; + return 1; } - #if (NXT_TEST_RTDTSC) -#define NXT_RBT_STEP (21 * nxt_pagesize / 10 / sizeof(nxt_rbtree_test_t)) - -static nxt_rbtree_t mb_tree; -static nxt_rbtree_test_t *mb_nodes; +#define NXT_RBT_STEP (21 * nxt_pagesize / 10 / sizeof(nxt_rbtree_test_t)) +static nxt_rbtree_t mb_tree; +static nxt_rbtree_test_t *mb_nodes; -nxt_int_t -nxt_rbtree_mb_start(nxt_thread_t *thr) -{ - uint32_t key; - uint64_t start, end; - nxt_uint_t i, n; +nxt_int_t nxt_rbtree_mb_start(nxt_thread_t *thr) { + uint32_t key; + uint64_t start, end; + nxt_uint_t i, n; - n = NXT_RBT_STEP; + n = NXT_RBT_STEP; - mb_nodes = nxt_malloc(NXT_RBT_NODES * n * sizeof(nxt_rbtree_test_t)); - if (mb_nodes == NULL) { - return NXT_ERROR; - } + mb_nodes = nxt_malloc(NXT_RBT_NODES * n * sizeof(nxt_rbtree_test_t)); + if (mb_nodes == NULL) { + return NXT_ERROR; + } - nxt_rbtree_init(&mb_tree, nxt_rbtree_test_comparison); + nxt_rbtree_init(&mb_tree, nxt_rbtree_test_comparison); - key = 0; + key = 0; - for (i = 0; i < NXT_RBT_NODES; i++) { - key = nxt_murmur_hash2(&key, sizeof(uint32_t)); - mb_nodes[n * i].key = key; - } + for (i = 0; i < NXT_RBT_NODES; i++) { + key = nxt_murmur_hash2(&key, sizeof(uint32_t)); + mb_nodes[n * i].key = key; + } - for (i = 0; i < NXT_RBT_NODES - 2; i++) { - nxt_rbtree_insert(&mb_tree, &mb_nodes[n * i].node); - } + for (i = 0; i < NXT_RBT_NODES - 2; i++) { + nxt_rbtree_insert(&mb_tree, &mb_nodes[n * i].node); + } - n *= (NXT_RBT_NODES - 2); + n *= (NXT_RBT_NODES - 2); - start = nxt_rdtsc(); - nxt_rbtree_insert(&mb_tree, &mb_nodes[n].node); - end = nxt_rdtsc(); + start = nxt_rdtsc(); + nxt_rbtree_insert(&mb_tree, &mb_nodes[n].node); + end = nxt_rdtsc(); - nxt_log_error(NXT_LOG_NOTICE, thr->log, - "rbtree mb cached insert: %L cycles", end - start); + nxt_log_error(NXT_LOG_NOTICE, thr->log, "rbtree mb cached insert: %L cycles", + end - start); - return NXT_OK; + return NXT_OK; } +void nxt_rbtree_mb_insert(nxt_thread_t *thr) { + uint64_t start, end; + nxt_uint_t n; -void -nxt_rbtree_mb_insert(nxt_thread_t *thr) -{ - uint64_t start, end; - nxt_uint_t n; + n = NXT_RBT_STEP; + n *= (NXT_RBT_NODES - 1); - n = NXT_RBT_STEP; - n *= (NXT_RBT_NODES - 1); + start = nxt_rdtsc(); + nxt_rbtree_insert(&mb_tree, &mb_nodes[n].node); + end = nxt_rdtsc(); - start = nxt_rdtsc(); - nxt_rbtree_insert(&mb_tree, &mb_nodes[n].node); - end = nxt_rdtsc(); - - nxt_log_error(NXT_LOG_NOTICE, thr->log, - "rbtree mb insert: %L cycles", end - start); + nxt_log_error(NXT_LOG_NOTICE, thr->log, "rbtree mb insert: %L cycles", + end - start); } +void nxt_rbtree_mb_delete(nxt_thread_t *thr) { + uint64_t start, end; + nxt_uint_t n; -void -nxt_rbtree_mb_delete(nxt_thread_t *thr) -{ - uint64_t start, end; - nxt_uint_t n; - - n = NXT_RBT_STEP; - n *= (NXT_RBT_NODES / 4 + 1); + n = NXT_RBT_STEP; + n *= (NXT_RBT_NODES / 4 + 1); - start = nxt_rdtsc(); - nxt_rbtree_delete(&mb_tree, &mb_nodes[n].node); - end = nxt_rdtsc(); + start = nxt_rdtsc(); + nxt_rbtree_delete(&mb_tree, &mb_nodes[n].node); + end = nxt_rdtsc(); - nxt_log_error(NXT_LOG_NOTICE, thr->log, - "rbtree mb delete: %L cycles", end - start); + nxt_log_error(NXT_LOG_NOTICE, thr->log, "rbtree mb delete: %L cycles", + end - start); - nxt_free(mb_nodes); + nxt_free(mb_nodes); } #endif diff --git a/src/test/nxt_sprintf_test.c b/src/test/nxt_sprintf_test.c index 7c6e20195..ff211e1ed 100644 --- a/src/test/nxt_sprintf_test.c +++ b/src/test/nxt_sprintf_test.c @@ -7,65 +7,56 @@ #include #include "nxt_tests.h" - typedef struct { - const char *format; - const char *test; - double number; + const char *format; + const char *test; + double number; } nxt_sprintf_double_test_t; - -static const nxt_sprintf_double_test_t double_test[] = -{ - { "%3.5f", "1234.56700", 1234.567 }, - { "%3.0f", "1234", 1234.567 }, - { "%f", "1234.567", 1234.567 }, - { "%f", "0.1", 0.1 }, - { "%f", "0.000001", 0.000001 }, - { "%f", "4503599627370495", 4503599627370495.0 }, +static const nxt_sprintf_double_test_t double_test[] = { + {"%3.5f", "1234.56700", 1234.567}, + {"%3.0f", "1234", 1234.567}, + {"%f", "1234.567", 1234.567}, + {"%f", "0.1", 0.1}, + {"%f", "0.000001", 0.000001}, + {"%f", "4503599627370495", 4503599627370495.0}, }; +static nxt_int_t nxt_sprintf_test_double(u_char *buf, u_char *end, + const char *fmt, const char *test, + double n) { + u_char *p; -static nxt_int_t -nxt_sprintf_test_double(u_char *buf, u_char *end, const char *fmt, - const char *test, double n) -{ - u_char *p; - - p = nxt_sprintf(buf, end, fmt, n); - *p = '\0'; + p = nxt_sprintf(buf, end, fmt, n); + *p = '\0'; - return nxt_strcmp(buf, test); + return nxt_strcmp(buf, test); } +nxt_int_t nxt_sprintf_test(nxt_thread_t *thr) { + nxt_int_t ret; + nxt_uint_t i; + u_char *end, buf[64]; -nxt_int_t -nxt_sprintf_test(nxt_thread_t *thr) -{ - nxt_int_t ret; - nxt_uint_t i; - u_char *end, buf[64]; + nxt_thread_time_update(thr); - nxt_thread_time_update(thr); + end = buf + 64; - end = buf + 64; + for (i = 0; i < nxt_nitems(double_test); i++) { - for (i = 0; i < nxt_nitems(double_test); i++) { + ret = nxt_sprintf_test_double(buf, end, double_test[i].format, + double_test[i].test, double_test[i].number); - ret = nxt_sprintf_test_double(buf, end, double_test[i].format, - double_test[i].test, - double_test[i].number); - - if (ret == NXT_OK) { - continue; - } + if (ret == NXT_OK) { + continue; + } - nxt_log_alert(thr->log, "nxt_sprintf(\"%s\") failed: \"%s\" vs \"%s\"", - double_test[i].format, double_test[i].test, buf); + nxt_log_alert(thr->log, "nxt_sprintf(\"%s\") failed: \"%s\" vs \"%s\"", + double_test[i].format, double_test[i].test, buf); - return NXT_ERROR; - } + return NXT_ERROR; + } - nxt_log_error(NXT_LOG_NOTICE, thr->log, "nxt_sprintf() test passed"); - return NXT_OK; + nxt_log_error(NXT_LOG_NOTICE, thr->log, "nxt_sprintf() test passed"); + return NXT_OK; } diff --git a/src/test/nxt_strverscmp_test.c b/src/test/nxt_strverscmp_test.c index 40adbfb26..85d0c9bc5 100644 --- a/src/test/nxt_strverscmp_test.c +++ b/src/test/nxt_strverscmp_test.c @@ -7,88 +7,65 @@ #include #include "nxt_tests.h" - typedef struct { - const char *v1; - const char res; - const char *v2; + const char *v1; + const char res; + const char *v2; } nxt_strverscmp_test_t; +nxt_int_t nxt_strverscmp_test(nxt_thread_t *thr) { + nxt_int_t ret; + nxt_uint_t i; + + static const nxt_strverscmp_test_t tests[] = { + {"word", '=', "word"}, {"42", '=', "42"}, {"000", '=', "000"}, + {"2", '>', "1"}, {"2", '<', "10"}, {"rc2", '>', "rc"}, + {"rc2", '<', "rc3"}, {"1.13.8", '>', "1.1.9"}, {"1.9", '<', "1.13.8"}, + {"9.9", '<', "10.0"}, {"1", '>', "007"}, {"2b01", '<', "2b013"}, + {"011", '>', "01"}, {"011", '>', "01.1"}, {"011", '>', "01+1"}, + {"011", '<', "01:1"}, {"011", '<', "01b"}, {"020", '>', "01b"}, + {"a0", '>', "a01"}, {"b00", '<', "b01"}, {"c000", '<', "c01"}, + {"000", '<', "00"}, {"000", '<', "00a"}, {"00.", '>', "000"}, + {"a.0", '<', "a0"}, {"b11", '>', "b0"}, + }; + + nxt_thread_time_update(thr); + + for (i = 0; i < nxt_nitems(tests); i++) { + + ret = nxt_strverscmp((u_char *)tests[i].v1, (u_char *)tests[i].v2); + + switch (tests[i].res) { + + case '<': + if (ret < 0) { + continue; + } -nxt_int_t -nxt_strverscmp_test(nxt_thread_t *thr) -{ - nxt_int_t ret; - nxt_uint_t i; - - static const nxt_strverscmp_test_t tests[] = { - { "word", '=', "word" }, - { "42", '=', "42" }, - { "000", '=', "000" }, - { "2", '>', "1" }, - { "2", '<', "10" }, - { "rc2", '>', "rc" }, - { "rc2", '<', "rc3" }, - { "1.13.8", '>', "1.1.9" }, - { "1.9", '<', "1.13.8" }, - { "9.9", '<', "10.0" }, - { "1", '>', "007" }, - { "2b01", '<', "2b013" }, - { "011", '>', "01" }, - { "011", '>', "01.1" }, - { "011", '>', "01+1" }, - { "011", '<', "01:1" }, - { "011", '<', "01b" }, - { "020", '>', "01b" }, - { "a0", '>', "a01" }, - { "b00", '<', "b01" }, - { "c000", '<', "c01" }, - { "000", '<', "00" }, - { "000", '<', "00a" }, - { "00.", '>', "000" }, - { "a.0", '<', "a0" }, - { "b11", '>', "b0" }, - }; - - nxt_thread_time_update(thr); - - for (i = 0; i < nxt_nitems(tests); i++) { - - ret = nxt_strverscmp((u_char *) tests[i].v1, (u_char *) tests[i].v2); - - switch (tests[i].res) { - - case '<': - if (ret < 0) { - continue; - } - - break; - - case '=': - if (ret == 0) { - continue; - } - - break; - - case '>': - if (ret > 0) { - continue; - } - - break; - } - - nxt_log_alert(thr->log, - "nxt_strverscmp() test \"%s\" %c \"%s\" failed: %i", - tests[i].v1, tests[i].res, tests[i].v2, ret); - - return NXT_ERROR; + break; + + case '=': + if (ret == 0) { + continue; + } + + break; + + case '>': + if (ret > 0) { + continue; + } + + break; } - nxt_log_error(NXT_LOG_NOTICE, thr->log, - "nxt_strverscmp() test passed"); + nxt_log_alert(thr->log, "nxt_strverscmp() test \"%s\" %c \"%s\" failed: %i", + tests[i].v1, tests[i].res, tests[i].v2, ret); + + return NXT_ERROR; + } + + nxt_log_error(NXT_LOG_NOTICE, thr->log, "nxt_strverscmp() test passed"); - return NXT_OK; + return NXT_OK; } diff --git a/src/test/nxt_term_parse_test.c b/src/test/nxt_term_parse_test.c index ceae3fe5b..e82c753b6 100644 --- a/src/test/nxt_term_parse_test.c +++ b/src/test/nxt_term_parse_test.c @@ -7,55 +7,49 @@ #include #include "nxt_tests.h" - typedef struct { - nxt_str_t string; - nxt_bool_t is_sec; - nxt_int_t value; + nxt_str_t string; + nxt_bool_t is_sec; + nxt_int_t value; } nxt_term_parse_test_t; - -static const nxt_term_parse_test_t terms[] = { - { nxt_string("1y"), 1, 365 * 24 * 60 * 60 }, - { nxt_string("1w"), 1, 7 * 24 * 60 * 60 }, - { nxt_string("1w"), 0, 7 * 24 * 60 * 60 * 1000 }, - { nxt_string("1w 1d"), 0, 8 * 24 * 60 * 60 * 1000 }, - { nxt_string("1w d"), 0, -1 }, - { nxt_string("w"), 0, -1 }, - { nxt_string("1d 1w"), 0, -1 }, - { nxt_string("1 "), 1, 1 }, - { nxt_string("25d"), 0, -2 }, - { nxt_string("300"), 1, 300 }, - { nxt_string("300"), 0, 300000 }, - { nxt_string("300s"), 1, 300 }, - { nxt_string("300ms"), 0, 300 }, - { nxt_string("1y 1M 1w1d1h1m1s"), 1, - (((((365 + 30 + 7 + 1) * 24 + 1) * 60) + 1) * 60) + 1 }, +static const nxt_term_parse_test_t terms[] = { + {nxt_string("1y"), 1, 365 * 24 * 60 * 60}, + {nxt_string("1w"), 1, 7 * 24 * 60 * 60}, + {nxt_string("1w"), 0, 7 * 24 * 60 * 60 * 1000}, + {nxt_string("1w 1d"), 0, 8 * 24 * 60 * 60 * 1000}, + {nxt_string("1w d"), 0, -1}, + {nxt_string("w"), 0, -1}, + {nxt_string("1d 1w"), 0, -1}, + {nxt_string("1 "), 1, 1}, + {nxt_string("25d"), 0, -2}, + {nxt_string("300"), 1, 300}, + {nxt_string("300"), 0, 300000}, + {nxt_string("300s"), 1, 300}, + {nxt_string("300ms"), 0, 300}, + {nxt_string("1y 1M 1w1d1h1m1s"), 1, + (((((365 + 30 + 7 + 1) * 24 + 1) * 60) + 1) * 60) + 1}, }; +nxt_int_t nxt_term_parse_test(nxt_thread_t *thr) { + nxt_int_t val; + nxt_uint_t i; + const nxt_str_t *s; -nxt_int_t -nxt_term_parse_test(nxt_thread_t *thr) -{ - nxt_int_t val; - nxt_uint_t i; - const nxt_str_t *s; - - nxt_thread_time_update(thr); + nxt_thread_time_update(thr); - for (i = 0; i < nxt_nitems(terms); i++) { + for (i = 0; i < nxt_nitems(terms); i++) { - s = &terms[i].string; - val = nxt_term_parse(s->start, s->length, terms[i].is_sec); + s = &terms[i].string; + val = nxt_term_parse(s->start, s->length, terms[i].is_sec); - if (val != terms[i].value) { - nxt_log_alert(thr->log, - "term parse test failed: \"%V\": %i %i", - s, terms[i].value, val); - return NXT_ERROR; - } + if (val != terms[i].value) { + nxt_log_alert(thr->log, "term parse test failed: \"%V\": %i %i", s, + terms[i].value, val); + return NXT_ERROR; } + } - nxt_log_error(NXT_LOG_NOTICE, thr->log, "term parse test passed"); - return NXT_OK; + nxt_log_error(NXT_LOG_NOTICE, thr->log, "term parse test passed"); + return NXT_OK; } diff --git a/src/test/nxt_tests.c b/src/test/nxt_tests.c index 03a2a1df4..4af2f819e 100644 --- a/src/test/nxt_tests.c +++ b/src/test/nxt_tests.c @@ -7,170 +7,162 @@ #include #include "nxt_tests.h" +extern char **environ; -extern char **environ; - -nxt_module_init_t nxt_init_modules[1]; -nxt_uint_t nxt_init_modules_n; - +nxt_module_init_t nxt_init_modules[1]; +nxt_uint_t nxt_init_modules_n; /* The function is defined here to prevent inline optimizations. */ -static nxt_bool_t -nxt_msec_less(nxt_msec_t first, nxt_msec_t second) -{ - return (nxt_msec_diff(first, second) < 0); +static nxt_bool_t nxt_msec_less(nxt_msec_t first, nxt_msec_t second) { + return (nxt_msec_diff(first, second) < 0); } +int nxt_cdecl main(int argc, char **argv) { + nxt_task_t task; + nxt_thread_t *thr; -int nxt_cdecl -main(int argc, char **argv) -{ - nxt_task_t task; - nxt_thread_t *thr; + if (nxt_lib_start("tests", argv, &environ) != NXT_OK) { + return 1; + } - if (nxt_lib_start("tests", argv, &environ) != NXT_OK) { - return 1; - } + nxt_main_log.level = NXT_LOG_INFO; + task.log = &nxt_main_log; - nxt_main_log.level = NXT_LOG_INFO; - task.log = &nxt_main_log; - - thr = nxt_thread(); - thr->task = &task; + thr = nxt_thread(); + thr->task = &task; #if (NXT_TEST_RTDTSC) - if (nxt_process_argv[1] != NULL - && memcmp(nxt_process_argv[1], "rbm", 3) == 0) - { - if (nxt_rbtree1_mb_start(thr) != NXT_OK) { - return 1; - } + if (nxt_process_argv[1] != NULL && + memcmp(nxt_process_argv[1], "rbm", 3) == 0) { + if (nxt_rbtree1_mb_start(thr) != NXT_OK) { + return 1; + } - if (nxt_rbtree_mb_start(thr) != NXT_OK) { - return 1; - } + if (nxt_rbtree_mb_start(thr) != NXT_OK) { + return 1; + } - if (nxt_lvlhsh_test(thr, 500 * 1000, 0) != NXT_OK) { - return 1; - } + if (nxt_lvlhsh_test(thr, 500 * 1000, 0) != NXT_OK) { + return 1; + } - nxt_rbtree1_mb_insert(thr); - nxt_rbtree_mb_insert(thr); + nxt_rbtree1_mb_insert(thr); + nxt_rbtree_mb_insert(thr); - if (nxt_lvlhsh_test(thr, 500 * 1000, 0) != NXT_OK) { - return 1; - } + if (nxt_lvlhsh_test(thr, 500 * 1000, 0) != NXT_OK) { + return 1; + } - nxt_rbtree1_mb_delete(thr); - nxt_rbtree_mb_delete(thr); + nxt_rbtree1_mb_delete(thr); + nxt_rbtree_mb_delete(thr); - return 0; - } + return 0; + } #endif - if (nxt_random_test(thr) != NXT_OK) { - return 1; - } + if (nxt_random_test(thr) != NXT_OK) { + return 1; + } - if (nxt_term_parse_test(thr) != NXT_OK) { - return 1; - } + if (nxt_term_parse_test(thr) != NXT_OK) { + return 1; + } - if (nxt_msec_diff_test(thr, nxt_msec_less) != NXT_OK) { - return 1; - } + if (nxt_msec_diff_test(thr, nxt_msec_less) != NXT_OK) { + return 1; + } - if (nxt_rbtree_test(thr, 100 * 1000) != NXT_OK) { - return 1; - } + if (nxt_rbtree_test(thr, 100 * 1000) != NXT_OK) { + return 1; + } - if (nxt_rbtree_test(thr, 1000 * 1000) != NXT_OK) { - return 1; - } + if (nxt_rbtree_test(thr, 1000 * 1000) != NXT_OK) { + return 1; + } - if (nxt_rbtree1_test(thr, 100 * 1000) != NXT_OK) { - return 1; - } + if (nxt_rbtree1_test(thr, 100 * 1000) != NXT_OK) { + return 1; + } - if (nxt_rbtree1_test(thr, 1000 * 1000) != NXT_OK) { - return 1; - } + if (nxt_rbtree1_test(thr, 1000 * 1000) != NXT_OK) { + return 1; + } - if (nxt_mp_test(thr, 100, 40000, 128 - 1) != NXT_OK) { - return 1; - } + if (nxt_mp_test(thr, 100, 40000, 128 - 1) != NXT_OK) { + return 1; + } - if (nxt_mp_test(thr, 100, 1000, 4096 - 1) != NXT_OK) { - return 1; - } + if (nxt_mp_test(thr, 100, 1000, 4096 - 1) != NXT_OK) { + return 1; + } - if (nxt_mp_test(thr, 1000, 100, 64 * 1024 - 1) != NXT_OK) { - return 1; - } + if (nxt_mp_test(thr, 1000, 100, 64 * 1024 - 1) != NXT_OK) { + return 1; + } - if (nxt_mem_zone_test(thr, 100, 20000, 128 - 1) != NXT_OK) { - return 1; - } + if (nxt_mem_zone_test(thr, 100, 20000, 128 - 1) != NXT_OK) { + return 1; + } - if (nxt_mem_zone_test(thr, 100, 10000, 4096 - 1) != NXT_OK) { - return 1; - } + if (nxt_mem_zone_test(thr, 100, 10000, 4096 - 1) != NXT_OK) { + return 1; + } - if (nxt_mem_zone_test(thr, 1000, 40, 64 * 1024 - 1) != NXT_OK) { - return 1; - } + if (nxt_mem_zone_test(thr, 1000, 40, 64 * 1024 - 1) != NXT_OK) { + return 1; + } - if (nxt_lvlhsh_test(thr, 2, 1) != NXT_OK) { - return 1; - } + if (nxt_lvlhsh_test(thr, 2, 1) != NXT_OK) { + return 1; + } - if (nxt_lvlhsh_test(thr, 100 * 1000, 1) != NXT_OK) { - return 1; - } + if (nxt_lvlhsh_test(thr, 100 * 1000, 1) != NXT_OK) { + return 1; + } - if (nxt_lvlhsh_test(thr, 100 * 1000, 0) != NXT_OK) { - return 1; - } + if (nxt_lvlhsh_test(thr, 100 * 1000, 0) != NXT_OK) { + return 1; + } - if (nxt_lvlhsh_test(thr, 1000 * 1000, 1) != NXT_OK) { - return 1; - } + if (nxt_lvlhsh_test(thr, 1000 * 1000, 1) != NXT_OK) { + return 1; + } - if (nxt_gmtime_test(thr) != NXT_OK) { - return 1; - } + if (nxt_gmtime_test(thr) != NXT_OK) { + return 1; + } - if (nxt_sprintf_test(thr) != NXT_OK) { - return 1; - } + if (nxt_sprintf_test(thr) != NXT_OK) { + return 1; + } - if (nxt_malloc_test(thr) != NXT_OK) { - return 1; - } + if (nxt_malloc_test(thr) != NXT_OK) { + return 1; + } - if (nxt_utf8_test(thr) != NXT_OK) { - return 1; - } + if (nxt_utf8_test(thr) != NXT_OK) { + return 1; + } - if (nxt_http_parse_test(thr) != NXT_OK) { - return 1; - } + if (nxt_http_parse_test(thr) != NXT_OK) { + return 1; + } - if (nxt_strverscmp_test(thr) != NXT_OK) { - return 1; - } + if (nxt_strverscmp_test(thr) != NXT_OK) { + return 1; + } - if (nxt_base64_test(thr) != NXT_OK) { - return 1; - } + if (nxt_base64_test(thr) != NXT_OK) { + return 1; + } #if (NXT_HAVE_CLONE_NEWUSER) - if (nxt_clone_creds_test(thr) != NXT_OK) { - return 1; - } + if (nxt_clone_creds_test(thr) != NXT_OK) { + return 1; + } #endif - return 0; + return 0; } diff --git a/src/test/nxt_tests.h b/src/test/nxt_tests.h index 463dc8519..a6db64fe1 100644 --- a/src/test/nxt_tests.h +++ b/src/test/nxt_tests.h @@ -7,32 +7,26 @@ #ifndef _NXT_TESTS_H_INCLUDED_ #define _NXT_TESTS_H_INCLUDED_ - typedef nxt_bool_t (*nxt_msec_less_t)(nxt_msec_t first, nxt_msec_t second); - -#define NXT_RBT_NODES 1500 - +#define NXT_RBT_NODES 1500 #if (__i386__ || __i386 || __amd64__ || __amd64) #if (NXT_GCC || NXT_CLANG) -#define NXT_TEST_RTDTSC 1 +#define NXT_TEST_RTDTSC 1 -nxt_inline uint64_t -nxt_rdtsc(void) -{ - uint32_t eax, edx; +nxt_inline uint64_t nxt_rdtsc(void) { + uint32_t eax, edx; - __asm__ volatile ("rdtsc" : "=a" (eax), "=d" (edx)); + __asm__ volatile("rdtsc" : "=a"(eax), "=d"(edx)); - return ((uint64_t) edx << 32) | eax; + return ((uint64_t)edx << 32) | eax; } #endif #endif - nxt_int_t nxt_term_parse_test(nxt_thread_t *thr); nxt_int_t nxt_msec_diff_test(nxt_thread_t *thr, nxt_msec_less_t); @@ -52,11 +46,10 @@ void nxt_rbtree1_mb_delete(nxt_thread_t *thr); #endif nxt_int_t nxt_mp_test(nxt_thread_t *thr, nxt_uint_t runs, nxt_uint_t nblocks, - size_t max_size); + size_t max_size); nxt_int_t nxt_mem_zone_test(nxt_thread_t *thr, nxt_uint_t runs, - nxt_uint_t nblocks, size_t max_size); -nxt_int_t nxt_lvlhsh_test(nxt_thread_t *thr, nxt_uint_t n, - nxt_bool_t use_pool); + nxt_uint_t nblocks, size_t max_size); +nxt_int_t nxt_lvlhsh_test(nxt_thread_t *thr, nxt_uint_t n, nxt_bool_t use_pool); nxt_int_t nxt_gmtime_test(nxt_thread_t *thr); nxt_int_t nxt_sprintf_test(nxt_thread_t *thr); @@ -67,5 +60,4 @@ nxt_int_t nxt_strverscmp_test(nxt_thread_t *thr); nxt_int_t nxt_base64_test(nxt_thread_t *thr); nxt_int_t nxt_clone_creds_test(nxt_thread_t *thr); - #endif /* _NXT_TESTS_H_INCLUDED_ */ diff --git a/src/test/nxt_unit_app_test.c b/src/test/nxt_unit_app_test.c index 5dcebe187..358dc279f 100644 --- a/src/test/nxt_unit_app_test.c +++ b/src/test/nxt_unit_app_test.c @@ -10,272 +10,239 @@ #include #include - -#define CONTENT_TYPE "Content-Type" -#define TEXT_PLAIN "text/plain" -#define HELLO_WORLD "Hello world!\n" - -#define NEW_LINE "\n" - -#define REQUEST_DATA "Request data:\n" -#define METHOD " Method: " -#define PROTOCOL " Protocol: " -#define REMOTE_ADDR " Remote addr: " -#define LOCAL_ADDR " Local addr: " -#define TARGET " Target: " -#define PATH " Path: " -#define QUERY " Query: " -#define FIELDS " Fields:\n" -#define FIELD_PAD " " -#define FIELD_SEP ": " -#define BODY " Body:\n" - +#define CONTENT_TYPE "Content-Type" +#define TEXT_PLAIN "text/plain" +#define HELLO_WORLD "Hello world!\n" + +#define NEW_LINE "\n" + +#define REQUEST_DATA "Request data:\n" +#define METHOD " Method: " +#define PROTOCOL " Protocol: " +#define REMOTE_ADDR " Remote addr: " +#define LOCAL_ADDR " Local addr: " +#define TARGET " Target: " +#define PATH " Path: " +#define QUERY " Query: " +#define FIELDS " Fields:\n" +#define FIELD_PAD " " +#define FIELD_SEP ": " +#define BODY " Body:\n" static int ready_handler(nxt_unit_ctx_t *ctx); static void *worker(void *main_ctx); static void greeting_app_request_handler(nxt_unit_request_info_t *req); static inline char *copy(char *p, const void *src, uint32_t len); +static int thread_count; +static pthread_t *threads; -static int thread_count; -static pthread_t *threads; - - -int -main(int argc, char **argv) -{ - int i, err; - nxt_unit_ctx_t *ctx; - nxt_unit_init_t init; +int main(int argc, char **argv) { + int i, err; + nxt_unit_ctx_t *ctx; + nxt_unit_init_t init; - if (argc == 3 && strcmp(argv[1], "-t") == 0) { - thread_count = atoi(argv[2]); - } - - memset(&init, 0, sizeof(nxt_unit_init_t)); + if (argc == 3 && strcmp(argv[1], "-t") == 0) { + thread_count = atoi(argv[2]); + } - init.callbacks.request_handler = greeting_app_request_handler; - init.callbacks.ready_handler = ready_handler; + memset(&init, 0, sizeof(nxt_unit_init_t)); - ctx = nxt_unit_init(&init); - if (ctx == NULL) { - return 1; - } + init.callbacks.request_handler = greeting_app_request_handler; + init.callbacks.ready_handler = ready_handler; - err = nxt_unit_run(ctx); + ctx = nxt_unit_init(&init); + if (ctx == NULL) { + return 1; + } - nxt_unit_debug(ctx, "main worker finished with %d code", err); + err = nxt_unit_run(ctx); - if (thread_count > 1) { - for (i = 0; i < thread_count - 1; i++) { - err = pthread_join(threads[i], NULL); + nxt_unit_debug(ctx, "main worker finished with %d code", err); - if (nxt_fast_path(err == 0)) { - nxt_unit_debug(ctx, "join thread #%d", i); + if (thread_count > 1) { + for (i = 0; i < thread_count - 1; i++) { + err = pthread_join(threads[i], NULL); - } else { - nxt_unit_alert(ctx, "pthread_join(#%d) failed: %s (%d)", - i, strerror(err), err); - } - } + if (nxt_fast_path(err == 0)) { + nxt_unit_debug(ctx, "join thread #%d", i); - nxt_unit_free(ctx, threads); + } else { + nxt_unit_alert(ctx, "pthread_join(#%d) failed: %s (%d)", i, + strerror(err), err); + } } - nxt_unit_done(ctx); - - nxt_unit_debug(NULL, "main worker done"); - - return 0; -} - + nxt_unit_free(ctx, threads); + } -static int -ready_handler(nxt_unit_ctx_t *ctx) -{ - int i, err; + nxt_unit_done(ctx); - nxt_unit_debug(ctx, "ready"); + nxt_unit_debug(NULL, "main worker done"); - if (thread_count <= 1) { - return NXT_UNIT_OK; - } + return 0; +} - threads = nxt_unit_malloc(ctx, sizeof(pthread_t) * (thread_count - 1)); - if (threads == NULL) { - return NXT_UNIT_ERROR; - } +static int ready_handler(nxt_unit_ctx_t *ctx) { + int i, err; - for (i = 0; i < thread_count - 1; i++) { - err = pthread_create(&threads[i], NULL, worker, ctx); - if (err != 0) { - return NXT_UNIT_ERROR; - } - } + nxt_unit_debug(ctx, "ready"); + if (thread_count <= 1) { return NXT_UNIT_OK; -} - + } -static void * -worker(void *main_ctx) -{ - int rc; - nxt_unit_ctx_t *ctx; + threads = nxt_unit_malloc(ctx, sizeof(pthread_t) * (thread_count - 1)); + if (threads == NULL) { + return NXT_UNIT_ERROR; + } - ctx = nxt_unit_ctx_alloc(main_ctx, NULL); - if (ctx == NULL) { - return NULL; + for (i = 0; i < thread_count - 1; i++) { + err = pthread_create(&threads[i], NULL, worker, ctx); + if (err != 0) { + return NXT_UNIT_ERROR; } + } - nxt_unit_debug(ctx, "start worker"); - - rc = nxt_unit_run(ctx); - - nxt_unit_debug(ctx, "worker finished with %d code", rc); - - nxt_unit_done(ctx); - - return (void *) (intptr_t) rc; + return NXT_UNIT_OK; } +static void *worker(void *main_ctx) { + int rc; + nxt_unit_ctx_t *ctx; -static void -greeting_app_request_handler(nxt_unit_request_info_t *req) -{ - int rc; - char *p; - ssize_t res; - uint32_t i; - nxt_unit_buf_t *buf; - nxt_unit_field_t *f; - nxt_unit_request_t *r; - - rc = nxt_unit_response_init(req, 200 /* Status code. */, - 1 /* Number of response headers. */, - nxt_length(CONTENT_TYPE) - + nxt_length(TEXT_PLAIN) - + nxt_length(HELLO_WORLD)); - if (nxt_slow_path(rc != NXT_UNIT_OK)) { - goto fail; - } - - rc = nxt_unit_response_add_field(req, - CONTENT_TYPE, nxt_length(CONTENT_TYPE), - TEXT_PLAIN, nxt_length(TEXT_PLAIN)); - if (nxt_slow_path(rc != NXT_UNIT_OK)) { - goto fail; - } + ctx = nxt_unit_ctx_alloc(main_ctx, NULL); + if (ctx == NULL) { + return NULL; + } - rc = nxt_unit_response_add_content(req, HELLO_WORLD, - nxt_length(HELLO_WORLD)); - if (nxt_slow_path(rc != NXT_UNIT_OK)) { - goto fail; - } + nxt_unit_debug(ctx, "start worker"); - rc = nxt_unit_response_send(req); - if (nxt_slow_path(rc != NXT_UNIT_OK)) { - goto fail; - } + rc = nxt_unit_run(ctx); - r = req->request; - - buf = nxt_unit_response_buf_alloc(req, (req->request_buf->end - - req->request_buf->start) - + nxt_length(REQUEST_DATA) - + nxt_length(METHOD) - + nxt_length(NEW_LINE) - + nxt_length(PROTOCOL) - + nxt_length(NEW_LINE) - + nxt_length(REMOTE_ADDR) - + nxt_length(NEW_LINE) - + nxt_length(LOCAL_ADDR) - + nxt_length(NEW_LINE) - + nxt_length(TARGET) - + nxt_length(NEW_LINE) - + nxt_length(PATH) - + nxt_length(NEW_LINE) - + nxt_length(QUERY) - + nxt_length(NEW_LINE) - + nxt_length(FIELDS) - + r->fields_count * ( - nxt_length(FIELD_PAD) - + nxt_length(FIELD_SEP)) - + nxt_length(BODY)); - if (nxt_slow_path(buf == NULL)) { - rc = NXT_UNIT_ERROR; - - goto fail; - } + nxt_unit_debug(ctx, "worker finished with %d code", rc); - p = buf->free; + nxt_unit_done(ctx); - p = copy(p, REQUEST_DATA, nxt_length(REQUEST_DATA)); + return (void *)(intptr_t)rc; +} - p = copy(p, METHOD, nxt_length(METHOD)); - p = copy(p, nxt_unit_sptr_get(&r->method), r->method_length); +static void greeting_app_request_handler(nxt_unit_request_info_t *req) { + int rc; + char *p; + ssize_t res; + uint32_t i; + nxt_unit_buf_t *buf; + nxt_unit_field_t *f; + nxt_unit_request_t *r; + + rc = nxt_unit_response_init( + req, 200 /* Status code. */, 1 /* Number of response headers. */, + nxt_length(CONTENT_TYPE) + nxt_length(TEXT_PLAIN) + + nxt_length(HELLO_WORLD)); + if (nxt_slow_path(rc != NXT_UNIT_OK)) { + goto fail; + } + + rc = nxt_unit_response_add_field(req, CONTENT_TYPE, nxt_length(CONTENT_TYPE), + TEXT_PLAIN, nxt_length(TEXT_PLAIN)); + if (nxt_slow_path(rc != NXT_UNIT_OK)) { + goto fail; + } + + rc = nxt_unit_response_add_content(req, HELLO_WORLD, nxt_length(HELLO_WORLD)); + if (nxt_slow_path(rc != NXT_UNIT_OK)) { + goto fail; + } + + rc = nxt_unit_response_send(req); + if (nxt_slow_path(rc != NXT_UNIT_OK)) { + goto fail; + } + + r = req->request; + + buf = nxt_unit_response_buf_alloc( + req, + (req->request_buf->end - req->request_buf->start) + + nxt_length(REQUEST_DATA) + nxt_length(METHOD) + nxt_length(NEW_LINE) + + nxt_length(PROTOCOL) + nxt_length(NEW_LINE) + + nxt_length(REMOTE_ADDR) + nxt_length(NEW_LINE) + + nxt_length(LOCAL_ADDR) + nxt_length(NEW_LINE) + nxt_length(TARGET) + + nxt_length(NEW_LINE) + nxt_length(PATH) + nxt_length(NEW_LINE) + + nxt_length(QUERY) + nxt_length(NEW_LINE) + nxt_length(FIELDS) + + r->fields_count * (nxt_length(FIELD_PAD) + nxt_length(FIELD_SEP)) + + nxt_length(BODY)); + if (nxt_slow_path(buf == NULL)) { + rc = NXT_UNIT_ERROR; + + goto fail; + } + + p = buf->free; + + p = copy(p, REQUEST_DATA, nxt_length(REQUEST_DATA)); + + p = copy(p, METHOD, nxt_length(METHOD)); + p = copy(p, nxt_unit_sptr_get(&r->method), r->method_length); + *p++ = '\n'; + + p = copy(p, PROTOCOL, nxt_length(PROTOCOL)); + p = copy(p, nxt_unit_sptr_get(&r->version), r->version_length); + *p++ = '\n'; + + p = copy(p, REMOTE_ADDR, nxt_length(REMOTE_ADDR)); + p = copy(p, nxt_unit_sptr_get(&r->remote), r->remote_length); + *p++ = '\n'; + + p = copy(p, LOCAL_ADDR, nxt_length(LOCAL_ADDR)); + p = copy(p, nxt_unit_sptr_get(&r->local_addr), r->local_addr_length); + *p++ = '\n'; + + p = copy(p, TARGET, nxt_length(TARGET)); + p = copy(p, nxt_unit_sptr_get(&r->target), r->target_length); + *p++ = '\n'; + + p = copy(p, PATH, nxt_length(PATH)); + p = copy(p, nxt_unit_sptr_get(&r->path), r->path_length); + *p++ = '\n'; + + if (r->query.offset) { + p = copy(p, QUERY, nxt_length(QUERY)); + p = copy(p, nxt_unit_sptr_get(&r->query), r->query_length); *p++ = '\n'; + } - p = copy(p, PROTOCOL, nxt_length(PROTOCOL)); - p = copy(p, nxt_unit_sptr_get(&r->version), r->version_length); - *p++ = '\n'; + p = copy(p, FIELDS, nxt_length(FIELDS)); - p = copy(p, REMOTE_ADDR, nxt_length(REMOTE_ADDR)); - p = copy(p, nxt_unit_sptr_get(&r->remote), r->remote_length); - *p++ = '\n'; + for (i = 0; i < r->fields_count; i++) { + f = r->fields + i; - p = copy(p, LOCAL_ADDR, nxt_length(LOCAL_ADDR)); - p = copy(p, nxt_unit_sptr_get(&r->local_addr), r->local_addr_length); + p = copy(p, FIELD_PAD, nxt_length(FIELD_PAD)); + p = copy(p, nxt_unit_sptr_get(&f->name), f->name_length); + p = copy(p, FIELD_SEP, nxt_length(FIELD_SEP)); + p = copy(p, nxt_unit_sptr_get(&f->value), f->value_length); *p++ = '\n'; + } - p = copy(p, TARGET, nxt_length(TARGET)); - p = copy(p, nxt_unit_sptr_get(&r->target), r->target_length); - *p++ = '\n'; + if (r->content_length > 0) { + p = copy(p, BODY, nxt_length(BODY)); - p = copy(p, PATH, nxt_length(PATH)); - p = copy(p, nxt_unit_sptr_get(&r->path), r->path_length); - *p++ = '\n'; + res = nxt_unit_request_read(req, p, buf->end - p); + p += res; + } - if (r->query.offset) { - p = copy(p, QUERY, nxt_length(QUERY)); - p = copy(p, nxt_unit_sptr_get(&r->query), r->query_length); - *p++ = '\n'; - } - - p = copy(p, FIELDS, nxt_length(FIELDS)); - - for (i = 0; i < r->fields_count; i++) { - f = r->fields + i; - - p = copy(p, FIELD_PAD, nxt_length(FIELD_PAD)); - p = copy(p, nxt_unit_sptr_get(&f->name), f->name_length); - p = copy(p, FIELD_SEP, nxt_length(FIELD_SEP)); - p = copy(p, nxt_unit_sptr_get(&f->value), f->value_length); - *p++ = '\n'; - } - - if (r->content_length > 0) { - p = copy(p, BODY, nxt_length(BODY)); + buf->free = p; - res = nxt_unit_request_read(req, p, buf->end - p); - p += res; - - } - - buf->free = p; - - rc = nxt_unit_buf_send(buf); + rc = nxt_unit_buf_send(buf); fail: - nxt_unit_request_done(req, rc); + nxt_unit_request_done(req, rc); } +static inline char *copy(char *p, const void *src, uint32_t len) { + memcpy(p, src, len); -static inline char * -copy(char *p, const void *src, uint32_t len) -{ - memcpy(p, src, len); - - return p + len; + return p + len; } diff --git a/src/test/nxt_unit_websocket_chat.c b/src/test/nxt_unit_websocket_chat.c index ec7c2cc33..ba308c3b6 100644 --- a/src/test/nxt_unit_websocket_chat.c +++ b/src/test/nxt_unit_websocket_chat.c @@ -18,331 +18,306 @@ #include #include - -#define CONTENT_TYPE "Content-Type" -#define CONTENT_LENGTH "Content-Length" -#define TEXT_HTML "text/html" +#define CONTENT_TYPE "Content-Type" +#define CONTENT_LENGTH "Content-Length" +#define TEXT_HTML "text/html" typedef struct { - nxt_queue_link_t link; - int id; + nxt_queue_link_t link; + int id; } ws_chat_request_data_t; - static int ws_chat_root(nxt_unit_request_info_t *req); static void ws_chat_broadcast(const char *buf, size_t size); +static const char ws_chat_index_html[]; +static const int ws_chat_index_html_size; -static const char ws_chat_index_html[]; -static const int ws_chat_index_html_size; - -static char ws_chat_index_content_length[34]; -static int ws_chat_index_content_length_size; +static char ws_chat_index_content_length[34]; +static int ws_chat_index_content_length_size; -static nxt_queue_t ws_chat_sessions; -static int ws_chat_next_id = 0; +static nxt_queue_t ws_chat_sessions; +static int ws_chat_next_id = 0; +static void ws_chat_request_handler(nxt_unit_request_info_t *req) { + static char buf[1024]; + int buf_size; + int rc = NXT_UNIT_OK; + nxt_unit_request_t *r; + ws_chat_request_data_t *data; -static void -ws_chat_request_handler(nxt_unit_request_info_t *req) -{ - static char buf[1024]; - int buf_size; - int rc = NXT_UNIT_OK; - nxt_unit_request_t *r; - ws_chat_request_data_t *data; + r = req->request; - r = req->request; + const char *target = nxt_unit_sptr_get(&r->target); - const char* target = nxt_unit_sptr_get(&r->target); + if (strcmp(target, "/") == 0) { + rc = ws_chat_root(req); + goto fail; + } - if (strcmp(target, "/") == 0) { - rc = ws_chat_root(req); - goto fail; + if (strcmp(target, "/chat") == 0) { + if (!nxt_unit_request_is_websocket_handshake(req)) { + goto notfound; } - if (strcmp(target, "/chat") == 0) { - if (!nxt_unit_request_is_websocket_handshake(req)) { - goto notfound; - } - - rc = nxt_unit_response_init(req, 101, 0, 0); - if (nxt_slow_path(rc != NXT_UNIT_OK)) { - goto fail; - } + rc = nxt_unit_response_init(req, 101, 0, 0); + if (nxt_slow_path(rc != NXT_UNIT_OK)) { + goto fail; + } - data = req->data; - nxt_queue_insert_tail(&ws_chat_sessions, &data->link); + data = req->data; + nxt_queue_insert_tail(&ws_chat_sessions, &data->link); - data->id = ws_chat_next_id++; + data->id = ws_chat_next_id++; - nxt_unit_response_upgrade(req); - nxt_unit_response_send(req); + nxt_unit_response_upgrade(req); + nxt_unit_response_send(req); + buf_size = snprintf(buf, sizeof(buf), "Guest #%d has joined.", data->id); - buf_size = snprintf(buf, sizeof(buf), "Guest #%d has joined.", data->id); + ws_chat_broadcast(buf, buf_size); - ws_chat_broadcast(buf, buf_size); - - return; - } + return; + } notfound: - rc = nxt_unit_response_init(req, 404, 0, 0); + rc = nxt_unit_response_init(req, 404, 0, 0); fail: - nxt_unit_request_done(req, rc); + nxt_unit_request_done(req, rc); } - -static int -ws_chat_root(nxt_unit_request_info_t *req) -{ - int rc; - - rc = nxt_unit_response_init(req, 200 /* Status code. */, - 2 /* Number of response headers. */, - nxt_length(CONTENT_TYPE) - + nxt_length(TEXT_HTML) - + nxt_length(CONTENT_LENGTH) - + ws_chat_index_content_length_size - + ws_chat_index_html_size); - if (nxt_slow_path(rc != NXT_UNIT_OK)) { - return rc; - } - - rc = nxt_unit_response_add_field(req, - CONTENT_TYPE, nxt_length(CONTENT_TYPE), - TEXT_HTML, nxt_length(TEXT_HTML)); - if (nxt_slow_path(rc != NXT_UNIT_OK)) { - return rc; - } - - rc = nxt_unit_response_add_field(req, - CONTENT_LENGTH, nxt_length(CONTENT_LENGTH), - ws_chat_index_content_length, - ws_chat_index_content_length_size); - if (nxt_slow_path(rc != NXT_UNIT_OK)) { - return rc; - } - - rc = nxt_unit_response_add_content(req, ws_chat_index_html, - ws_chat_index_html_size); - if (nxt_slow_path(rc != NXT_UNIT_OK)) { - return rc; - } - - return nxt_unit_response_send(req); +static int ws_chat_root(nxt_unit_request_info_t *req) { + int rc; + + rc = nxt_unit_response_init( + req, 200 /* Status code. */, 2 /* Number of response headers. */, + nxt_length(CONTENT_TYPE) + nxt_length(TEXT_HTML) + + nxt_length(CONTENT_LENGTH) + ws_chat_index_content_length_size + + ws_chat_index_html_size); + if (nxt_slow_path(rc != NXT_UNIT_OK)) { + return rc; + } + + rc = nxt_unit_response_add_field(req, CONTENT_TYPE, nxt_length(CONTENT_TYPE), + TEXT_HTML, nxt_length(TEXT_HTML)); + if (nxt_slow_path(rc != NXT_UNIT_OK)) { + return rc; + } + + rc = nxt_unit_response_add_field( + req, CONTENT_LENGTH, nxt_length(CONTENT_LENGTH), + ws_chat_index_content_length, ws_chat_index_content_length_size); + if (nxt_slow_path(rc != NXT_UNIT_OK)) { + return rc; + } + + rc = nxt_unit_response_add_content(req, ws_chat_index_html, + ws_chat_index_html_size); + if (nxt_slow_path(rc != NXT_UNIT_OK)) { + return rc; + } + + return nxt_unit_response_send(req); } +static void ws_chat_broadcast(const char *buf, size_t size) { + ws_chat_request_data_t *data; + nxt_unit_request_info_t *req; -static void -ws_chat_broadcast(const char *buf, size_t size) -{ - ws_chat_request_data_t *data; - nxt_unit_request_info_t *req; + nxt_unit_debug(NULL, "broadcast: %*.s", (int)size, buf); - nxt_unit_debug(NULL, "broadcast: %*.s", (int) size, buf); + nxt_queue_each(data, &ws_chat_sessions, ws_chat_request_data_t, link) { - nxt_queue_each(data, &ws_chat_sessions, ws_chat_request_data_t, link) { + req = nxt_unit_get_request_info_from_data(data); - req = nxt_unit_get_request_info_from_data(data); + nxt_unit_req_debug(req, "send: %*.s", (int)size, buf); - nxt_unit_req_debug(req, "send: %*.s", (int) size, buf); - - nxt_unit_websocket_send(req, NXT_WEBSOCKET_OP_TEXT, 1, buf, size); - } nxt_queue_loop; + nxt_unit_websocket_send(req, NXT_WEBSOCKET_OP_TEXT, 1, buf, size); + } + nxt_queue_loop; } +static void ws_chat_websocket_handler(nxt_unit_websocket_frame_t *ws) { + int buf_size; + static char buf[1024]; + ws_chat_request_data_t *data; -static void -ws_chat_websocket_handler(nxt_unit_websocket_frame_t *ws) -{ - int buf_size; - static char buf[1024]; - ws_chat_request_data_t *data; + if (ws->header->opcode != NXT_WEBSOCKET_OP_TEXT) { + return; + } - if (ws->header->opcode != NXT_WEBSOCKET_OP_TEXT) { - return; - } + data = ws->req->data; - data = ws->req->data; + buf_size = snprintf(buf, sizeof(buf), "Guest #%d: ", data->id); - buf_size = snprintf(buf, sizeof(buf), "Guest #%d: ", data->id); + buf_size += nxt_unit_websocket_read(ws, buf + buf_size, + nxt_min(sizeof(buf), ws->content_length)); - buf_size += nxt_unit_websocket_read(ws, buf + buf_size, - nxt_min(sizeof(buf), - ws->content_length)); + ws_chat_broadcast(buf, buf_size); - ws_chat_broadcast(buf, buf_size); - - nxt_unit_websocket_done(ws); + nxt_unit_websocket_done(ws); } +static void ws_chat_close_handler(nxt_unit_request_info_t *req) { + int buf_size; + static char buf[1024]; + ws_chat_request_data_t *data; -static void -ws_chat_close_handler(nxt_unit_request_info_t *req) -{ - int buf_size; - static char buf[1024]; - ws_chat_request_data_t *data; - - data = req->data; - buf_size = snprintf(buf, sizeof(buf), "Guest #%d has disconnected.", - data->id); + data = req->data; + buf_size = + snprintf(buf, sizeof(buf), "Guest #%d has disconnected.", data->id); - nxt_queue_remove(&data->link); - nxt_unit_request_done(req, NXT_UNIT_OK); + nxt_queue_remove(&data->link); + nxt_unit_request_done(req, NXT_UNIT_OK); - ws_chat_broadcast(buf, buf_size); + ws_chat_broadcast(buf, buf_size); } +int main(void) { + nxt_unit_ctx_t *ctx; + nxt_unit_init_t init; -int -main(void) -{ - nxt_unit_ctx_t *ctx; - nxt_unit_init_t init; - - ws_chat_index_content_length_size = - snprintf(ws_chat_index_content_length, - sizeof(ws_chat_index_content_length), "%d", - ws_chat_index_html_size); + ws_chat_index_content_length_size = snprintf( + ws_chat_index_content_length, sizeof(ws_chat_index_content_length), "%d", + ws_chat_index_html_size); - nxt_queue_init(&ws_chat_sessions); + nxt_queue_init(&ws_chat_sessions); - memset(&init, 0, sizeof(nxt_unit_init_t)); + memset(&init, 0, sizeof(nxt_unit_init_t)); - init.callbacks.request_handler = ws_chat_request_handler; - init.callbacks.websocket_handler = ws_chat_websocket_handler; - init.callbacks.close_handler = ws_chat_close_handler; + init.callbacks.request_handler = ws_chat_request_handler; + init.callbacks.websocket_handler = ws_chat_websocket_handler; + init.callbacks.close_handler = ws_chat_close_handler; - init.request_data_size = sizeof(ws_chat_request_data_t); + init.request_data_size = sizeof(ws_chat_request_data_t); - ctx = nxt_unit_init(&init); - if (ctx == NULL) { - return 1; - } + ctx = nxt_unit_init(&init); + if (ctx == NULL) { + return 1; + } - nxt_unit_run(ctx); + nxt_unit_run(ctx); - nxt_unit_done(ctx); + nxt_unit_done(ctx); - return 0; + return 0; } - static const char ws_chat_index_html[] = -"\n" -"\n" -" WebSocket Chat Examples\n" -" \n" -" \n" -"\n" -"\n" -"

Seems your browser doesn't support Javascript! Websockets rely on Javascript being enabled. Please enable\n" -" Javascript and reload this page!

\n" -"
\n" -"

\n" -"
\n" -"
\n" -"
\n" -"
\n" -"\n" -"\n" -; - -static const int ws_chat_index_html_size = nxt_length(ws_chat_index_html); + "\n" + "\n" + " WebSocket Chat Examples\n" + " \n" + " \n" + "\n" + "\n" + "\n" + "
\n" + "

\n" + "
\n" + "
\n" + "
\n" + "
\n" + "\n" + "\n"; + +static const int ws_chat_index_html_size = nxt_length(ws_chat_index_html); diff --git a/src/test/nxt_unit_websocket_echo.c b/src/test/nxt_unit_websocket_echo.c index eab2e45fe..aaf76bf78 100644 --- a/src/test/nxt_unit_websocket_echo.c +++ b/src/test/nxt_unit_websocket_echo.c @@ -12,94 +12,85 @@ #include #include +static void ws_echo_request_handler(nxt_unit_request_info_t *req) { + int rc; + const char *target; -static void -ws_echo_request_handler(nxt_unit_request_info_t *req) -{ - int rc; - const char *target; + rc = NXT_UNIT_OK; + target = nxt_unit_sptr_get(&req->request->target); - rc = NXT_UNIT_OK; - target = nxt_unit_sptr_get(&req->request->target); - - if (strcmp(target, "/") == 0) { - if (!nxt_unit_request_is_websocket_handshake(req)) { - goto notfound; - } + if (strcmp(target, "/") == 0) { + if (!nxt_unit_request_is_websocket_handshake(req)) { + goto notfound; + } - rc = nxt_unit_response_init(req, 101, 0, 0); - if (nxt_slow_path(rc != NXT_UNIT_OK)) { - goto fail; - } + rc = nxt_unit_response_init(req, 101, 0, 0); + if (nxt_slow_path(rc != NXT_UNIT_OK)) { + goto fail; + } - nxt_unit_response_upgrade(req); - nxt_unit_response_send(req); + nxt_unit_response_upgrade(req); + nxt_unit_response_send(req); - return; - } + return; + } notfound: - rc = nxt_unit_response_init(req, 404, 0, 0); + rc = nxt_unit_response_init(req, 404, 0, 0); fail: - nxt_unit_request_done(req, rc); + nxt_unit_request_done(req, rc); } +static void ws_echo_websocket_handler(nxt_unit_websocket_frame_t *ws) { + uint8_t opcode; + ssize_t size; + nxt_unit_request_info_t *req; -static void -ws_echo_websocket_handler(nxt_unit_websocket_frame_t *ws) -{ - uint8_t opcode; - ssize_t size; - nxt_unit_request_info_t *req; - - static size_t buf_size = 0; - static uint8_t *buf = NULL; + static size_t buf_size = 0; + static uint8_t *buf = NULL; - if (buf_size < ws->content_length) { - buf = realloc(buf, ws->content_length); - buf_size = ws->content_length; - } + if (buf_size < ws->content_length) { + buf = realloc(buf, ws->content_length); + buf_size = ws->content_length; + } - req = ws->req; - opcode = ws->header->opcode; + req = ws->req; + opcode = ws->header->opcode; - if (opcode == NXT_WEBSOCKET_OP_PONG) { - nxt_unit_websocket_done(ws); - return; - } + if (opcode == NXT_WEBSOCKET_OP_PONG) { + nxt_unit_websocket_done(ws); + return; + } - size = nxt_unit_websocket_read(ws, buf, ws->content_length); + size = nxt_unit_websocket_read(ws, buf, ws->content_length); - nxt_unit_websocket_send(req, opcode, ws->header->fin, buf, size); - nxt_unit_websocket_done(ws); + nxt_unit_websocket_send(req, opcode, ws->header->fin, buf, size); + nxt_unit_websocket_done(ws); - if (opcode == NXT_WEBSOCKET_OP_CLOSE) { - nxt_unit_request_done(req, NXT_UNIT_OK); - } + if (opcode == NXT_WEBSOCKET_OP_CLOSE) { + nxt_unit_request_done(req, NXT_UNIT_OK); + } } +int main(void) { + nxt_unit_ctx_t *ctx; + nxt_unit_init_t init; -int -main(void) -{ - nxt_unit_ctx_t *ctx; - nxt_unit_init_t init; - - memset(&init, 0, sizeof(nxt_unit_init_t)); + memset(&init, 0, sizeof(nxt_unit_init_t)); - init.callbacks.request_handler = ws_echo_request_handler; - init.callbacks.websocket_handler = ws_echo_websocket_handler; + init.callbacks.request_handler = ws_echo_request_handler; + init.callbacks.websocket_handler = ws_echo_websocket_handler; - ctx = nxt_unit_init(&init); - if (ctx == NULL) { - return 1; - } + ctx = nxt_unit_init(&init); + if (ctx == NULL) { + return 1; + } - nxt_unit_run(ctx); - nxt_unit_done(ctx); + nxt_unit_run(ctx); + nxt_unit_done(ctx); - return 0; + return 0; } diff --git a/src/test/nxt_utf8_file_name_test.c b/src/test/nxt_utf8_file_name_test.c index 5723e19bb..5f5b21a33 100644 --- a/src/test/nxt_utf8_file_name_test.c +++ b/src/test/nxt_utf8_file_name_test.c @@ -6,143 +6,135 @@ #include - -extern char **environ; +extern char **environ; static nxt_int_t nxt_utf8_file_name_test(nxt_thread_t *thr); +nxt_module_init_t nxt_init_modules[1]; +nxt_uint_t nxt_init_modules_n; -nxt_module_init_t nxt_init_modules[1]; -nxt_uint_t nxt_init_modules_n; - +int nxt_cdecl main(int argc, char **argv) { + nxt_thread_t *thr; -int nxt_cdecl -main(int argc, char **argv) -{ - nxt_thread_t *thr; + if (nxt_lib_start("utf8_file_name_test", argv, &environ) != NXT_OK) { + return 1; + } - if (nxt_lib_start("utf8_file_name_test", argv, &environ) != NXT_OK) { - return 1; - } + nxt_main_log.level = NXT_LOG_INFO; - nxt_main_log.level = NXT_LOG_INFO; + thr = nxt_thread(); - thr = nxt_thread(); + if (nxt_utf8_file_name_test(thr) != NXT_OK) { + return 1; + } - if (nxt_utf8_file_name_test(thr) != NXT_OK) { - return 1; - } - - return 0; + return 0; } +static nxt_int_t nxt_utf8_file_name_test(nxt_thread_t *thr) { + u_char *p, test[4], buf[32]; + ssize_t n; + uint32_t uc, lc; + nxt_int_t ret; + nxt_task_t task; + nxt_file_t uc_file, lc_file; + const u_char *pp; + nxt_file_name_t uc_name[10], lc_name[10]; + static const u_char utf8[4] = "UTF8"; -static nxt_int_t -nxt_utf8_file_name_test(nxt_thread_t *thr) -{ - u_char *p, test[4], buf[32]; - ssize_t n; - uint32_t uc, lc; - nxt_int_t ret; - nxt_task_t task; - nxt_file_t uc_file, lc_file; - const u_char *pp; - nxt_file_name_t uc_name[10], lc_name[10]; - static const u_char utf8[4] = "UTF8"; - - nxt_thread_time_update(thr); - - uc_name[0] = 'u'; - uc_name[1] = 't'; - uc_name[2] = 'f'; - uc_name[3] = '8'; - uc_name[4] = '_'; + nxt_thread_time_update(thr); - lc_name[0] = 'u'; - lc_name[1] = 't'; - lc_name[2] = 'f'; - lc_name[3] = '8'; - lc_name[4] = '_'; + uc_name[0] = 'u'; + uc_name[1] = 't'; + uc_name[2] = 'f'; + uc_name[3] = '8'; + uc_name[4] = '_'; - nxt_memzero(&uc_file, sizeof(nxt_file_t)); + lc_name[0] = 'u'; + lc_name[1] = 't'; + lc_name[2] = 'f'; + lc_name[3] = '8'; + lc_name[4] = '_'; - uc_file.name = uc_name; - uc_file.log_level = NXT_LOG_ALERT; + nxt_memzero(&uc_file, sizeof(nxt_file_t)); - nxt_memzero(&lc_file, sizeof(nxt_file_t)); + uc_file.name = uc_name; + uc_file.log_level = NXT_LOG_ALERT; - lc_file.name = lc_name; + nxt_memzero(&lc_file, sizeof(nxt_file_t)); - task.thread = thr; - task.log = thr->log; + lc_file.name = lc_name; - for (uc = 0x41; uc < 0x110000; uc++) { + task.thread = thr; + task.log = thr->log; - p = nxt_utf8_encode(&uc_name[5], uc); + for (uc = 0x41; uc < 0x110000; uc++) { - if (p == NULL) { - nxt_log_alert(thr->log, "nxt_utf8_encode(%05uxD) failed", uc); - return NXT_ERROR; - } + p = nxt_utf8_encode(&uc_name[5], uc); - *p = '\0'; + if (p == NULL) { + nxt_log_alert(thr->log, "nxt_utf8_encode(%05uxD) failed", uc); + return NXT_ERROR; + } - pp = &uc_name[5]; - lc = nxt_utf8_lowcase(&pp, p); + *p = '\0'; - if (lc == 0xFFFFFFFF) { - nxt_log_alert(thr->log, "nxt_utf8_lowcase(%05uxD) failed: %05uxD", - uc, lc); - return NXT_ERROR; - } + pp = &uc_name[5]; + lc = nxt_utf8_lowcase(&pp, p); - if (uc == lc) { - continue; - } + if (lc == 0xFFFFFFFF) { + nxt_log_alert(thr->log, "nxt_utf8_lowcase(%05uxD) failed: %05uxD", uc, + lc); + return NXT_ERROR; + } - p = nxt_utf8_encode(&lc_name[5], lc); + if (uc == lc) { + continue; + } - if (p == NULL) { - nxt_log_alert(thr->log, "nxt_utf8_encode(%05uxD) failed", lc); - return NXT_ERROR; - } + p = nxt_utf8_encode(&lc_name[5], lc); - *p = '\0'; + if (p == NULL) { + nxt_log_alert(thr->log, "nxt_utf8_encode(%05uxD) failed", lc); + return NXT_ERROR; + } - ret = nxt_file_open(&task, &uc_file, NXT_FILE_WRONLY, NXT_FILE_TRUNCATE, - NXT_FILE_DEFAULT_ACCESS); - if (ret != NXT_OK) { - return NXT_ERROR; - } + *p = '\0'; - if (nxt_file_write(&uc_file, utf8, 4, 0) != 4) { - return NXT_ERROR; - } + ret = nxt_file_open(&task, &uc_file, NXT_FILE_WRONLY, NXT_FILE_TRUNCATE, + NXT_FILE_DEFAULT_ACCESS); + if (ret != NXT_OK) { + return NXT_ERROR; + } - nxt_file_close(&task, &uc_file); + if (nxt_file_write(&uc_file, utf8, 4, 0) != 4) { + return NXT_ERROR; + } - ret = nxt_file_open(&task, &lc_file, NXT_FILE_RDONLY, NXT_FILE_OPEN, - NXT_FILE_DEFAULT_ACCESS); + nxt_file_close(&task, &uc_file); - if (ret == NXT_OK) { - n = nxt_file_read(&lc_file, test, 4, 0); + ret = nxt_file_open(&task, &lc_file, NXT_FILE_RDONLY, NXT_FILE_OPEN, + NXT_FILE_DEFAULT_ACCESS); - nxt_file_close(&task, &lc_file); + if (ret == NXT_OK) { + n = nxt_file_read(&lc_file, test, 4, 0); - if (n != 4 || memcmp(utf8, test, 4) != 0) { - nxt_log_alert(thr->log, "nxt_file_read() mismatch"); + nxt_file_close(&task, &lc_file); - nxt_file_delete(lc_file.name); - } + if (n != 4 || memcmp(utf8, test, 4) != 0) { + nxt_log_alert(thr->log, "nxt_file_read() mismatch"); - p = nxt_sprintf(buf, buf + 32, "%04uXD; C; %04uXD;%n", uc, lc); + nxt_file_delete(lc_file.name); + } - nxt_fd_write(nxt_stdout, buf, p - buf); - } + p = nxt_sprintf(buf, buf + 32, "%04uXD; C; %04uXD;%n", uc, lc); - nxt_file_delete(uc_file.name); + nxt_fd_write(nxt_stdout, buf, p - buf); } - nxt_log_error(NXT_LOG_NOTICE, thr->log, "utf8 file name test passed"); - return NXT_OK; + nxt_file_delete(uc_file.name); + } + + nxt_log_error(NXT_LOG_NOTICE, thr->log, "utf8 file name test passed"); + return NXT_OK; } diff --git a/src/test/nxt_utf8_test.c b/src/test/nxt_utf8_test.c index 31e5bff94..b47dd21d7 100644 --- a/src/test/nxt_utf8_test.c +++ b/src/test/nxt_utf8_test.c @@ -7,185 +7,234 @@ #include #include "nxt_tests.h" +#define NXT_UTF8_START_TEST 0xC2 +// #define NXT_UTF8_START_TEST 0 -#define NXT_UTF8_START_TEST 0xC2 -//#define NXT_UTF8_START_TEST 0 - - -static u_char invalid[] = { +static u_char invalid[] = { /* Invalid first byte less than 0xC2. */ - 1, 0x80, 0x00, 0x00, 0x00, - 1, 0xC0, 0x00, 0x00, 0x00, - 2, 0xC0, 0x00, 0x00, 0x00, - 3, 0xC0, 0x00, 0x00, 0x00, - 4, 0xC0, 0x00, 0x00, 0x00, + 1, + 0x80, + 0x00, + 0x00, + 0x00, + 1, + 0xC0, + 0x00, + 0x00, + 0x00, + 2, + 0xC0, + 0x00, + 0x00, + 0x00, + 3, + 0xC0, + 0x00, + 0x00, + 0x00, + 4, + 0xC0, + 0x00, + 0x00, + 0x00, /* Invalid 0x110000 value. */ - 4, 0xF4, 0x90, 0x80, 0x80, + 4, + 0xF4, + 0x90, + 0x80, + 0x80, /* Incomplete length. */ - 2, 0xE0, 0xAF, 0xB5, 0x00, + 2, + 0xE0, + 0xAF, + 0xB5, + 0x00, /* Overlong values. */ - 2, 0xC0, 0x80, 0x00, 0x00, - 2, 0xC1, 0xB3, 0x00, 0x00, - 3, 0xE0, 0x80, 0x80, 0x00, - 3, 0xE0, 0x81, 0xB3, 0x00, - 3, 0xE0, 0x90, 0x9A, 0x00, - 4, 0xF0, 0x80, 0x8A, 0x80, - 4, 0xF0, 0x80, 0x81, 0xB3, - 4, 0xF0, 0x80, 0xAF, 0xB5, + 2, + 0xC0, + 0x80, + 0x00, + 0x00, + 2, + 0xC1, + 0xB3, + 0x00, + 0x00, + 3, + 0xE0, + 0x80, + 0x80, + 0x00, + 3, + 0xE0, + 0x81, + 0xB3, + 0x00, + 3, + 0xE0, + 0x90, + 0x9A, + 0x00, + 4, + 0xF0, + 0x80, + 0x8A, + 0x80, + 4, + 0xF0, + 0x80, + 0x81, + 0xB3, + 4, + 0xF0, + 0x80, + 0xAF, + 0xB5, }; +static nxt_int_t nxt_utf8_overlong(nxt_thread_t *thr, u_char *overlong, + size_t len) { + u_char *p, utf8[4]; + size_t size; + uint32_t u, d; + nxt_uint_t i; + const u_char *pp; -static nxt_int_t -nxt_utf8_overlong(nxt_thread_t *thr, u_char *overlong, size_t len) -{ - u_char *p, utf8[4]; - size_t size; - uint32_t u, d; - nxt_uint_t i; - const u_char *pp; - - pp = overlong; + pp = overlong; - d = nxt_utf8_decode(&pp, overlong + len); + d = nxt_utf8_decode(&pp, overlong + len); - len = pp - overlong; + len = pp - overlong; - if (d != 0xFFFFFFFF) { - p = nxt_utf8_encode(utf8, d); + if (d != 0xFFFFFFFF) { + p = nxt_utf8_encode(utf8, d); - size = (p != NULL) ? p - utf8 : 0; + size = (p != NULL) ? p - utf8 : 0; - if (len != size || memcmp(overlong, utf8, size) != 0) { + if (len != size || memcmp(overlong, utf8, size) != 0) { - u = 0; - for (i = 0; i < len; i++) { - u = (u << 8) + overlong[i]; - } + u = 0; + for (i = 0; i < len; i++) { + u = (u << 8) + overlong[i]; + } - nxt_log_alert(thr->log, - "nxt_utf8_decode(%05uxD, %uz) failed: %05uxD, %uz", - u, len, d, size); + nxt_log_alert(thr->log, + "nxt_utf8_decode(%05uxD, %uz) failed: %05uxD, %uz", u, len, + d, size); - return NXT_ERROR; - } + return NXT_ERROR; } + } - return NXT_OK; + return NXT_OK; } +nxt_int_t nxt_utf8_test(nxt_thread_t *thr) { + u_char *p, utf8[4]; + size_t len; + int32_t n; + uint32_t u, d; + nxt_uint_t i, k, l, m; + const u_char *pp; -nxt_int_t -nxt_utf8_test(nxt_thread_t *thr) -{ - u_char *p, utf8[4]; - size_t len; - int32_t n; - uint32_t u, d; - nxt_uint_t i, k, l, m; - const u_char *pp; + nxt_thread_time_update(thr); - nxt_thread_time_update(thr); + nxt_log_error(NXT_LOG_NOTICE, thr->log, "utf8 test started"); - nxt_log_error(NXT_LOG_NOTICE, thr->log, "utf8 test started"); + /* Test valid UTF-8. */ - /* Test valid UTF-8. */ + for (u = 0; u < 0x110000; u++) { - for (u = 0; u < 0x110000; u++) { + p = nxt_utf8_encode(utf8, u); - p = nxt_utf8_encode(utf8, u); - - if (p == NULL) { - nxt_log_alert(thr->log, "nxt_utf8_encode(%05uxD) failed", u); - return NXT_ERROR; - } + if (p == NULL) { + nxt_log_alert(thr->log, "nxt_utf8_encode(%05uxD) failed", u); + return NXT_ERROR; + } - pp = utf8; + pp = utf8; - d = nxt_utf8_decode(&pp, p); + d = nxt_utf8_decode(&pp, p); - if (u != d) { - nxt_log_alert(thr->log, "nxt_utf8_decode(%05uxD) failed: %05uxD", - u, d); - return NXT_ERROR; - } + if (u != d) { + nxt_log_alert(thr->log, "nxt_utf8_decode(%05uxD) failed: %05uxD", u, d); + return NXT_ERROR; } + } - /* Test some invalid UTF-8. */ + /* Test some invalid UTF-8. */ - for (i = 0; i < sizeof(invalid); i += 5) { + for (i = 0; i < sizeof(invalid); i += 5) { - len = invalid[i]; - utf8[0] = invalid[i + 1]; - utf8[1] = invalid[i + 2]; - utf8[2] = invalid[i + 3]; - utf8[3] = invalid[i + 4]; + len = invalid[i]; + utf8[0] = invalid[i + 1]; + utf8[1] = invalid[i + 2]; + utf8[2] = invalid[i + 3]; + utf8[3] = invalid[i + 4]; - pp = utf8; + pp = utf8; - d = nxt_utf8_decode(&pp, utf8 + len); + d = nxt_utf8_decode(&pp, utf8 + len); - if (d != 0xFFFFFFFF) { + if (d != 0xFFFFFFFF) { - u = 0; - for (i = 0; i < len; i++) { - u = (u << 8) + utf8[i]; - } + u = 0; + for (i = 0; i < len; i++) { + u = (u << 8) + utf8[i]; + } - nxt_log_alert(thr->log, - "nxt_utf8_decode(%05uxD, %uz) failed: %05uxD", - u, len, d); - return NXT_ERROR; - } + nxt_log_alert(thr->log, "nxt_utf8_decode(%05uxD, %uz) failed: %05uxD", u, + len, d); + return NXT_ERROR; } + } - /* Test all overlong UTF-8. */ + /* Test all overlong UTF-8. */ - for (i = NXT_UTF8_START_TEST; i < 256; i++) { - utf8[0] = i; + for (i = NXT_UTF8_START_TEST; i < 256; i++) { + utf8[0] = i; - if (nxt_utf8_overlong(thr, utf8, 1) != NXT_OK) { - return NXT_ERROR; - } + if (nxt_utf8_overlong(thr, utf8, 1) != NXT_OK) { + return NXT_ERROR; + } - for (k = 0; k < 256; k++) { - utf8[1] = k; + for (k = 0; k < 256; k++) { + utf8[1] = k; - if (nxt_utf8_overlong(thr, utf8, 2) != NXT_OK) { - return NXT_ERROR; - } + if (nxt_utf8_overlong(thr, utf8, 2) != NXT_OK) { + return NXT_ERROR; + } - for (l = 0; l < 256; l++) { - utf8[2] = l; + for (l = 0; l < 256; l++) { + utf8[2] = l; - if (nxt_utf8_overlong(thr, utf8, 3) != NXT_OK) { - return NXT_ERROR; - } + if (nxt_utf8_overlong(thr, utf8, 3) != NXT_OK) { + return NXT_ERROR; + } - for (m = 0; m < 256; m++) { - utf8[3] = m; + for (m = 0; m < 256; m++) { + utf8[3] = m; - if (nxt_utf8_overlong(thr, utf8, 4) != NXT_OK) { - return NXT_ERROR; - } - } - } + if (nxt_utf8_overlong(thr, utf8, 4) != NXT_OK) { + return NXT_ERROR; + } } + } } + } - n = nxt_utf8_casecmp((u_char *) "ABC АБВ ΑΒΓ", - (u_char *) "abc абв αβγ", - nxt_length("ABC АБВ ΑΒΓ"), - nxt_length("abc абв αβγ")); + n = nxt_utf8_casecmp((u_char *)"ABC АБВ ΑΒΓ", (u_char *)"abc абв αβγ", + nxt_length("ABC АБВ ΑΒΓ"), nxt_length("abc абв αβγ")); - if (n != 0) { - nxt_log_alert(thr->log, "nxt_utf8_casecmp() failed"); - return NXT_ERROR; - } + if (n != 0) { + nxt_log_alert(thr->log, "nxt_utf8_casecmp() failed"); + return NXT_ERROR; + } - nxt_log_error(NXT_LOG_NOTICE, thr->log, "utf8 test passed"); - return NXT_OK; + nxt_log_error(NXT_LOG_NOTICE, thr->log, "utf8 test passed"); + return NXT_OK; } diff --git a/src/wasm/nxt_rt_wasmtime.c b/src/wasm/nxt_rt_wasmtime.c index bf0b0a0f9..c589b45b2 100644 --- a/src/wasm/nxt_rt_wasmtime.c +++ b/src/wasm/nxt_rt_wasmtime.c @@ -13,421 +13,374 @@ #include "nxt_wasm.h" - -typedef struct nxt_wasmtime_ctx_s nxt_wasmtime_ctx_t; +typedef struct nxt_wasmtime_ctx_s nxt_wasmtime_ctx_t; struct nxt_wasmtime_ctx_s { - wasm_engine_t *engine; - wasmtime_store_t *store; - wasmtime_memory_t memory; - wasmtime_module_t *module; - wasmtime_linker_t *linker; - wasmtime_context_t *ctx; + wasm_engine_t *engine; + wasmtime_store_t *store; + wasmtime_memory_t memory; + wasmtime_module_t *module; + wasmtime_linker_t *linker; + wasmtime_context_t *ctx; }; -static nxt_wasmtime_ctx_t nxt_wasmtime_ctx; - - -static void -nxt_wasmtime_err_msg(wasmtime_error_t *error, wasm_trap_t *trap, - const char *fmt, ...) -{ - va_list args; - wasm_byte_vec_t error_message; - - fprintf(stderr, "WASMTIME ERROR: "); - va_start(args, fmt); - vfprintf(stderr, fmt, args); - va_end(args); - fprintf(stderr, "\n"); - - if (error == NULL && trap == NULL) { - return; - } - - if (error != NULL) { - wasmtime_error_message(error, &error_message); - wasmtime_error_delete(error); - } else { - wasm_trap_message(trap, &error_message); - wasm_trap_delete(trap); - } - fprintf(stderr, "%.*s\n", (int)error_message.size, error_message.data); - - wasm_byte_vec_delete(&error_message); +static nxt_wasmtime_ctx_t nxt_wasmtime_ctx; + +static void nxt_wasmtime_err_msg(wasmtime_error_t *error, wasm_trap_t *trap, + const char *fmt, ...) { + va_list args; + wasm_byte_vec_t error_message; + + fprintf(stderr, "WASMTIME ERROR: "); + va_start(args, fmt); + vfprintf(stderr, fmt, args); + va_end(args); + fprintf(stderr, "\n"); + + if (error == NULL && trap == NULL) { + return; + } + + if (error != NULL) { + wasmtime_error_message(error, &error_message); + wasmtime_error_delete(error); + } else { + wasm_trap_message(trap, &error_message); + wasm_trap_delete(trap); + } + fprintf(stderr, "%.*s\n", (int)error_message.size, error_message.data); + + wasm_byte_vec_delete(&error_message); } - static wasm_trap_t * nxt_wasm_get_init_mem_size(void *env, wasmtime_caller_t *caller, const wasmtime_val_t *args, size_t nargs, - wasmtime_val_t *results, size_t nresults) -{ - results[0].of.i32 = NXT_WASM_MEM_SIZE; + wasmtime_val_t *results, size_t nresults) { + results[0].of.i32 = NXT_WASM_MEM_SIZE; - return NULL; + return NULL; } +static wasm_trap_t *nxt_wasm_response_end(void *env, wasmtime_caller_t *caller, + const wasmtime_val_t *args, + size_t nargs, wasmtime_val_t *results, + size_t nresults) { + nxt_wasm_do_response_end(env); -static wasm_trap_t * -nxt_wasm_response_end(void *env, wasmtime_caller_t *caller, - const wasmtime_val_t *args, size_t nargs, - wasmtime_val_t *results, size_t nresults) -{ - nxt_wasm_do_response_end(env); - - return NULL; + return NULL; } +static wasm_trap_t *nxt_wasm_send_response(void *env, wasmtime_caller_t *caller, + const wasmtime_val_t *args, + size_t nargs, + wasmtime_val_t *results, + size_t nresults) { + nxt_wasm_do_send_response(env, args[0].of.i32); -static wasm_trap_t * -nxt_wasm_send_response(void *env, wasmtime_caller_t *caller, - const wasmtime_val_t *args, size_t nargs, - wasmtime_val_t *results, size_t nresults) -{ - nxt_wasm_do_send_response(env, args[0].of.i32); - - return NULL; + return NULL; } +static wasm_trap_t *nxt_wasm_send_headers(void *env, wasmtime_caller_t *caller, + const wasmtime_val_t *args, + size_t nargs, wasmtime_val_t *results, + size_t nresults) { + nxt_wasm_do_send_headers(env, args[0].of.i32); -static wasm_trap_t * -nxt_wasm_send_headers(void *env, wasmtime_caller_t *caller, - const wasmtime_val_t *args, size_t nargs, - wasmtime_val_t *results, size_t nresults) -{ - nxt_wasm_do_send_headers(env, args[0].of.i32); - - return NULL; + return NULL; } - static wasm_trap_t * nxt_wasm_set_resp_status(void *env, wasmtime_caller_t *caller, const wasmtime_val_t *args, size_t nargs, - wasmtime_val_t *results, size_t nresults) -{ - nxt_wasm_ctx_t *ctx = env; + wasmtime_val_t *results, size_t nresults) { + nxt_wasm_ctx_t *ctx = env; - ctx->status = args[0].of.i32; + ctx->status = args[0].of.i32; - return NULL; + return NULL; } - -static void -nxt_wasmtime_execute_hook(const nxt_wasm_ctx_t *ctx, nxt_wasm_fh_t hook) -{ - const char *name = ctx->fh[hook].func_name; - wasm_trap_t *trap = NULL; - wasmtime_error_t *error; - nxt_wasmtime_ctx_t *rt_ctx = &nxt_wasmtime_ctx; - const nxt_wasm_func_t *func = &ctx->fh[hook].func; - - if (name == NULL) { - return; - } - - error = wasmtime_func_call(rt_ctx->ctx, func, NULL, 0, NULL, 0, &trap); - if (error != NULL || trap != NULL) { - nxt_wasmtime_err_msg(error, trap, "failed to call hook function [%s]", - name); - } -} - - -static int -nxt_wasmtime_execute_request(const nxt_wasm_ctx_t *ctx) -{ - int i = 0; - wasm_trap_t *trap = NULL; - wasmtime_val_t args[1] = { }; - wasmtime_val_t results[1] = { }; - wasmtime_error_t *error; - nxt_wasmtime_ctx_t *rt_ctx = &nxt_wasmtime_ctx; - const nxt_wasm_func_t *func = &ctx->fh[NXT_WASM_FH_REQUEST].func; - - args[i].kind = WASMTIME_I32; - args[i++].of.i32 = ctx->baddr_off; - - error = wasmtime_func_call(rt_ctx->ctx, func, args, i, results, 1, &trap); - if (error != NULL || trap != NULL) { - nxt_wasmtime_err_msg(error, trap, - "failed to call function [->wasm_request_handler]" - ); - return -1; - } - - return results[0].of.i32; +static void nxt_wasmtime_execute_hook(const nxt_wasm_ctx_t *ctx, + nxt_wasm_fh_t hook) { + const char *name = ctx->fh[hook].func_name; + wasm_trap_t *trap = NULL; + wasmtime_error_t *error; + nxt_wasmtime_ctx_t *rt_ctx = &nxt_wasmtime_ctx; + const nxt_wasm_func_t *func = &ctx->fh[hook].func; + + if (name == NULL) { + return; + } + + error = wasmtime_func_call(rt_ctx->ctx, func, NULL, 0, NULL, 0, &trap); + if (error != NULL || trap != NULL) { + nxt_wasmtime_err_msg(error, trap, "failed to call hook function [%s]", + name); + } } - -static void -nxt_wasmtime_set_function_imports(nxt_wasm_ctx_t *ctx) -{ - nxt_wasmtime_ctx_t *rt_ctx = &nxt_wasmtime_ctx; - - static const struct { - const char *func_name; - - wasmtime_func_callback_t func; - wasm_valkind_t params[1]; - wasm_valkind_t results[1]; - - enum { - NXT_WASM_FT_0_0, - NXT_WASM_FT_1_0, - NXT_WASM_FT_0_1, - } ft; - } import_functions[] = { - { - .func_name = "nxt_wasm_get_init_mem_size", - .func = nxt_wasm_get_init_mem_size, - .results = { WASM_I32 }, - .ft = NXT_WASM_FT_0_1 - }, { - .func_name = "nxt_wasm_response_end", - .func = nxt_wasm_response_end, - .ft = NXT_WASM_FT_0_0 - }, { - .func_name = "nxt_wasm_send_response", - .func = nxt_wasm_send_response, - .params = { WASM_I32 }, - .ft = NXT_WASM_FT_1_0 - }, { - .func_name = "nxt_wasm_send_headers", - .func = nxt_wasm_send_headers, - .params = { WASM_I32 }, - .ft = NXT_WASM_FT_1_0 - }, { - .func_name = "nxt_wasm_set_resp_status", - .func = nxt_wasm_set_resp_status, - .params = { WASM_I32 }, - .ft = NXT_WASM_FT_1_0 - }, - - { } - }, *imf; - - for (imf = import_functions; imf->func_name != NULL; imf++) { - wasm_functype_t *func_ty; - - switch (imf->ft) { - case NXT_WASM_FT_0_0: - func_ty = wasm_functype_new_0_0(); - break; - case NXT_WASM_FT_1_0: - func_ty = wasm_functype_new_1_0(wasm_valtype_new(imf->params[0])); - break; - case NXT_WASM_FT_0_1: - func_ty = wasm_functype_new_0_1(wasm_valtype_new(imf->results[0])); - break; - default: - /* Stop GCC complaining about func_ty being used uninitialised */ - func_ty = NULL; - } - - wasmtime_linker_define_func(rt_ctx->linker, "env", 3, - imf->func_name, strlen(imf->func_name), - func_ty, imf->func, ctx, NULL); - wasm_functype_delete(func_ty); - } +static int nxt_wasmtime_execute_request(const nxt_wasm_ctx_t *ctx) { + int i = 0; + wasm_trap_t *trap = NULL; + wasmtime_val_t args[1] = {}; + wasmtime_val_t results[1] = {}; + wasmtime_error_t *error; + nxt_wasmtime_ctx_t *rt_ctx = &nxt_wasmtime_ctx; + const nxt_wasm_func_t *func = &ctx->fh[NXT_WASM_FH_REQUEST].func; + + args[i].kind = WASMTIME_I32; + args[i++].of.i32 = ctx->baddr_off; + + error = wasmtime_func_call(rt_ctx->ctx, func, args, i, results, 1, &trap); + if (error != NULL || trap != NULL) { + nxt_wasmtime_err_msg(error, trap, + "failed to call function [->wasm_request_handler]"); + return -1; + } + + return results[0].of.i32; } - -static int -nxt_wasmtime_get_function_exports(nxt_wasm_ctx_t *ctx) -{ - int i; - nxt_wasmtime_ctx_t *rt_ctx = &nxt_wasmtime_ctx; - - for (i = 0; i < NXT_WASM_FH_NR; i++) { - bool ok; - wasmtime_extern_t item; - - if (ctx->fh[i].func_name == NULL) { - continue; - } - - ok = wasmtime_linker_get(rt_ctx->linker, rt_ctx->ctx, "", 0, - ctx->fh[i].func_name, - strlen(ctx->fh[i].func_name), &item); - if (!ok) { - nxt_wasmtime_err_msg(NULL, NULL, - "couldn't get (%s) export from module", - ctx->fh[i].func_name); - return -1; - } - ctx->fh[i].func = item.of.func; +static void nxt_wasmtime_set_function_imports(nxt_wasm_ctx_t *ctx) { + nxt_wasmtime_ctx_t *rt_ctx = &nxt_wasmtime_ctx; + + static const struct { + const char *func_name; + + wasmtime_func_callback_t func; + wasm_valkind_t params[1]; + wasm_valkind_t results[1]; + + enum { + NXT_WASM_FT_0_0, + NXT_WASM_FT_1_0, + NXT_WASM_FT_0_1, + } ft; + } import_functions[] = {{.func_name = "nxt_wasm_get_init_mem_size", + .func = nxt_wasm_get_init_mem_size, + .results = {WASM_I32}, + .ft = NXT_WASM_FT_0_1}, + {.func_name = "nxt_wasm_response_end", + .func = nxt_wasm_response_end, + .ft = NXT_WASM_FT_0_0}, + {.func_name = "nxt_wasm_send_response", + .func = nxt_wasm_send_response, + .params = {WASM_I32}, + .ft = NXT_WASM_FT_1_0}, + {.func_name = "nxt_wasm_send_headers", + .func = nxt_wasm_send_headers, + .params = {WASM_I32}, + .ft = NXT_WASM_FT_1_0}, + {.func_name = "nxt_wasm_set_resp_status", + .func = nxt_wasm_set_resp_status, + .params = {WASM_I32}, + .ft = NXT_WASM_FT_1_0}, + + {}}, + *imf; + + for (imf = import_functions; imf->func_name != NULL; imf++) { + wasm_functype_t *func_ty; + + switch (imf->ft) { + case NXT_WASM_FT_0_0: + func_ty = wasm_functype_new_0_0(); + break; + case NXT_WASM_FT_1_0: + func_ty = wasm_functype_new_1_0(wasm_valtype_new(imf->params[0])); + break; + case NXT_WASM_FT_0_1: + func_ty = wasm_functype_new_0_1(wasm_valtype_new(imf->results[0])); + break; + default: + /* Stop GCC complaining about func_ty being used uninitialised */ + func_ty = NULL; } - return 0; + wasmtime_linker_define_func(rt_ctx->linker, "env", 3, imf->func_name, + strlen(imf->func_name), func_ty, imf->func, ctx, + NULL); + wasm_functype_delete(func_ty); + } } +static int nxt_wasmtime_get_function_exports(nxt_wasm_ctx_t *ctx) { + int i; + nxt_wasmtime_ctx_t *rt_ctx = &nxt_wasmtime_ctx; -static int -nxt_wasmtime_wasi_init(const nxt_wasm_ctx_t *ctx) -{ - char **dir; - wasi_config_t *wasi_config; - wasmtime_error_t *error; - nxt_wasmtime_ctx_t *rt_ctx = &nxt_wasmtime_ctx; - - wasi_config = wasi_config_new(); + for (i = 0; i < NXT_WASM_FH_NR; i++) { + bool ok; + wasmtime_extern_t item; - wasi_config_inherit_env(wasi_config); - wasi_config_inherit_stdin(wasi_config); - wasi_config_inherit_stdout(wasi_config); - wasi_config_inherit_stderr(wasi_config); - - for (dir = ctx->dirs; dir != NULL && *dir != NULL; dir++) { - wasi_config_preopen_dir(wasi_config, *dir, *dir); + if (ctx->fh[i].func_name == NULL) { + continue; } - error = wasmtime_context_set_wasi(rt_ctx->ctx, wasi_config); - if (error != NULL) { - nxt_wasmtime_err_msg(error, NULL, "failed to instantiate WASI"); - return -1; + ok = wasmtime_linker_get(rt_ctx->linker, rt_ctx->ctx, "", 0, + ctx->fh[i].func_name, strlen(ctx->fh[i].func_name), + &item); + if (!ok) { + nxt_wasmtime_err_msg(NULL, NULL, "couldn't get (%s) export from module", + ctx->fh[i].func_name); + return -1; } + ctx->fh[i].func = item.of.func; + } - return 0; + return 0; } +static int nxt_wasmtime_wasi_init(const nxt_wasm_ctx_t *ctx) { + char **dir; + wasi_config_t *wasi_config; + wasmtime_error_t *error; + nxt_wasmtime_ctx_t *rt_ctx = &nxt_wasmtime_ctx; -static int -nxt_wasmtime_init_memory(nxt_wasm_ctx_t *ctx) -{ - int i = 0; - bool ok; - wasm_trap_t *trap = NULL; - wasmtime_val_t args[1] = { }; - wasmtime_val_t results[1] = { }; - wasmtime_error_t *error; - wasmtime_extern_t item; - nxt_wasmtime_ctx_t *rt_ctx = &nxt_wasmtime_ctx; - const nxt_wasm_func_t *func = &ctx->fh[NXT_WASM_FH_MALLOC].func; - - args[i].kind = WASMTIME_I32; - args[i++].of.i32 = NXT_WASM_MEM_SIZE + NXT_WASM_PAGE_SIZE; - - error = wasmtime_func_call(rt_ctx->ctx, func, args, i, results, 1, &trap); - if (error != NULL || trap != NULL) { - nxt_wasmtime_err_msg(error, trap, - "failed to call function [->wasm_malloc_handler]" - ); - return -1; - } + wasi_config = wasi_config_new(); - ok = wasmtime_linker_get(rt_ctx->linker, rt_ctx->ctx, "", 0, "memory", - strlen("memory"), &item); - if (!ok) { - nxt_wasmtime_err_msg(NULL, NULL, "couldn't get 'memory' from module\n"); - return -1; - } - rt_ctx->memory = item.of.memory; + wasi_config_inherit_env(wasi_config); + wasi_config_inherit_stdin(wasi_config); + wasi_config_inherit_stdout(wasi_config); + wasi_config_inherit_stderr(wasi_config); - ctx->baddr_off = results[0].of.i32; - ctx->baddr = wasmtime_memory_data(rt_ctx->ctx, &rt_ctx->memory); + for (dir = ctx->dirs; dir != NULL && *dir != NULL; dir++) { + wasi_config_preopen_dir(wasi_config, *dir, *dir); + } - ctx->baddr += ctx->baddr_off; + error = wasmtime_context_set_wasi(rt_ctx->ctx, wasi_config); + if (error != NULL) { + nxt_wasmtime_err_msg(error, NULL, "failed to instantiate WASI"); + return -1; + } - return 0; + return 0; } +static int nxt_wasmtime_init_memory(nxt_wasm_ctx_t *ctx) { + int i = 0; + bool ok; + wasm_trap_t *trap = NULL; + wasmtime_val_t args[1] = {}; + wasmtime_val_t results[1] = {}; + wasmtime_error_t *error; + wasmtime_extern_t item; + nxt_wasmtime_ctx_t *rt_ctx = &nxt_wasmtime_ctx; + const nxt_wasm_func_t *func = &ctx->fh[NXT_WASM_FH_MALLOC].func; + + args[i].kind = WASMTIME_I32; + args[i++].of.i32 = NXT_WASM_MEM_SIZE + NXT_WASM_PAGE_SIZE; + + error = wasmtime_func_call(rt_ctx->ctx, func, args, i, results, 1, &trap); + if (error != NULL || trap != NULL) { + nxt_wasmtime_err_msg(error, trap, + "failed to call function [->wasm_malloc_handler]"); + return -1; + } + + ok = wasmtime_linker_get(rt_ctx->linker, rt_ctx->ctx, "", 0, "memory", + strlen("memory"), &item); + if (!ok) { + nxt_wasmtime_err_msg(NULL, NULL, "couldn't get 'memory' from module\n"); + return -1; + } + rt_ctx->memory = item.of.memory; + + ctx->baddr_off = results[0].of.i32; + ctx->baddr = wasmtime_memory_data(rt_ctx->ctx, &rt_ctx->memory); + + ctx->baddr += ctx->baddr_off; + + return 0; +} -static int -nxt_wasmtime_init(nxt_wasm_ctx_t *ctx) -{ - int err; - FILE *fp; - size_t file_size; - wasm_byte_vec_t wasm; - wasmtime_error_t *error; - nxt_wasmtime_ctx_t *rt_ctx = &nxt_wasmtime_ctx; - - rt_ctx->engine = wasm_engine_new(); - rt_ctx->store = wasmtime_store_new(rt_ctx->engine, NULL, NULL); - rt_ctx->ctx = wasmtime_store_context(rt_ctx->store); - - rt_ctx->linker = wasmtime_linker_new(rt_ctx->engine); - error = wasmtime_linker_define_wasi(rt_ctx->linker); - if (error != NULL) { - nxt_wasmtime_err_msg(error, NULL, "failed to link wasi"); - return -1; - } - - fp = fopen(ctx->module_path, "r"); - if (!fp) { - nxt_wasmtime_err_msg(NULL, NULL, - "error opening file (%s)", ctx->module_path); - return -1; - } - fseek(fp, 0L, SEEK_END); - file_size = ftell(fp); - wasm_byte_vec_new_uninitialized(&wasm, file_size); - fseek(fp, 0L, SEEK_SET); - if (fread(wasm.data, file_size, 1, fp) != 1) { - nxt_wasmtime_err_msg(NULL, NULL, "error loading module"); - fclose(fp); - return -1; - } +static int nxt_wasmtime_init(nxt_wasm_ctx_t *ctx) { + int err; + FILE *fp; + size_t file_size; + wasm_byte_vec_t wasm; + wasmtime_error_t *error; + nxt_wasmtime_ctx_t *rt_ctx = &nxt_wasmtime_ctx; + + rt_ctx->engine = wasm_engine_new(); + rt_ctx->store = wasmtime_store_new(rt_ctx->engine, NULL, NULL); + rt_ctx->ctx = wasmtime_store_context(rt_ctx->store); + + rt_ctx->linker = wasmtime_linker_new(rt_ctx->engine); + error = wasmtime_linker_define_wasi(rt_ctx->linker); + if (error != NULL) { + nxt_wasmtime_err_msg(error, NULL, "failed to link wasi"); + return -1; + } + + fp = fopen(ctx->module_path, "r"); + if (!fp) { + nxt_wasmtime_err_msg(NULL, NULL, "error opening file (%s)", + ctx->module_path); + return -1; + } + fseek(fp, 0L, SEEK_END); + file_size = ftell(fp); + wasm_byte_vec_new_uninitialized(&wasm, file_size); + fseek(fp, 0L, SEEK_SET); + if (fread(wasm.data, file_size, 1, fp) != 1) { + nxt_wasmtime_err_msg(NULL, NULL, "error loading module"); fclose(fp); - - error = wasmtime_module_new(rt_ctx->engine, (uint8_t *)wasm.data, wasm.size, - &rt_ctx->module); - if (!rt_ctx->module) { - nxt_wasmtime_err_msg(error, NULL, "failed to compile module"); - return -1; - } - wasm_byte_vec_delete(&wasm); - - nxt_wasmtime_set_function_imports(ctx); - - nxt_wasmtime_wasi_init(ctx); - - error = wasmtime_linker_module(rt_ctx->linker, rt_ctx->ctx, "", 0, - rt_ctx->module); - if (error != NULL) { - nxt_wasmtime_err_msg(error, NULL, "failed to instantiate"); - return -1; - } - - err = nxt_wasmtime_get_function_exports(ctx); - if (err) { - return -1; - } - - err = nxt_wasmtime_init_memory(ctx); - if (err) { - return -1; - } - - return 0; + return -1; + } + fclose(fp); + + error = wasmtime_module_new(rt_ctx->engine, (uint8_t *)wasm.data, wasm.size, + &rt_ctx->module); + if (!rt_ctx->module) { + nxt_wasmtime_err_msg(error, NULL, "failed to compile module"); + return -1; + } + wasm_byte_vec_delete(&wasm); + + nxt_wasmtime_set_function_imports(ctx); + + nxt_wasmtime_wasi_init(ctx); + + error = wasmtime_linker_module(rt_ctx->linker, rt_ctx->ctx, "", 0, + rt_ctx->module); + if (error != NULL) { + nxt_wasmtime_err_msg(error, NULL, "failed to instantiate"); + return -1; + } + + err = nxt_wasmtime_get_function_exports(ctx); + if (err) { + return -1; + } + + err = nxt_wasmtime_init_memory(ctx); + if (err) { + return -1; + } + + return 0; } +static void nxt_wasmtime_destroy(const nxt_wasm_ctx_t *ctx) { + int i = 0; + wasmtime_val_t args[1] = {}; + nxt_wasmtime_ctx_t *rt_ctx = &nxt_wasmtime_ctx; + const nxt_wasm_func_t *func = &ctx->fh[NXT_WASM_FH_FREE].func; -static void -nxt_wasmtime_destroy(const nxt_wasm_ctx_t *ctx) -{ - int i = 0; - wasmtime_val_t args[1] = { }; - nxt_wasmtime_ctx_t *rt_ctx = &nxt_wasmtime_ctx; - const nxt_wasm_func_t *func = &ctx->fh[NXT_WASM_FH_FREE].func; - - args[i].kind = WASMTIME_I32; - args[i++].of.i32 = ctx->baddr_off; + args[i].kind = WASMTIME_I32; + args[i++].of.i32 = ctx->baddr_off; - wasmtime_func_call(rt_ctx->ctx, func, args, i, NULL, 0, NULL); + wasmtime_func_call(rt_ctx->ctx, func, args, i, NULL, 0, NULL); - wasmtime_module_delete(rt_ctx->module); - wasmtime_store_delete(rt_ctx->store); - wasm_engine_delete(rt_ctx->engine); + wasmtime_module_delete(rt_ctx->module); + wasmtime_store_delete(rt_ctx->store); + wasm_engine_delete(rt_ctx->engine); } - -const nxt_wasm_operations_t nxt_wasm_ops = { - .init = nxt_wasmtime_init, - .destroy = nxt_wasmtime_destroy, - .exec_request = nxt_wasmtime_execute_request, - .exec_hook = nxt_wasmtime_execute_hook, +const nxt_wasm_operations_t nxt_wasm_ops = { + .init = nxt_wasmtime_init, + .destroy = nxt_wasmtime_destroy, + .exec_request = nxt_wasmtime_execute_request, + .exec_hook = nxt_wasmtime_execute_hook, }; diff --git a/src/wasm/nxt_wasm.c b/src/wasm/nxt_wasm.c index db79d6aee..cba9ef892 100644 --- a/src/wasm/nxt_wasm.c +++ b/src/wasm/nxt_wasm.c @@ -10,306 +10,282 @@ #include "nxt_wasm.h" +#define NXT_WASM_VERSION "0.1" -#define NXT_WASM_VERSION "0.1" +#define NXT_WASM_DO_HOOK(hook) nxt_wops->exec_hook(&nxt_wasm_ctx, hook); -#define NXT_WASM_DO_HOOK(hook) nxt_wops->exec_hook(&nxt_wasm_ctx, hook); - - -static uint32_t compat[] = { - NXT_VERNUM, NXT_DEBUG, +static uint32_t compat[] = { + NXT_VERNUM, + NXT_DEBUG, }; -static nxt_wasm_ctx_t nxt_wasm_ctx; +static nxt_wasm_ctx_t nxt_wasm_ctx; -static const nxt_wasm_operations_t *nxt_wops; +static const nxt_wasm_operations_t *nxt_wops; -enum { - NXT_WASM_HTTP_OK = 200, - NXT_WASM_HTTP_ERROR = 500 -}; +enum { NXT_WASM_HTTP_OK = 200, NXT_WASM_HTTP_ERROR = 500 }; +void nxt_wasm_do_response_end(nxt_wasm_ctx_t *ctx) { + nxt_unit_request_done(ctx->req, NXT_UNIT_OK); -void -nxt_wasm_do_response_end(nxt_wasm_ctx_t *ctx) -{ - nxt_unit_request_done(ctx->req, NXT_UNIT_OK); - - NXT_WASM_DO_HOOK(NXT_WASM_FH_RESPONSE_END); + NXT_WASM_DO_HOOK(NXT_WASM_FH_RESPONSE_END); } +void nxt_wasm_do_send_headers(nxt_wasm_ctx_t *ctx, uint32_t offset) { + size_t fields_len; + unsigned int i; + nxt_wasm_response_fields_t *rh; -void -nxt_wasm_do_send_headers(nxt_wasm_ctx_t *ctx, uint32_t offset) -{ - size_t fields_len; - unsigned int i; - nxt_wasm_response_fields_t *rh; + rh = (nxt_wasm_response_fields_t *)(ctx->baddr + offset); - rh = (nxt_wasm_response_fields_t *)(ctx->baddr + offset); + fields_len = 0; + for (i = 0; i < rh->nfields; i++) { + fields_len += rh->fields[i].name_len + rh->fields[i].value_len; + } - fields_len = 0; - for (i = 0; i < rh->nfields; i++) { - fields_len += rh->fields[i].name_len + rh->fields[i].value_len; - } + nxt_unit_response_init(ctx->req, ctx->status, rh->nfields, fields_len); - nxt_unit_response_init(ctx->req, ctx->status, rh->nfields, fields_len); + for (i = 0; i < rh->nfields; i++) { + const char *name; + const char *val; - for (i = 0; i < rh->nfields; i++) { - const char *name; - const char *val; + name = (const char *)rh + rh->fields[i].name_off; + val = (const char *)rh + rh->fields[i].value_off; - name = (const char *)rh + rh->fields[i].name_off; - val = (const char *)rh + rh->fields[i].value_off; + nxt_unit_response_add_field(ctx->req, name, rh->fields[i].name_len, val, + rh->fields[i].value_len); + } - nxt_unit_response_add_field(ctx->req, name, rh->fields[i].name_len, - val, rh->fields[i].value_len); - } - - nxt_unit_response_send(ctx->req); + nxt_unit_response_send(ctx->req); } +void nxt_wasm_do_send_response(nxt_wasm_ctx_t *ctx, uint32_t offset) { + nxt_wasm_response_t *resp; + nxt_unit_request_info_t *req = ctx->req; -void -nxt_wasm_do_send_response(nxt_wasm_ctx_t *ctx, uint32_t offset) -{ - nxt_wasm_response_t *resp; - nxt_unit_request_info_t *req = ctx->req; - - if (!nxt_unit_response_is_init(req)) { - nxt_unit_response_init(req, ctx->status, 0, 0); - } + if (!nxt_unit_response_is_init(req)) { + nxt_unit_response_init(req, ctx->status, 0, 0); + } - resp = (nxt_wasm_response_t *)(nxt_wasm_ctx.baddr + offset); + resp = (nxt_wasm_response_t *)(nxt_wasm_ctx.baddr + offset); - nxt_unit_response_write(req, (const char *)resp->data, resp->size); + nxt_unit_response_write(req, (const char *)resp->data, resp->size); } - -static void -nxt_wasm_request_handler(nxt_unit_request_info_t *req) -{ - int err; - size_t offset, read_bytes, content_sent, content_len; - ssize_t bytes_read; - nxt_unit_field_t *sf, *sf_end; - nxt_unit_request_t *r; - nxt_wasm_request_t *wr; - nxt_wasm_http_field_t *df; - - NXT_WASM_DO_HOOK(NXT_WASM_FH_REQUEST_INIT); - - wr = (nxt_wasm_request_t *)nxt_wasm_ctx.baddr; - -#define SET_REQ_MEMBER(dmember, smember) \ - do { \ - const char *str = nxt_unit_sptr_get(&r->smember); \ - wr->dmember##_off = offset; \ - wr->dmember##_len = strlen(str); \ - memcpy((uint8_t *)wr + offset, str, wr->dmember##_len + 1); \ - offset += wr->dmember##_len + 1; \ - } while (0) - - r = req->request; - offset = sizeof(nxt_wasm_request_t) - + (r->fields_count * sizeof(nxt_wasm_http_field_t)); - - SET_REQ_MEMBER(path, path); - SET_REQ_MEMBER(method, method); - SET_REQ_MEMBER(version, version); - SET_REQ_MEMBER(query, query); - SET_REQ_MEMBER(remote, remote); - SET_REQ_MEMBER(local_addr, local_addr); - SET_REQ_MEMBER(local_port, local_port); - SET_REQ_MEMBER(server_name, server_name); +static void nxt_wasm_request_handler(nxt_unit_request_info_t *req) { + int err; + size_t offset, read_bytes, content_sent, content_len; + ssize_t bytes_read; + nxt_unit_field_t *sf, *sf_end; + nxt_unit_request_t *r; + nxt_wasm_request_t *wr; + nxt_wasm_http_field_t *df; + + NXT_WASM_DO_HOOK(NXT_WASM_FH_REQUEST_INIT); + + wr = (nxt_wasm_request_t *)nxt_wasm_ctx.baddr; + +#define SET_REQ_MEMBER(dmember, smember) \ + do { \ + const char *str = nxt_unit_sptr_get(&r->smember); \ + wr->dmember##_off = offset; \ + wr->dmember##_len = strlen(str); \ + memcpy((uint8_t *)wr + offset, str, wr->dmember##_len + 1); \ + offset += wr->dmember##_len + 1; \ + } while (0) + + r = req->request; + offset = sizeof(nxt_wasm_request_t) + + (r->fields_count * sizeof(nxt_wasm_http_field_t)); + + SET_REQ_MEMBER(path, path); + SET_REQ_MEMBER(method, method); + SET_REQ_MEMBER(version, version); + SET_REQ_MEMBER(query, query); + SET_REQ_MEMBER(remote, remote); + SET_REQ_MEMBER(local_addr, local_addr); + SET_REQ_MEMBER(local_port, local_port); + SET_REQ_MEMBER(server_name, server_name); #undef SET_REQ_MEMBER - df = wr->fields; - sf_end = r->fields + r->fields_count; - for (sf = r->fields; sf < sf_end; sf++) { - const char *name = nxt_unit_sptr_get(&sf->name); - const char *value = nxt_unit_sptr_get(&sf->value); + df = wr->fields; + sf_end = r->fields + r->fields_count; + for (sf = r->fields; sf < sf_end; sf++) { + const char *name = nxt_unit_sptr_get(&sf->name); + const char *value = nxt_unit_sptr_get(&sf->value); - df->name_off = offset; - df->name_len = strlen(name); - memcpy((uint8_t *)wr + offset, name, df->name_len + 1); - offset += df->name_len + 1; + df->name_off = offset; + df->name_len = strlen(name); + memcpy((uint8_t *)wr + offset, name, df->name_len + 1); + offset += df->name_len + 1; - df->value_off = offset; - df->value_len = strlen(value); - memcpy((uint8_t *)wr + offset, value, df->value_len + 1); - offset += df->value_len + 1; + df->value_off = offset; + df->value_len = strlen(value); + memcpy((uint8_t *)wr + offset, value, df->value_len + 1); + offset += df->value_len + 1; - df++; - } + df++; + } - wr->tls = r->tls; - wr->nfields = r->fields_count; - wr->content_off = offset; - wr->content_len = content_len = r->content_length; + wr->tls = r->tls; + wr->nfields = r->fields_count; + wr->content_off = offset; + wr->content_len = content_len = r->content_length; - read_bytes = nxt_min(wr->content_len, NXT_WASM_MEM_SIZE - offset); + read_bytes = nxt_min(wr->content_len, NXT_WASM_MEM_SIZE - offset); - bytes_read = nxt_unit_request_read(req, (uint8_t *)wr + offset, read_bytes); - wr->content_sent = wr->total_content_sent = content_sent = bytes_read; + bytes_read = nxt_unit_request_read(req, (uint8_t *)wr + offset, read_bytes); + wr->content_sent = wr->total_content_sent = content_sent = bytes_read; - wr->request_size = offset + bytes_read; + wr->request_size = offset + bytes_read; - nxt_wasm_ctx.status = NXT_WASM_HTTP_OK; - nxt_wasm_ctx.req = req; - err = nxt_wops->exec_request(&nxt_wasm_ctx); - if (err) { - goto out_err_500; - } + nxt_wasm_ctx.status = NXT_WASM_HTTP_OK; + nxt_wasm_ctx.req = req; + err = nxt_wops->exec_request(&nxt_wasm_ctx); + if (err) { + goto out_err_500; + } - if (content_len == content_sent) { - goto request_done; - } + if (content_len == content_sent) { + goto request_done; + } - offset = sizeof(nxt_wasm_request_t); - do { - read_bytes = nxt_min(content_len - content_sent, - NXT_WASM_MEM_SIZE - offset); - bytes_read = nxt_unit_request_read(req, (uint8_t *)wr + offset, - read_bytes); + offset = sizeof(nxt_wasm_request_t); + do { + read_bytes = + nxt_min(content_len - content_sent, NXT_WASM_MEM_SIZE - offset); + bytes_read = nxt_unit_request_read(req, (uint8_t *)wr + offset, read_bytes); - content_sent += bytes_read; - wr->request_size = wr->content_sent = bytes_read; - wr->total_content_sent = content_sent; - wr->content_off = offset; + content_sent += bytes_read; + wr->request_size = wr->content_sent = bytes_read; + wr->total_content_sent = content_sent; + wr->content_off = offset; - err = nxt_wops->exec_request(&nxt_wasm_ctx); - if (err) { - goto out_err_500; - } - } while (content_sent < content_len); + err = nxt_wops->exec_request(&nxt_wasm_ctx); + if (err) { + goto out_err_500; + } + } while (content_sent < content_len); - goto request_done; + goto request_done; out_err_500: - nxt_unit_response_init(req, NXT_WASM_HTTP_ERROR, 0, 0); - nxt_unit_request_done(req, NXT_UNIT_OK); + nxt_unit_response_init(req, NXT_WASM_HTTP_ERROR, 0, 0); + nxt_unit_request_done(req, NXT_UNIT_OK); request_done: - NXT_WASM_DO_HOOK(NXT_WASM_FH_REQUEST_END); + NXT_WASM_DO_HOOK(NXT_WASM_FH_REQUEST_END); } +static nxt_int_t nxt_wasm_start(nxt_task_t *task, nxt_process_data_t *data) { + nxt_int_t ret; + nxt_unit_ctx_t *unit_ctx; + nxt_unit_init_t wasm_init; + nxt_common_app_conf_t *conf; -static nxt_int_t -nxt_wasm_start(nxt_task_t *task, nxt_process_data_t *data) -{ - nxt_int_t ret; - nxt_unit_ctx_t *unit_ctx; - nxt_unit_init_t wasm_init; - nxt_common_app_conf_t *conf; - - conf = data->app; + conf = data->app; - ret = nxt_unit_default_init(task, &wasm_init, conf); - if (nxt_slow_path(ret != NXT_OK)) { - nxt_alert(task, "nxt_unit_default_init() failed"); - return ret; - } + ret = nxt_unit_default_init(task, &wasm_init, conf); + if (nxt_slow_path(ret != NXT_OK)) { + nxt_alert(task, "nxt_unit_default_init() failed"); + return ret; + } - wasm_init.callbacks.request_handler = nxt_wasm_request_handler; + wasm_init.callbacks.request_handler = nxt_wasm_request_handler; - unit_ctx = nxt_unit_init(&wasm_init); - if (nxt_slow_path(unit_ctx == NULL)) { - return NXT_ERROR; - } + unit_ctx = nxt_unit_init(&wasm_init); + if (nxt_slow_path(unit_ctx == NULL)) { + return NXT_ERROR; + } - NXT_WASM_DO_HOOK(NXT_WASM_FH_MODULE_INIT); - nxt_unit_run(unit_ctx); - nxt_unit_done(unit_ctx); - NXT_WASM_DO_HOOK(NXT_WASM_FH_MODULE_END); + NXT_WASM_DO_HOOK(NXT_WASM_FH_MODULE_INIT); + nxt_unit_run(unit_ctx); + nxt_unit_done(unit_ctx); + NXT_WASM_DO_HOOK(NXT_WASM_FH_MODULE_END); - if (nxt_wasm_ctx.dirs != NULL) { - char **p; + if (nxt_wasm_ctx.dirs != NULL) { + char **p; - for (p = nxt_wasm_ctx.dirs; *p != NULL; p++) { - nxt_free(*p); - } - nxt_free(nxt_wasm_ctx.dirs); + for (p = nxt_wasm_ctx.dirs; *p != NULL; p++) { + nxt_free(*p); } + nxt_free(nxt_wasm_ctx.dirs); + } - nxt_wops->destroy(&nxt_wasm_ctx); + nxt_wops->destroy(&nxt_wasm_ctx); - exit(EXIT_SUCCESS); + exit(EXIT_SUCCESS); } +static nxt_int_t nxt_wasm_setup(nxt_task_t *task, nxt_process_t *process, + nxt_common_app_conf_t *conf) { + int n, i, err; + nxt_conf_value_t *dirs = NULL; + nxt_wasm_app_conf_t *c; + nxt_wasm_func_handler_t *fh; + static const nxt_str_t filesystem_str = nxt_string("filesystem"); -static nxt_int_t -nxt_wasm_setup(nxt_task_t *task, nxt_process_t *process, - nxt_common_app_conf_t *conf) -{ - int n, i, err; - nxt_conf_value_t *dirs = NULL; - nxt_wasm_app_conf_t *c; - nxt_wasm_func_handler_t *fh; - static const nxt_str_t filesystem_str = nxt_string("filesystem"); + c = &conf->u.wasm; - c = &conf->u.wasm; + nxt_wops = &nxt_wasm_ops; - nxt_wops = &nxt_wasm_ops; + nxt_wasm_ctx.module_path = c->module; - nxt_wasm_ctx.module_path = c->module; + fh = nxt_wasm_ctx.fh; - fh = nxt_wasm_ctx.fh; + fh[NXT_WASM_FH_REQUEST].func_name = c->request_handler; + fh[NXT_WASM_FH_MALLOC].func_name = c->malloc_handler; + fh[NXT_WASM_FH_FREE].func_name = c->free_handler; - fh[NXT_WASM_FH_REQUEST].func_name = c->request_handler; - fh[NXT_WASM_FH_MALLOC].func_name = c->malloc_handler; - fh[NXT_WASM_FH_FREE].func_name = c->free_handler; + /* Optional function handlers (hooks) */ + fh[NXT_WASM_FH_MODULE_INIT].func_name = c->module_init_handler; + fh[NXT_WASM_FH_MODULE_END].func_name = c->module_end_handler; + fh[NXT_WASM_FH_REQUEST_INIT].func_name = c->request_init_handler; + fh[NXT_WASM_FH_REQUEST_END].func_name = c->request_end_handler; + fh[NXT_WASM_FH_RESPONSE_END].func_name = c->response_end_handler; - /* Optional function handlers (hooks) */ - fh[NXT_WASM_FH_MODULE_INIT].func_name = c->module_init_handler; - fh[NXT_WASM_FH_MODULE_END].func_name = c->module_end_handler; - fh[NXT_WASM_FH_REQUEST_INIT].func_name = c->request_init_handler; - fh[NXT_WASM_FH_REQUEST_END].func_name = c->request_end_handler; - fh[NXT_WASM_FH_RESPONSE_END].func_name = c->response_end_handler; + /* Get any directories to pass through to the WASM module */ + if (c->access != NULL) { + dirs = nxt_conf_get_object_member(c->access, &filesystem_str, NULL); + } - /* Get any directories to pass through to the WASM module */ - if (c->access != NULL) { - dirs = nxt_conf_get_object_member(c->access, &filesystem_str, NULL); - } - - n = (dirs != NULL) ? nxt_conf_object_members_count(dirs) : 0; - if (n == 0) { - goto out_init; - } + n = (dirs != NULL) ? nxt_conf_object_members_count(dirs) : 0; + if (n == 0) { + goto out_init; + } - nxt_wasm_ctx.dirs = nxt_zalloc((n + 1) * sizeof(char *)); - if (nxt_slow_path(nxt_wasm_ctx.dirs == NULL)) { - return NXT_ERROR; - } + nxt_wasm_ctx.dirs = nxt_zalloc((n + 1) * sizeof(char *)); + if (nxt_slow_path(nxt_wasm_ctx.dirs == NULL)) { + return NXT_ERROR; + } - for (i = 0; i < n; i++) { - nxt_str_t str; - nxt_conf_value_t *value; + for (i = 0; i < n; i++) { + nxt_str_t str; + nxt_conf_value_t *value; - value = nxt_conf_get_array_element(dirs, i); - nxt_conf_get_string(value, &str); + value = nxt_conf_get_array_element(dirs, i); + nxt_conf_get_string(value, &str); - nxt_wasm_ctx.dirs[i] = nxt_zalloc(str.length + 1); - memcpy(nxt_wasm_ctx.dirs[i], str.start, str.length); - } + nxt_wasm_ctx.dirs[i] = nxt_zalloc(str.length + 1); + memcpy(nxt_wasm_ctx.dirs[i], str.start, str.length); + } out_init: - err = nxt_wops->init(&nxt_wasm_ctx); - if (err) { - exit(EXIT_FAILURE); - } + err = nxt_wops->init(&nxt_wasm_ctx); + if (err) { + exit(EXIT_FAILURE); + } - return NXT_OK; + return NXT_OK; } - -NXT_EXPORT nxt_app_module_t nxt_app_module = { - .compat_length = sizeof(compat), - .compat = compat, - .type = nxt_string("wasm"), - .version = NXT_WASM_VERSION, - .mounts = NULL, - .nmounts = 0, - .setup = nxt_wasm_setup, - .start = nxt_wasm_start, +NXT_EXPORT nxt_app_module_t nxt_app_module = { + .compat_length = sizeof(compat), + .compat = compat, + .type = nxt_string("wasm"), + .version = NXT_WASM_VERSION, + .mounts = NULL, + .nmounts = 0, + .setup = nxt_wasm_setup, + .start = nxt_wasm_start, }; diff --git a/src/wasm/nxt_wasm.h b/src/wasm/nxt_wasm.h index 6bc3ae35a..eebc0a398 100644 --- a/src/wasm/nxt_wasm.h +++ b/src/wasm/nxt_wasm.h @@ -16,127 +16,124 @@ #include #endif - -#define NXT_WASM_PAGE_SIZE (64 * 1024) -#define NXT_WASM_MEM_SIZE (32UL * 1024 * 1024) +#define NXT_WASM_PAGE_SIZE (64 * 1024) +#define NXT_WASM_MEM_SIZE (32UL * 1024 * 1024) #if defined(NXT_HAVE_WASM_WASMTIME) -typedef wasmtime_func_t nxt_wasm_func_t; +typedef wasmtime_func_t nxt_wasm_func_t; #endif - -typedef struct nxt_wasm_http_field_s nxt_wasm_http_field_t; -typedef struct nxt_wasm_request_s nxt_wasm_request_t; -typedef struct nxt_wasm_response_s nxt_wasm_response_t; -typedef struct nxt_wasm_response_fields_s nxt_wasm_response_fields_t; -typedef enum nxt_wasm_fh_e nxt_wasm_fh_t; -typedef struct nxt_wasm_func_handler_s nxt_wasm_func_handler_t; -typedef struct nxt_wasm_ctx_s nxt_wasm_ctx_t; -typedef struct nxt_wasm_operations_s nxt_wasm_operations_t; +typedef struct nxt_wasm_http_field_s nxt_wasm_http_field_t; +typedef struct nxt_wasm_request_s nxt_wasm_request_t; +typedef struct nxt_wasm_response_s nxt_wasm_response_t; +typedef struct nxt_wasm_response_fields_s nxt_wasm_response_fields_t; +typedef enum nxt_wasm_fh_e nxt_wasm_fh_t; +typedef struct nxt_wasm_func_handler_s nxt_wasm_func_handler_t; +typedef struct nxt_wasm_ctx_s nxt_wasm_ctx_t; +typedef struct nxt_wasm_operations_s nxt_wasm_operations_t; struct nxt_wasm_http_field_s { - uint32_t name_off; - uint32_t name_len; - uint32_t value_off; - uint32_t value_len; + uint32_t name_off; + uint32_t name_len; + uint32_t value_off; + uint32_t value_len; }; struct nxt_wasm_request_s { - uint32_t method_off; - uint32_t method_len; - uint32_t version_off; - uint32_t version_len; - uint32_t path_off; - uint32_t path_len; - uint32_t query_off; - uint32_t query_len; - uint32_t remote_off; - uint32_t remote_len; - uint32_t local_addr_off; - uint32_t local_addr_len; - uint32_t local_port_off; - uint32_t local_port_len; - uint32_t server_name_off; - uint32_t server_name_len; - - uint64_t content_len; - uint64_t total_content_sent; - uint32_t content_sent; - uint32_t content_off; - - uint32_t request_size; - - uint32_t nfields; - - uint32_t tls; - - char __pad[4]; - - nxt_wasm_http_field_t fields[]; + uint32_t method_off; + uint32_t method_len; + uint32_t version_off; + uint32_t version_len; + uint32_t path_off; + uint32_t path_len; + uint32_t query_off; + uint32_t query_len; + uint32_t remote_off; + uint32_t remote_len; + uint32_t local_addr_off; + uint32_t local_addr_len; + uint32_t local_port_off; + uint32_t local_port_len; + uint32_t server_name_off; + uint32_t server_name_len; + + uint64_t content_len; + uint64_t total_content_sent; + uint32_t content_sent; + uint32_t content_off; + + uint32_t request_size; + + uint32_t nfields; + + uint32_t tls; + + char __pad[4]; + + nxt_wasm_http_field_t fields[]; }; struct nxt_wasm_response_s { - uint32_t size; + uint32_t size; - uint8_t data[]; + uint8_t data[]; }; struct nxt_wasm_response_fields_s { - uint32_t nfields; + uint32_t nfields; - nxt_wasm_http_field_t fields[]; + nxt_wasm_http_field_t fields[]; }; enum nxt_wasm_fh_e { - NXT_WASM_FH_REQUEST = 0, - NXT_WASM_FH_MALLOC, - NXT_WASM_FH_FREE, - - /* Optional handlers */ - NXT_WASM_FH_MODULE_INIT, - NXT_WASM_FH_MODULE_END, - NXT_WASM_FH_REQUEST_INIT, - NXT_WASM_FH_REQUEST_END, - NXT_WASM_FH_RESPONSE_END, - - NXT_WASM_FH_NR + NXT_WASM_FH_REQUEST = 0, + NXT_WASM_FH_MALLOC, + NXT_WASM_FH_FREE, + + /* Optional handlers */ + NXT_WASM_FH_MODULE_INIT, + NXT_WASM_FH_MODULE_END, + NXT_WASM_FH_REQUEST_INIT, + NXT_WASM_FH_REQUEST_END, + NXT_WASM_FH_RESPONSE_END, + + NXT_WASM_FH_NR }; struct nxt_wasm_func_handler_s { - const char *func_name; - nxt_wasm_func_t func; + const char *func_name; + nxt_wasm_func_t func; }; struct nxt_wasm_ctx_s { - const char *module_path; + const char *module_path; - nxt_wasm_func_handler_t fh[NXT_WASM_FH_NR]; + nxt_wasm_func_handler_t fh[NXT_WASM_FH_NR]; - char **dirs; + char **dirs; - nxt_unit_request_info_t *req; + nxt_unit_request_info_t *req; - uint8_t *baddr; - size_t baddr_off; + uint8_t *baddr; + size_t baddr_off; - size_t response_off; + size_t response_off; - uint16_t status; + uint16_t status; }; struct nxt_wasm_operations_s { - int (*init)(nxt_wasm_ctx_t *ctx); - void (*destroy)(const nxt_wasm_ctx_t *ctx); - int (*exec_request)(const nxt_wasm_ctx_t *ctx); - void (*exec_hook)(const nxt_wasm_ctx_t *ctx, nxt_wasm_fh_t hook); + int (*init)(nxt_wasm_ctx_t *ctx); + void (*destroy)(const nxt_wasm_ctx_t *ctx); + int (*exec_request)(const nxt_wasm_ctx_t *ctx); + void (*exec_hook)(const nxt_wasm_ctx_t *ctx, nxt_wasm_fh_t hook); }; -extern const nxt_wasm_operations_t nxt_wasm_ops; - +extern const nxt_wasm_operations_t nxt_wasm_ops; /* Exported to the WASM module */ extern void nxt_wasm_do_response_end(nxt_wasm_ctx_t *ctx); extern void nxt_wasm_do_send_response(nxt_wasm_ctx_t *ctx, uint32_t offset); extern void nxt_wasm_do_send_headers(nxt_wasm_ctx_t *ctx, uint32_t offset); -#endif /* _NXT_WASM_H_INCLUDED_ */ +#endif /* _NXT_WASM_H_INCLUDED_ */