יום שבת, אוגוסט 29, 2015

באג הזויי בshrew

בעולם הוינדוס בו אני חיי יש מעט פתרון ללקוחות ipsec חופשיים שפשוט עובדים ויש להם ממשק שהוא נוח לאנשים לא טכניים -  shrew הוא אחד כזה.

יש פתרונות קוד פתוח אחרים אבל נכון להיום המועמד היחידי ששקלתי היה strongswan אבל הוא אינו מתאים לקונפיגורציית לוחם בדרכים (כתובות דינמיות, מאחורי NAT וכן הלאה).

רק מה השבוע הייתי צריך לשדרג מכונות win7 לגירסה 2.2 שהוא מאוד ישן, ואיזו הפתעה חיכתה לי - לאחר השידרוג המכונה פשוט הפסיקה להגיב אז מי שמתכנן שידרוג לגירסת ה  community של shrew יש באג הזויי אם מותקן openvpn על המחשב (לא קרה על מכונות בהם לא היה openvpn).



תודה לחברת הסלולאר שהחזירה אותי לשנות ה 90

אני חייב להגיד תודה ענקית לחברת הסלולאר לה אני מנויי, בגלל תקלה אצלה (יש כאלה שמאשימים את ה HLR) לא היה לי חיווי שיחות נכנסות לא היו SMSים ולא היו MMSים, במהלך התהליך הייתי כה נואש שאף ניסיתי לנסות לתקשר באמצעות MMS ל מייל ונאדה. ממש חזרתי לשנות ה 90 העליזות.


אבל הקטע המדהים בכל הנושא הזה שיכלתי להוציא שיחות החוצה, ורק באמצעות חברי שיצרו איתי קשר ב jabber גיליתי על התקלה.


ביחד עם המזל המדהים שלי (טוב נו ראיתי שידורים מדב קונף) גם חבילת הגלישה שלי הייתה על 0 "הורדת מהירות" - ולמי שלא נתקל באפקט של   "הורדת מהירות" :


מדובר על מצב בו אי אפשר להתחבר לאתר של ספק הסלולר שלך לבדוק מצב חשבון מהירות שנעה מתחת ל 64Kbps - אז כן ה RSSים עובדים אבל אין IMAP.

המהירות כל כך נמוכה שאתה משתעשע ברעיון של להרים שרת dialin להתקין של mgetty ו PPD הפעלת AutoPPP ורק אז להיזכר שאתה צריך ממשק טורי שימיר v34 ויהיה מחובר איכשהו לטלפון/ מחשב, וזאת בעקבות כי חברות הסלולאר חסמו CSD שמבוצע ע"י ATD  (אם יש משהוא שיודע איך להפעיל זאת מודה מראש). לפחות בסופ"ש חזר החיבור הנורמאלי.

אבל מה שהכי הרג אותי זה היה שירות הלקוחות המדהים :


אני : כאשר מתקשרים לקו שלי XXXYYYZZ נאמר כאילו אני לא זמין, אין לי בעייה להוציא שיחות באותו הזמן וחלק קטן מהשיחות אף הצליח להכנס.

שירות הלקוחות : בוצעו מספר ניסיונות היום 25/08/2015 ליצור עמך קשר, אך לצערנו שיחותנו נותרו ללא מענה.

ניסיתי את הטריק הישן והטוב של החלפת רשתות ונעילה על רשת 3G בלבד אבל כלום, זה פשוט לא מתפקד. לאחר מספר ימים התחלתי לקבל שיחות אבל שוב פעם אין לי דרך לדעת אם התקשרתם או לא.

יום שישי, אוגוסט 28, 2015

ייתוש שמפרסם הודעות

אחד הדברים החמים שיצא לי לעבוד בהם לאחרונה היא הטכנולוגיה ה"ישנה" בשם MQTT.
מדובר על פרוטוקול שמאפשר העברת הודעות עם overhead מאוד נמוך ושאחד הפיטצרים שלו הוא חיוויי הודעות.

כן כן אני יודע שב TCP יש retransmit, פה מדובר ברמת האפליקציה בלקוחות SOAP נאלצנו לייצר ACK מהלקוח לקבל תצורה כזאת בכל פעם ופה זה מגיע מובנה.

בשונה בפרוטוקולים כמו SOAP ב MQTT ניתן לבקש כי הודעת שרת תישלח רק פעם אחת , לפחות פעם אחת או בלי שום בדיקה.

כמשתמש קצה הדוגמה הקלאסית לשימוש ב MQTT היא ב facebook messanger (שם זה מגיע יחד עם thrift) או התקנה של ייתוש ולימוד שימוש בו.

מאוד בגדול ב MQTT מדובר בתוצרת מפרסם / מקבל ע"ג תור הודעות שמנוהל ע"י שרת מרכזי.

מאוד בגדול המערכת תורכב משלושה ישויות .

ברוקר - שרת שמקשר הודעות, פה מתנהל ניהול ה queue של ההודעות.
תוכנת פרסום - תוכנה שתודיע על קיום הודעה חדשה ושליחתה לברוקר.
תוכנת מקבל    - תוכנה שמושכת הודעות מהברוקר.

ה QOS עליו דיברתי מכיל שלושה ערכים אפשרים:

0 - אין שום אינדקציה לקבלת / שליחת ההודעה.
1 - פעם אחת לפחות (מחכה להודעת PUBACK)
2 - בדיוק פעם אחת.

בדומה למה שעושים ב REST יש endpoint שמציג מאפייני הודעות למשל עבור פייסבוק :

                /inbox
                /mercury
                /messaging_events
                /orca_presence
                /orca_typing_notifications
                /pp
                /t_ms
                /t_p
                /t_rtc
                /webrtc
                /webrtc_response

למה אני ממליץ על הייתוש (ואני שונא ייתושים) ולא אחרים ?

1. יש לו אחלה תיעוד
2. הוא מגיע מובנה בדביאן בלי שום דרישות מיוחדות.
3. הוא עובד בווינדוס


יום חמישי, אוגוסט 27, 2015

מפגש של GDG באר שבע בקרוב ....

בחור המקורב למוזילה הזכיר כי לא שומעים על מפגשים וכנסים בזמן האחרון , אז הנה יש מפגש (שאני מאמין שיהיה קשור טיפה לקוד פתוח ) - המידע נטפס באמצעות טסריט ה meetup
DESCRIPTION:We are excited to invite you to a sweet and M-azing event     
GDG Beer Sheva\, Herzeliya\, Tel-Aviv together with Android Academy On September 7th Google is hosting the “Google Next” event\, at the end of this event we will be holding our joint Marshmallow event!    

Schedule :  16:00-17:00  Android Performance - Ran Nachmany(Google)  Support library -Royi Benyossef(Vidmind)  

17:00-18:00  How i failed to make lecture
about "@" - Idan Felix(Varonis)   Android M Demos - Yossi Elkrief(Tikal)  & Nir Hartman(Drippler)  
18:00-19:00  Firebase - Uri Shaked(Watchdox)
Data Binding - Yonatan Levin(Gett) & Leonid Olevsky(MyHeritage)    
17:00 -19:00  We want to help you get your app perMission ready:  During the e vent we will be holding an Android M Test lab\, where you can bring your  apps\, and test them on an Android M device- Elad Gelman(Appmyday)  
Attending this meetup is not suffice to attend the event.  You need to register to the “Google Next”  event. You can (and should :) ) attend the event itself and then continue to our event\, or you can come straight
אז מי אמר אני ולא קיבל ? ואם גם אתם יודעים על מפגשים בעלי קשר לקוד פתוח ותוכנה חופשית יאללה לפרסם.

יום ראשון, אוגוסט 23, 2015

debconf rss reader

בשביל לראות את ההרצאות מדב-קונף תפעילו את הסריפט הבא.

עריכה - אני לא בטוח שכולם עדיין תומכים בגירסה 0.9 אז הנה עבור גירסה 2.0 :
#!/usr/bin/perl  

use LWP 5.64; # Loads all important LWP classes, and makes
use HTTP::Cookies; # Allow work with cookies
use WWW::Mechanize;
use XML::RSS;
use Encode qw(decode encode);
use Data::Dumper;

my $browser = LWP::UserAgent->new;

$browser->cookie_jar( HTTP::Cookies->new(
    'file' => '/tmp/headers',
        # where to read/write cookies
    'autosave' => 1,
        # save it to disk when done
  ));

$browser->agent('Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1)');

my $url = "https://wiki.debconf.org/wiki/Videoteam/Subtitles/videos_debconf15";

my $response = $browser->get( $url );
#for each cookie we got, add it to the current jar

$browser->cookie_jar->extract_cookies( $response );

$response = $browser->get( $url );

my $rss = XML::RSS->new( version => '2.0' );
          $rss->channel(
          title        => "video grabber for $url",
          link         => "$url",
          description  => "debconf video grabber ");



$rss->parsefile("$0.rss") if -f "$0.rss";

my $link = $response->content;

while  ($link =~ /<a[ \t]*.*class="external text" href="(.*)">(.*)<\/a>/g)
{

  my $waslinkfoundinarrayofitems=0;

  #don't ask me why but mode insert with RSS 2.0 failed to identify duplicates on my machine
  for my $item  (@{$rss->{'items'}})
  {
    if ($item->{'link'} eq $1)
    {
      $waslinkfoundinarrayofitems=1;
    }
  }

  if ($waslinkfoundinarrayofitems eq 0)
  {
    $rss->add_item( title => $2,description=> "Debconf video $2",link=>$1,language=>"en-us", enclosure => { url => $1, type=>"video/webm"}, mode  => 'insert');
  }

   $link  =~ s/<a[ \t]*.*class="external text" href="(.*)">(.*)<\/a>//;
}

$rss->save("$0.rss");

__END__


=head1 NAME

vg  RSS - a script to get an RSS from debconf videos. 

=head1 SYNOPSIS

Create an RSS 0.9 file based on the messages page.

=head1 DESCRIPTION

This script provide a basic example on how one could get the RSS from the rusty pages without the RSS interface, 

=head1 BUGS

=head1 AUTHOR

Original code:Boris Shtrasman 

=head1 COPYRIGHT

Copyright (c) 2015 Boris Shtrasman 

=head1 LICENSE

this script is free software. You can redistribute it and/or modify it under the same terms as Perl itself.

=head1 CREDITS

Rael Dornfest <rael@oreilly.com>

Jonathan Eisenzopf <eisen@pobox.com>

Wojciech Zwiefka <wojtekz@cnt.pl>

Chris Nandor <pudge@pobox.com>


=head1 SEE ALSO


perl(1), XML::Parser(3), LWP(3), XML::RSS(3),HTTP::Cookies(3)

=cut


, זה יהיה נחמד אם משהוא יוכל להריץ על איזה שרת

#!/usr/bin/perl  

use LWP 5.64; # Loads all important LWP classes, and makes
use HTTP::Cookies; # Allow work with cookies
use WWW::Mechanize;
use XML::RSS;
use Encode qw(decode encode);

my $browser = LWP::UserAgent->new;

$browser->cookie_jar( HTTP::Cookies->new(
    'file' => '/tmp/headers',
        # where to read/write cookies
    'autosave' => 1,
        # save it to disk when done
  ));

$browser->agent('Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1)');

my $url = "https://wiki.debconf.org/wiki/Videoteam/Subtitles/videos_debconf15";

my $response = $browser->get( $url );

#for each cookie we got, add it to the current jar

$browser->cookie_jar->extract_cookies( $response );

$response = $browser->get( $url );

my $rss = XML::RSS->new( version => '0.9' );

          $rss->channel(
          title        => "video grabber  for $url",
          link         => "$url",
          description  => "vg");

$rss->parsefile("$0.rss") if -f "$0.rss";

my $link = $response->content;

while  ($link =~ /<a[ \t]*.*class="external text" href="(.*)">(.*)<\/a>/g)
{
  $rss->add_item( title => $2, link => $1, mode  => 'insert');
  $link  =~ s/<a[ \t]*.*class="external text" href="(.*)">(.*)<\/a>//;
}

$rss->save("$0.rss");

__END__


=head1 NAME

vg  RSS - a script to get an RSS from debconf videos. 

=head1 SYNOPSIS

Create an RSS 0.9 file based on the messages page.

=head1 DESCRIPTION

This script provide a basic example on how one could get the RSS from the rusty pages without the RSS interface, 

=head1 BUGS



=head1 AUTHOR



Original code:Boris Shtrasman 



=head1 COPYRIGHT



Copyright (c) 2015 Boris Shtrasman 



=head1 LICENSE


this script is free software. You can redistribute it and/or modify it under the same terms as Perl itself.


=head1 CREDITS

Rael Dornfest <rael@oreilly.com>

Jonathan Eisenzopf <eisen@pobox.com>

Wojciech Zwiefka <wojtekz@cnt.pl>

Chris Nandor <pudge@pobox.com>

=head1 SEE ALSO

perl(1), XML::Parser(3), LWP(3), XML::RSS(3),HTTP::Cookies(3)


=cut

יום חמישי, אוגוסט 20, 2015

בדיקות דרך קומפילציה

לא מזמן יצא לי לדבר על בדיקות עם ידידי משכבר הימים ויצא לי להציג שיטות תאומות שאני אוהב לדחוף -

היום הרבה מידידי משתמשים בכלים מצויינים כמו ג'נקינס ו TFS (יש הרבה אחרים אבל הרעיון דומה), מאוד בגדול מדובר על מערכות שדוגמת גרסה מסויימת מריצה מספר בדיקות ונותנת את תוצאת הבדיקות (אצלי המצב טיפה שונה כי יש פתרון in-house) ומדווחת למתכנתים .

השיטה הקלאסית שאני מכיר מדברת על מודל בדיקות שמופעל חיצונית למודל הפנימי שלך או מופעלים בזמן ריצה (מקרה קלאסי של gtest):


#include <iostream>
#include <gtest/gtest.h>

struct foo
{
  int random(){return 4;};//chosen by fair dice roll.
                          //guarnteed to be random :P
                          //by xkcd 221

};



TEST(foo, random) {
  foo f;
  EXPECT_EQ(0, f.random());
}



int main (int argc, char **argv)

{
  ::testing::InitGoogleTest(&argc, argv);
  return RUN_ALL_TESTS();
}

שיטה נוספת מדברת על בנייה ספציפית לקומפיילר בה מקפלים מקרה בודד לבד כל פעם (מה שעושים עם lit ו QTest הרבה מאוד פעמים) , אמנם זה פתרון טוב הרבה מאוד פעמים זה לא עונה על הצרכים שלי (לא להחזיק מקטעי קוד נפרדים).

הבעייה בגישה של בדיקה בזמן ריצה (אפילו בתחילת ריצה) או בזמן בנייה כטסריט חיצוני  היא שזה עדיין משאיר פתח עצום למתכנת לעשות קומיט לדחוף אותו לרפוסטורי כשהוא לא נבנה (אני באמת רוצה לראות את איש ה IT שיצליח לדחוף הוק שמבצע בנייה על מכונה של מפתח שתמנע ממנו לעשות push אם בנייה נכשלת).

עכשיו בגלל שאני חי בעולם יחסית טוב (בכל זאת כותב בשפות מקומפלת) יש לי אפשרות נוספת שהתרגלתי להשתמש בה - כתיבת בדיקות שמכשילות קומפילציה שזה בשונה מבניית פרוייקט כן מתקבלת כקרס (גם ב git ו גם svn) בצד מפתח.

אני יודע זה נשמע עקום מאוד בהתחלה אבל ברגע שמתרגלים לזה זה נהיה מאוד נוח, דבר ראשון זה לא דורש שום סיפריה חיצונית (וחברי שנתקלו בבירוקרטיה לינקוקית יודעים על מה אני מדבר) ודבר שני זה מרגיש מאוד טבעי בקוד.

דוגמה קלאסית למטה דטה של מבנים (שתכשיל קומפילציה ) :



#include <iostream>
#include <cstddef>
#include <type_traits>

struct mytype_t
{
   //these are just example for some fields 
   int field1;
   int field2;

//   int non_declared_field_in_cmo_field_table_name;//this field had not been declared in cmo_field_table_name

   char y[3];
};

struct metadata_t
{
   size_t size;       
   size_t offset;     
   size_t allignment; 
   const char *  name;

} ;

//we have macro that fill metadata_t
//

static constexpr const struct metadata_t cmo_field_table_name[] = 
{
  {sizeof(mytype_t::field1),offsetof(mytype_t,field1) , std::alignment_of < decltype (mytype_t::field1 )> :: value,"1"},
  {sizeof(mytype_t::field2),offsetof(mytype_t,field2) , std::alignment_of < decltype (mytype_t::field2 )> :: value,"bla"},
  {sizeof(mytype_t::y),offsetof(mytype_t,y), std::alignment_of <decltype( mytype_t::y) > :: value,"2"},
};



//We declare a type that will fail compilation in case
template <bool>

struct check_struct_for_missing_field
{

};

template <>

struct check_struct_for_missing_field<true>
{
 //I named this field as field and not anything else so the compiler error will be more understandble 
 enum {field = 0};
};


//the magic start here 
//a recursive defintion that check on compile time if all the previous fields had been declared correctly
//in case of non declared fields this will fail compilation and will give us an error that will prevent a person commiting errosly like this mornign
//
//compile_type_check.cc: In instantiation of ‘struct check_if_all_fields_for_struct_correctly_declared_argument_is_field_number<((const metadata_t*)(& cmo_field_table_name)), 2>’:
//compile_type_check.cc:74:178:   required from here
//compile_type_check.cc:62:9: error: ‘field’ is not a member of ‘check_struct_for_missing_field<false>’
//    enum {check =  check_struct_for_missing_field < check_if_all_fields_for_struct_correctly_declared_argument_is_field_number < ptr,index_in_ptr - 1> :: value == ptr[index_in_ptr].offset  > ::field};
//             ^
//             compile_type_check.cc:74:1: error: static assertion failed: missing fields in tab
//              static_assert(check_if_all_fields_for_struct_correctly_declared_argument_is_field_number <cmo_field_table_name, sizeof(cmo_field_table_name)/sizeof(cmo_field_table_name[0]) -1 >::value == sizeof(mytype_t) , "missing fields in tab");
//
//
template < const struct metadata_t * ptr, int index_in_ptr>
struct check_if_all_fields_for_struct_correctly_declared_argument_is_field_number
{
  //incorrect declartion (type mismatchs) are found here
  //a correct offset of field N is  (alligment + size + offset ) for field N - 1
  enum {value =
        (
          ( ptr[index_in_ptr].allignment != ptr[index_in_ptr].size)?

            ptr[index_in_ptr].size + ptr[index_in_ptr].allignment
            :
            ptr[index_in_ptr].size)
            //this will iterate for the previous fields until the first declared in ptr
          + check_if_all_fields_for_struct_correctly_declared_argument_is_field_number<ptr,index_in_ptr-1>::value};
   //in case we have a missing field the next will fail compilation saying : 
   //
   enum {check =  check_struct_for_missing_field < check_if_all_fields_for_struct_correctly_declared_argument_is_field_number < ptr,index_in_ptr - 1> :: value == ptr[index_in_ptr].offset  > ::field};



};

//this is the final step of fields (the zero in the index

template <const struct metadata_t * ptr>

struct check_if_all_fields_for_struct_correctly_declared_argument_is_field_number <ptr,0>
{
 public:
   enum {value = //cmo_field_table_name[0].offset + 
        ( ptr[0].allignment != ptr[0].size)? ptr[0].size +   ptr[0].allignment :ptr[0].size
       };
};


static_assert(check_if_all_fields_for_struct_correctly_declared_argument_is_field_number <cmo_field_table_name, sizeof(cmo_field_table_name)/sizeof(cmo_field_table_name[0]) -1 >::value == sizeof(mytype_t) , "missing fields in tab");



int main(int argc, char *argv[])
{
  for (auto & r: cmo_field_table_name)
  {

    std::cout << "name:" << r.name<< " offset:" << r.offset << " allignment: " << r.allignment << " size:" << r.size << "total: " << r.size + r.allignment << std::endl;

  };

  return 0;

};

בחרתי ב C++  כי לדעתי היא פשוטה מספיק להבנה אבל דבר מאוד דומה ניתן לבצע גם בשפות אחרות.

JAVA: כן אני זוכר את הנושא של המרה לobject ובעיית הstatic הנקודה היא שימוש בטיפוסי הנתונים כמשתנים.

C: יחי המקרו ! יאפ בנייה על בסיס מקרו.

FPC: אם משהו עדיין משתמש בזה - "

FPC 2.4.0 is neither complete nor practically usable yet. Until that is so, templates can be used." אבל אני די בטוח שיש פתרון אחר.

הכשלת קימפול בגלל בדיקות מאפשרת יכולת נבוט טובות יותר ואני מאמין עם ערך wtf/minute נמוך יחסית.
אני ועוד חבר שהיינו באוגוסט פינגווין האחרון שמנו לב לתופעה "מוזרה" לאחר שהתחברנו לרשתות אלחוטיות, ה DNS הלוקלי בו עבדנו לא תפקד היטב.

שמנו לב שכאשר dhcpclient מופעל במקום למשוך את ה domain מהשרת מתקבל shenkar.local.

אם זה נשמע שאין אם זה שום בעייה, צריך להזכר שלפעמים אנו לא מפיצים את ה DNS שלנו לכל העולם אלא רק עובדים בתוך הרשת הפרטית שלנו תחת ה .local, בגלל שזה לא יענה נכונה ההודעה תמשיך לISP שלנו לחפש את הכתובות הדרושות.

הבעייה הייתה ב /var/lib/dhcp/dhclient.leases שם הופיע shenkar.local עבור lease בפועל, מחיקת ה lease פתרה את הבעייה.