void sip_register_task(void *pvParameters) { while (1) { /* ================= CREATE SOCKET ================= */ struct sockaddr_in server = {0}; server.sin_family = AF_INET; server.sin_port = htons(SIP_PORT); server.sin_addr.s_addr = inet_addr(ASTERISK_IP); int sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); if (sock < 0) { ESP_LOGE(TAG, "Socket failed"); vTaskDelay(pdMS_TO_TICKS(5000)); continue; } struct timeval timeout = { .tv_sec = 3, .tv_usec = 0 }; setsockopt(sock, SOL_SOCKET, SO_RCVTIMEO, &timeout, sizeof(timeout)); /* ================= FIRST REGISTER ================= */ char register_msg[512]; snprintf(register_msg, sizeof(register_msg), "REGISTER sip:%s SIP/2.0\r\n" "Via: SIP/2.0/UDP 0.0.0.0:5062\r\n" "From: ;tag=1234\r\n" "To: \r\n" "Call-ID: esp32-0001\r\n" "CSeq: 1 REGISTER\r\n" "Contact: \r\n" "Expires: 300\r\n" "Content-Length: 0\r\n" "\r\n", ASTERISK_IP, ASTERISK_IP, ASTERISK_IP); ESP_LOGI(TAG, "Sending REGISTER..."); sendto(sock, register_msg, strlen(register_msg), 0, (struct sockaddr *)&server, sizeof(server)); /* ================= RECEIVE 401 ================= */ char response[1024]; socklen_t addr_len = sizeof(server); int len = recvfrom(sock, response, sizeof(response) - 1, 0, (struct sockaddr *)&server, &addr_len); if (len <= 0) { ESP_LOGE(TAG, "No response"); close(sock); vTaskDelay(pdMS_TO_TICKS(5000)); continue; } response[len] = '\0'; printf("401 RESPONSE:\n%s\n", response); if (!strstr(response, "401")) { ESP_LOGE(TAG, "Expected 401 Unauthorized"); close(sock); vTaskDelay(pdMS_TO_TICKS(5000)); continue; } /* ================= EXTRACT NONCE ================= */ char sip_nonce[256] = {0}; char *n = strstr(response, "nonce=\""); if (!n) { ESP_LOGE(TAG, "No nonce found"); close(sock); vTaskDelay(pdMS_TO_TICKS(5000)); continue; } n += 7; char *end = strchr(n, '"'); if (!end) { ESP_LOGE(TAG, "Bad nonce format"); close(sock); vTaskDelay(pdMS_TO_TICKS(5000)); continue; } size_t nlen = end - n; if (nlen >= sizeof(sip_nonce)) { ESP_LOGE(TAG, "Nonce too long"); close(sock); vTaskDelay(pdMS_TO_TICKS(5000)); continue; } strncpy(sip_nonce, n, nlen); sip_nonce[nlen] = '\0'; ESP_LOGI(TAG, "Nonce: %s", sip_nonce); /* ================= EXTRACT REALM ================= */ char sip_realm[128] = {0}; char *r = strstr(response, "realm=\""); if (!r) { ESP_LOGE(TAG, "Realm not found"); close(sock); vTaskDelay(pdMS_TO_TICKS(5000)); continue; } r += 7; char *rend = strchr(r, '"'); if (!rend) { ESP_LOGE(TAG, "Bad realm format"); close(sock); vTaskDelay(pdMS_TO_TICKS(5000)); continue; } size_t rlen = rend - r; strncpy(sip_realm, r, rlen); sip_realm[rlen] = '\0'; ESP_LOGI(TAG, "Realm: %s", sip_realm); /* ================= COMPUTE DIGEST ================= */ char response_hash[64]; sip_compute_response( "1001", sip_realm, "secret123", sip_nonce, "sip:" ASTERISK_IP, response_hash); /* ================= AUTH REGISTER ================= */ char auth[1024]; snprintf(auth, sizeof(auth), "REGISTER sip:%s SIP/2.0\r\n" "Via: SIP/2.0/UDP 0.0.0.0:5062\r\n" "From: ;tag=1234\r\n" "To: \r\n" "Call-ID: esp32-0001\r\n" "CSeq: 2 REGISTER\r\n" "Contact: \r\n" "Authorization: Digest username=\"1001\", realm=\"%s\", nonce=\"%s\", uri=\"sip:%s\", response=\"%s\"\r\n" "Expires: 300\r\n" "Content-Length: 0\r\n" "\r\n", ASTERISK_IP, ASTERISK_IP, ASTERISK_IP, sip_realm, sip_nonce, ASTERISK_IP, response_hash); ESP_LOGI(TAG, "Sending AUTH REGISTER..."); sendto(sock, auth, strlen(auth), 0, (struct sockaddr *)&server, sizeof(server)); /* ================= FINAL RESPONSE ================= */ char final_resp[1024]; int len2 = recvfrom(sock, final_resp, sizeof(final_resp) - 1, 0, (struct sockaddr *)&server, &addr_len); if (len2 > 0) { final_resp[len2] = '\0'; printf("FINAL RESPONSE:\n%s\n", final_resp); if (strstr(final_resp, "200 OK")) { ESP_LOGI(TAG, "🎉 SIP REGISTER SUCCESS"); } else { ESP_LOGW(TAG, "REGISTER FAILED"); } } else { ESP_LOGW(TAG, "No final response"); } close(sock); ESP_LOGI(TAG, "Waiting 240 seconds before refreshing registration..."); vTaskDelay(pdMS_TO_TICKS(240000)); } }