Apr 15

Kurzer Merker für mich (Bezgl.: Endgeräte werden in bestimmten Konstellationen bei überlangen SMS zugespammt.)

Beim Versand von SMSsen über UCP/EMI (Command 51) gibt es zwei Möglichkeiten wie man mit „überlangen“ SMS (>160 GSM-Chars) umgehen kann:

  1. Concatenated Messages. Man teilt die Messages in 160er Chunks auf und sendet im UDH (User Data Header) folgendes für die Einzelteile:
    1. 0x00 = Concatenated Message
    2. 0x03 = Länge des Infoelements (Folgt jetzt)
    3. 0xC0 = Referenz-ID (kann ausgewürfelt werden. Ist Unique auf Receipient und diese ID)
    4. 0x02 = Anzahl der einzelnen Mulitpart-SMSsen
    5. 0x01 = Diese Message ist Part 1 von dem was in Byte 4 steht.
  2. LongMessage (Feature muss SMS-C seitig aktiviert sein). In dem Falle geht das Ding mit dem Standard UDH in einem Block raus (Maximale Länge ist beim SMSC zu erfragen – in meinem Fall waren 550 Chars durchaus machbar)

So, und nun wird es spannend.

Acknowledgehandling

Im Fall 1 wird

  • jeder einzelne Part fein vom SMSC eingequed,
  • ans SS7 überstellt und
  • für jeden einzelnen Part ein ACK generiert – SS7 generiert das Acknowledge, wenn die (Teil-)Message beim Empfänger angekommen ist, und übergibt das ACK dann ans SMSC welches dieses per UCP/EMI an mich weitergibt.

Das ist ne ziemlich zeitaufwendige Angelegenheit, die man wirklich extrem spürt. Der Durchsatz SMS/sec ist halt nur 1/n so groß wie wenn ich nur eine 160er Nachricht versende (n=Anzahl der Parts).

Fall 2 ist da schon (vermeintlich) eleganter. Wir überstellen den „Blob“ ans SMS-C und bekommen (bei erfolgreicher delivery) genau ein ACK zurück. Und hier liegt der Hase im Pfeffer. Aufgefallen ist mir das ganze, weil es Empfänger gibt, die sich bei mir über nicht aufhörend wollende SMSsen beschwert haben (Empfänger bekommt die selbe SMS wieder und wieder. Hört so gut wie nicht auf. 2000 sind keine seltenheit). Also der Sache auf den Grund gegangen:

  1. die LongMessages werden per UCP/EMI mit ACK-Req (ohne geht nicht) ans SMSC übergeben.
  2. SMSC schiebt die LongMessage ans SS7 durch.
  3. SS7 merkt „Oh, ne LongMessage“ und splitted die in 160er Chunks (Auch wenn es LongMessages gibt. GSM/SMS kann – egal wie – nur 160er Chunks)
  4. Gleichzeitig schiebt das SS7 ein(!) ACK ans SMS-C zurück, wenn der erste Part zugestellt wurde.
  5. ACK kommt via UCP/EMI bei mir an

Schaut man sich das jetzt genauer an, stellt man fest, dass das ACK schon beim ersten erfolgreichen Zustellversuch des ersten Chunks kommt. Jetzt gibt es da draussen irgendwelche irren Endgeräte, die das ACK in genau diesem Fall nicht sauber senden. Mit dem unschönen Nebeneffekt, dass das SMSC für die nicht geackten Chunks immer wieder dem SS7 auf die Füße tritt („Send nochmal“). Je nach unglücklicher Konstellation ist das Endgerät nun in einem ewigen loop.

Fragt mich bitte nicht, warum das im Fall 1 nicht auch passiert. Laut meinem SMSC Kontakt liegt es am Zusammenspiel SMSC/SS7. Einzige Abhilfe war, alles auf MuPart umzustellen. Mit all den häßlichen Nebenwirkungen bezgl. Durchsatz und Co.

Ich denke die einzige Alternative dagegen wäre es, sich selbst ein SS7-Account zu besorgen. Ob man das aber will (zum rumspielen bestimmt mal gerne – aber produktiv)…

 

Vielleicht hat ja einer meiner Leser da ein paar mehr Hintergründe (Jetzt bitte kein: Nimm doch SMPP. Hat sich nämlich rausgestellt, dass überall wo „Simple“ im Protokollnamen vorkommt, es alles andere als Simpel ist. Stehe nicht so auf irre XML/SOAP-Requests)

Tagged with:
Apr 23

node.js ist nett. Vor allem, wenn man auf WebRTC/Sockets setzt. Komplex wird es, wenn man das ganze hinter einem Apache betreibt. Habe jetzt 2h damit verbracht die WS irgendwie an den internen node prozess weiterzuleiten, ohne dass socket.io sich verschluckt. Damit nicht der Nächste vor dem selben Problemchen steht und Stunden versenkt, hier der relevante Teil der apache-conf:

Annahmen:

  • Der interne node.js-prozess horcht auf Port 6543
  • Alles was Websocket ist, wird via /socket.io abgewickelt und hat auch den Transportheader auf „websocket“

<IfModule mod_proxy.c>
  RewriteEngine On
  ProxyVia On
  ProxyRequests Off
  ProxyPreserveHost on
  
  RewriteCond %{REQUEST_URI}  ^/socket.io            [NC]
  RewriteCond %{QUERY_STRING} transport=websocket    [NC]
  RewriteRule /(.*)           ws://internal.etherpad.ip:6543/$1 [P,L]
  ProxyPassReverse /socket.io ws://internal.etherpad.ip:6543/socket.io
  
  RewriteCond %{REQUEST_URI} !^/p/
  RewriteCond %{REQUEST_URI} !^/static/
  RewriteCond %{REQUEST_URI} !^/ep/
  RewriteCond %{REQUEST_URI} !^/minified/
  RewriteCond %{REQUEST_URI} !^/api/
  RewriteCond %{REQUEST_URI} !^/ro/
  RewriteCond %{REQUEST_URI} !^/error/
  RewriteCond %{REQUEST_URI} !^/jserror
  RewriteCond %{REQUEST_URI} !/favicon.ico
  RewriteCond %{REQUEST_URI} !/robots.txt
  
  ProxyPass / http://internal.etherpad.ip:6543/ 
  ProxyPassReverse / http://internal.etherpad.ip:6543/
  <Proxy *>
    Options +FollowSymLinks -MultiViews
    AllowOverride All
    Order allow,deny
    allow from all
  <Proxy>
<IfModule>

									

Tagged with:
Sep 24

IN-Listen lassen sich bei einer Oracle leider nicht als Bind-Var übergeben. Wirklich nicht ? Doch, geht mit Trick:

SELECT   REGEXP_SUBSTR (:txt,'[^,]+',1,LEVEL) as token
   FROM   dual
   CONNECT BY   LEVEL <= LENGTH (:txt) - LENGTH (REPLACE (:txt, ',', '')) + 1
									

Durch den RegEx und das Connect by Prior macht die ORACLE eine Tabelle aus jedem Element, welches in :txt übergeben wird. Getrennt wird per „,“. Einsetzen lässt sich das ganze dann wie folgt:

SELECT * FROM emp WHERE emp_id IN (SELECT   REGEXP_SUBSTR (:txt,'[^,]+',1,LEVEL) as token
   FROM   dual
   CONNECT BY   LEVEL <= LENGTH (:txt) - LENGTH (REPLACE (:txt, ',', '')) + 1)
									

Nicht schön, aber funktional; Und am performantesten von all‘ den Workarounds, die ich bisher so gesehen habe.

Tagged with:
Mrz 15

Wer bei einem Kunden Webanwendungen einführt, welcher nach Jahren immer noch den IE6 (ja, Internetexploder Version sechs !) einsetzt, der muss sich heutzutage immernoch mit dessen inkompatbilitäten herumschlagen. Nun gut, auf einigen Kisten läuft schon der IE8, allerdings hat irgendein schlauer Admin in den IE-Einstellungen das Häkchen bei „Intranetsites in Kompatibilitätsansicht anzeigen“  gesetzt. Angeblich geht das über die Gruppenrichtlinien (von den MS-Jüngern liebevoll „GruRiLis“ genannt – dass alleine ist schon einen Facepalm wert).

Jetzt will ich aber partout nicht in irgendwelchen IE-Modi arbeiten. Der „Kompatibilitätsmodus“ ist nämlich in Wahrheit ein Inkompatibilitätsmodus, der dem IE sagt – Hey, Du kannst zwar W3C-Standard, aber render das mal im IE6/7 Format. Die MSDN (MasoSadoDistributionNetwork) sagt: Meta-Tag setzen (<meta http-equiv=“X-UA-Compatible“ content=“IE=edge“ />). Klappt aber (erwartungsgemäss) nicht.

An der Stelle sei eine Frage erlaubt: Wenn der international angehauchte Developer unter dem Schlagwort „Intranetsites in Kompatibilitätsansicht anzeigen“ nichts findet (was nicht allzu unwahrscheinlich ist, da sich mit dem Dreck keiner auseinandersetzen will), was googlet man da ?

Egal – zurück zum Thema – sonst laufe ich noch Amok: Ein zusätzlicher HTTP-Header mit dem schicken Namen „X-UA-Compatible:“ schafft dann doch tatsächlich abhilfe. Setzt man also in den HTTP-Header  (NICHT zu verwechseln mit dem HTML-Head Element) X-UA-Compatible: IE=IE8, dann klappt es auch mit dem W3C-Standard.

Mal wieder typisch MS: Einen Workaround anbringen, den auch noch frecherweise mit „nicht Kompatibilitätsmodus verwenden“ bezeichnen, um Standardrendering hervorzurufen.

Andrererseits: Es wäre vermutlich zuviel verlangt gewesen, dass MS mal die Biege bekommt, und alte Zöpfe abschneidet. Hat alles sein für und wieder.

Disclaimer: Dieser Blogeintrag enthält zynische Bestandteile und ist rant-frei – wer will, darf die behalten 🙂

Tagged with:
Mrz 01

Wenn man per Cron, PL/SQL, whatever Mails mit mehr als einem Empfänger im Enterpriseumfeld versendet, dann bekommt man meist diese schäbigen Abwesenheitsnotizen & Co. zurück, die einem das Absenderpostfach zumüllen.

Lösungsansätze gibt es da zwei (wovon ich den zweiten bevorzuge):

  1. no-reply@enterprisecompany.tld als Absender verwenden
  2. Einen Mail-Header mitsenden, nämlich: „X-Auto-Response-Suppress: DR,RN,NRN,OOF,AutoReply“

Nummer 2 hat den charmanten Vorteil, dass man Bounces & Co. noch weiterhin bekommt. Nachteil: Der MTA muss es auch erkennen. Bei „Exchange“ ist das der Fall.

Tagged with:
Dez 06

Args. Was ein pfu. Doch von vorne:

Am Freitag letzter Woche ging es los. Meine gute SmartUPS 1500RM hatte auf einmal Hitzewellen. Woher die kamen ? Keine Ahnung. Entdeckt habe ich das ganze eher durch Zufall, da ich ab und an dann doch mal einen Blick ins cacti werfe. Da sah das ganze dann so aus:Hitzewellen in der APC 1500 Interessant in dem Zusammenhang: Die USV wirft erst einen Alert ab ca. 60 Grad Celsius. Meiner Meinung nach – die sollte sich später noch bestätigen – viel zu spät. Das Rack, indem sich die APC 1500 befindet, hat übrigens direkte Aussenbelüftung – im „Serverraum“ waren es also die ganze Zeit über so um die 16 Grad. Bei den Peaks bin ich dann doch mal ‚runter gegangen und hab die Schranktür des Racks aufgemacht, und siehe da: Temp wieder normal.

Am Wochenende stand das gute Stück also erstmal unter Beobachtung. Wie man oben erkennt, war es jedoch ruhig. Pünktlich zum Wochenbeginn fing die USV dann aber wieder an zickig zu werden. Da mir dass ganze (wörtlich !) zu heiss wurde, habe ich mich dann entschlossen das Batterypack (ist in so einer Cartridge) zumindest abzuklemmen. Da die Notstromversorgung Hot (!)-Pluggable ist, also kein Problem.

Sofern die angeschlossenen Geräte in diesem Zustand (Batterien abgezogen / disconnected) noch laufen, sollte man es tunlichst unterlassen der USV den Strom zu klauen. Nicht nur, dass dann alles aus ist – das wäre zu einfach – man bekommt auch keinen Saft wieder auf die USV. Die lässt sich nämlich nur mit angepömpelten Akkus starten (FAIL !!).

Also erstmal Ersatzakkus bestellen. Aber € 520,- für ’ne Cartridge (RBC24) mit 4 Moppedakkus ? Ja sind die wahnsinnig bei APC ? Das muss doch günstiger gehen. Geht es: Diverse Händler verkaufen die Akkus einzeln zum Stückpreis von € 20,- . Da die Akkus bisher noch nicht eingetroffen sind, spreche ich da noch keine Empfehlung aus 🙂

Demontage:

Ansich nett gedacht. Frontblende der UPS entfernen, 4 Schrauben lösen und dann einfach die Cartridge mit den 4 Bleigelakkus rausziehen. Was aber tun, wenn die Dinger aufgequollen sind ? Mit Gewalt ziehen, hat geholfen. Hier das Resultat:

Nun „nur noch“ die 4 Akkus aus der Blechwanne entfernen. Haha ! Kein Tutorial, keine versteckte Klammer mit der die Dinger da gehalten werden – nix. Fühlt sich an wie festgeklebt. So war es auch. Jeder Akku ist mit einem dusseligen doppelseitigem Klebestreifen an der Wanne festgeklebt. (2ter FAIL !!) Also auch hier wieder Gewalt anwenden, und die Dinger vorsichtig mit dem Schraubenzieher anhebeln – irgendwann kommen die von alleine 🙂 Der Sicherheit halber, habe ich die Anschlüsse mal zusammengetaped, isoliert, und mit Nümmerchen versehen. Jeder Platz in der Aluwanne hat dann die korrespondierende Nummer bekommen. Jetzt heisst es warten auf die Ersatzlieferung, und hoffen das der Strom nicht ausfällt.

PS: Vor ca. 6 Jahren ist mir mal eine 750er Desktop-SmartUPS unterm Schreibtisch hochgegangen. War nicht lustig. Die musste ich mit dem Topflappen auf den Balkon befördern… Von daher: Wenn Euch die Akku-Temperatur (Internal Temperature bei APC) komisch vorkommt – lieber heute als morgen die Akkus wechseln.

Tagged with:
Nov 07

Herr Koehntopp philosophiert ueber NULL in PERL vs. NULL in mySQL.

Sehr lesenswert fuer alle, die sich schonmal gefragt haben, wie man am sinnvollsten mit NULL-Werten in Datenbanken umgeht. Das Thema ist ja doch nicht so ganz ohne…

Tagged with:
Okt 26

Kennwort unter Solaris „expired“ ?

Beim Login per ssh per key-auth kommt nix, und bei einem su – xxx kommt die Meldung „Password for user ‚xxx‘ has expired – use passwd(1) to update it“ ? Da gibts eine Loesung:

Einfach auf der Shell (als anderer User) das Tool „login“ aufrufen, mit den „alten“ Credentials einloggen, und schont kommt der Password-Change-Prompt. Gut versteckt das ganze !

Tagged with:
Jan 27

Allen die bei einer Entfernung von über 50cm (ist ja jetzt nicht wirklich viel 🙂 zwischen MacPro und Bluetooth Gerät (MagicMouse / MightyMouse / Keyboard / etc.) Probleme mit der Verbindung haben, sei dieser Artikel bei MacRumours ans Herz gelegt. Mein MacPro (MacPro1,1 / Early 2007) hatte genau diese „falsche Verkabelung“, die dort in Step5 beschrieben ist.

Jetzt, nach Umverdrahtung der „Pigtails“ klappt alles einwandfrei 🙂

Tagged with:
Jun 12

Komisch das ich da noch nie draufgestossen bin (passiert wahrscheinlich erst, wenn man mehr als einen Submit-Button hat – kommt ja idR selten vor). Trotzdem, zum merken und mitschreiben:


Der Internet Explorer (getestet bis Version 6.0) verhält sich bei dieser Art Button leider falsch. Er sendet die Buttonbeschriftung, nicht den Inhalt des value-Attributes. Existieren mehrere Absende-Buttons, werden die Beschriftungen aller Buttons gesendet, nicht nur die des geklickten. Deshalb muss man dem IE leider attestieren, dass er dieses Feature derzeit noch nicht korrekt unterstützt.

via selftml

Tagged with:
Mai 29

Das Perl-Modul WWW::Shorten::Bitly als solches bietet die Moeglichkeit URLs, die zuvor mit bit.ly verkuerzt worden sind, wieder zu „expanden“ und auch diverse Clickstatistiken auf diese URLs zu fahren.

Leider hat das Modul ein paar Schoenheitsfehler:

  1. Beim „Expanden“ meint das Modul die Methode „GET“ nutzen zu wollen. Die API von bit.ly schreibt hier aber ein „POST“ vor. Das ist recht zuegig gefixed. Einfach in der Zeile 257 (Methode „expand“ der Version 1.14) aus dem get ein post machen -> Fertig 🙂
  2. Beim Aufruf der Methode „clicks“ auf URLs mit vielen Statistik-Daten (Referrers, etc.) versagt der SAX-Parser auf ganzer Linie. Er quittiert das Parsen mit einer Fehlermeldung a’la: End tag mismatch (nodeKey != nodeValue) [Ln: x, Col: yyyyy]Das Problem laesst sich dadurch loesen, dass man dem XML::Simple Modul sagt, es soll gefaelligst einen Ordentlichen parser benutzen. z.B. den XML::Parser (der zuvor via cpan installiert werden muss (setzt libexpat1-dev vorraus !)). Wir teilen dies dem Bitly Modul nach dem Einbinden von XML::Simple ueber folgenden String mit: $XML::Simple::PREFERRED_PARSER = 'XML::Parser'; … und oh Wunder: Alles funktioniert

In diffs ausgedrueckt sind folgende Aenderungen an WWW::Shorten::Bitly Version 1.14 notwendig:

22a23,24
> $XML::Simple::PREFERRED_PARSER = 'XML::Parser';
>
257c259
< $self->{response} = $self->{browser}->get($self->{BASE} . '/expand', [
---
> $self->{response} = $self->{browser}->post($self->{BASE} . '/expand', [

Ab nun klappt auch das Auslesen mit dem Modul.

Tagged with:
Apr 30

Kurzer Test/Kompatibilitaetsbericht:

– Originalheadset vom Blackberry 8900: Miese Qualitaet, fiel schon nach 3 Tagen auseinander

– Originalheadset vom Blackberry 9000: Dank In-Ear werden die Umgebungsgeraeusche zwar isoliert, aber man hoert auch jede Bewegung des Headsets

– iPhone 3GS Headset am Blackberry 8900: Prima. Annehmen funktioniert / lauter & leiser leider nicht

– iPhone Classic Headset am Blackberry 8900: Prima. Annehmen funktioniert.

– iPhone 3GS Headset am Blackberry 9000: Funktioniert ueberhaupt nicht (kein Ton, wird nicht als Headset erkannt)

– iPhone Classic Headset am Blackberry 9000: Prima. Annehmen funktioniert.

Fazit: iPhone Classic-Headset (Das bei dem man eh nicht lauter & leiser einstellen kann) mit BB ist eine recht gute Kombination.

Tagged with:
Feb 17

Gegeben sei folgende Tabelle:

Wert Orderer
A 10
B 20
C 30
D 40
E 50
F 60
G 70
H 80
I 90

Nun mal angenommen folgendes möchten wir irgendwie aus der DB bekommen (Um eine 3 spaltige Tabelle mit tr,td aufzubauen:

Wert Wert Wert
A D G
B E H
C F I

Dann benötigen wir die Daten ja in folgender Reihenfolge:

A,D,G,B,E,H,C,F,I

Nach langem herumprobieren habe ich alle Versuche über Bord geworfen, und bin zu folgendem, suboptimalen (aufgrund der Subselects), Ergebnis gekommen:


SELECT wert
FROM (SELECT wert,
x,
ROW_NUMBER () OVER (PARTITION BY x ORDER BY orderer) AS y
FROM (SELECT wert,
orderer,
NTILE (:3) OVER (ORDER BY orderer) AS x
FROM tabelle))
ORDER BY y, x

Hat jemand einen besseren Vorschlag… Ich meine: Funktionieren tut das ganze (In BIND-Variable 3 wird die Anzahl der Spalten übergeben). Aber Sexy geht irgendwie anders…

Tagged with:
Jan 09

Args !

Die Thickbox Library als solches ist ganz nett. Mit Hilfe des Frameworks, welches auf jquery aufsetzt, kann man wunderbare Layer-PopUps basteln (Ja, die braucht man auch schonmal ausserhalb der Werbebanner-Welt). Das Ding ist ziemlich ausgereift, und beisst sich auch nicht mit meinem CGI::Ajax Modul. Einzig der Superbrowser aus Redmond in der Version 6 (InternetEplorer 6 / IE6) macht, wie könnte es anders sein, Probleme !

Das Handling von Seitenbreite und Seitenhöhe dieser Browserwurst kommt nämlich bei dynamisch nachgeladenen Bildchen durcheinander. Soll heissen: Ist die Seite nach dem Laden eines img’s Breiter als vorher, dann behält der Internet Exploder 6 stur die alte Seitenbreite. Da nun Thickbox die PopUps aber immer mittig platzieren will (Mitte = Seitenbreite / 2) passt hier nun garnichts mehr.

Wenn man in der Thickbox.js die Funktion tb_position durch folgendes, mühsam erarbeitetes, Stückchen Kot ersetzt, dann klappts auch mit dem Internet Exploiter…


function tb_position() {
var scrolledX = $(document).scrollLeft()
if ( !(jQuery.browser.msie6)) { // take away IE6
$("#TB_window").css({marginTop: '-' + parseInt((TB_HEIGHT / 2),10) + 'px'});
$("#TB_window").css({marginLeft: '-' + parseInt(( (TB_WIDTH) / 2),10) + 'px', width: TB_WIDTH + 'px'});
} else { // Krankheit aus Redmond !!! Friss dieses:
$("#TB_window").css({marginLeft: parseInt(( (-1)*(TB_WIDTH) / 2)+scrolledX,10) + 'px', width: TB_WIDTH + 'px'});
}
}

Tagged with:
Jan 07

Da ich gerade mal wieder mit den Eigenarten des Internetexploders am kämpfen bin, ist dieses Dokument recht interessant. Erschreckend, dass kein einziger (!) Browser die Content-Disposition – Typen korrekt nach RFC interpretiert.

Jeder, der schonmal fluchenderweise versucht hat Anhänge, via Webserver, mit selbstgebautem Header auszuliefern, weiss worum es hier geht.

Interessant wäre doch ein derartiger Test auch mal mit „CacheControl“, „Cache-Control“, und wer weiss wieviel Varianten es davon noch gibt…

Tagged with:
preload preload preload