After upgrade to XCode 8, my iphone with IOS 10 cannot receive push notification any more.
I have enable the "Automatically manage signing".
I re-generate the certificate from Apple website, the universal one.
My local codes is running without any error.
I can get device token correctly with the codes (swift 3):
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
print("start didFinishLaunchingWithOptions")
// Register the supported interaction types.
let types = UIUserNotificationType([.alert, .badge, .sound])
let mySettings = UIUserNotificationSettings(types: types, categories: nil)
UIApplication.shared.registerUserNotificationSettings(mySettings)
// Register for remote notifications.
UIApplication.shared.registerForRemoteNotifications()
return true
}
func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {
print("start didRegisterForRemoteNotificationsWithDeviceToken")
let deviceTokenString = ((deviceToken as NSData).description.trimmingCharacters(in: CharacterSet(charactersIn: "<>")) as NSString).replacingOccurrences(of: " ", with: "")
....
}
My PHP in server side always return 200 which is successful.
$ch = curl_init();
if (!defined('CURL_HTTP_VERSION_2_0')) {
define('CURL_HTTP_VERSION_2_0', 3);
}
curl_setopt($ch, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_2_0);
$pem_file = '/var/my.pem';
$pem_secret = 'xxxxxx';
$apns_topic = 'xxxxxx';
$apns_expiration = 2;
$change_alert = "{
\"aps\": {
\"alert\": \"$alert_message\",
\"badge\": $badge,
\"sound\": \"default\"
},
\"xxxxxxxx\": \"$xxxxxx\"
}";
$url = "https://api.development.push.apple.com/3/device/$device_token";
//$url = "https://api.push.apple.com/3/device/$device_token";
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_POSTFIELDS, $change_alert);
curl_setopt($ch, CURLOPT_HTTPHEADER, array("apns-topic: $apns_topic", "apns-expiration: $apns_expiration"));
curl_setopt($ch, CURLOPT_SSLCERT, $pem_file);
//curl_setopt($ch, CURLOPT_SSLCERTPASSWD, $pem_secret);
$response = curl_exec($ch);
$httpcode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
My apns-topic is the same with my app bundle id.
Any idea for this issue?
BTW, XCode 8 is not as stable as the previous version.
===============
CURL logs:
* Trying 17.188.135.156...
* Connected to api.push.apple.com (17.188.135.156) port 443 (#0)
* ALPN, offering h2
* ALPN, offering http/1.1
* Cipher selection: ALL:!EXPORT:!EXPORT40:!EXPORT56:!aNULL:!LOW:!RC4:#STRENGTH
* successfully set certificate verify locations:
* CAfile: /etc/pki/tls/certs/ca-bundle.crt
CApath: none
* SSL connection using TLSv1.2 / ECxxxxxxxxxxxxxxxxxx
* ALPN, server accepted to use h2
* Server certificate:
* subject: CN=api.push.apple.com; OU=management:idms.group.533599; O=Apple Inc.; ST=California; C=US
* start date: Aug 28 19:03:46 2015 GMT
* expire date: Sep 26 19:03:46 2017 GMT
* subjectAltName: host "api.push.apple.com" matched cert's "api.push.apple.com"
* issuer: CN=Apple IST CA 2 - G1; OU=Certification Authority; O=Apple Inc.; C=US
* SSL certificate verify ok.
* Using HTTP2, server supports multi-use
* Connection state changed (HTTP/2 confirmed)
* TCP_NODELAY set
* Copying HTTP/2 data in stream buffer to connection buffer after upgrade: len=0
* Using Stream ID: 1 (easy handle 0x7f2d6eda3970)
> POST /3/device/3xxxxxxxxxxxxxxxxxx HTTP/1.1
Host: api.push.apple.com
Accept: */*
apns-topic: xxxxxxxxxx
apns-expiration: 0
Content-Length: 316
Content-Type: application/x-www-form-urlencoded
* Connection state changed (MAX_CONCURRENT_STREAMS updated)!
* We are completely uploaded and fine
< HTTP/2.0 200
< apns-id:AF034xxxxxxxxxxxx0F9F27
<
* Connection #0 to host api.push.apple.com left intact
Related
I am trying to do TCP connection between two stm32 device. Firstly everything is perfect between the line we see on the wireshark.When the TCP client reset and try to send new data, wireshark shows me Retransmittion TCP message but when I debug the server side, server side get the message and send echo message after client receive this echo message.
Why the retransmition message shows, althoug I get and send message to other side ?
FULL client code: https://paste.ubuntu.com/p/VJHzgv29FM/
FULL server code : https://paste.ubuntu.com/p/Wm9gvkSfF7/
/**
* #brief Initializes the tcp echo server
* #param None
* #retval None
*/
void tcp_echoserver_init(void)
{
/* create new tcp pcb */
tcp_echoserver_pcb = tcp_new();
if (tcp_echoserver_pcb != NULL)
{
err_t err;
/* bind echo_pcb to port 7 (ECHO protocol) */
err = tcp_bind(tcp_echoserver_pcb, IP_ADDR_ANY, 7);
if (err == ERR_OK)
{
/* start tcp listening for echo_pcb */
tcp_echoserver_pcb = tcp_listen(tcp_echoserver_pcb);
/* initialize LwIP tcp_accept callback function */
tcp_accept(tcp_echoserver_pcb, tcp_echoserver_accept);
}
else
{
/* deallocate the pcb */
memp_free(MEMP_TCP_PCB, tcp_echoserver_pcb);
}
}
}
Client:
/**
* #brief Connects to the TCP echo server
* #param None
* #retval None
*/
void tcp_echoclient_connect(void)
{
ip_addr_t DestIPaddr;
/* create new tcp pcb */
echoclient_pcb = tcp_new();
if (echoclient_pcb != NULL)
{
IP4_ADDR(&DestIPaddr, (uint8_t)192, (uint8_t)168, (uint8_t)1, (uint8_t)40);
/* connect to destination address/port */
tcp_connect(echoclient_pcb,&DestIPaddr,7,tcp_echoclient_connected);
}
else
{
SerialPrint("not null");
memp_free(MEMP_TCP_PCB, echoclient_pcb);
}
}
When using wireshark to analyze network stream, here is a doc from wireshark that can help you understand what these words means.
We can see the following thing:
TCP Retransmission
Set when all of the following are true:
This is not a keepalive packet.
In the forward direction, the segment length is greater than zero or the SYN or FIN flag is set.
The next expected sequence number is greater than the current sequence number.
For your circumstance, the problem is that the segment length is greater than zero or the SYN or FIN flag is set. This is caused by your reset, so this doesn't mean that your TCP connection causes retransmission.
I am trying to expose few metrics as a stream using SSE. I am able to consume the SSE event from the restController but when I added custom actuator endpoint , it just closes the connection right way.
#Component
#Endpoint(id = "test")
public class StreamMetrics {
#ReadOperation
public Flux<ServerSentEvent<String>> streamEvents() {
return Flux.interval(Duration.ofSeconds(1))
.map(sequence -> ServerSentEvent.<String> builder()
.id(String.valueOf(sequence))
.event("pingpong")
.data("ping")
.build());
}
}
Result
curl -n -v http://localhost:9080/actuator/test
* Trying ::1:9080...
* TCP_NODELAY set
* Connected to localhost (::1) port 9080 (#0)
> GET /actuator/test HTTP/1.1
> Host: localhost:9080
> User-Agent: curl/7.68.0
> Accept: */*
>
* Mark bundle as not supporting multiuse
< HTTP/1.1 200 OK
< transfer-encoding: chunked
< Content-Type: text/event-stream;charset=UTF-8
<
id:0
event:pingpong
data:ping
* Connection #0 to host localhost left intact
this is terminated right after the fist event
where as
#RestController
#RequestMapping(value = "/test")
public class SSETest {
#GetMapping("/stream-sse")
public Flux<ServerSentEvent<String>> streamEvents() {
return Flux.interval(Duration.ofSeconds(1))
.map(sequence -> ServerSentEvent.<String> builder()
.id(String.valueOf(sequence))
.event("pingpong")
.data("ping")
.build());
}
}
Result
curl -v -n http://localhost:9080/test/stream-sse
* Trying ::1:9080...
* TCP_NODELAY set
* Connected to localhost (::1) port 9080 (#0)
> GET /test/stream-sse HTTP/1.1
> Host: localhost:9080
> User-Agent: curl/7.68.0
> Accept: */*
>
* Mark bundle as not supporting multiuse
< HTTP/1.1 200 OK
< transfer-encoding: chunked
< Content-Type: text/event-stream;charset=UTF-8
<
id:0
event:pingpong
data:ping
id:1
event:pingpong
data:ping
id:2
event:pingpong
data:ping
this goes on without getting terminated.
What is special about endpoint annotation that is terminating the event (continuous flow)?
I tested this in '2.2.4 ' and '2.3.0'
I found an answer. #ReadOperation(produces = "text/event-stream") will alter the default content type application/vnd.spring-boot.actuator.v3+json in actuator endpoints. There was not a document so I looked at the code.
#Component
#Endpoint(id = "test")
public class StreamMetrics {
#ReadOperation(produces = "text/event-stream")
public Flux<ServerSentEvent<String>> streamEvents() {
return Flux.interval(Duration.ofSeconds(1))
.map(sequence -> ServerSentEvent.<String> builder()
.id(String.valueOf(sequence))
.event("pingpong")
.data("ping")
.build());
}
}
i have a php script which help to store data into google firebase.
i am using this url to access my php scipt and input the data:
arduino.byethost22.com/FirebaseTest.php?slot1_data=empty&slot2_data=occupied
i have tried it and it is able to store slot1_data as empty and slot2_data as occupied. However i need to use arduino to send this url. i am using this code currently
#include "SoftwareSerial.h"
#define DEBUG false // turn debug message on or off in serial
String server = "arduino.byethost22.com";
String uri = "/FirebaseTest.php?slot1_data=empty&slot2_data=occupied";
void setup() {
Serial3.begin(115200); //serial3 for esp8266
Serial.begin(115200);
sendData("AT+RST\r\n",2000,DEBUG); // reset module
sendData("AT+CWMODE=3\r\n",1000,DEBUG); // configure as access point
//sendData("AT+CWJAP=\"WifiName\",\"Password\"\r\n",3000,DEBUG);
//delay(20000);
sendData("AT+CIFSR\r\n",1000,DEBUG); // get ip address
sendData("AT+CIPMUX=0\r\n",1000,DEBUG); // configure for single connections
}
void loop() {
Serial3.println("AT+CIPSTART=\"TCP\",\"" + server + "\",80");//start a TCP connection.
if( Serial3.find("OK")) {
Serial.println("TCP connection ready");
}
delay(1000);
String getRequest = "GET " + uri + " HTTP/1.1\r\n" +
"Host: " + server + "\r\n\r\n";
String sendCmd = "AT+CIPSEND=";//determine the number of caracters to be sent.
Serial3.print(sendCmd);
Serial3.println(getRequest.length() );
delay(500);
if(Serial3.find(">")) {
Serial.println("Sending..");
}
Serial3.print(getRequest);
if( Serial3.find("SEND OK")) {
Serial.println("Packet sent");
}
while (Serial3.available()) {
String tmpResp = Serial3.readString();
Serial.println(tmpResp);
}
delay(20000);
}
String sendData(String command, const int timeout, boolean debug)
{
String response = "";
Serial3.print(command); // send the read character to the esp8266
long int time = millis();
while( (time+timeout) > millis())
{
while(Serial3.available())
{
// The esp has data so display its output to the serial window
char c = Serial3.read(); // read the next character.
response+=c;
}
}
//if(debug)
//{
Serial.print(response);
//}
return response;
}
it seems that it have problem sending the get request to the php script.
i am getting packet sent in the serial monitor but nothing changed in the firebase data
i am also getting
+IPD,1104:HTTP/1.1 200 OK
Server: nginx
Date: Sat, 15 Oct 2016 09:21:34 GMT
Content-Type: text/html
Content-Length: 875
Connection: keep-alive
Vary: Accept-Encoding
Expires: Thu, 01 Jan 1970 00:00:01 GMT
Cache-Control: no-cache
<html><body><script type="text/javascript" src="/aes.js" ></script><script>function toNumbers(d){var e=[];d.replace(/(..)/g,function(d){e.push(parseInt(d,16))});return e}function toHex(){for(var d=[],d=1==arguments.length&&arguments[0].constructor==Array?arguments[0]:arguments,e="",f=0;f<d.length;f++)e+=(16>d[f]?"0":"")+d[f].toString(16);return e.toLowerCase()}var a=toNumbers("f655ba9d09a112d4968c63579db590b4"),b=toNumbers("98344c2eee86c3994890592585b49f80"),c=toNumbers("b5ebc3b806c39a4a7fc1e4cecb45feab");document.cookie="__test="+toHex(slowAES.decrypt(c,2,a,b))+"; expires=Thu, 31-Dec-37 23:55:55 GMT; path=/"; location.href="http://arduino.byethost22.com/FirebaseTest.php?slot1_data=0&slot2_data=1&i=1";</script><noscript>This site requires Javascript to work, please enable Javascript in your browser or use a browser with Javascript support</noscript></body></html>
It asked me to enable javascript in my browser, but i am using arduino, how do i do it?
When i key in the same uri in google chrome, the data can be updated
how do i solve this problem?
My code finally can work and send data online. i change to use 000webhost as my host server instead of byethost and the data manage to be updated.
i dont really know why but i guess that byethost dont support javascript.
Here is the wget command :
wget --auth-no-challenge --http-user=auth_user --http-password=auth_pass --save-cookies cookies.txt --keep-session-cookies --post-data 'user_login=username&pass=password' https://www.helloworld.com/login.php
Here is the groovy script:
static List<String> login(String baseUrl, String path, query, method = Method.POST) {
try {
def ret = null
def http = new HTTPBuilder(baseUrl)
http.request(method, ContentType.URLENC) {
uri.path = path
uri.query = query
headers.'Authorization' = "Basic ${"auth_user:auth_pass".bytes.encodeBase64().toString()}"
// response handler for a success response code
response.success = { resp, data ->
println "response status: ${resp.statusLine}"
resp.getHeaders('Set-Cookie').each {
def cookie = it.value.split(";").toString()
println cookie
.add(cookie)
}
println 'Response : ' + resp.getData()
}
}
return cookies
} catch (groovyx.net.http.HttpResponseException ex) {
ex.printStackTrace()
} catch (java.net.ConnectException ex) {
ex.printStackTrace()
}
}
def url = "https://www.helloworld.com/login.php"
def path = ""
def query = [ user_login: "username#calypso", pass: "password" ]
// Submit a request via POST
def response = login(url, path, query)
So wget command get me cookie but this groovy script doesn't. This is the response I am getting:
response status: HTTP/1.1 200 OK
Header:
Date : Mon, 28 Mar 2016 19:56:20 GMT
Server : Apache/2.2.3 (CentOS)
Last-Modified : Sat, 03 May 2003 21:37:01 GMT
ETag : "56b0013-1d4-3bcc9546cd940"
Accept-Ranges : bytes
Content-Length : 468
Keep-Alive : timeout=999
Connection : Keep-Alive
Content-Type : text/html; charset=UTF-8
You probably should not do authentication by yourself. If only successful authentication creates a cookie this could explain the phenomenon.
Try
def http = new HTTPBuilder(baseUrl)
http.auth.basic 'auth_user', 'auth_pass'
See also the documentation. Additionally the non-empty response body might give you a hint about what's going wrong.
I think the problem is that you are calling toString on your array after splitting. Try getting the first value of the array:
String cookie = it.value.split(';')[0]
Is it possible that the cookie is httpOnly and your groovy script is honoring that, but wget is not ?
I am trying this example from the doc: Streaming a Response in Symfony2.
/**
* #param Request $request
* #return Response $render
* #Route("/streamedResponse", name="streamed_response")
* #Template("AcmeTestBundle::streamedResponse.html.twig")
*/
public function streamedResponseAction(Request $request)
{
$response = new StreamedResponse();
$response->setCallback(function () {
echo 'Hello World';
flush();
sleep(3);
echo 'Hello World';
flush();
});
return $response;
}
This outputs everything at the same time. Have I done something wrong?
I tried adding ob_flush() and it seems to be working. Here is my code:
public function streamedAction()
{
$response = new StreamedResponse();
$response->setCallback(function () {
echo 'Hello World';
ob_flush();
flush();
sleep(3);
echo 'Hello World';
ob_flush();
flush();
});
return $response;
}
This returns chunked transfer encoding header with chunked data. Here is output of results:
$ telnet localhost 80
Trying ::1...
Connected to localhost.
Escape character is '^]'.
GET /app_dev.php/streamed HTTP/1.1
Host: symfony21.localdomain
HTTP/1.1 200 OK
Date: Wed, 12 Sep 2012 05:34:12 GMT
Server: Apache/2.2.17 (Unix) DAV/2 mod_ssl/2.2.17 OpenSSL/0.9.8o
cache-control: no-cache, private
x-debug-token: 50501eda7d437
Transfer-Encoding: chunked
Content-Type: text/html; charset=UTF-8
b
Hello World
b
Hello World
0
Connection closed by foreign host.
If you see this response in browser, it will display "HelloWorldHelloWorld" after about 3 seconds loading as browser will wait until all chunked data is received as Content-Type is text/*, but when you see the network stream, it is actually doing streaming by sending chunked data.